bugfix; added 'return #from_enclosing'
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 26 Feb 2023 03:22:03 +0000 (21:22 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 26 Feb 2023 03:22:03 +0000 (21:22 -0600)
compiler/include/astnodes.h
compiler/src/checker.c
compiler/src/parser.c
compiler/src/wasm_emit.c
shared/include/bh.h

index 60eb86930e842c51545cab16e28d10ef5f8edf54..ac294ef5c7f24161bf74da97cba42f9ac57047a3 100644 (file)
@@ -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 {
index 8494d84286dc707946cd1c24ab6b31bf67b01a04..17d4c51a5982608c36bcabb5dbd692f59b87c1f7 100644 (file)
@@ -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;
index 0e195ec0f13031de11b1c511b0a15d4b204384e0..fb01ac60047b458a2f85fab0b88e9620ba6cbb09 100644 (file)
@@ -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 != ';') {
index cc337cd9d41c896f777d06b3fe91c8780a514eff..2f77783dfa471f080d79edaae10188b6f2994add 100644 (file)
@@ -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);
index 41c3d8c8e76fe8934dcb70d8d442f2c3480bce9b..70e129e73ab926b1e3c81d5a07625305c8adf93d 100644 (file)
@@ -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;