refactored for cleaner code generation.
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 17 Apr 2021 03:06:56 +0000 (22:06 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 17 Apr 2021 03:06:56 +0000 (22:06 -0500)
bin/onyx
include/onyxastnodes.h
include/onyxwasm.h
src/onyxchecker.c
src/onyxclone.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index 80e1155d8b863fe850596dfa52667f06eb7e83fe..5e002a9d88a1e2917fe43a92c604fca0ed34f032 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 2ef127812532a30629abe9e2c0d4e56edbca4d88..efbee08158ff3446b363a4cdd9f7e37e038a9e5d 100644 (file)
@@ -755,7 +755,6 @@ struct AstFunction {
     AstType* return_type;
 
     AstBlock *body;
-    bh_arr(AstTyped *) allocate_exprs;
 
     OnyxToken* name;
 
index a369cfb2033a333ee7c255636207a3446e3692a1..872f002e5249a21f6ef9cd28933a6bb3ca1288c4 100644 (file)
@@ -507,6 +507,10 @@ typedef struct StrLitInfo {
     u32 len;
 } StrLitInfo;
 
+typedef struct PatchInfo {
+    u32 instruction_index;
+} PatchInfo;
+
 typedef struct OnyxWasmModule {
     bh_allocator allocator;
 
@@ -527,6 +531,8 @@ typedef struct OnyxWasmModule {
     bh_arr(DeferredStmt)   deferred_stmts;
     bh_arr(AllocatedSpace) local_allocations; 
 
+    bh_arr(PatchInfo) stack_leave_patches;
+
     // NOTE: Used internally as a map from strings that represent function types,
     // 0x7f 0x7f : 0x7f ( (i32, i32) -> i32 )
     // to the function type index if it has been created.
index b33617e6452c74f96e9f065a70e50084c1342447..7e5bdaf46975bd8c451f2e99cc8dc3b096d9edb0 100644 (file)
@@ -1492,6 +1492,9 @@ CheckStatus check_statement_chain(AstNode** start) {
 CheckStatus check_block(AstBlock* block) {
     CHECK(statement_chain, &block->body);
 
+    // CLEANUP: There will need to be some other method of 
+    // checking the following conditions.
+    //
     // bh_arr_each(AstTyped *, value, block->allocate_exprs) {
     //     fill_in_type(*value);
 
index 4a7617d31930138df1978c9c3b75327b27d4c407..26c46732e9c197d9be5f3d572ac23946ee5d0021 100644 (file)
@@ -365,9 +365,6 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        df->return_type = (AstType *) ast_clone(a, sf->return_type);
                        df->body = (AstBlock *) ast_clone(a, sf->body);
 
-                       df->allocate_exprs = NULL;
-                   bh_arr_new(global_heap_allocator, df->allocate_exprs, 4);
-
                        df->params = NULL;
                        bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params));
 
@@ -460,7 +457,4 @@ void clone_function_body(bh_allocator a, AstFunction* dest, AstFunction* source)
     if (source->kind != Ast_Kind_Function) return;
 
     dest->body = (AstBlock *) ast_clone(a, source->body);
-
-    dest->allocate_exprs = NULL;
-    bh_arr_new(global_heap_allocator, dest->allocate_exprs, 4);
 }
index 79a689f6fb89f467ab49a9b5b5c5d70dda4cf663..f2325b8e9f4a653dcc40c6cbec88d8a842edf6ba 100644 (file)
@@ -1869,7 +1869,6 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok
     AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
     func_def->token = token;
 
-    bh_arr_new(global_heap_allocator, func_def->allocate_exprs, 4);
     bh_arr_new(global_heap_allocator, func_def->params, 4);
 
     bh_arr(AstPolyParam) polymorphic_vars = NULL;
index a7aadca7bcba4e5e4ce7a27551eafdb9e106bece..240a06ce7aff61af60c85dd0ffb04f3dc9da3d00 100644 (file)
@@ -249,8 +249,6 @@ static SymresStatus symres_type(AstType** type) {
 static SymresStatus symres_local(AstLocal** local) {
     SYMRES(type, &(*local)->type_node);
 
-    bh_arr_push(curr_function->allocate_exprs, (AstTyped *) *local);
-
     if ((*local)->token != NULL)
         symbol_introduce(curr_scope, (*local)->token, (AstNode *) *local);
 
@@ -402,9 +400,6 @@ static SymresStatus symres_array_literal(AstArrayLiteral* al) {
     bh_arr_each(AstTyped *, expr, al->values)
         SYMRES(expression, expr);
 
-    if (curr_function != NULL)
-        bh_arr_push(curr_function->allocate_exprs, (AstTyped *) al);
-
     return Symres_Success;
 }
 
index 05e26b9d4e1154a275abbb3ab05d9ef7a4570257..2368fafe3c9c91a2c24aa41bb4b942a2d6aec8ca 100644 (file)
@@ -1,13 +1,15 @@
 //
 // There are several things I'm seeing in this file that I want to clean up.
 // They are:
-//  [ ] remove the need to know if the stack is needed before generating the function.
+//  [x] remove the need to know if the stack is needed before generating the function.
 //      Just leave 5 nops at the beginning because they will be automatically removed
 //      by the WASM outputter.
-//  [ ] remove the need to have "allocate_exprs" on blocks and in functions. This will
+//  [x] remove the need to have "allocate_exprs" on blocks and in functions. This will
 //      be easy once the above is done.
 //  [ ] there should be a better way to emit pending deferred statements because there
 //      is some code duplication between emit_return and emit_structured_jump.
+//
+//  [ ] Change the calling convention so it is easier to use from both JS and in the compiler.
 
 
 
@@ -217,6 +219,7 @@ enum StructuredBlockType {
     local_raw_free(mod->local_alloc, type1);              \
     local_raw_free(mod->local_alloc, type2);              \
     }
+#define SUBMIT_PATCH(patch_arr, offset) bh_arr_push((patch_arr), ((PatchInfo) { bh_arr_length(code) - offset }))
 
 EMIT_FUNC(function_body,                 AstFunction* fd);
 EMIT_FUNC(block,                         AstBlock* block, b32 generate_block_headers);
@@ -255,7 +258,6 @@ EMIT_FUNC(expression,                    AstTyped* expr);
 EMIT_FUNC(cast,                          AstUnaryOp* cast);
 EMIT_FUNC(return,                        AstReturn* ret);
 EMIT_FUNC(stack_enter,                   u64 stacksize);
-EMIT_FUNC(stack_leave,                   u32 unused);
 EMIT_FUNC(zero_value,                    WasmType wt);
 EMIT_FUNC(zero_value_for_type,           Type* type, OnyxToken* where);
 
@@ -2516,8 +2518,9 @@ EMIT_FUNC(return, AstReturn* ret) {
         }
     }
 
-    if (mod->has_stack_locals)
-        emit_stack_leave(mod, &code, 0);
+    SUBMIT_PATCH(mod->stack_leave_patches, 0);
+    WI(WI_NOP);
+    WI(WI_NOP);
 
     WI(WI_RETURN);
 
@@ -2545,16 +2548,6 @@ EMIT_FUNC(stack_enter, u64 stacksize) {
         code[3] = (WasmInstruction) { WI_I32_ADD,    0 };
         code[4] = (WasmInstruction) { WI_GLOBAL_SET, { .l = stack_top_idx } };
     }
-    *pcode = code;
-}
-
-EMIT_FUNC(stack_leave, u32 unused) {
-    bh_arr(WasmInstruction) code = *pcode;
-
-    u64 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
-
-    WIL(WI_LOCAL_GET, mod->stack_base_idx);
-    WID(WI_GLOBAL_SET, stack_top_idx);
 
     *pcode = code;
 }
@@ -2768,23 +2761,29 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
         mod->curr_cc = type_function_get_cc(fd->type);
         assert(mod->curr_cc != CC_Undefined);
 
-        mod->has_stack_locals = (mod->curr_cc == CC_Return_Stack);
-        bh_arr_each(AstTyped *, expr, fd->allocate_exprs)
-            mod->has_stack_locals |= !local_is_wasm_local(*expr);
+        bh_arr_clear(mod->stack_leave_patches);
 
-        if (mod->has_stack_locals) {
-            // NOTE: '5' needs to match the number of instructions it takes
-            // to setup a stack frame
-            bh_arr_insert_end(wasm_func.code, 5);
-            mod->stack_base_idx = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
-        }
+        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
         emit_function_body(mod, &wasm_func.code, fd);
 
-        if (mod->has_stack_locals) {
+        if (mod->local_alloc->max_stack > 0 || mod->curr_cc == CC_Return_Stack) {
             emit_stack_enter(mod, &wasm_func.code, mod->local_alloc->max_stack);
-            emit_stack_leave(mod, &wasm_func.code, 0);
+
+            // Place all stack leaves in patch locations. These will (probably) all be
+            // right before a "return" instruction.
+            u64 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
+            bh_arr_push(wasm_func.code, ((WasmInstruction) { WI_LOCAL_GET,  { .l = mod->stack_base_idx } }));
+            bh_arr_push(wasm_func.code, ((WasmInstruction) { WI_GLOBAL_SET, { .l = stack_top_idx } }));
+
+            bh_arr_each(PatchInfo, patch, mod->stack_leave_patches) {
+                wasm_func.code[patch->instruction_index + 0] = (WasmInstruction) { WI_LOCAL_GET,  { .l = mod->stack_base_idx } };
+                wasm_func.code[patch->instruction_index + 1] = (WasmInstruction) { WI_GLOBAL_SET, { .l = stack_top_idx } };
+            }
         }
     }
 
@@ -3124,6 +3123,8 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
         .next_elem_idx = 0,
 
         .structured_jump_target = NULL,
+        .local_allocations = NULL,
+        .stack_leave_patches = NULL,
 
         .stack_top_ptr = NULL,
         .stack_base_idx = 0,
@@ -3159,11 +3160,13 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
 
     bh_arr_new(global_heap_allocator, module.deferred_stmts, 4);
     bh_arr_new(global_heap_allocator, module.local_allocations, 4);
+    bh_arr_new(global_heap_allocator, module.stack_leave_patches, 4);
 
     WasmExport mem_export = {
         .kind = WASM_FOREIGN_MEMORY,
         .idx = 0,
     };
+    // :ArbitraryConstant
     bh_table_put(WasmExport, module.exports, "memory", mem_export);
     module.export_count++;