progress, but not working yet
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 9 Jan 2023 18:26:17 +0000 (12:26 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 9 Jan 2023 18:26:17 +0000 (12:26 -0600)
compiler/include/types.h
compiler/src/onyx_run_standalone.c [new file with mode: 0644]
compiler/src/types.c
compiler/src/wasm_emit.c
docs/struct_asm_rewrite.md
interpreter/build.sh
shared/lib/linux_x86_64/lib/libovmwasm.so

index 183bd81df972113d58151d0e024cf6bb773f84c5..b62ca12eef6bfc9cbfc15ee2cf86cd15a6c2ea41 100644 (file)
@@ -116,7 +116,6 @@ typedef enum StructProcessingStatus {
         Table(StructMember *) members;                            \
         bh_arr(StructMember *) memarr;                            \
         bh_arr(struct AstPolySolution) poly_sln;                  \
-        bh_arr(TypeWithOffset) linear_members;                    \
         struct AstType *constructed_from;                         \
         bh_arr(struct AstTyped *) meta_tags;                      \
         StructProcessingStatus status;                            \
diff --git a/compiler/src/onyx_run_standalone.c b/compiler/src/onyx_run_standalone.c
new file mode 100644 (file)
index 0000000..3a8837a
--- /dev/null
@@ -0,0 +1,21 @@
+#define BH_DEFINE
+#define BH_NO_TABLE
+#define STB_DS_IMPLEMENTATION
+#include "bh.h"
+
+#include "wasm_emit.h"
+
+extern const char _binary__tmp_out_wasm_start;
+extern const char _binary__tmp_out_wasm_end;
+
+void onyx_run_initialize(int debug);
+int  onyx_run_wasm(bh_buffer, int argc, char **argv);
+
+int main(int argc, char *argv[]) {
+    onyx_run_initialize(0);
+
+    bh_buffer data;
+    data.data = (char *) &_binary__tmp_out_wasm_start;
+    data.length = &_binary__tmp_out_wasm_end - &_binary__tmp_out_wasm_start;
+    return onyx_run_wasm(data, argc - 1, argv + 1);
+}
index 38339ebbad89d1e32e16f2735d192b52ab63e304..6a560376c2585edb737810497c0dc433659fb71e 100644 (file)
@@ -448,10 +448,6 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             s_type->Struct.alignment = alignment;
             s_type->Struct.size = size;
 
-            s_type->Struct.linear_members = NULL;
-            bh_arr_new(global_heap_allocator, s_type->Struct.linear_members, s_type->Struct.mem_count);
-            build_linear_types_with_offset(s_type, &s_type->Struct.linear_members, 0);
-
             s_type->Struct.status = SPS_Members_Done;
             return s_type;
         }
@@ -785,9 +781,6 @@ Type* type_build_implicit_type_of_struct_literal(bh_allocator alloc, AstStructLi
 
     type->Struct.alignment = alignment;
     type->Struct.size = size;
-    type->Struct.linear_members = NULL;
-    bh_arr_new(global_heap_allocator, type->Struct.linear_members, type->Struct.mem_count);
-    build_linear_types_with_offset(type, &type->Struct.linear_members, 0);
 
     type->Struct.status = SPS_Uses_Done;
     lit->generated_inferred_type = type;
@@ -908,6 +901,8 @@ Type* type_make_varargs(bh_allocator alloc, Type* of) {
 }
 
 void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u32 offset) {
+    // nocheckin :StructAsm
+    /*
     if (type_is_structlike_strict(type)) {
         u32 mem_count = type_structlike_mem_count(type);
         StructMember smem = { 0 };
@@ -916,7 +911,9 @@ void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u
             build_linear_types_with_offset(smem.type, pdest, offset + smem.offset);
         }
 
-    } else if (type->kind == Type_Kind_Compound) {
+    } else */
+
+    if (type->kind == Type_Kind_Compound) {
         u32 elem_offset = 0;
         fori (i, 0, type->Compound.count) {
             build_linear_types_with_offset(type->Compound.types[i], pdest, offset + elem_offset);
@@ -1244,7 +1241,6 @@ i32 type_linear_member_count(Type* type) {
         case Type_Kind_VarArgs:  return 2;
         case Type_Kind_DynArray: return 5;
         case Type_Kind_Compound: return bh_arr_length(type->Compound.linear_members);
-        case Type_Kind_Struct:   return bh_arr_length(type->Struct.linear_members);
         default: return 1;
     }
 }
@@ -1286,7 +1282,6 @@ b32 type_linear_member_lookup(Type* type, i32 idx, TypeWithOffset* two) {
             return 1;
         }
         case Type_Kind_Compound: *two = type->Compound.linear_members[idx]; return 1;
-        case Type_Kind_Struct:   *two = type->Struct.linear_members[idx];   return 1;
 
         case Type_Kind_Distinct:
             two->type = type->Distinct.base_type;
@@ -1327,32 +1322,26 @@ i32 type_get_idx_of_linear_member_with_offset(Type* type, u32 offset) {
 
             return -1;
         }
-        case Type_Kind_Struct: {
-            i32 idx = 0;
-            bh_arr_each(TypeWithOffset, two, type->Struct.linear_members) {
-                if (two->offset == offset) return idx;
-                idx++;
-            }
-
+        default:
+            if (offset == 0) return 0;
             return -1;
-        }
-        default: return -1;
     }
 }
 
-b32 type_struct_is_simple(Type* type) {
+/*b32 type_struct_is_simple(Type* type) {
     if (type->kind != Type_Kind_Struct) return 0;
 
     b32 is_simple = 1;
     bh_arr_each(StructMember *, mem, type->Struct.memarr) {
-        if (type_is_compound((*mem)->type) || (*mem)->type->kind == Type_Kind_Array) {
+        if (type_linear_member_count((*mem)->type) != 1
+            (*mem)->type->kind == Type_Kind_Array) {
             is_simple = 0;
             break;
         }
     }
 
     return is_simple;
-}
+}*/
 
 b32 type_is_pointer(Type* type) {
     if (type == NULL) return 0;
@@ -1413,23 +1402,14 @@ b32 type_is_numeric(Type* type) {
 b32 type_is_compound(Type* type) {
     if (type == NULL) return 0;
 
-    if (type->kind == Type_Kind_Struct) {
-        //
-        // This is for the kind of common case where a structure simply wraps a
-        // single non-compound value; in this situation, the structure can be
-        // "dissolved" at compile-time and turn into the underlying type.
-        //
-
-        if (bh_arr_length(type->Struct.linear_members) != 1) return 1;
-        return type_is_compound(type->Struct.linear_members[0].type);
-    }
-
     return type->kind != Type_Kind_Basic
         && type->kind != Type_Kind_Pointer
         && type->kind != Type_Kind_Enum
         && type->kind != Type_Kind_Function
         && type->kind != Type_Kind_Array
-        && type->kind != Type_Kind_Distinct;
+        && type->kind != Type_Kind_Distinct
+        && type->kind != Type_Kind_Struct
+        && type->kind != Type_Kind_DynArray;
 }
 
 b32 type_is_simd(Type* type) {
@@ -1494,10 +1474,10 @@ u32 type_structlike_mem_count(Type* type) {
 u32 type_structlike_is_simple(Type* type) {
     if (type == NULL) return 0;
     switch (type->kind) {
-        case Type_Kind_Struct:   return type_struct_is_simple(type);
         case Type_Kind_Slice:    return 1;
         case Type_Kind_VarArgs:  return 1;
         case Type_Kind_DynArray: return 0;
+        case Type_Kind_Struct:   return 0; // :StructAsm type_struct_is_simple(type);
         default: return 0;
     }
 }
index 99b42247656645dab7883a33a95bab5dbe63b422..bffb045194c6e076ce91d303e730b2282b8b0108 100644 (file)
 #define WASM_TYPE_FUNC    WASM_TYPE_INT32
 #define WASM_TYPE_VOID    0x00
 
+static b32 onyx_type_is_stored_in_memory(Type *type) {
+    if (type->kind == Type_Kind_Struct || type->kind == Type_Kind_DynArray) {
+        return 1;
+    }
+
+    return 0;
+}
+
 static WasmType onyx_type_to_wasm_type(Type* type) {
-    if (type->kind == Type_Kind_Struct) {
-        if (type_linear_member_count(type) == 1) {
+    if (onyx_type_is_stored_in_memory(type)) {
+        /*if (type_linear_member_count(type) == 1) {
             return onyx_type_to_wasm_type(type->Struct.linear_members[0].type);
-        }
+        }*/
         
         // :StructAsm
-        return WASM_TYPE_VOID;
+        return WASM_TYPE_PTR;
     }
 
     if (type->kind == Type_Kind_Slice) {
@@ -84,6 +92,17 @@ static WasmType onyx_type_to_wasm_type(Type* type) {
     return WASM_TYPE_VOID;
 }
 
+static b32 onyx_type_is_multiple_wasm_values(Type *type) {
+    if (type->kind == Type_Kind_Slice || type->kind == Type_Kind_VarArgs) {
+        return 1;
+    }
+
+    // Dynamic arrays and slices are represented as a single pointer to
+    // data for the structure.
+
+    return 0;
+}
+
 static i32 generate_type_idx(OnyxWasmModule* mod, Type* ft);
 static i32 get_element_idx(OnyxWasmModule* mod, AstFunction* func);
 
@@ -517,9 +536,9 @@ EMIT_FUNC(memory_reservation_location,   AstMemRes* memres);
 EMIT_FUNC(location_return_offset,        AstTyped* expr, u64* offset_return);
 EMIT_FUNC(location,                      AstTyped* expr);
 EMIT_FUNC(compound_load,                 Type* type, u64 offset, i32 ignored_value_count);
-EMIT_FUNC(struct_lval,                   AstTyped* lval);
-EMIT_FUNC(struct_literal,                AstStructLiteral* sl);
 EMIT_FUNC(compound_store,                Type* type, u64 offset, b32 location_first);
+EMIT_FUNC(struct_store,                  Type* type, u32 offset);
+EMIT_FUNC(struct_literal,                AstStructLiteral* sl);
 EMIT_FUNC(array_store,                   Type* type, u32 offset);
 EMIT_FUNC(array_literal,                 AstArrayLiteral* al);
 EMIT_FUNC(range_literal,                 AstRangeLiteral* range);
@@ -828,6 +847,7 @@ EMIT_FUNC(assignment, AstBinaryOp* assign) {
         }
     }
 
+    /*
     if (lval->kind == Ast_Kind_Field_Access) {
         // :StructAsm
         // This code was never right anyway...
@@ -842,6 +862,7 @@ EMIT_FUNC(assignment, AstBinaryOp* assign) {
             return;
         }
     }
+    */
 
     if (lval->kind == Ast_Kind_Global) {
         emit_expression(mod, &code, assign->right);
@@ -930,22 +951,27 @@ EMIT_FUNC(compound_assignment, AstBinaryOp* assign) {
 EMIT_FUNC(store_instruction, Type* type, u32 offset) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    // :StructAsm
+    if (onyx_type_is_stored_in_memory(type)) {
+        emit_struct_store(mod, pcode, type, offset);
+        return;
+    }
+
+    if (type->kind == Type_Kind_Array) {
+        emit_array_store(mod, pcode, type, offset);
+        return;
+    }
+
     if (type_is_compound(type)) {
         emit_compound_store(mod, pcode, type, offset, 0);
         return;
     }
 
-    // :StructAsm
+    /*
     if (type->kind == Type_Kind_Struct) {
         assert(bh_arr_length(type->Struct.linear_members) == 1);
         type = type->Struct.linear_members[0].type;
     }
-
-    if (type->kind == Type_Kind_Array) {
-        emit_array_store(mod, pcode, type, offset);
-        return;
-    }
+    */
 
     if (type->kind == Type_Kind_Enum)     type = type->Enum.backing;
     if (type->kind == Type_Kind_Distinct) type = type->Distinct.base_type;
@@ -986,12 +1012,13 @@ EMIT_FUNC(flip_and_store_instruction, AstTyped *lval, OnyxToken *token) {
     u64 expr_tmp = local_raw_allocate(mod->local_alloc, wt);
     WIL(token, WI_LOCAL_SET, expr_tmp);
 
-    u64 offset = 0;
-    emit_location_return_offset(mod, &code, lval, &offset);
+    // nocheckin
+    // emit_location_return_offset(mod, &code, lval, &offset);
+    emit_location(mod, &code, lval);
     WIL(token, WI_LOCAL_GET, expr_tmp);
 
     local_raw_free(mod->local_alloc, wt);
-    emit_store_instruction(mod, &code, lval->type, offset);
+    emit_store_instruction(mod, &code, lval->type, 0);
 
     *pcode = code;
     return;
@@ -1005,13 +1032,12 @@ EMIT_FUNC(generic_store_instruction, AstTyped *lval, OnyxToken *token) {
     bh_arr(WasmInstruction) code = *pcode;
 
     // If this is a structure, use the emit_struct_lval function.
-    // :StructAsm
-    if (type_is_structlike_strict(lval->type)) {
-        emit_struct_lval(mod, &code, lval);
-    }
+    // if (type_is_structlike_strict(lval->type)) {
+    //     emit_struct_lval(mod, &code, lval);
+    // }
 
     // If this is a WASM local, simply set the local and continue.
-    else if (bh_imap_get(&mod->local_map, (u64) lval) & LOCAL_IS_WASM) {
+    if (bh_imap_get(&mod->local_map, (u64) lval) & LOCAL_IS_WASM) {
         u64 localidx = bh_imap_get(&mod->local_map, (u64) lval);
         WIL(token, WI_LOCAL_SET, localidx);
     }
@@ -1048,27 +1074,27 @@ EMIT_FUNC(load_with_ignored_instruction, Type* type, u32 offset, i32 ignored_val
 EMIT_FUNC(load_instruction, Type* type, u32 offset) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    // :StructAsm
+    if (type->kind == Type_Kind_Array || onyx_type_is_stored_in_memory(type)) {
+        if (offset != 0) {
+            WID(NULL, WI_PTR_CONST, offset);
+            WI(NULL, WI_PTR_ADD);
+        }
+
+        *pcode = code;
+        return;
+    }
+
     if (type_is_compound(type)) {
         emit_compound_load(mod, pcode, type, offset, 0);
         return;
     }
 
-    // :StructAsm
+    /*
     if (type->kind == Type_Kind_Struct) {
         assert(bh_arr_length(type->Struct.linear_members) == 1);
         type = type->Struct.linear_members[0].type;
     }
-
-    if (type->kind == Type_Kind_Array) {
-        if (offset != 0) {
-            WID(NULL, WI_PTR_CONST, offset);
-            WI(NULL, WI_PTR_ADD);
-        }
-
-        *pcode = code;
-        return;
-    }
+    */
 
     if (type->kind == Type_Kind_Enum)     type = type->Enum.backing;
     if (type->kind == Type_Kind_Distinct) type = type->Distinct.base_type;
@@ -1412,8 +1438,8 @@ EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local) {
         remove_info.iterator_data_ptr = iterator_data_ptr;
         remove_info.iterator_remove_func = iterator_remove_func;
 
-        TypeWithOffset remove_func_type;
-        type_linear_member_lookup(for_node->iter->type, 3, &remove_func_type);
+        StructMember remove_func_type;
+        type_lookup_member_by_idx(for_node->iter->type, 3, &remove_func_type);
         remove_info.remove_func_type_idx = generate_type_idx(mod, remove_func_type.type);
 
         bh_arr_push(mod->for_remove_info, remove_info);
@@ -1433,8 +1459,8 @@ EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local) {
     emit_enter_structured_block(mod, &code, SBT_Basic_Block, for_node->token);
 
     if (!for_node->no_close) {
-        TypeWithOffset close_func_type;
-        type_linear_member_lookup(for_node->iter->type, 2, &close_func_type);
+        StructMember close_func_type;
+        type_lookup_member_by_idx(for_node->iter->type, 2, &close_func_type);
         i32 close_type_idx = generate_type_idx(mod, close_func_type.type);
 
         WasmInstruction* close_instructions = bh_alloc_array(global_heap_allocator, WasmInstruction, 8);
@@ -1462,11 +1488,8 @@ EMIT_FUNC(for_iterator, AstFor* for_node, u64 iter_local) {
         // CLEANUP: Calling a function is way too f-ing complicated. FACTOR IT!!
         u64 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
 
-        // :StructAsm
-        // :StructAsm
-        // :StructAsm
-        TypeWithOffset next_func_type;
-        type_linear_member_lookup(for_node->iter->type, 1, &next_func_type);
+        StructMember next_func_type;
+        type_lookup_member_by_idx(for_node->iter->type, 1, &next_func_type);
         Type* return_type = next_func_type.type->Function.return_type;
 
         u32 return_size = type_size_of(return_type);
@@ -1977,7 +2000,6 @@ EMIT_FUNC(call, AstCall* call) {
             place_on_stack = 1;
         }
 
-        // :StructAsm
         if (place_on_stack) WIL(call_token, WI_LOCAL_GET, stack_top_store_local);
 
         emit_expression(mod, &code, arg->value);
@@ -1998,7 +2020,20 @@ EMIT_FUNC(call, AstCall* call) {
             }
 
             if (arg->pass_as_any) {
-                WIL(call_token, WI_I32_CONST, arg->value->type->id);
+                u32 arg_size = type_size_of(arg->value->type);
+
+                u64 ugly_temporary = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+                WIL(call_token, WI_LOCAL_SET, ugly_temporary);
+
+                WIL(call_token, WI_LOCAL_GET, stack_top_store_local);
+                WIL(call_token, WI_LOCAL_GET, ugly_temporary);
+                emit_store_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], reserve_size + arg_size + 0);
+
+                WIL(call_token, WI_LOCAL_GET, stack_top_store_local);
+                WID(call_token, WI_I32_CONST, arg->value->type->id);
+                emit_store_instruction(mod, &code, &basic_types[Basic_Kind_Type_Index], reserve_size + arg_size + 4);
+
+                reserve_size += 2 * POINTER_SIZE;
             }
 
             reserve_size += type_size_of(arg->value->type);
@@ -2096,10 +2131,6 @@ EMIT_FUNC(call, AstCall* call) {
     }
 
     if (cc == CC_Return_Stack) {
-        // :StructAsm
-        // :StructAsm
-        // :StructAsm
-        // :StructAsm
         WID(call_token, WI_GLOBAL_GET, stack_top_idx);
         emit_load_with_ignored_instruction(mod, &code, return_type, reserve_size - return_size, call->ignored_return_value_count);
     }
@@ -2744,19 +2775,6 @@ EMIT_FUNC(local_location, AstLocal* local, u64* offset_return) {
     *pcode = code;
 }
 
-EMIT_FUNC(struct_lval, AstTyped* lval) {
-    bh_arr(WasmInstruction) code = *pcode;
-
-    // :StructAsm
-    assert(type_is_structlike_strict(lval->type));
-
-    u64 offset = 0;
-    emit_location_return_offset(mod, &code, lval, &offset);
-    emit_compound_store(mod, &code, lval->type, offset, 1);
-
-    *pcode = code;
-}
-
 EMIT_FUNC(compound_load, Type* type, u64 offset, i32 ignored_value_count) {
     bh_arr(WasmInstruction) code = *pcode;
     i32 mem_count = type_linear_member_count(type);
@@ -2830,14 +2848,102 @@ EMIT_FUNC(compound_store, Type* type, u64 offset, b32 location_first) {
 EMIT_FUNC(struct_literal, AstStructLiteral* sl) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    // :StructAsm
+    if (!onyx_type_is_stored_in_memory(sl->type)) {
+        bh_arr_each(AstTyped *, val, sl->args.values) {
+            emit_expression(mod, &code, *val);
+        }
+
+        *pcode = code;
+        return;
+    }
+
+    emit_local_allocation(mod, &code, (AstTyped *) sl);
+
+    u64 local_offset = (u64) bh_imap_get(&mod->local_map, (u64) sl);
+    assert((local_offset & LOCAL_IS_WASM) == 0);
+
+    i32 idx = 0;
+    StructMember smem;
     bh_arr_each(AstTyped *, val, sl->args.values) {
+        type_lookup_member_by_idx(sl->type, idx, &smem);
+
+        // CLEANUP: When emitting a structure literal inside of a structure literal,
+        // there should be a separate path taken to reduce the amount of redundant memory.
+        WIL(sl->token, WI_LOCAL_GET, mod->stack_base_idx);
         emit_expression(mod, &code, *val);
+        emit_store_instruction(mod, &code, (*val)->type, smem.offset);
+
+        idx += 1;
+    }
+
+    WIL(sl->token, WI_LOCAL_GET, mod->stack_base_idx);
+
+    if (local_offset > 0) {
+        WIL(sl->token, WI_PTR_CONST, local_offset);
+        WI(sl->token, WI_PTR_ADD);
     }
 
     *pcode = code;
 }
 
+// <src_ptr>   <- top of stack
+// <dest_ptr>
+EMIT_FUNC(struct_store, Type *type, u32 offset) {
+    assert(onyx_type_is_stored_in_memory(type));
+    bh_arr(WasmInstruction) code = *pcode;
+
+    if (offset != 0) {
+        u64 rptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+        WIL(NULL, WI_LOCAL_SET, rptr_local);
+
+        WIL(NULL, WI_PTR_CONST, offset);
+        WI(NULL, WI_PTR_ADD);
+        WIL(NULL, WI_LOCAL_GET, rptr_local);
+
+        local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+    }
+
+    u64 rptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+    u64 lptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+    WIL(NULL, WI_LOCAL_SET, rptr_local);
+    WIL(NULL, WI_LOCAL_SET, lptr_local);
+
+    WIL(NULL, WI_LOCAL_GET, rptr_local);
+    WID(NULL, WI_I32_CONST, 0);
+    WI(NULL, WI_I32_NE);
+    emit_enter_structured_block(mod, &code, SBT_Basic_If, NULL);
+
+        WIL(NULL, WI_LOCAL_GET, lptr_local);
+        WIL(NULL, WI_LOCAL_GET, rptr_local);
+        WIL(NULL, WI_I32_CONST, type_size_of(type));
+
+        // Use a simple memory copy if it is available.
+        if (context.options->use_post_mvp_features) {
+            WI(NULL, WI_MEMORY_COPY);
+        } else {
+            emit_intrinsic_memory_copy(mod, &code);
+        }
+
+    WI(NULL, WI_ELSE);
+
+        WIL(NULL, WI_LOCAL_GET, lptr_local);
+        WIL(NULL, WI_I32_CONST, 0);
+        WIL(NULL, WI_I32_CONST, type_size_of(type));
+
+        if (context.options->use_post_mvp_features) {
+            WI(NULL, WI_MEMORY_FILL);
+        } else {
+            emit_intrinsic_memory_fill(mod, &code);
+        }
+
+    emit_leave_structured_block(mod, &code);
+    local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+    local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+
+    *pcode = code;
+    return;
+}
+
 EMIT_FUNC(array_store, Type* type, u32 offset) {
     assert(type->kind == Type_Kind_Array);
     bh_arr(WasmInstruction) code = *pcode;
@@ -2963,6 +3069,8 @@ EMIT_FUNC(array_store, Type* type, u32 offset) {
 EMIT_FUNC(array_literal, AstArrayLiteral* al) {
     bh_arr(WasmInstruction) code = *pcode;
 
+    emit_local_allocation(mod, &code, (AstTyped *) al);
+
     u64 local_offset = (u64) bh_imap_get(&mod->local_map, (u64) al);
     assert((local_offset & LOCAL_IS_WASM) == 0);
 
@@ -3058,7 +3166,6 @@ EMIT_FUNC(location_return_offset, AstTyped* expr, u64* offset_return) {
     expr = (AstTyped *) strip_aliases((AstNode *) expr);
 
     switch (expr->kind) {
-        // :StructAsm
         case Ast_Kind_Param:
         case Ast_Kind_Local:
         case Ast_Kind_Array_Literal:
@@ -3233,13 +3340,11 @@ EMIT_FUNC(expression, AstTyped* expr) {
         }
 
         case Ast_Kind_Struct_Literal: {
-            // :StructAsm
             emit_struct_literal(mod, &code, (AstStructLiteral *) expr);
             break;
         }
 
         case Ast_Kind_Array_Literal: {
-            emit_local_allocation(mod, &code, expr);
             emit_array_literal(mod, &code, (AstArrayLiteral *) expr);
             break;
         }
@@ -3309,7 +3414,9 @@ EMIT_FUNC(expression, AstTyped* expr) {
                 }
             }
 
-            if (is_lval((AstNode *) field->expr) || type_is_pointer(field->expr->type)) {
+            if (is_lval((AstNode *) field->expr)
+                || type_is_pointer(field->expr->type)
+                || onyx_type_is_stored_in_memory(field->expr->type)) {
                 u64 offset = 0;
                 emit_field_access_location(mod, &code, field, &offset);
                 emit_load_instruction(mod, &code, field->type, offset);
@@ -3646,7 +3753,6 @@ EMIT_FUNC(return, AstReturn* ret) {
             emit_generic_store_instruction(mod, &code, (AstTyped *) dest, NULL);
 
         } else if (mod->curr_cc == CC_Return_Stack) {
-            // :StructAsm
             WIL(NULL, WI_LOCAL_GET, mod->stack_base_idx);
             WID(NULL, WI_I32_CONST, type_size_of(ret->expr->type));
             WI(NULL, WI_I32_SUB);
@@ -3733,7 +3839,7 @@ EMIT_FUNC(zero_value, WasmType wt) {
 EMIT_FUNC(zero_value_for_type, Type* type, OnyxToken* where) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    if (type_is_structlike_strict(type)) {
+    if (onyx_type_is_multiple_wasm_values(type)) {
         i32 mem_count = type_linear_member_count(type);
         TypeWithOffset two;
 
@@ -3741,11 +3847,11 @@ EMIT_FUNC(zero_value_for_type, Type* type, OnyxToken* where) {
             type_linear_member_lookup(type, i, &two);
             emit_zero_value_for_type(mod, &code, two.type, where);
         }
-    }
-    else if (type->kind == Type_Kind_Function) {
+
+    else if (type->kind == Type_Kind_Function) {
         WID(NULL, WI_I32_CONST, mod->null_proc_func_idx);
-    }
-    else {
+
+    else {
         WasmType wt = onyx_type_to_wasm_type(type);
         if (wt == WASM_TYPE_VOID) {
             onyx_report_error(where->pos, Error_Critical, "Cannot produce a zero-value for this type.");
@@ -3767,10 +3873,15 @@ static i32 generate_type_idx(OnyxWasmModule* mod, Type* ft) {
     i32 params_left = param_count;
 
     while (params_left-- > 0) {
-        if (type_get_param_pass(*param_type) == Param_Pass_By_Implicit_Pointer) {
+        if ((*param_type)->kind == Type_Kind_Struct) {
+            *(t++) = (char) onyx_type_to_wasm_type(*param_type);
+        }
+
+        else if (type_get_param_pass(*param_type) == Param_Pass_By_Implicit_Pointer) {
             *(t++) = (char) onyx_type_to_wasm_type(&basic_types[Basic_Kind_Rawptr]);
 
         }
+
         // :StructAsm
         else if (type_is_structlike_strict(*param_type)) {
             u32 mem_count = type_structlike_mem_count(*param_type);
@@ -3791,11 +3902,14 @@ static i32 generate_type_idx(OnyxWasmModule* mod, Type* ft) {
     }
     *(t++) = ':';
 
-    // HACK: Slightly: the wasm type for structs has to be 0x00
     WasmType return_type = onyx_type_to_wasm_type(ft->Function.return_type);
-    if (ft->Function.return_type->kind == Type_Kind_Struct && !type_is_compound(ft->Function.return_type)) {
+
+    /*
+    if (ft->Function.return_type->kind == Type_Kind_Struct
+        && type_linear_member_count(ft->Function.return_type) == 1) {
         return_type = onyx_type_to_wasm_type(ft->Function.return_type->Struct.linear_members[0].type);
     }
+    */
 
     *(t++) = (char) return_type;
     *t = '\0';
@@ -3927,8 +4041,6 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
         bh_arr_insert_end(wasm_func.code, 5);
         fori (i, 0, 5) wasm_func.code[i] = (WasmInstruction) { WI_NOP, 0 };
 
-        // TODO: Emit debug info for the above instructions
-
         mod->stack_base_idx = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
         debug_function_set_ptr_idx(mod, func_idx, mod->stack_base_idx);
 
index f5732cdd8721a5640e714e2b9db7745617faad5b..1fd728988b3c6860914721dab411899a036ef046 100644 (file)
@@ -69,3 +69,19 @@ which is obviously a structure. In the new system, passing each result as a para
 to the next function would not work as shown with the array example above. A solution
 to this problem must be found before this refactor can be completed.
 
+
+
+
+
+SOLUTION
+========
+
+I was very dumb when I wrote the above text.
+
+This is actually very simple, and already something that the compiler is doing. I am
+just doing it wrong in the fixed-size array case. The rule has to be: ALL structure
+arguments need to be copied into a buffer for ARGUMENTS to the call. This already
+happens with non-simple structure. Currently, it does not happen for array, so that
+is why I thought this was a larger issue. The optimization that l-value structures
+passed by value can simply be their pointer and not-copied can be done in the future,
+but to get this optimization working, that does not have to be done.
index c58d91f53094ff7388c2423b63f182de8d9717c6..d311e432f24069a4f109be01600d2519f91154a6 100755 (executable)
@@ -2,9 +2,9 @@
 
 . ../settings.sh
 
-FLAGS="-g3 -O2 -DOVM_DEBUG=1"
+FLAGS="-g3 -O2 -DOVM_DEBUG=1"
 # FLAGS="-g3 -DOVM_VERBOSE=1"
-FLAGS="-Ofast -fno-stack-protector"
+FLAGS="-Ofast -fno-stack-protector"
 LIBS="-pthread"
 TARGET="../shared/lib/linux_$(uname -m)/lib/libovmwasm.so"
 C_FILES="src/wasm.c src/vm/*.c src/wasm/*.c src/debug/*.c"
index 9368eae74de37c5ae3881b88ef51afc83c84d371..23b9203abd121fcf2a05b22811e9e11b4f83de80 100755 (executable)
Binary files a/shared/lib/linux_x86_64/lib/libovmwasm.so and b/shared/lib/linux_x86_64/lib/libovmwasm.so differ