From: Brendan Hansen Date: Tue, 21 Jul 2020 19:40:22 +0000 (-0500) Subject: Bug fixes on interactions between struct members and arrays X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=27d38dbab7c8fd9b8cdb862252764614fc95ad4b;p=onyx.git Bug fixes on interactions between struct members and arrays --- diff --git a/include/onyxmsgs.h b/include/onyxmsgs.h index 2af7b721..26f2b57c 100644 --- a/include/onyxmsgs.h +++ b/include/onyxmsgs.h @@ -29,10 +29,14 @@ typedef enum MsgType { Msg_Type_Function_Param_Mismatch, Msg_Type_Duplicate_Member, + Msg_Type_No_Field, Msg_Type_Unresolved_Type, Msg_Type_Unresolved_Symbol, + Msg_Type_Failed_Gen_Load, + Msg_Type_Failed_Gen_Store, + Msg_Type_Count, } MsgType; diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 2a941ab2..cb21fb14 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -100,9 +100,10 @@ Type* type_make_pointer(bh_allocator alloc, Type* to); const char* type_get_name(Type* type); u32 type_get_alignment_log2(Type* type); -StructMember type_struct_lookup_member(Type* type, char* member); +b32 type_struct_lookup_member(Type* type, char* member, StructMember* smem); b32 type_is_pointer(Type* type); +b32 type_is_array(Type* tyoe); b32 type_is_struct(Type* type); b32 type_is_bool(Type* type); b32 type_results_in_void(Type* type); diff --git a/onyx b/onyx index f1f7782c..6cb71073 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/arrays.onyx b/progs/arrays.onyx index d121c0f5..669e310c 100644 --- a/progs/arrays.onyx +++ b/progs/arrays.onyx @@ -1,7 +1,7 @@ use "progs/intrinsics" use "progs/print_funcs" -global_arr :: global ^i32; +global_arr :: global []i32; min_i32 :: proc (a: i32, b: i32) -> i32 { least := a; @@ -20,7 +20,7 @@ min :: proc #overloaded { } // NOTE: in-place insertion sort -sort :: proc (src: ^i32, len: i32) { +sort :: proc (src: []i32, len: i32) { for i: 0, len { smallest := i; @@ -44,7 +44,7 @@ str_test :: proc #export { // Address of and dereference cancel each other out print(^*hello_str); - print(hello_str, 5); + print(hello_str as []u8, 5); for i: 0, 10, 2 print(i); @@ -56,8 +56,8 @@ proc #export "main2" { print(__heap_start as i32); len :: 10; - global_arr = alloc((len * 4) as u32) as ^i32; - other_arr := alloc((len * 4) as u32) as ^i32; + global_arr = alloc(sizeof [10]i32) as []i32; + other_arr := alloc((len * 4) as u32) as []i32; print(global_arr as i32); print(other_arr as i32); @@ -94,8 +94,8 @@ alloc :: proc (size: u32) -> rawptr { return ((__heap_start as u32) + curr_offset) as rawptr; } -alloc_2darr :: proc (rows: u32, cols: u32) -> ^^i32 { - arr := alloc(rows * 4) as ^^i32; +alloc_2darr :: proc (rows: u32, cols: u32) -> []^i32 { + arr := alloc(rows * 4) as []^i32; for i: 0, cols arr[i] = alloc(cols * 4) as ^i32; return arr; } diff --git a/progs/structs.onyx b/progs/structs.onyx index 091e911d..23bcce71 100644 --- a/progs/structs.onyx +++ b/progs/structs.onyx @@ -37,7 +37,7 @@ foo_get :: proc (fooarr: []Foo, i: i32) -> ^Foo { return ^fooarr[i]; } -proc #export "main" { +proc #export "main3" { // foo := foo_make(); // other_foo := foo_make(); // other_foo.i = 1234; @@ -126,7 +126,7 @@ link_print :: proc (start: ^Link) -> i32 { return count; } -link_test :: proc #export "main2" { +link_test :: proc #export "main4" { node_head := alloc(sizeof ^Link) as ^^Link; *node_head = 0 as ^Link; @@ -142,21 +142,63 @@ link_test :: proc #export "main2" { // TODO: Make everything below this comment work -// SOA :: struct { -// x : [3]i32; -// y : [3]i32; -// } +multi_arr :: proc #export "main2" { + arr1 := alloc(sizeof [5][5] i32) as [5][5] i32; // Sizeof 25 * 4 + arr2 := alloc(sizeof [5]^ i32) as [5]^ i32; // Sizeof 20 -// soa_test :: proc #export "main" { -// m_arr := alloc(sizeof [5][5]i32) as [5][5]i32; + arr2[3][2] = 5; // (arr1 + (3 * 5 * 4) + (2 * 4)) + print(arr2[3][2]); + // arr2[3][2] = 5; // (arr1[3] + 2 * 4) +} + +Vec2 :: struct { + x : i32; + y : i32; +} -// for y: 0, 5 { -// for x: 0, 5 { -// m_arr[y][x] = x + y * 5; -// } -// } +SOA :: struct { + positions : [10] Vec2; + velocities : [10] Vec2; + things : [10] ^Vec2; +} + +vec2_set :: proc (v: ^Vec2) { + v.x = 1234; + v.y = 5678; +} -// print(m_arr[2][4]); // 14 +soa_test :: proc #export "main" { -// print(sizeof SOA); -// } \ No newline at end of file + // print(sizeof SOA); // 240 + + soa := alloc(sizeof SOA + 20 * sizeof Vec2) as ^SOA; + + for i: 0, 10 { + soa.things[i] = alloc(sizeof Vec2) as ^Vec2; + } + + soa.velocities[2].x = 10; + soa.velocities[2].y = 12; + soa.positions[5].x = 1; + soa.positions[5].y = 2; + soa.positions[2].x = 1001; + vec2_set(^(soa.positions[6])); + vec2_set(soa.things[2]); + + print(soa.positions[5].y); + print(soa.velocities[2].x); + print(soa.things[2].x); + print(soa.things[2].y); + print(soa.positions[6].x); + print(soa.positions[6].y); + + m_arr := alloc(sizeof [5][5]i32) as [5][5]i32; + + for y: 0, 5 { + for x: 0, 5 { + m_arr[y][x] = x + y * 5; + } + } + + for i: 0, 25 print((m_arr as [] i32)[i]); +} \ No newline at end of file diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 35945643..8ac0d5eb 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -88,6 +88,8 @@ CHECK(for, AstFor* fornode) { if (fornode->step) if (check_expression(fornode->step)) return 1; + if (check_expression((AstTyped *) fornode->var)) return 1; + // HACK if (!types_are_compatible(fornode->start->type, &basic_types[Basic_Kind_I32])) { onyx_message_add(Msg_Type_Literal, @@ -474,11 +476,20 @@ CHECK(field_access, AstFieldAccess* field) { } token_toggle_end(field->token); - StructMember smem = type_struct_lookup_member(field->expr->type, field->token->text); + StructMember smem; + if (!type_struct_lookup_member(field->expr->type, field->token->text, &smem)) { + onyx_message_add(Msg_Type_No_Field, + field->token->pos, + field->token->text, + type_get_name(field->expr->type)); + token_toggle_end(field->token); + return 1; + } + field->offset = smem.offset; field->type = smem.type; - token_toggle_end(field->token); + token_toggle_end(field->token); return 0; } diff --git a/src/onyxmsgs.c b/src/onyxmsgs.c index 0a45933f..afd76686 100644 --- a/src/onyxmsgs.c +++ b/src/onyxmsgs.c @@ -27,9 +27,13 @@ static const char* msg_formats[] = { "function '%b' expected type '%s' in position '%d', got '%s'", "duplicate declaration of struct member '%s'", + "field '%s' does not exist on '%s'", "unable to resolve type for symbol '%b'", "unable to resolve symbol '%b'", + + "failed to generate load instruction for type '%s'", + "failed to generate store instruction for type '%s'", }; void onyx_message_init(bh_allocator allocator, bh_table(bh_file_contents)* files) { diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 1f01b57d..4a56ecc5 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -298,15 +298,15 @@ u32 type_get_alignment_log2(Type* type) { return 2; } -StructMember type_struct_lookup_member(Type* type, char* member) { - if (!type_is_struct(type)) return (StructMember) { 0 }; +b32 type_struct_lookup_member(Type* type, char* member, StructMember* smem) { + if (!type_is_struct(type)) return 0; if (type->kind == Type_Kind_Pointer) type = type->Pointer.elem; TypeStruct* stype = &type->Struct; - if (!bh_table_has(StructMember, stype->members, member)) return (StructMember) { 0 }; - StructMember smem = bh_table_get(StructMember, stype->members, member); - return smem; + if (!bh_table_has(StructMember, stype->members, member)) return 0; + *smem = bh_table_get(StructMember, stype->members, member); + return 1; } b32 type_is_pointer(Type* type) { @@ -314,6 +314,10 @@ b32 type_is_pointer(Type* type) { || (type->kind == Type_Kind_Array); } +b32 type_is_array(Type* type) { + return type->kind == Type_Kind_Array; +} + b32 type_is_struct(Type* type) { if (type->kind == Type_Kind_Struct) return 1; if (type->kind == Type_Kind_Pointer && type->Pointer.elem->kind == Type_Kind_Struct) return 1; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 93e21ead..228561e3 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -385,12 +385,13 @@ COMPILE_FUNC(store_instruction, Type* type, u32 alignment, u32 offset) { i32 store_size = type_size_of(type); i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer; - i32 is_integer = is_basic && - ((type->Basic.flags & Basic_Flag_Integer) - || (type->Basic.flags & Basic_Flag_Pointer)); - i32 is_float = is_basic && type->Basic.flags & Basic_Flag_Float; + i32 is_pointer = is_basic && (type->Basic.flags & Basic_Flag_Pointer); + i32 is_integer = is_basic && (type->Basic.flags & Basic_Flag_Integer); + i32 is_float = is_basic && type->Basic.flags & Basic_Flag_Float; - if (is_integer) { + if (is_pointer) { + WID(WI_I32_STORE, ((WasmInstructionData) { alignment, offset })); + } else if (is_integer) { if (store_size == 1) WID(WI_I32_STORE_8, ((WasmInstructionData) { alignment, offset })); else if (store_size == 2) WID(WI_I32_STORE_16, ((WasmInstructionData) { alignment, offset })); else if (store_size == 4) WID(WI_I32_STORE, ((WasmInstructionData) { alignment, offset })); @@ -399,9 +400,9 @@ COMPILE_FUNC(store_instruction, Type* type, u32 alignment, u32 offset) { if (store_size == 4) WID(WI_F32_STORE, ((WasmInstructionData) { alignment, offset })); else if (store_size == 8) WID(WI_F64_STORE, ((WasmInstructionData) { alignment, offset })); } else { - onyx_message_add(Msg_Type_Literal, + onyx_message_add(Msg_Type_Failed_Gen_Store, (OnyxFilePos) { 0 }, - "failed to generate store instruction"); + type_get_name(type)); } *pcode = code; @@ -412,23 +413,26 @@ COMPILE_FUNC(load_instruction, Type* type, u32 offset) { i32 load_size = type_size_of(type); i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer; - i32 is_integer = is_basic && - ((type->Basic.flags & Basic_Flag_Integer) - || (type->Basic.flags & Basic_Flag_Pointer)); + i32 is_pointer = is_basic && (type->Basic.flags & Basic_Flag_Pointer); + i32 is_integer = is_basic && (type->Basic.flags & Basic_Flag_Integer); i32 is_float = is_basic && type->Basic.flags & Basic_Flag_Float; i32 is_unsigned = is_basic && type->Basic.flags & Basic_Flag_Unsigned; WasmInstructionType instr = WI_NOP; i32 alignment = type_get_alignment_log2(type); - if (is_integer) { + if (is_pointer) { + instr = WI_I32_LOAD; + } + else if (is_integer) { if (load_size == 1) instr = WI_I32_LOAD_8_S; else if (load_size == 2) instr = WI_I32_LOAD_16_S; else if (load_size == 4) instr = WI_I32_LOAD; else if (load_size == 8) instr = WI_I64_LOAD; if (load_size < 4 && is_unsigned) instr += 1; - } else if (is_float) { + } + else if (is_float) { if (load_size == 4) instr = WI_F32_LOAD; else if (load_size == 8) instr = WI_F64_LOAD; } @@ -436,9 +440,9 @@ COMPILE_FUNC(load_instruction, Type* type, u32 offset) { WID(instr, ((WasmInstructionData) { alignment, offset })); if (instr == WI_NOP) { - onyx_message_add(Msg_Type_Literal, + onyx_message_add(Msg_Type_Failed_Gen_Load, (OnyxFilePos) { 0 }, - "failed to generate load instruction"); + type_get_name(type)); } *pcode = code; @@ -765,16 +769,26 @@ COMPILE_FUNC(intrinsic_call, AstIntrinsicCall* call) { COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return) { bh_arr(WasmInstruction) code = *pcode; - *offset_return = 0; - compile_expression(mod, &code, aa->expr); if (aa->elem_size != 1) { WID(WI_I32_CONST, aa->elem_size); WI(WI_I32_MUL); } - compile_expression(mod, &code, aa->addr); + + u64 offset = 0; + if (aa->addr->kind == Ast_Kind_Array_Access + && aa->addr->type->kind == Type_Kind_Array) { + compile_array_access_location(mod, &code, (AstArrayAccess *) aa->addr, &offset); + } else if (aa->addr->kind == Ast_Kind_Field_Access + && aa->addr->type->kind == Type_Kind_Array) { + compile_field_access_location(mod, &code, (AstFieldAccess *) aa->addr, &offset); + } else { + compile_expression(mod, &code, aa->addr); + } WI(WI_I32_ADD); + *offset_return += offset; + *pcode = code; } @@ -789,7 +803,8 @@ COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return) { source_expr = (AstTyped *) ((AstFieldAccess *) source_expr)->expr; } - if (source_expr->kind == Ast_Kind_Array_Access) { + if (source_expr->kind == Ast_Kind_Array_Access + && source_expr->type->kind != Type_Kind_Pointer) { u64 o2 = 0; compile_array_access_location(mod, &code, (AstArrayAccess *) source_expr, &o2); offset += o2; @@ -1308,6 +1323,13 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) { module->next_func_idx = program->foreign_func_count; module->next_global_idx = program->foreign_global_count; + WasmExport mem_export = { + .kind = WASM_FOREIGN_MEMORY, + .idx = 0, + }; + bh_table_put(WasmExport, module->exports, "memory", mem_export); + module->export_count++; + bh_arr_each(Entity, entity, program->entities) { switch (entity->type) { case Entity_Type_Function_Header: {