added unreachable intrinsic; added `any_utils`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 15 Oct 2022 18:55:45 +0000 (13:55 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 15 Oct 2022 18:55:45 +0000 (13:55 -0500)
19 files changed:
compiler/include/astnodes.h
compiler/src/builtins.c
compiler/src/wasm_emit.c
compiler/src/wasm_output.h
core/intrinsics/wasm.onyx
core/misc/any_utils.onyx [new file with mode: 0644]
core/runtime/common.onyx
core/std.onyx
interpreter/include/ovm_debug.h
interpreter/include/vm.h
interpreter/include/vm_codebuilder.h
interpreter/src/vm/code_builder.c
interpreter/src/vm/vm.c
interpreter/src/wasm/instance.c
interpreter/src/wasm/module_parsing.h
misc/vscode/onyx-0.0.4.vsix
misc/vscode/out/ovmDebug.js
misc/vscode/ovmDebug.ts
shared/lib/linux_x86_64/lib/libovmwasm.so

index 4ac685b28c1f67dfa06ee62412a682311ffce2f0..c58df410c3046dcb3bb94f430cea90c95012c302 100644 (file)
@@ -351,6 +351,8 @@ extern const char *binaryop_string[Binary_Op_Count];
 typedef enum OnyxIntrinsic {
     ONYX_INTRINSIC_UNDEFINED,
 
+    ONYX_INTRINSIC_UNREACHABLE,
+
     ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW,
     ONYX_INTRINSIC_MEMORY_COPY, ONYX_INTRINSIC_MEMORY_FILL,
 
index 8b60c4f1007453a7127c16d2197084880fa89ca3..86d6a441a711d230d43a6e33291c256837f0f079 100644 (file)
@@ -105,6 +105,8 @@ const BuiltinSymbol builtin_symbols[] = {
 IntrinsicTable intrinsic_table;
 
 static IntrinsicMap builtin_intrinsics[] = {
+    { "unreachable",  ONYX_INTRINSIC_UNREACHABLE },
+
     { "memory_size",  ONYX_INTRINSIC_MEMORY_SIZE },
     { "memory_grow",  ONYX_INTRINSIC_MEMORY_GROW },
     { "memory_copy",  ONYX_INTRINSIC_MEMORY_COPY },
index 21e3693936b212d748e1fbb8b29d71b482a6a3ca..5a31d87fe9fa8f3aaf3209335154dc317c933f79 100644 (file)
@@ -2240,6 +2240,8 @@ EMIT_FUNC(intrinsic_call, AstCall* call) {
     }
 
     switch (call->intrinsic) {
+        case ONYX_INTRINSIC_UNREACHABLE:  WI(call->token, WI_UNREACHABLE); break;
+        
         case ONYX_INTRINSIC_MEMORY_SIZE:  WID(call->token, WI_MEMORY_SIZE, 0x00); break;
         case ONYX_INTRINSIC_MEMORY_GROW:  WID(call->token, WI_MEMORY_GROW, 0x00); break;
         case ONYX_INTRINSIC_MEMORY_COPY:
index f03eb6b37cf7967770264ba6e8492cfc7cad1bd7..964d1d8b01f09812a8c145429bb36ecadc1db409 100644 (file)
@@ -428,8 +428,6 @@ static void output_instruction(WasmFunc* func, WasmInstruction* instr, bh_buffer
     i32 leb_len;
     u8* leb;
 
-    if (instr->type == WI_UNREACHABLE) assert(("EMITTING UNREACHABLE!!", 0));
-
     if (instr->type == WI_NOP && !context.options->debug_enabled) return;
 
     if (instr->type & SIMD_INSTR_MASK) {
index c33ebf6a7035616181fb21aa56c56ea220fd3cd0..cab1716d041cb52b366417ad3c172d60ca561fd6 100644 (file)
@@ -1,5 +1,8 @@
 package core.intrinsics.wasm
 
+// This does not return.
+unreachable  :: () -> void #intrinsic ---
+
 memory_size  :: () -> u32 #intrinsic ---
 memory_grow  :: (val: u32) -> i32 #intrinsic ---
 memory_copy  :: (dst: rawptr, src: rawptr, count: i32) -> void #intrinsic ---
diff --git a/core/misc/any_utils.onyx b/core/misc/any_utils.onyx
new file mode 100644 (file)
index 0000000..412a89b
--- /dev/null
@@ -0,0 +1,53 @@
+package core.misc
+
+use runtime.info {
+    get_type_info,
+    Type_Info_Pointer,
+    Type_Info_Struct,
+
+    get_struct_member
+}
+
+to_any :: macro (x: ^$T) => any.{x, T};
+
+any_deference :: (v: any) -> any {
+    t := get_type_info(v.type);
+    if t.kind == .Pointer {
+        p := cast(^Type_Info_Pointer) t;
+        return any.{*cast(^rawptr) v.data, p.to};
+    }
+
+    return .{null, void};
+}
+
+any_get_member :: (v: any, member_name: str) -> any {
+    t := get_type_info(v.type);
+    if t.kind == .Struct {
+        member := get_struct_member(v.type, member_name);
+        if member != null {
+            return any.{cast(^u8) v.data + member.offset, member.type};
+        }
+    }
+
+    return .{null, void};
+}
+
+any_to_map :: (v: any) -> (Map(str, any), success: bool) {
+    vals := v;
+    if get_type_info(vals.type).kind == .Pointer {
+        vals = any_deference(vals);
+    }
+
+    val_info := cast(^Type_Info_Struct) get_type_info(vals.type);
+    if val_info.kind != .Struct {
+        return .{}, false;
+    }
+
+    out: Map(str, any);
+    for ^ val_info.members {
+        out->put(it.name, any_get_member(vals, it.name));
+    }
+
+    return out, true;
+}
+
index 6a22b59b2b9b5c7e96aba0ddd20bf7b260d78842..07730cafc1a880b29383f9e47b809b690db60732 100644 (file)
@@ -16,8 +16,10 @@ __assert_handler :: (msg: str, site: CallSite) {
 
     __output_string("\n");
 
-    // __exit(1);
-    *(cast(^i32) 0xffffffff);
+    core.intrinsics.wasm.unreachable();
+
+    // This will never return
+    return;
 }
 
 // This procedure should only be called once at the very begining
index 51eceef095da4f1fd6097de794fd3eb4b4cd7f08..210d9fed19aeddb6a139e13442e362fcb28d8b75 100644 (file)
@@ -39,6 +39,8 @@ package core
 
 #load "./test/testing"
 
+#load "./misc/any_utils"
+
 #local runtime :: package runtime
 #if runtime.runtime == .Wasi || runtime.runtime == .Onyx {
     #load "./os/file"
index 37eecea2276c41339321d2053dd0779018c12a45..a2c08670d47ba67d8809c76079aeb967e270f93f 100644 (file)
@@ -215,6 +215,7 @@ typedef enum debug_exec_state_t {
 typedef enum debug_pause_reason_t {
     debug_pause_entry = 1,
     debug_pause_step = 2,
+    debug_pause_exception = 3,
 } debug_pause_reason_t;
 
 typedef struct debug_breakpoint_t {
index 44868f87dc7cbaef6a827e12199afb03f1d6200b..3dd52548ba106e3ae7616d474c6a9dad48b20b9f 100644 (file)
@@ -335,6 +335,8 @@ struct ovm_instr_t {
 
 #define OVMI_CMPXCHG           0x70   // %r = %r == %a ? %b : %r 
 
+#define OVMI_BREAK             0xff
+
 //
 // OVM_TYPED_INSTR(OVMI_ADD, OVM_TYPE_I32) == instruction for adding i32s
 //
index 80a062b0e814d817fc2e12d49844dc43ad711244..347ee5a088921ad02c1173243608e6ff2a314480 100644 (file)
@@ -64,6 +64,7 @@ void               ovm_code_builder_pop_label_target(ovm_code_builder_t *builder
 void               ovm_code_builder_patch_else(ovm_code_builder_t *builder, label_target_t if_target);
 void               ovm_code_builder_free(ovm_code_builder_t *builder);
 void               ovm_code_builder_add_nop(ovm_code_builder_t *builder);
+void               ovm_code_builder_add_break(ovm_code_builder_t *builder);
 void               ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr);
 void               ovm_code_builder_add_unop(ovm_code_builder_t *builder, u32 instr);
 void               ovm_code_builder_add_imm(ovm_code_builder_t *builder, u32 ovm_type, void *imm);
index eb27a810bb19447ac41787607f1e20ebe45dbacc..d7f696f2657064d9e2048227bf95140c3f0d0fd3 100644 (file)
@@ -142,6 +142,13 @@ void ovm_code_builder_add_nop(ovm_code_builder_t *builder) {
     ovm_program_add_instructions(builder->program, 1, &nop);
 }
 
+void ovm_code_builder_add_break(ovm_code_builder_t *builder) {
+    ovm_instr_t break_ = {0};
+    break_.full_instr = OVMI_BREAK;
+    debug_info_builder_emit_location(builder->debug_builder);
+    ovm_program_add_instructions(builder->program, 1, &break_);
+}
+
 void ovm_code_builder_add_binop(ovm_code_builder_t *builder, u32 instr) {
     i32 right  = POP_VALUE(builder);
     i32 left   = POP_VALUE(builder);
index 3a85c538e4dbd8ee52dea5e50273bed758d83876..46f2f9bdbc244045365c81192026248974e1b89e 100644 (file)
@@ -1245,6 +1245,19 @@ ovm_value_t ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t
 
 #undef CMPXCHG
 
+            case OVMI_BREAK:
+                printf("onyx: exiting early due to reaching an unreachable instruction.\n");
+                
+                if (state->debug) {
+                    state->debug->state = debug_state_pausing;
+                    state->debug->pause_reason = debug_pause_exception;
+
+                    assert(write(state->debug->state_change_write_fd, "1", 1));
+                    sem_wait(&state->debug->wait_semaphore);
+                }
+                
+                return ((ovm_value_t) {0});
+
             default:
                 printf("ERROR:\n");
                 ovm_program_print_instructions(program, state->pc - 1, 1);
index 4a998f67eddfa7d74c5a2c6302edcdf71bc7381c..1ffbb5f772f19698094a8ccb54e0d3837ede9b46 100644 (file)
@@ -51,6 +51,11 @@ struct ovm_wasm_binding {
 #define OVM_TO_WASM(o, w) { \
     (w).of.i64 = 0;\
     switch ((o).type) { \
+        case OVM_TYPE_NONE: \
+            (w).kind = WASM_I32; \
+            (w).of.i32 = 0; \
+            break; \
+ \
         case OVM_TYPE_I8: \
             (w).kind = WASM_I32; \
             (w).of.i32 = (i32) (o).i8; \
index ce36d5d00aab506815fe152e7be0cd65d182a5b6..ef9e9dd7f00bafa07a484ce72bf8f21810249a8b 100644 (file)
@@ -518,6 +518,7 @@ static void parse_instruction(build_context *ctx) {
     unsigned char instr_byte = CONSUME_BYTE(ctx);
     switch (instr_byte) {
         case 0x00:
+            ovm_code_builder_add_break(&ctx->builder);
             break;
 
         case 0x01:
index 2c47d8835c0bc49bc165a2c734220f0178904992..bcbdae298514b57f4e7a2edaf77cd6df53998327 100644 (file)
Binary files a/misc/vscode/onyx-0.0.4.vsix and b/misc/vscode/onyx-0.0.4.vsix differ
index 6a3f2d7c0558ba58a854bf583b9054ce150e95a4..58653c235ab17956cf0be72377f997fe086b2698 100644 (file)
@@ -455,6 +455,9 @@ class OVMDebugger extends EventEmitter {
                         case 2:
                             reason = "step";
                             break;
+                        case 3:
+                            reason = "exception";
+                            break;
                     }
                     this.sendEvent("paused", { reason, threadId: thread_id });
                     break;
index 0fa1c54f40bab9ae676e1f6d8185ae07689d4788..35ce3d5383a44f6469d62a250e298909a065ebec 100644 (file)
@@ -631,6 +631,7 @@ class OVMDebugger extends EventEmitter {
                                        switch (reason_id) {
                                                case 1: reason = "entry"; break;
                                                case 2: reason = "step"; break;
+                                               case 3: reason = "exception"; break;
                                        }
 
                                        this.sendEvent("paused", { reason, threadId: thread_id });
index bb90f89b5692c7b6157ae1f5a4033bd68fad1106..09751b8ad553586d5954f279e4ec5c4cb6fdd705 100755 (executable)
Binary files a/shared/lib/linux_x86_64/lib/libovmwasm.so and b/shared/lib/linux_x86_64/lib/libovmwasm.so differ