};
// 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 {
}
// 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);
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;
}
}
}
- 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);
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;
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 != ';') {
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);
// 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);
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);
}
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) {
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;