#foreign_library; vector fields (x, y, z, w) for count <= 4

This commit is contained in:
Ginger Bill
2016-11-15 12:06:58 +00:00
parent 3ce044f84f
commit 0cab083b8f
12 changed files with 296 additions and 198 deletions

View File

@@ -4,7 +4,7 @@
set exe_name=odin.exe
:: Debug = 0, Release = 1
set release_mode=1
set release_mode=0
set compiler_flags= -nologo -Oi -TP -W4 -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
@@ -48,7 +48,7 @@ rem pushd %build_dir%
cl %compiler_settings% "src\main.cpp" ^
/link %linker_settings% -OUT:%exe_name% ^
&& odin run code/demo.odin
&& odin run w:/Freyr/src/main.odin
rem odin run code/demo.odin

View File

@@ -47,3 +47,7 @@ TexParameterf :: proc(target: i32, pname: i32, param: f32) #foreign "glTex
BindTexture :: proc(target: i32, texture: u32) #foreign "glBindTexture"
TexImage2D :: proc(target, level, internal_format, width, height, border, format, _type: i32, pixels: rawptr) #foreign "glTexImage2D"

View File

@@ -56,25 +56,25 @@ stderr := ^__std_files[File_Standard.ERROR]
read_entire_file :: proc(name: string) -> (string, bool) {
read_entire_file :: proc(name: string) -> ([]byte, bool) {
buf: [300]byte
copy(buf[:], name as []byte)
f, file_ok := open(name)
if !file_ok {
return "", false
return nil, false
}
defer close(^f)
length: i64
file_size_ok := win32.GetFileSizeEx(f.handle as win32.HANDLE, ^length) != 0
if !file_size_ok {
return "", false
return nil, false
}
data := new_slice(u8, length)
if data.data == nil {
return "", false
return nil, false
}
single_read_length: i32
@@ -93,13 +93,13 @@ read_entire_file :: proc(name: string) -> (string, bool) {
win32.ReadFile(f.handle as win32.HANDLE, ^data[total_read], to_read, ^single_read_length, nil)
if single_read_length <= 0 {
free(data.data)
return "", false
return nil, false
}
total_read += single_read_length as i64
}
return data as string, true
return data, true
}

View File

@@ -10,6 +10,7 @@ HCURSOR :: type HANDLE
HMENU :: type HANDLE
HBRUSH :: type HANDLE
HGDIOBJ :: type HANDLE
HMODULE :: type HANDLE
WPARAM :: type uint
LPARAM :: type int
LRESULT :: type int
@@ -208,6 +209,9 @@ StretchDIBits :: proc(hdc: HDC,
LoadLibraryA :: proc(c_str: ^u8) -> HMODULE #foreign
FreeLibrary :: proc(h: HMODULE) #foreign
GetProcAddress :: proc(h: HMODULE, c_str: ^u8) -> proc() #foreign
@@ -280,6 +284,7 @@ ReleaseDC :: proc(wnd: HWND, hdc: HDC) -> i32 #foreign #dll_import
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092
WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126
WGL_CONTEXT_CORE_PROFILE_BIT_ARB :: 0x0001
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002
wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign #dll_import

View File

@@ -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;

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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);
}