From: Brendan Hansen Date: Sun, 26 Feb 2023 03:22:03 +0000 (-0600) Subject: bugfix; added 'return #from_enclosing' X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=1e5d17f100972cb5cb629eab5d148eaf4765089d;p=onyx.git bugfix; added 'return #from_enclosing' --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 60eb8693..ac294ef5 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -758,7 +758,7 @@ struct AstDirectiveSolidify { }; // Intruction Node -struct AstReturn { AstNode_base; AstTyped* expr; }; +struct AstReturn { AstNode_base; AstTyped* expr; b32 from_enclosing_scope: 1; }; struct AstJump { AstNode_base; JumpType jump; u32 count; }; typedef struct QualifiedUse { diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 8494d842..17d4c51a 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -133,9 +133,21 @@ static inline void fill_in_type(AstTyped* node) { } // HACK: This should be baked into a structure, not a global variable. -static Type** expected_return_type = NULL; +static bh_arr(Type **) expected_return_type_stack = NULL; CheckStatus check_return(AstReturn* retnode) { + Type ** expected_return_type; + + if (retnode->from_enclosing_scope) { + if (bh_arr_length(expected_return_type_stack) <= 1) { + ERROR(retnode->token->pos, "#from_enclosing is not valid here, as this return statement is not inside of a do-block or expression macro."); + } + + expected_return_type = expected_return_type_stack[bh_arr_length(expected_return_type_stack) - 2]; + } else { + expected_return_type = expected_return_type_stack[bh_arr_length(expected_return_type_stack) - 1]; + } + if (retnode->expr) { CHECK(expression, &retnode->expr); @@ -1632,15 +1644,15 @@ CheckStatus check_do_block(AstDoBlock** pdoblock) { fill_in_type((AstTyped *) doblock); - Type** old_expected_return_type = expected_return_type; - expected_return_type = &doblock->type; + bh_arr_push(expected_return_type_stack, &doblock->type); doblock->block->rules = Block_Rule_Do_Block; CHECK(block, doblock->block); if (doblock->type == &type_auto_return) doblock->type = &basic_types[Basic_Kind_Void]; - expected_return_type = old_expected_return_type; + bh_arr_pop(expected_return_type_stack); + doblock->flags |= Ast_Flag_Has_Been_Checked; return Check_Success; } @@ -2478,7 +2490,8 @@ CheckStatus check_function(AstFunction* func) { } } - expected_return_type = &func->type->Function.return_type; + bh_arr_clear(expected_return_type_stack); + bh_arr_push(expected_return_type_stack, &func->type->Function.return_type); inside_for_iterator = 0; if (for_node_stack) bh_arr_clear(for_node_stack); @@ -2489,13 +2502,12 @@ CheckStatus check_function(AstFunction* func) { ERROR(func->generated_from->pos, "Error in polymorphic procedure generated from this location."); if (status != Check_Success) { - expected_return_type = NULL; return status; } } - if (*expected_return_type == &type_auto_return) { - *expected_return_type = &basic_types[Basic_Kind_Void]; + if (*bh_arr_last(expected_return_type_stack) == &type_auto_return) { + *bh_arr_last(expected_return_type_stack) = &basic_types[Basic_Kind_Void]; } func->flags |= Ast_Flag_Has_Been_Checked; diff --git a/compiler/src/parser.c b/compiler/src/parser.c index 0e195ec0..fb01ac60 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -1413,6 +1413,10 @@ static AstReturn* parse_return_stmt(OnyxParser* parser) { AstReturn* return_node = make_node(AstReturn, Ast_Kind_Return); return_node->token = expect_token(parser, Token_Type_Keyword_Return); + if (parse_possible_directive(parser, "from_enclosing")) { + return_node->from_enclosing_scope = 1; + } + AstTyped* expr = NULL; if (parser->curr->type != ';') { diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index cc337cd9..2f77783d 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -3754,13 +3754,18 @@ EMIT_FUNC(cast, AstUnaryOp* cast) { EMIT_FUNC(return, AstReturn* ret) { bh_arr(WasmInstruction) code = *pcode; + AstLocal* result_destination = NULL; + i64 jump_label = get_structured_jump_label(mod, Jump_Type_Return, ret->from_enclosing_scope ? 2 : 1); + + if (bh_arr_length(mod->return_location_stack) > 0 && jump_label >= 0) { + result_destination = bh_arr_last(mod->return_location_stack); + } + // If we have an expression to return, we see if it should be placed on the linear memory stack, or the WASM stack. if (ret->expr) { - if (bh_arr_length(mod->return_location_stack) > 0) { - AstLocal* dest = bh_arr_last(mod->return_location_stack); - + if (result_destination) { emit_expression(mod, &code, ret->expr); - emit_generic_store_instruction(mod, &code, (AstTyped *) dest, NULL); + emit_generic_store_instruction(mod, &code, (AstTyped *) result_destination, NULL); } else if (mod->curr_cc == CC_Return_Stack) { WIL(NULL, WI_LOCAL_GET, mod->stack_base_idx); @@ -3809,7 +3814,6 @@ EMIT_FUNC(return, AstReturn* ret) { // Clear the normal deferred statements emit_deferred_stmts(mod, &code); - i64 jump_label = get_structured_jump_label(mod, Jump_Type_Return, 1); if (jump_label >= 0) { WIL(NULL, WI_JUMP, jump_label); @@ -4654,6 +4658,9 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { module.debug_context->next_file_id = 0; module.debug_context->next_sym_id = 0; module.debug_context->last_token = NULL; + module.debug_context->sym_info = NULL; + module.debug_context->sym_patches = NULL; + module.debug_context->funcs = NULL; sh_new_arena(module.debug_context->file_info); bh_arr_new(global_heap_allocator, module.debug_context->sym_info, 32); diff --git a/shared/include/bh.h b/shared/include/bh.h index 41c3d8c8..70e129e7 100644 --- a/shared/include/bh.h +++ b/shared/include/bh.h @@ -926,7 +926,9 @@ ptr bh_alloc(bh_allocator a, isize size) { } ptr bh_alloc_aligned(bh_allocator a, isize size, isize alignment) { - return a.proc(a.data, bh_allocator_action_alloc, size, alignment, NULL, 0); + ptr ret = a.proc(a.data, bh_allocator_action_alloc, size, alignment, NULL, 0); + if (ret) memset(ret, 0, size); + return ret; } ptr bh_resize(bh_allocator a, ptr data, isize new_size) { @@ -1294,8 +1296,8 @@ BH_ALLOCATOR_PROC(bh_scratch_allocator_proc) { scratch->curr = bh_pointer_add(scratch->curr, size); if (scratch->curr >= scratch->end) { - scratch->curr = scratch->memory; - retval = scratch->curr; + retval = scratch->memory; + scratch->curr = bh_pointer_add(scratch->memory, size); } } break;