From: Brendan Hansen Date: Thu, 29 Sep 2022 03:24:22 +0000 (-0500) Subject: changed how -> is code generated X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=34c77c5b086a625d20f65be789f9221cec36aee4;p=onyx.git changed how -> is code generated --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index f52e2f00..5246f114 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -282,6 +282,8 @@ typedef enum AstFlags { Ast_Flag_Param_Symbol_Dirty = BH_BIT(21), Ast_Flag_Dead = BH_BIT(22), + + Ast_Flag_Extra_Field_Access = BH_BIT(23) } AstFlags; typedef enum UnaryOp { @@ -1727,6 +1729,7 @@ AstArgument* make_argument(bh_allocator a, AstTyped* value); AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field); AstAddressOf* make_address_of(bh_allocator a, AstTyped* node); AstLocal* make_local(bh_allocator a, OnyxToken* token, AstType* type_node); +AstLocal* make_local_with_type(bh_allocator a, OnyxToken* token, Type* type); AstNode* make_symbol(bh_allocator a, OnyxToken* sym); AstUnaryOp* make_cast(bh_allocator a, AstTyped* expr, Type* to); AstZeroValue* make_zero_value(bh_allocator a, OnyxToken *token, Type* type); diff --git a/compiler/src/astnodes.c b/compiler/src/astnodes.c index dedddf47..7c9d7924 100644 --- a/compiler/src/astnodes.c +++ b/compiler/src/astnodes.c @@ -1285,6 +1285,14 @@ AstLocal* make_local(bh_allocator a, OnyxToken* token, AstType* type_node) { return local; } +AstLocal* make_local_with_type(bh_allocator a, OnyxToken* token, Type* type) { + AstLocal* local = onyx_ast_node_new(a, sizeof(AstLocal), Ast_Kind_Local); + local->token = token; + local->type = type; + + return local; +} + AstNode* make_symbol(bh_allocator a, OnyxToken* sym) { AstNode* symbol = onyx_ast_node_new(a, sizeof(AstNode), Ast_Kind_Symbol); symbol->token = sym; diff --git a/compiler/src/checker.c b/compiler/src/checker.c index e184f08b..ba04efe9 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -1728,6 +1728,7 @@ CheckStatus check_field_access(AstFieldAccess** pfield) { new_access->type = containing_member.type; new_access->expr = field->expr; new_access->flags |= Ast_Flag_Has_Been_Checked; + new_access->flags |= Ast_Flag_Extra_Field_Access; field->expr = (AstTyped *) new_access; } @@ -1810,12 +1811,19 @@ CheckStatus check_method_call(AstBinaryOp** pmcall) { bh_arr_insertn(call_node->args.values, 0, 1); call_node->args.values[0] = implicit_argument; - *pmcall = (AstBinaryOp *) mcall->right; mcall->right->next = mcall->next; mcall->flags |= Ast_Flag_Has_Been_Checked; } - CHECK(call, (AstCall **) pmcall); + CHECK(call, (AstCall **) &mcall->right); + + if (mcall->right->kind != Ast_Kind_Call) { + *pmcall = (AstBinaryOp *) mcall->right; + + } else { + mcall->type = mcall->right->type; + } + return Check_Success; } diff --git a/compiler/src/symres.c b/compiler/src/symres.c index 81481d6b..78ba5cc2 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -451,9 +451,12 @@ static SymresStatus symres_method_call(AstBinaryOp** mcall) { (*mcall)->flags |= Ast_Flag_Has_Been_Symres; } - assert((*mcall)->right->kind == Ast_Kind_Call); SYMRES(expression, (AstTyped **) &(*mcall)->right); + if ((*mcall)->right->kind != Ast_Kind_Call) { + *mcall = (AstBinaryOp *) (*mcall)->right; + } + return Symres_Success; } diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index 8c7fd5df..c724a136 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -709,7 +709,7 @@ EMIT_FUNC(local_allocation, AstTyped* stmt) { u64 local_idx = local_allocate(mod->local_alloc, stmt); bh_imap_put(&mod->local_map, (u64) stmt, local_idx); - if (local_is_wasm_local(stmt)) { + if (stmt->token && local_is_wasm_local(stmt)) { debug_introduce_symbol(mod, stmt->token, DSL_REGISTER, local_idx, stmt->type); } else { debug_introduce_symbol(mod, stmt->token, DSL_STACK, local_idx, stmt->type); @@ -2080,6 +2080,78 @@ EMIT_FUNC(call, AstCall* call) { *pcode = code; } +EMIT_FUNC(method_call, AstBinaryOp *mcall) { + AstCall *call_node = (AstCall *) mcall->right; + + // + // This this is calling a function directly, just emit the call. + if (call_node->callee->kind == Ast_Kind_Function) { + emit_call(mod, pcode, call_node); + return; + } + + // + // If this method call is anything more complicated, there should + // be a field access for the call's callee node. + assert(call_node->callee->kind == Ast_Kind_Field_Access); + + bh_arr(WasmInstruction) code = *pcode; + + AstFieldAccess *fa = (AstFieldAccess *) call_node->callee; + AstFieldAccess **object = (AstFieldAccess **) &fa->expr; + + // + // If this field access has another field access from a use + // by pointer member, descend into that structure. + if (fa->expr->flags & Ast_Flag_Extra_Field_Access) { + object = (AstFieldAccess**) &(*object)->expr; + } + + // + // Create a local variable to store the result of the lookup. + AstLocal *tmp_local = make_local_with_type(context.ast_alloc, NULL, (*object)->type); + tmp_local->flags |= Ast_Flag_Decl_Followed_By_Init; + emit_local_allocation(mod, &code, (AstTyped *) tmp_local); + + // + // Lookup information about the local variable. + u64 tmp_local_idx = bh_imap_get(&mod->local_map, (u64) tmp_local); + b32 tmp_is_wasm_local = (b32) ((tmp_local_idx & LOCAL_IS_WASM) != 0); + u64 offset = 0; + + // + // Do the common assignment pattern found everywhere else. + if (!tmp_is_wasm_local) emit_local_location(mod, &code, tmp_local, &offset); + + emit_expression(mod, &code, *object); + + if (!tmp_is_wasm_local) emit_store_instruction(mod, &code, tmp_local->type, offset); + else WIL(mcall->token, WI_LOCAL_SET, tmp_local_idx); + + // + // Replace the field access with the local variable + *object = (AstFieldAccess *) tmp_local; + + // + // Replace the first argument of the function with a field access. + // If the first argument was an implicit address of, take the address + // of the local variable. + AstArgument *first_arg = (AstArgument *) call_node->args.values[0]; + if (first_arg->value->kind == Ast_Kind_Address_Of && ((AstAddressOf *) first_arg->value)->can_be_removed) { + first_arg->value = (AstTyped *) make_address_of(context.ast_alloc, (AstTyped *) tmp_local); + } else { + first_arg->value = (AstTyped *) tmp_local; + } + + // + // Actually emit the function call. + emit_call(mod, &code, call_node); + + *pcode = code; +} + + + // BUG: This implementation assumes that the host system C's implementation is using // little endian integers. #define SIMD_INT_CONST_INTRINSIC(type, count) { \ @@ -3162,6 +3234,7 @@ EMIT_FUNC(expression, AstTyped* expr) { case Ast_Kind_Binary_Op: emit_binop(mod, &code, (AstBinaryOp *) expr); break; case Ast_Kind_Unary_Op: emit_unaryop(mod, &code, (AstUnaryOp *) expr); break; case Ast_Kind_Alias: emit_expression(mod, &code, ((AstAlias *) expr)->alias); break; + case Ast_Kind_Method_Call: emit_method_call(mod, &code, (AstBinaryOp *) expr); break; case Ast_Kind_Address_Of: { AstAddressOf* aof = (AstAddressOf *) expr; diff --git a/scripts/core_tests.onyx b/scripts/core_tests.onyx index 5a096469..526ee8b1 100644 --- a/scripts/core_tests.onyx +++ b/scripts/core_tests.onyx @@ -4,8 +4,9 @@ use core -#inject -core.Running_Tests :: true +#inject core { + Running_Tests :: true +} main :: () { test.run_tests(); diff --git a/tests/bugs/method_call_source_double b/tests/bugs/method_call_source_double new file mode 100644 index 00000000..d4d5592f --- /dev/null +++ b/tests/bugs/method_call_source_double @@ -0,0 +1,5 @@ +Made foo! +FOOOO!!! +1234 +FOOOO!!! +5678 diff --git a/tests/bugs/method_call_source_double.onyx b/tests/bugs/method_call_source_double.onyx new file mode 100644 index 00000000..8ec3db60 --- /dev/null +++ b/tests/bugs/method_call_source_double.onyx @@ -0,0 +1,36 @@ +#load "core/std" + +use core + +Foo :: struct { + use vtable: ^VTable; + x: u32; + + VTable :: struct { + f: (^Foo) -> void; + } +} + +good_foo := Foo.VTable.{ + f = (f) => { + println("FOOOO!!!"); + println(f.x); + } +} + +make_foo :: () -> Foo { + foo : Foo; + foo.vtable = ^good_foo; + foo.x = 1234; + + printf("Made foo!\n"); + return foo; +} + +main :: () { + foo := make_foo(); + foo->f(); + + Foo.{^good_foo, 5678}->f(); +} +