aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-11-15 12:06:58 +0000
committerGinger Bill <bill@gingerbill.org>2016-11-15 12:06:58 +0000
commit0cab083b8fb31f33e96b68f3699ba5a83dbd3353 (patch)
tree14171c7e35dca94fee8c8b54f8120b08a76e8178 /src
parent3ce044f84f24b096156d6b4ce527c93a15f19147 (diff)
#foreign_library; vector fields (x, y, z, w) for count <= 4
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.cpp2
-rw-r--r--src/checker/entity.cpp20
-rw-r--r--src/checker/expr.cpp23
-rw-r--r--src/checker/stmt.cpp4
-rw-r--r--src/checker/types.cpp25
-rw-r--r--src/main.cpp4
-rw-r--r--src/parser.cpp69
-rw-r--r--src/ssa.cpp322
8 files changed, 279 insertions, 190 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp
index 355b8cac7..a2eb0c2b1 100644
--- a/src/checker/checker.cpp
+++ b/src/checker/checker.cpp
@@ -1047,7 +1047,7 @@ void check_parsed_files(Checker *c) {
case_ast_node(id, ImportDecl, decl);
// NOTE(bill): Handle later
case_end;
- case_ast_node(fsl, ForeignSystemLibrary, decl);
+ case_ast_node(fsl, ForeignLibrary, decl);
// NOTE(bill): ignore
case_end;
diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp
index 3a0bee3df..44c32bece 100644
--- a/src/checker/entity.cpp
+++ b/src/checker/entity.cpp
@@ -29,11 +29,12 @@ String const entity_strings[] = {
};
enum EntityFlag : u32 {
- EntityFlag_Visited = 1<<0,
- EntityFlag_Used = 1<<1,
- EntityFlag_Anonymous = 1<<2,
- EntityFlag_Field = 1<<3,
- EntityFlag_Param = 1<<4,
+ EntityFlag_Visited = 1<<0,
+ EntityFlag_Used = 1<<1,
+ EntityFlag_Anonymous = 1<<2,
+ EntityFlag_Field = 1<<3,
+ EntityFlag_Param = 1<<4,
+ EntityFlag_VectorElem = 1<<5,
};
struct Entity {
@@ -141,6 +142,15 @@ Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type,
return entity;
}
+Entity *make_entity_vector_elem(gbAllocator a, Scope *scope, Token token, Type *type, i32 field_src_index) {
+ Entity *entity = make_entity_variable(a, scope, token, type);
+ entity->Variable.field_src_index = field_src_index;
+ entity->Variable.field_index = field_src_index;
+ entity->flags |= EntityFlag_Field;
+ entity->flags |= EntityFlag_VectorElem;
+ return entity;
+}
+
Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type) {
Entity *entity = alloc_entity(a, Entity_Procedure, scope, token, signature_type);
return entity;
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp
index 50367e027..c42040ad5 100644
--- a/src/checker/expr.cpp
+++ b/src/checker/expr.cpp
@@ -1429,9 +1429,22 @@ b32 check_is_expr_vector_index(Checker *c, AstNode *expr) {
expr = unparen_expr(expr);
if (expr->kind == AstNode_IndexExpr) {
ast_node(ie, IndexExpr, expr);
- Type *t = type_of_expr(&c->info, ie->expr);
+ Type *t = type_deref(type_of_expr(&c->info, ie->expr));
if (t != NULL) {
- return is_type_vector(base_type(t));
+ return is_type_vector(t);
+ }
+ }
+ return false;
+}
+
+b32 check_is_vector_elem(Checker *c, AstNode *expr) {
+ // HACK(bill): Handle this correctly. Maybe with a custom AddressingMode
+ expr = unparen_expr(expr);
+ if (expr->kind == AstNode_SelectorExpr) {
+ ast_node(se, SelectorExpr, expr);
+ Type *t = type_deref(type_of_expr(&c->info, se->expr));
+ if (t != NULL && is_type_vector(t)) {
+ return true;
}
}
return false;
@@ -1443,7 +1456,8 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
switch (op.kind) {
case Token_Pointer: { // Pointer address
if (o->mode != Addressing_Variable ||
- check_is_expr_vector_index(c, o->expr)) {
+ check_is_expr_vector_index(c, o->expr) ||
+ check_is_vector_elem(c, o->expr)) {
ast_node(ue, UnaryExpr, node);
gbString str = expr_to_string(ue->expr);
defer (gb_string_free(str));
@@ -3666,6 +3680,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
switch (t->kind) {
case Type_Record: {
if (!is_type_struct(t)) {
+ if (cl->elems.count != 0) {
+ error(ast_node_token(node), "Illegal compound literal");
+ }
break;
}
if (cl->elems.count == 0) {
diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp
index 54ae39ba3..8f651184e 100644
--- a/src/checker/stmt.cpp
+++ b/src/checker/stmt.cpp
@@ -438,8 +438,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
isize lhs_count = as->lhs.count;
isize rhs_count = operands.count;
- isize operand_index = 0;
- for_array(i, operands) {
+ isize operand_count = gb_min(as->lhs.count, operands.count);
+ for (isize i = 0; i < operand_count; i++) {
AstNode *lhs = as->lhs[i];
check_assignment_variable(c, &operands[i], lhs);
}
diff --git a/src/checker/types.cpp b/src/checker/types.cpp
index 071cd0fa3..ba1ace5ff 100644
--- a/src/checker/types.cpp
+++ b/src/checker/types.cpp
@@ -908,6 +908,28 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Vector.count));
return sel;
}
+ if (type->Vector.count <= 4 && !is_type_boolean(type->Vector.elem)) {
+ // HACK(bill): Memory leak
+ switch (type->Vector.count) {
+ #define _VECTOR_FIELD(_name, length) \
+ case (length): \
+ if (field_name == _name) { \
+ selection_add_index(&sel, (length)-1); \
+ sel.entity = make_entity_field(a, NULL, make_token_ident(make_string(_name)), type->Vector.elem, false, (length)-1); \
+ return sel; \
+ } \
+ /*fallthrough*/
+
+ _VECTOR_FIELD("w", 4);
+ _VECTOR_FIELD("z", 3);
+ _VECTOR_FIELD("y", 2);
+ _VECTOR_FIELD("x", 1);
+ case 0: break;
+
+ #undef _VECTOR_FIELD
+ }
+ }
+
} else if (type->kind == Type_Slice) {
String data_str = make_string("data");
String count_str = make_string("count");
@@ -1059,7 +1081,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
switch (t->Record.kind) {
case TypeRecord_Struct:
if (t->Record.field_count > 0) {
- if (!t->Record.struct_is_ordered) {
+ // TODO(bill): What is this supposed to be?
+ if (t->Record.struct_is_packed) {
i64 max = s.word_size;
for (isize i = 1; i < t->Record.field_count; i++) {
// NOTE(bill): field zero is null
diff --git a/src/main.cpp b/src/main.cpp
index 0c6ab2c25..55b115a64 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -234,8 +234,8 @@ int main(int argc, char **argv) {
gbString lib_str = gb_string_make(heap_allocator(), "Kernel32.lib");
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {};
- for_array(i, parser.system_libraries) {
- String lib = parser.system_libraries[i];
+ for_array(i, parser.foreign_libraries) {
+ String lib = parser.foreign_libraries[i];
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" %.*s.lib", LIT(lib));
lib_str = gb_string_appendc(lib_str, lib_str_buf);
diff --git a/src/parser.cpp b/src/parser.cpp
index 4c390932b..d794f86eb 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -56,7 +56,7 @@ struct Parser {
Array<AstFile> files;
Array<ImportedFile> imports;
gbAtomic32 import_index;
- Array<String> system_libraries;
+ Array<String> foreign_libraries;
isize total_token_count;
gbMutex mutex;
};
@@ -261,8 +261,9 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \
b32 is_load; \
AstNode *note; \
}) \
- AST_NODE_KIND(ForeignSystemLibrary, "foreign system library", struct { \
+ AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
Token token, filepath; \
+ b32 is_system; \
}) \
AST_NODE_KIND(_DeclEnd, "", struct{}) \
AST_NODE_KIND(_TypeBegin, "", struct{}) \
@@ -460,8 +461,8 @@ Token ast_node_token(AstNode *node) {
return node->TypeDecl.token;
case AstNode_ImportDecl:
return node->ImportDecl.token;
- case AstNode_ForeignSystemLibrary:
- return node->ForeignSystemLibrary.token;
+ case AstNode_ForeignLibrary:
+ return node->ForeignLibrary.token;
case AstNode_Parameter: {
if (node->Parameter.names.count > 0) {
return ast_node_token(node->Parameter.names[0]);
@@ -965,10 +966,11 @@ AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_n
return result;
}
-AstNode *make_foreign_system_library(AstFile *f, Token token, Token filepath) {
- AstNode *result = make_node(f, AstNode_ForeignSystemLibrary);
- result->ForeignSystemLibrary.token = token;
- result->ForeignSystemLibrary.filepath = filepath;
+AstNode *make_foreign_library(AstFile *f, Token token, Token filepath, b32 is_system) {
+ AstNode *result = make_node(f, AstNode_ForeignLibrary);
+ result->ForeignLibrary.token = token;
+ result->ForeignLibrary.filepath = filepath;
+ result->ForeignLibrary.is_system = is_system;
return result;
}
@@ -2123,8 +2125,8 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
}
case Token_raw_union: {
- Token token = expect_token_after(f, Token_OpenBrace, "`raw_union`");
- Token open = expect_token(f, Token_OpenBrace);
+ Token token = expect_token(f, Token_raw_union);
+ Token open = expect_token_after(f, Token_OpenBrace, "`raw_union`");
isize decl_count = 0;
AstNodeArray decls = parse_struct_params(f, &decl_count, true);
Token close = expect_token(f, Token_CloseBrace);
@@ -2791,10 +2793,17 @@ AstNode *parse_stmt(AstFile *f) {
} else if (tag == "foreign_system_library") {
Token file_path = expect_token(f, Token_String);
if (f->curr_proc == NULL) {
- return make_foreign_system_library(f, s->TagStmt.token, file_path);
+ return make_foreign_library(f, s->TagStmt.token, file_path, true);
}
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
return make_bad_decl(f, token, file_path);
+ } else if (tag == "foreign_library") {
+ Token file_path = expect_token(f, Token_String);
+ if (f->curr_proc == NULL) {
+ return make_foreign_library(f, s->TagStmt.token, file_path, false);
+ }
+ syntax_error(token, "You cannot use #foreign_library within a procedure. This must be done at the file scope");
+ return make_bad_decl(f, token, file_path);
} else if (tag == "thread_local") {
AstNode *var_decl = parse_simple_stmt(f);
if (var_decl->kind != AstNode_VarDecl) {
@@ -2918,7 +2927,7 @@ void destroy_ast_file(AstFile *f) {
b32 init_parser(Parser *p) {
array_init(&p->files, heap_allocator());
array_init(&p->imports, heap_allocator());
- array_init(&p->system_libraries, heap_allocator());
+ array_init(&p->foreign_libraries, heap_allocator());
gb_mutex_init(&p->mutex);
return true;
}
@@ -2935,7 +2944,7 @@ void destroy_parser(Parser *p) {
#endif
array_free(&p->files);
array_free(&p->imports);
- array_free(&p->system_libraries);
+ array_free(&p->foreign_libraries);
gb_mutex_destroy(&p->mutex);
}
@@ -2991,17 +3000,17 @@ String get_fullpath_core(gbAllocator a, String path) {
}
// NOTE(bill): Returns true if it's added
-b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
+b32 try_add_foreign_library_path(Parser *p, String import_file) {
gb_mutex_lock(&p->mutex);
defer (gb_mutex_unlock(&p->mutex));
- for_array(i, p->system_libraries) {
- String import = p->system_libraries[i];
+ for_array(i, p->foreign_libraries) {
+ String import = p->foreign_libraries[i];
if (import == import_file) {
return false;
}
}
- array_add(&p->system_libraries, import_file);
+ array_add(&p->foreign_libraries, import_file);
return true;
}
@@ -3118,18 +3127,36 @@ void parse_file(Parser *p, AstFile *f) {
id->fullpath = import_file;
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
- } else if (node->kind == AstNode_ForeignSystemLibrary) {
- auto *id = &node->ForeignSystemLibrary;
+ } else if (node->kind == AstNode_ForeignLibrary) {
+ auto *id = &node->ForeignLibrary;
String file_str = id->filepath.string;
if (!is_import_path_valid(file_str)) {
- syntax_error(ast_node_token(node), "Invalid `foreign_system_library` path");
+ if (id->is_system) {
+ syntax_error(ast_node_token(node), "Invalid `foreign_system_library` path");
+ } else {
+ syntax_error(ast_node_token(node), "Invalid `foreign_library` path");
+ }
// NOTE(bill): It's a naughty name
f->decls[i] = make_bad_decl(f, id->token, id->token);
continue;
}
- try_add_foreign_system_library_path(p, file_str);
+ if (!id->is_system) {
+ gbAllocator allocator = heap_allocator(); // TODO(bill): Change this allocator
+
+ String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
+ String import_file = rel_path;
+ if (!gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
+ String abs_path = get_fullpath_core(allocator, file_str);
+ if (gb_file_exists(cast(char *)abs_path.text)) {
+ import_file = abs_path;
+ }
+ }
+ file_str = import_file;
+ }
+
+ try_add_foreign_library_path(p, file_str);
}
}
}
diff --git a/src/ssa.cpp b/src/ssa.cpp
index 6d0969e46..060be979c 100644
--- a/src/ssa.cpp
+++ b/src/ssa.cpp
@@ -811,7 +811,7 @@ ssaValue *ssa_make_instr_array_element_ptr(ssaProcedure *p, ssaValue *address, s
Type *t = ssa_type(address);
GB_ASSERT(is_type_pointer(t));
t = base_type(type_deref(t));
- GB_ASSERT(is_type_array(t));
+ GB_ASSERT(is_type_array(t) || is_type_vector(t));
Type *result_type = make_type_pointer(p->module->allocator, t->Array.elem);
@@ -1524,7 +1524,7 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, TokenKind op_kind, ssaValue *left, s
ssaValue *ssa_emit_array_ep(ssaProcedure *proc, ssaValue *s, ssaValue *index) {
Type *st = base_type(type_deref(ssa_type(s)));
- GB_ASSERT(is_type_array(st));
+ GB_ASSERT(is_type_array(st) || is_type_vector(st));
// NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32
index = ssa_emit_conv(proc, index, t_i32);
@@ -1693,6 +1693,8 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S
}
} else if (type->kind == Type_Slice) {
e = ssa_emit_struct_ep(proc, e, index);
+ } else if (type->kind == Type_Vector) {
+ e = ssa_emit_array_ep(proc, e, index);
} else {
GB_PANIC("un-gep-able type");
}
@@ -1854,9 +1856,11 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
return f->token.string;
}
}
- String name = lookup_polymorphic_field(info, dst, f->type);
- if (name.len > 0) {
- return name;
+ if (is_type_struct(f->type)) {
+ String name = lookup_polymorphic_field(info, dst, f->type);
+ if (name.len > 0) {
+ return name;
+ }
}
}
}
@@ -2673,156 +2677,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case_ast_node(cl, CompoundLit, expr);
- ssa_emit_comment(proc, make_string("CompoundLit"));
- Type *type = type_of_expr(proc->module->info, expr);
- Type *bt = base_type(type);
- ssaValue *v = ssa_add_local_generated(proc, type);
-
- Type *et = NULL;
- switch (bt->kind) {
- case Type_Vector: et = bt->Vector.elem; break;
- case Type_Array: et = bt->Array.elem; break;
- case Type_Slice: et = bt->Slice.elem; break;
- }
-
- auto is_elem_const = [](ssaModule *m, AstNode *elem, Type *elem_type) -> b32 {
- if (base_type(elem_type) == t_any) {
- return false;
- }
- if (elem->kind == AstNode_FieldValue) {
- elem = elem->FieldValue.value;
- }
- TypeAndValue *tav = type_and_value_of_expression(m->info, elem);
- GB_ASSERT(tav != NULL);
- return tav->value.kind != ExactValue_Invalid;
- };
-
- switch (bt->kind) {
- default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
-
- case Type_Vector: {
- ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
- for_array(index, cl->elems) {
- AstNode *elem = cl->elems[index];
- if (is_elem_const(proc->module, elem, et)) {
- continue;
- }
- ssaValue *field_elem = ssa_build_expr(proc, elem);
- Type *t = ssa_type(field_elem);
- GB_ASSERT(t->kind != Type_Tuple);
- ssaValue *ev = ssa_emit_conv(proc, field_elem, et);
- ssaValue *i = ssa_make_const_int(proc->module->allocator, index);
- result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
- }
-
- if (cl->elems.count == 1 && bt->Vector.count > 1) {
- isize index_count = bt->Vector.count;
- i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
- for (isize i = 0; i < index_count; i++) {
- indices[i] = 0;
- }
- ssaValue *sv = ssa_emit(proc, ssa_make_instr_vector_shuffle(proc, result, indices, index_count));
- ssa_emit_store(proc, v, sv);
- return ssa_emit_load(proc, v);
- }
- return result;
- } break;
-
- case Type_Record: {
- GB_ASSERT(is_type_struct(bt));
- auto *st = &bt->Record;
- if (cl->elems.count > 0) {
- ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
- for_array(field_index, cl->elems) {
- AstNode *elem = cl->elems[field_index];
-
- ssaValue *field_expr = NULL;
- Entity *field = NULL;
- isize index = field_index;
-
- if (elem->kind == AstNode_FieldValue) {
- ast_node(fv, FieldValue, elem);
- Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
- index = sel.index[0];
- elem = fv->value;
- } else {
- TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
- Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
- index = sel.index[0];
- }
-
- field = st->fields[index];
- if (is_elem_const(proc->module, elem, field->type)) {
- continue;
- }
-
- field_expr = ssa_build_expr(proc, elem);
-
- GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple);
-
-
-
- Type *ft = field->type;
- ssaValue *fv = ssa_emit_conv(proc, field_expr, ft);
- ssaValue *gep = ssa_emit_struct_ep(proc, v, index);
- ssa_emit_store(proc, gep, fv);
- }
- }
- } break;
- case Type_Array: {
- if (cl->elems.count > 0) {
- ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
- for_array(i, cl->elems) {
- AstNode *elem = cl->elems[i];
- if (is_elem_const(proc->module, elem, et)) {
- continue;
- }
- ssaValue *field_expr = ssa_build_expr(proc, elem);
- Type *t = ssa_type(field_expr);
- GB_ASSERT(t->kind != Type_Tuple);
- ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
- ssaValue *gep = ssa_emit_array_ep(proc, v, i);
- ssa_emit_store(proc, gep, ev);
- }
- }
- } break;
- case Type_Slice: {
- if (cl->elems.count > 0) {
- Type *elem_type = bt->Slice.elem;
- Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type);
- Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type);
- Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int);
- ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
- GB_ASSERT(slice->kind == ssaValue_ConstantSlice);
-
- ssaValue *data = ssa_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
-
- for_array(i, cl->elems) {
- AstNode *elem = cl->elems[i];
- if (is_elem_const(proc->module, elem, et)) {
- continue;
- }
-
- ssaValue *field_expr = ssa_build_expr(proc, elem);
- Type *t = ssa_type(field_expr);
- GB_ASSERT(t->kind != Type_Tuple);
- ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type);
- ssaValue *offset = ssa_emit_ptr_offset(proc, data, ssa_make_const_int(proc->module->allocator, i));
- ssa_emit_store(proc, offset, ev);
- }
-
- ssaValue *gep0 = ssa_emit_struct_ep(proc, v, 0);
- ssaValue *gep1 = ssa_emit_struct_ep(proc, v, 1);
- ssaValue *gep2 = ssa_emit_struct_ep(proc, v, 1);
-
- ssa_emit_store(proc, gep0, data);
- ssa_emit_store(proc, gep1, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
- ssa_emit_store(proc, gep2, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
- }
- } break;
- }
-
- return ssa_emit_load(proc, v);
+ return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr);
case_end;
@@ -3630,6 +3485,160 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
ssa_emit_store(proc, v, e);
return ssa_make_addr(v, expr);
case_end;
+
+
+ case_ast_node(cl, CompoundLit, expr);
+ ssa_emit_comment(proc, make_string("CompoundLit"));
+ Type *type = type_of_expr(proc->module->info, expr);
+ Type *bt = base_type(type);
+ ssaValue *v = ssa_add_local_generated(proc, type);
+
+ Type *et = NULL;
+ switch (bt->kind) {
+ case Type_Vector: et = bt->Vector.elem; break;
+ case Type_Array: et = bt->Array.elem; break;
+ case Type_Slice: et = bt->Slice.elem; break;
+ }
+
+ auto is_elem_const = [](ssaModule *m, AstNode *elem, Type *elem_type) -> b32 {
+ if (base_type(elem_type) == t_any) {
+ return false;
+ }
+ if (elem->kind == AstNode_FieldValue) {
+ elem = elem->FieldValue.value;
+ }
+ TypeAndValue *tav = type_and_value_of_expression(m->info, elem);
+ GB_ASSERT(tav != NULL);
+ return tav->value.kind != ExactValue_Invalid;
+ };
+
+ switch (bt->kind) {
+ default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
+
+ case Type_Vector: {
+ ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
+ for_array(index, cl->elems) {
+ AstNode *elem = cl->elems[index];
+ if (is_elem_const(proc->module, elem, et)) {
+ continue;
+ }
+ ssaValue *field_elem = ssa_build_expr(proc, elem);
+ Type *t = ssa_type(field_elem);
+ GB_ASSERT(t->kind != Type_Tuple);
+ ssaValue *ev = ssa_emit_conv(proc, field_elem, et);
+ ssaValue *i = ssa_make_const_int(proc->module->allocator, index);
+ result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
+ }
+
+ if (cl->elems.count == 1 && bt->Vector.count > 1) {
+ isize index_count = bt->Vector.count;
+ i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
+ for (isize i = 0; i < index_count; i++) {
+ indices[i] = 0;
+ }
+ ssaValue *sv = ssa_emit(proc, ssa_make_instr_vector_shuffle(proc, result, indices, index_count));
+ ssa_emit_store(proc, v, sv);
+ return ssa_make_addr(v, expr);
+ }
+ ssa_emit_store(proc, v, result);
+ } break;
+
+ case Type_Record: {
+ GB_ASSERT(is_type_struct(bt));
+ auto *st = &bt->Record;
+ if (cl->elems.count > 0) {
+ ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
+ for_array(field_index, cl->elems) {
+ AstNode *elem = cl->elems[field_index];
+
+ ssaValue *field_expr = NULL;
+ Entity *field = NULL;
+ isize index = field_index;
+
+ if (elem->kind == AstNode_FieldValue) {
+ ast_node(fv, FieldValue, elem);
+ Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
+ index = sel.index[0];
+ elem = fv->value;
+ } else {
+ TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
+ Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
+ index = sel.index[0];
+ }
+
+ field = st->fields[index];
+ if (is_elem_const(proc->module, elem, field->type)) {
+ continue;
+ }
+
+ field_expr = ssa_build_expr(proc, elem);
+
+ GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple);
+
+ Type *ft = field->type;
+ ssaValue *fv = ssa_emit_conv(proc, field_expr, ft);
+ ssaValue *gep = ssa_emit_struct_ep(proc, v, index);
+ ssa_emit_store(proc, gep, fv);
+ }
+ }
+ } break;
+ case Type_Array: {
+ if (cl->elems.count > 0) {
+ ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
+ for_array(i, cl->elems) {
+ AstNode *elem = cl->elems[i];
+ if (is_elem_const(proc->module, elem, et)) {
+ continue;
+ }
+ ssaValue *field_expr = ssa_build_expr(proc, elem);
+ Type *t = ssa_type(field_expr);
+ GB_ASSERT(t->kind != Type_Tuple);
+ ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
+ ssaValue *gep = ssa_emit_array_ep(proc, v, i);
+ ssa_emit_store(proc, gep, ev);
+ }
+ }
+ } break;
+ case Type_Slice: {
+ if (cl->elems.count > 0) {
+ Type *elem_type = bt->Slice.elem;
+ Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type);
+ Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type);
+ Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int);
+ ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
+ GB_ASSERT(slice->kind == ssaValue_ConstantSlice);
+
+ ssaValue *data = ssa_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32);
+
+ for_array(i, cl->elems) {
+ AstNode *elem = cl->elems[i];
+ if (is_elem_const(proc->module, elem, et)) {
+ continue;
+ }
+
+ ssaValue *field_expr = ssa_build_expr(proc, elem);
+ Type *t = ssa_type(field_expr);
+ GB_ASSERT(t->kind != Type_Tuple);
+ ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type);
+ ssaValue *offset = ssa_emit_ptr_offset(proc, data, ssa_make_const_int(proc->module->allocator, i));
+ ssa_emit_store(proc, offset, ev);
+ }
+
+ ssaValue *gep0 = ssa_emit_struct_ep(proc, v, 0);
+ ssaValue *gep1 = ssa_emit_struct_ep(proc, v, 1);
+ ssaValue *gep2 = ssa_emit_struct_ep(proc, v, 1);
+
+ ssa_emit_store(proc, gep0, data);
+ ssa_emit_store(proc, gep1, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
+ ssa_emit_store(proc, gep2, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
+ }
+ } break;
+ }
+
+ return ssa_make_addr(v, expr);
+ case_end;
+
+
}
TokenPos token_pos = ast_node_token(expr).pos;
@@ -3777,6 +3786,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
for_array(i, inits) {
+ if (lvals[i].addr == NULL) {
+ continue;
+ }
ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_addr_type(lvals[i]));
ssa_addr_store(proc, lvals[i], v);
}