mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-04 17:54:39 +00:00
#foreign_library; vector fields (x, y, z, w) for count <= 4
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
12
core/os.odin
12
core/os.odin
@@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
322
src/ssa.cpp
322
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user