#include "onyxutils.h"
static inline b32 should_clone(AstNode* node) {
- if (node->flags & Ast_Flag_No_Clone) return 0;
-
- switch (node->kind) {
- // List of nodes that should not be copied
- case Ast_Kind_Global:
- case Ast_Kind_Memres:
- case Ast_Kind_StrLit:
- case Ast_Kind_Package:
- case Ast_Kind_Enum_Type:
- case Ast_Kind_Enum_Value:
- case Ast_Kind_Overloaded_Function:
- case Ast_Kind_Polymorphic_Proc:
- case Ast_Kind_Alias:
- case Ast_Kind_Code_Block:
- case Ast_Kind_Macro:
- case Ast_Kind_File_Contents:
- return 0;
-
- default: return 1;
- }
+ if (node->flags & Ast_Flag_No_Clone) return 0;
+
+ switch (node->kind) {
+ // List of nodes that should not be copied
+ case Ast_Kind_Global:
+ case Ast_Kind_Memres:
+ case Ast_Kind_StrLit:
+ case Ast_Kind_Package:
+ case Ast_Kind_Enum_Type:
+ case Ast_Kind_Enum_Value:
+ case Ast_Kind_Overloaded_Function:
+ case Ast_Kind_Polymorphic_Proc:
+ case Ast_Kind_Alias:
+ case Ast_Kind_Code_Block:
+ case Ast_Kind_Macro:
+ case Ast_Kind_File_Contents:
+ return 0;
+
+ default: return 1;
+ }
}
static inline i32 ast_kind_to_size(AstNode* node) {
- switch (node->kind) {
+ switch (node->kind) {
case Ast_Kind_Error: return sizeof(AstNode);
case Ast_Kind_Package: return sizeof(AstPackage);
case Ast_Kind_Load_File: return sizeof(AstInclude);
case Ast_Kind_Static_If: return sizeof(AstIfWhile);
case Ast_Kind_If_Expression: return sizeof(AstIfExpression);
case Ast_Kind_Directive_Insert: return sizeof(AstDirectiveInsert);
+ case Ast_Kind_Do_Block: return sizeof(AstDoBlock);
case Ast_Kind_Count: return 0;
- }
+ }
return 0;
}
AstNode* ast_clone_list(bh_allocator a, void* n) {
- AstNode* node = (AstNode *) n;
- if (node == NULL) return NULL;
-
- AstNode* root = ast_clone(a, node);
- AstNode* curr = root->next;
- AstNode** insertion = &root->next;
-
- while (curr != NULL) {
- curr = ast_clone(a, curr);
- *insertion = curr;
- insertion = &curr->next;
- curr = curr->next;
- }
+ AstNode* node = (AstNode *) n;
+ if (node == NULL) return NULL;
+
+ AstNode* root = ast_clone(a, node);
+ AstNode* curr = root->next;
+ AstNode** insertion = &root->next;
+
+ while (curr != NULL) {
+ curr = ast_clone(a, curr);
+ *insertion = curr;
+ insertion = &curr->next;
+ curr = curr->next;
+ }
- return root;
+ return root;
}
#define C(nt, mname) ((nt *) nn)->mname = (void *) ast_clone(a, ((nt *) node)->mname);
// NOTE: Using void* to avoid a lot of unnecessary casting
AstNode* ast_clone(bh_allocator a, void* n) {
- AstNode* node = (AstNode *) n;
+ AstNode* node = (AstNode *) n;
- if (node == NULL) return NULL;
- if (!should_clone(node)) return node;
+ if (node == NULL) return NULL;
+ if (!should_clone(node)) return node;
- static int clone_depth = 0;
- clone_depth++;
+ static int clone_depth = 0;
+ clone_depth++;
- i32 node_size = ast_kind_to_size(node);
- // bh_printf("Cloning %s with size %d\n", onyx_ast_node_kind_string(node->kind), node_size);
+ i32 node_size = ast_kind_to_size(node);
+ // bh_printf("Cloning %s with size %d\n", onyx_ast_node_kind_string(node->kind), node_size);
- AstNode* nn = onyx_ast_node_new(a, node_size, node->kind);
- memmove(nn, node, node_size);
+ AstNode* nn = onyx_ast_node_new(a, node_size, node->kind);
+ memmove(nn, node, node_size);
- switch ((u16) node->kind) {
- case Ast_Kind_Binary_Op:
+ switch ((u16) node->kind) {
+ case Ast_Kind_Binary_Op:
case Ast_Kind_Pipe:
case Ast_Kind_Method_Call:
- C(AstBinaryOp, left);
- C(AstBinaryOp, right);
- break;
+ C(AstBinaryOp, left);
+ C(AstBinaryOp, right);
+ break;
- case Ast_Kind_Unary_Op:
- C(AstUnaryOp, expr);
- C(AstUnaryOp, type_node);
- break;
+ case Ast_Kind_Unary_Op:
+ C(AstUnaryOp, expr);
+ C(AstUnaryOp, type_node);
+ break;
- case Ast_Kind_Param:
- case Ast_Kind_Local:
- C(AstLocal, type_node);
- break;
+ case Ast_Kind_Param:
+ case Ast_Kind_Local:
+ C(AstLocal, type_node);
+ break;
- case Ast_Kind_Call:
+ case Ast_Kind_Call:
arguments_deep_clone(a, &((AstCall *) nn)->args, &((AstCall *) node)->args);
- break;
+ break;
- case Ast_Kind_Argument:
- C(AstArgument, value);
- break;
+ case Ast_Kind_Argument:
+ C(AstArgument, value);
+ break;
- case Ast_Kind_Address_Of:
- C(AstAddressOf, expr);
- break;
+ case Ast_Kind_Address_Of:
+ C(AstAddressOf, expr);
+ break;
- case Ast_Kind_Dereference:
- C(AstDereference, expr);
- break;
+ case Ast_Kind_Dereference:
+ C(AstDereference, expr);
+ break;
- case Ast_Kind_Slice:
- case Ast_Kind_Subscript:
- C(AstSubscript, addr);
- C(AstSubscript, expr);
- break;
+ case Ast_Kind_Slice:
+ case Ast_Kind_Subscript:
+ C(AstSubscript, addr);
+ C(AstSubscript, expr);
+ break;
- case Ast_Kind_Field_Access:
- C(AstFieldAccess, expr);
- break;
+ case Ast_Kind_Field_Access:
+ C(AstFieldAccess, expr);
+ break;
- case Ast_Kind_Size_Of:
- C(AstSizeOf, so_ast_type);
- break;
+ case Ast_Kind_Size_Of:
+ C(AstSizeOf, so_ast_type);
+ break;
- case Ast_Kind_Align_Of:
- C(AstAlignOf, ao_ast_type);
- break;
+ case Ast_Kind_Align_Of:
+ C(AstAlignOf, ao_ast_type);
+ break;
- case Ast_Kind_Struct_Literal: {
- AstStructLiteral* st = (AstStructLiteral *) node;
- AstStructLiteral* dt = (AstStructLiteral *) nn;
+ case Ast_Kind_Struct_Literal: {
+ AstStructLiteral* st = (AstStructLiteral *) node;
+ AstStructLiteral* dt = (AstStructLiteral *) nn;
- dt->stnode = (AstTyped *) ast_clone(a, st->stnode);
+ dt->stnode = (AstTyped *) ast_clone(a, st->stnode);
arguments_deep_clone(a, &dt->args, &st->args);
- break;
- }
+ break;
+ }
- case Ast_Kind_Array_Literal: {
- AstArrayLiteral* st = (AstArrayLiteral *) node;
- AstArrayLiteral* dt = (AstArrayLiteral *) nn;
+ case Ast_Kind_Array_Literal: {
+ AstArrayLiteral* st = (AstArrayLiteral *) node;
+ AstArrayLiteral* dt = (AstArrayLiteral *) nn;
- dt->atnode = (AstTyped *) ast_clone(a, st->atnode);
+ dt->atnode = (AstTyped *) ast_clone(a, st->atnode);
- dt->values = NULL;
- bh_arr_new(global_heap_allocator, dt->values, bh_arr_length(st->values));
- bh_arr_each(AstTyped *, val, st->values)
- bh_arr_push(dt->values, (AstTyped *) ast_clone(a, *val));
+ dt->values = NULL;
+ bh_arr_new(global_heap_allocator, dt->values, bh_arr_length(st->values));
+ bh_arr_each(AstTyped *, val, st->values)
+ bh_arr_push(dt->values, (AstTyped *) ast_clone(a, *val));
- break;
- }
+ break;
+ }
case Ast_Kind_Range_Literal:
- C(AstRangeLiteral, low);
- C(AstRangeLiteral, high);
- C(AstRangeLiteral, step);
- break;
-
- case Ast_Kind_Return:
- C(AstReturn, expr);
- break;
-
- case Ast_Kind_Block:
- ((AstBlock *) nn)->body = ast_clone_list(a, ((AstBlock *) node)->body);
- break;
-
- case Ast_Kind_Defer:
- C(AstDefer, stmt);
- break;
-
- case Ast_Kind_For:
- C(AstFor, var);
- C(AstFor, iter);
- C(AstFor, stmt);
- break;
-
- case Ast_Kind_If:
- case Ast_Kind_While:
- C(AstIfWhile, local);
- C(AstIfWhile, assignment);
-
- if (((AstIfWhile *) nn)->assignment)
- ((AstIfWhile *) nn)->assignment->left = (AstTyped *) ((AstIfWhile *) nn)->local;
-
- C(AstIfWhile, cond);
- //fallthrough
-
- case Ast_Kind_Static_If:
- C(AstIfWhile, true_stmt);
- C(AstIfWhile, false_stmt);
- break;
-
- case Ast_Kind_Switch: {
- AstSwitch* dw = (AstSwitch *) nn;
- AstSwitch* sw = (AstSwitch *) node;
-
- dw->local = (AstLocal *) ast_clone(a, sw->local);
- dw->assignment = (AstBinaryOp *) ast_clone(a, sw->assignment);
- if (dw->assignment)
- dw->assignment->left = (AstTyped *) sw->local;
- dw->expr = (AstTyped *) ast_clone(a, sw->expr);
-
- dw->default_case = (AstBlock *) ast_clone(a, sw->default_case);
-
- dw->cases = NULL;
- bh_arr_new(global_heap_allocator, dw->cases, bh_arr_length(sw->cases));
-
- bh_arr_each(AstSwitchCase, c, sw->cases) {
- bh_arr(AstTyped *) new_values = NULL;
- bh_arr_new(global_heap_allocator, new_values, bh_arr_length(c->values));
- bh_arr_each(AstTyped *, value, c->values)
- bh_arr_push(new_values, (AstTyped *) ast_clone(a, *value));
-
- AstSwitchCase sc;
- sc.values = new_values;
- sc.block = (AstBlock *) ast_clone(a, c->block);
- bh_arr_push(dw->cases, sc);
- }
- break;
- }
-
- case Ast_Kind_Pointer_Type:
- C(AstPointerType, elem);
- break;
-
- case Ast_Kind_Array_Type:
- C(AstArrayType, count_expr);
- C(AstArrayType, elem);
- break;
-
- case Ast_Kind_Slice_Type:
- C(AstSliceType, elem);
- break;
-
- case Ast_Kind_DynArr_Type:
- C(AstDynArrType, elem);
- break;
-
- case Ast_Kind_VarArg_Type:
- C(AstVarArgType, elem);
- break;
-
- case Ast_Kind_Type_Alias:
- C(AstTypeAlias, to);
- break;
+ C(AstRangeLiteral, low);
+ C(AstRangeLiteral, high);
+ C(AstRangeLiteral, step);
+ break;
+
+ case Ast_Kind_Return:
+ C(AstReturn, expr);
+ break;
+
+ case Ast_Kind_Block:
+ ((AstBlock *) nn)->body = ast_clone_list(a, ((AstBlock *) node)->body);
+ break;
+
+ case Ast_Kind_Defer:
+ C(AstDefer, stmt);
+ break;
+
+ case Ast_Kind_For:
+ C(AstFor, var);
+ C(AstFor, iter);
+ C(AstFor, stmt);
+ break;
+
+ case Ast_Kind_If:
+ case Ast_Kind_While:
+ C(AstIfWhile, local);
+ C(AstIfWhile, assignment);
+
+ if (((AstIfWhile *) nn)->assignment)
+ ((AstIfWhile *) nn)->assignment->left = (AstTyped *) ((AstIfWhile *) nn)->local;
+
+ C(AstIfWhile, cond);
+ //fallthrough
+
+ case Ast_Kind_Static_If:
+ C(AstIfWhile, true_stmt);
+ C(AstIfWhile, false_stmt);
+ break;
+
+ case Ast_Kind_Switch: {
+ AstSwitch* dw = (AstSwitch *) nn;
+ AstSwitch* sw = (AstSwitch *) node;
+
+ dw->local = (AstLocal *) ast_clone(a, sw->local);
+ dw->assignment = (AstBinaryOp *) ast_clone(a, sw->assignment);
+ if (dw->assignment)
+ dw->assignment->left = (AstTyped *) sw->local;
+ dw->expr = (AstTyped *) ast_clone(a, sw->expr);
+
+ dw->default_case = (AstBlock *) ast_clone(a, sw->default_case);
+
+ dw->cases = NULL;
+ bh_arr_new(global_heap_allocator, dw->cases, bh_arr_length(sw->cases));
+
+ bh_arr_each(AstSwitchCase, c, sw->cases) {
+ bh_arr(AstTyped *) new_values = NULL;
+ bh_arr_new(global_heap_allocator, new_values, bh_arr_length(c->values));
+ bh_arr_each(AstTyped *, value, c->values)
+ bh_arr_push(new_values, (AstTyped *) ast_clone(a, *value));
+
+ AstSwitchCase sc;
+ sc.values = new_values;
+ sc.block = (AstBlock *) ast_clone(a, c->block);
+ bh_arr_push(dw->cases, sc);
+ }
+ break;
+ }
+
+ case Ast_Kind_Pointer_Type:
+ C(AstPointerType, elem);
+ break;
+
+ case Ast_Kind_Array_Type:
+ C(AstArrayType, count_expr);
+ C(AstArrayType, elem);
+ break;
+
+ case Ast_Kind_Slice_Type:
+ C(AstSliceType, elem);
+ break;
+
+ case Ast_Kind_DynArr_Type:
+ C(AstDynArrType, elem);
+ break;
+
+ case Ast_Kind_VarArg_Type:
+ C(AstVarArgType, elem);
+ break;
+
+ case Ast_Kind_Type_Alias:
+ C(AstTypeAlias, to);
+ break;
case Ast_Kind_Struct_Type: {
AstStructType* ds = (AstStructType *) nn;
}
case Ast_Kind_Struct_Member:
- C(AstStructMember, type_node);
- C(AstStructMember, initial_value);
+ C(AstStructMember, type_node);
+ C(AstStructMember, initial_value);
break;
case Ast_Kind_Poly_Call_Type: {
break;
}
- case Ast_Kind_Function_Type:
- C(AstFunctionType, return_type);
- ((AstFunctionType *) nn)->param_count = ((AstFunctionType *) node)->param_count;
- fori (i, 0, (i64) ((AstFunctionType *) nn)->param_count) {
- ((AstFunctionType *) nn)->params[i] = (AstType *) ast_clone(a, ((AstFunctionType *) node)->params[i]);
- }
- break;
-
- case Ast_Kind_Binding:
- bh_printf("Cloning binding: %b\n", node->token->text, node->token->length);
- C(AstTyped, type_node);
- C(AstBinding, node);
- break;
-
- case Ast_Kind_Function: {
- if (clone_depth > 1) {
- clone_depth--;
- return node;
- }
-
- AstFunction* df = (AstFunction *) nn;
- AstFunction* sf = (AstFunction *) node;
-
- if (sf->flags & Ast_Flag_Foreign) return node;
-
- df->return_type = (AstType *) ast_clone(a, sf->return_type);
- df->body = (AstBlock *) ast_clone(a, sf->body);
-
- df->params = NULL;
- bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params));
-
- bh_arr_each(AstParam, param, sf->params) {
- AstParam new_param = { 0 };
- new_param.local = (AstLocal *) ast_clone(a, param->local);
- new_param.default_value = (AstTyped *) ast_clone(a, param->default_value);
+ case Ast_Kind_Function_Type:
+ C(AstFunctionType, return_type);
+ ((AstFunctionType *) nn)->param_count = ((AstFunctionType *) node)->param_count;
+ fori (i, 0, (i64) ((AstFunctionType *) nn)->param_count) {
+ ((AstFunctionType *) nn)->params[i] = (AstType *) ast_clone(a, ((AstFunctionType *) node)->params[i]);
+ }
+ break;
+
+ case Ast_Kind_Binding:
+ bh_printf("Cloning binding: %b\n", node->token->text, node->token->length);
+ C(AstTyped, type_node);
+ C(AstBinding, node);
+ break;
+
+ case Ast_Kind_Function: {
+ if (clone_depth > 1) {
+ clone_depth--;
+ return node;
+ }
+
+ AstFunction* df = (AstFunction *) nn;
+ AstFunction* sf = (AstFunction *) node;
+
+ if (sf->flags & Ast_Flag_Foreign) return node;
+
+ df->return_type = (AstType *) ast_clone(a, sf->return_type);
+ df->body = (AstBlock *) ast_clone(a, sf->body);
+
+ df->params = NULL;
+ bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params));
+
+ bh_arr_each(AstParam, param, sf->params) {
+ AstParam new_param = { 0 };
+ new_param.local = (AstLocal *) ast_clone(a, param->local);
+ new_param.default_value = (AstTyped *) ast_clone(a, param->default_value);
new_param.vararg_kind = param->vararg_kind;
- bh_arr_push(df->params, new_param);
- }
+ bh_arr_push(df->params, new_param);
+ }
- break;
- }
+ break;
+ }
- case Ast_Kind_Use:
- C(AstUse, expr);
- break;
+ case Ast_Kind_Use:
+ C(AstUse, expr);
+ break;
- case Ast_Kind_Directive_Solidify: {
- AstDirectiveSolidify* dd = (AstDirectiveSolidify *) nn;
- AstDirectiveSolidify* sd = (AstDirectiveSolidify *) node;
+ case Ast_Kind_Directive_Solidify: {
+ AstDirectiveSolidify* dd = (AstDirectiveSolidify *) nn;
+ AstDirectiveSolidify* sd = (AstDirectiveSolidify *) node;
- dd->poly_proc = (AstPolyProc *) ast_clone(a, (AstNode *) sd->poly_proc);
- dd->resolved_proc = NULL;
+ dd->poly_proc = (AstPolyProc *) ast_clone(a, (AstNode *) sd->poly_proc);
+ dd->resolved_proc = NULL;
- dd->known_polyvars = NULL;
- bh_arr_new(global_heap_allocator, dd->known_polyvars, bh_arr_length(sd->known_polyvars));
+ dd->known_polyvars = NULL;
+ bh_arr_new(global_heap_allocator, dd->known_polyvars, bh_arr_length(sd->known_polyvars));
- bh_arr_each(AstPolySolution, sln, sd->known_polyvars) {
- AstPolySolution new_sln;
+ bh_arr_each(AstPolySolution, sln, sd->known_polyvars) {
+ AstPolySolution new_sln;
new_sln.kind = sln->kind;
- new_sln.poly_sym = (AstNode *) ast_clone(a, (AstNode *) sln->poly_sym);
- new_sln.ast_type = (AstType *) ast_clone(a, (AstNode *) sln->ast_type);
- bh_arr_push(dd->known_polyvars, new_sln);
- }
+ new_sln.poly_sym = (AstNode *) ast_clone(a, (AstNode *) sln->poly_sym);
+ new_sln.ast_type = (AstType *) ast_clone(a, (AstNode *) sln->ast_type);
+ bh_arr_push(dd->known_polyvars, new_sln);
+ }
- break;
- }
+ break;
+ }
case Ast_Kind_Compound: {
AstCompound* cd = (AstCompound *) nn;
}
case Ast_Kind_Named_Value:
- C(AstNamedValue, value);
+ C(AstNamedValue, value);
break;
case Ast_Kind_If_Expression:
- C(AstIfExpression, cond);
- C(AstIfExpression, true_expr);
- C(AstIfExpression, false_expr);
+ C(AstIfExpression, cond);
+ C(AstIfExpression, true_expr);
+ C(AstIfExpression, false_expr);
break;
- case Ast_Kind_Directive_Insert:
- C(AstDirectiveInsert, code_expr);
- break;
+ case Ast_Kind_Directive_Insert:
+ C(AstDirectiveInsert, code_expr);
+ break;
- case Ast_Kind_Typeof:
- C(AstTypeOf, expr);
- ((AstTypeOf *) nn)->resolved_type = NULL;
- break;
- }
+ case Ast_Kind_Typeof:
+ C(AstTypeOf, expr);
+ ((AstTypeOf *) nn)->resolved_type = NULL;
+ break;
+
+ case Ast_Kind_Do_Block:
+ C(AstDoBlock, block);
+ ((AstDoBlock *) nn)->type_node = (AstType *) &basic_type_auto_return;
+ break;
+ }
- clone_depth--;
- return nn;
+ clone_depth--;
+ return nn;
}
#undef C
EMIT_FUNC(array_literal, AstArrayLiteral* al);
EMIT_FUNC(range_literal, AstRangeLiteral* range);
EMIT_FUNC(if_expression, AstIfExpression* if_expr);
+EMIT_FUNC(do_block, AstDoBlock* doblock);
EMIT_FUNC(expression, AstTyped* expr);
EMIT_FUNC(cast, AstUnaryOp* cast);
EMIT_FUNC(return, AstReturn* ret);
generate_block_headers = generate_block_headers && (block->rules & Block_Rule_New_Scope);
- if (generate_block_headers)
- emit_enter_structured_block(mod, &code, SBT_Breakable_Block);
+ if (generate_block_headers) {
+ emit_enter_structured_block(mod, &code, (block->rules & Block_Rule_Override_Return)
+ ? SBT_Return_Block
+ : SBT_Breakable_Block);
+ }
forll (AstNode, stmt, block->body, next) {
emit_statement(mod, &code, stmt);
*pcode = code;
}
-EMIT_FUNC(structured_jump, AstJump* jump) {
- bh_arr(WasmInstruction) code = *pcode;
-
+i64 get_structured_jump_label(OnyxWasmModule* mod, JumpType jump_type, u32 jump_count) {
// :CLEANUP These numbers should become constants because they are shared with
// enter_structured_block's definitions.
static const u8 wants[Jump_Type_Count] = { 1, 2, 3, 4 };
- u64 labelidx = 0;
- u8 wanted = wants[jump->jump];
+ i64 labelidx = 0;
+ u8 wanted = wants[jump_type];
b32 success = 0;
- u32 jump_count = jump->count;
-
i32 len = bh_arr_length(mod->structured_jump_target) - 1;
for (u8* t = &bh_arr_last(mod->structured_jump_target); len >= 0; len--, t--) {
if (*t == wanted) jump_count--;
labelidx++;
}
+ return (success == 0) ? -1 : labelidx;
+}
+
+EMIT_FUNC(structured_jump, AstJump* jump) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ i64 labelidx = get_structured_jump_label(mod, jump->jump, jump->count);
+
if (bh_arr_length(mod->deferred_stmts) != 0) {
i32 i = bh_arr_length(mod->deferred_stmts) - 1;
i32 d = bh_arr_length(mod->structured_jump_target) - (labelidx + 1);
}
}
- if (success) {
+ if (labelidx >= 0) {
// NOTE: If the previous instruction was a non conditional jump,
// don't emit another jump since it will never be reached.
if (bh_arr_last(code).type != WI_JUMP)
case Ast_Kind_Block: emit_block(mod, &code, (AstBlock *) stmt, 1); break;
case Ast_Kind_Defer: emit_defer(mod, &code, (AstDefer *) stmt); break;
case Ast_Kind_Local: emit_local_allocation(mod, &code, (AstTyped *) stmt); break;
-
+
case Ast_Kind_Directive_Insert: break;
default: emit_expression(mod, &code, (AstTyped *) stmt); break;
if (!result_is_local) {
emit_local_location(mod, &code, (AstLocal *) if_expr, &offset);
emit_load_instruction(mod, &code, if_expr->type, offset);
-
+
+ } else {
+ WIL(WI_LOCAL_GET, result_local);
+ }
+
+ *pcode = code;
+}
+
+EMIT_FUNC(do_block, AstDoBlock* doblock) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ u64 result_local = local_allocate(mod->local_alloc, (AstTyped *) doblock);
+ b32 result_is_local = (b32) ((result_local & LOCAL_IS_WASM) != 0);
+
+ bh_imap_put(&mod->local_map, (u64) doblock, result_local);
+ bh_arr_push(mod->return_location_stack, (AstLocal *) doblock);
+
+ emit_block(mod, &code, doblock->block, 1);
+
+ u64 offset = 0;
+ if (!result_is_local) {
+ emit_local_location(mod, &code, (AstLocal *) doblock, &offset);
+ emit_load_instruction(mod, &code, doblock->type, offset);
+
} else {
WIL(WI_LOCAL_GET, result_local);
}
+ bh_arr_pop(mod->return_location_stack);
+
*pcode = code;
}
}
case Ast_Kind_Block: emit_block(mod, &code, (AstBlock *) expr, 1); break;
+ case Ast_Kind_Do_Block: emit_do_block(mod, &code, (AstDoBlock *) expr); break;
case Ast_Kind_Call: emit_call(mod, &code, (AstCall *) expr); break;
case Ast_Kind_Argument: emit_expression(mod, &code, ((AstArgument *) expr)->value); break;
case Ast_Kind_Intrinsic_Call: emit_intrinsic_call(mod, &code, (AstCall *) expr); break;
if (fromidx != -1 && toidx != -1) {
WasmInstructionType cast_op = cast_map[fromidx][toidx];
assert(cast_op != WI_UNREACHABLE);
-
+
if (cast_op != WI_NOP) {
WI(cast_op);
}
// 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 (mod->curr_cc == CC_Return_Stack) {
+ if (bh_arr_length(mod->return_location_stack) > 0) {
+ AstLocal* dest = bh_arr_last(mod->return_location_stack);
+ u64 dest_loc = bh_imap_get(&mod->local_map, (u64) dest);
+ b32 dest_is_local = (b32) ((dest_loc & LOCAL_IS_WASM) != 0);
+
+ u64 offset = 0;
+ if (!dest_is_local) emit_local_location(mod, &code, dest, &offset);
+
+ emit_expression(mod, &code, ret->expr);
+
+ if (!dest_is_local) emit_store_instruction(mod, &code, dest->type, offset);
+ else WIL(WI_LOCAL_SET, dest_loc);
+
+ } else if (mod->curr_cc == CC_Return_Stack) {
WIL(WI_LOCAL_GET, mod->stack_base_idx);
WID(WI_I32_CONST, type_size_of(ret->expr->type));
WI(WI_I32_SUB);
}
}
- // Make a patch for the two instructions needed to restore the stack pointer
- SUBMIT_PATCH(mod->stack_leave_patches, 0);
- WI(WI_NOP);
- WI(WI_NOP);
+ i64 jump_label = get_structured_jump_label(mod, Jump_Type_Return, 1);
+ if (jump_label >= 0) {
+ WIL(WI_JUMP, jump_label);
- WI(WI_RETURN);
+ } else {
+ // Make a patch for the two instructions needed to restore the stack pointer
+ SUBMIT_PATCH(mod->stack_leave_patches, 0);
+ WI(WI_NOP);
+ WI(WI_NOP);
+
+ WI(WI_RETURN);
+ }
*pcode = code;
}
EMIT_FUNC(zero_value_for_type, Type* type, OnyxToken* where) {
bh_arr(WasmInstruction) code = *pcode;
-
+
if (type_is_structlike_strict(type)) {
i32 mem_count = type_linear_member_count(type);
TypeWithOffset two;
bh_arr_insert_end(wasm_func.code, 5);
fori (i, 0, 5) wasm_func.code[i] = (WasmInstruction) { WI_NOP, 0 };
-
+
mod->stack_base_idx = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
// Generate code
StrLitInfo sti = bh_table_get(StrLitInfo, mod->string_literals, (char *) strdata);
strlit->addr = sti.addr;
strlit->length = sti.len;
-
+
bh_free(global_heap_allocator, strdata);
return;
}
i++;
}
- break;
+ break;
}
case Ast_Kind_Struct_Literal: {
if (effective_type->kind == Type_Kind_Enum)
effective_type = effective_type->Enum.backing;
-
+
switch (effective_type->Basic.kind) {
case Basic_Kind_Bool:
case Basic_Kind_I8:
.next_elem_idx = 0,
.structured_jump_target = NULL,
+ .return_location_stack = NULL,
.local_allocations = NULL,
.stack_leave_patches = NULL,
bh_arr_new(alloc, module.data, 4);
bh_arr_new(alloc, module.elems, 4);
+ bh_arr_new(global_heap_allocator, module.return_location_stack, 4);
bh_arr_new(global_heap_allocator, module.structured_jump_target, 16);
bh_arr_set_length(module.structured_jump_target, 0);
switch (ent->type) {
case Entity_Type_Foreign_Function_Header:
if (!should_emit_function(ent->function)) break;
-
+
module->foreign_function_count++;
emit_foreign_function(module, ent->function);
// fallthrough
ent->expr->token->pos.line,
ent->expr->token->pos.column);
}
-
+
bh_imap_put(&module->index_map, (u64) ent->function, module->next_func_idx++);
if (ent->function->flags & Ast_Flag_Proc_Is_Null) {