From: Brendan Hansen Date: Sat, 15 Oct 2022 18:55:45 +0000 (-0500) Subject: added unreachable intrinsic; added `any_utils` X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8acee2644383b8e2a93244e5944457c0c7349c24;p=onyx.git added unreachable intrinsic; added `any_utils` --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 4ac685b2..c58df410 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -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, diff --git a/compiler/src/builtins.c b/compiler/src/builtins.c index 8b60c4f1..86d6a441 100644 --- a/compiler/src/builtins.c +++ b/compiler/src/builtins.c @@ -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 }, diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index 21e36939..5a31d87f 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -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: diff --git a/compiler/src/wasm_output.h b/compiler/src/wasm_output.h index f03eb6b3..964d1d8b 100644 --- a/compiler/src/wasm_output.h +++ b/compiler/src/wasm_output.h @@ -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) { diff --git a/core/intrinsics/wasm.onyx b/core/intrinsics/wasm.onyx index c33ebf6a..cab1716d 100644 --- a/core/intrinsics/wasm.onyx +++ b/core/intrinsics/wasm.onyx @@ -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 index 00000000..412a89bf --- /dev/null +++ b/core/misc/any_utils.onyx @@ -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; +} + diff --git a/core/runtime/common.onyx b/core/runtime/common.onyx index 6a22b59b..07730caf 100644 --- a/core/runtime/common.onyx +++ b/core/runtime/common.onyx @@ -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 diff --git a/core/std.onyx b/core/std.onyx index 51eceef0..210d9fed 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -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" diff --git a/interpreter/include/ovm_debug.h b/interpreter/include/ovm_debug.h index 37eecea2..a2c08670 100644 --- a/interpreter/include/ovm_debug.h +++ b/interpreter/include/ovm_debug.h @@ -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 { diff --git a/interpreter/include/vm.h b/interpreter/include/vm.h index 44868f87..3dd52548 100644 --- a/interpreter/include/vm.h +++ b/interpreter/include/vm.h @@ -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 // diff --git a/interpreter/include/vm_codebuilder.h b/interpreter/include/vm_codebuilder.h index 80a062b0..347ee5a0 100644 --- a/interpreter/include/vm_codebuilder.h +++ b/interpreter/include/vm_codebuilder.h @@ -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); diff --git a/interpreter/src/vm/code_builder.c b/interpreter/src/vm/code_builder.c index eb27a810..d7f696f2 100644 --- a/interpreter/src/vm/code_builder.c +++ b/interpreter/src/vm/code_builder.c @@ -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); diff --git a/interpreter/src/vm/vm.c b/interpreter/src/vm/vm.c index 3a85c538..46f2f9bd 100644 --- a/interpreter/src/vm/vm.c +++ b/interpreter/src/vm/vm.c @@ -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); diff --git a/interpreter/src/wasm/instance.c b/interpreter/src/wasm/instance.c index 4a998f67..1ffbb5f7 100644 --- a/interpreter/src/wasm/instance.c +++ b/interpreter/src/wasm/instance.c @@ -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; \ diff --git a/interpreter/src/wasm/module_parsing.h b/interpreter/src/wasm/module_parsing.h index ce36d5d0..ef9e9dd7 100644 --- a/interpreter/src/wasm/module_parsing.h +++ b/interpreter/src/wasm/module_parsing.h @@ -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: diff --git a/misc/vscode/onyx-0.0.4.vsix b/misc/vscode/onyx-0.0.4.vsix index 2c47d883..bcbdae29 100644 Binary files a/misc/vscode/onyx-0.0.4.vsix and b/misc/vscode/onyx-0.0.4.vsix differ diff --git a/misc/vscode/out/ovmDebug.js b/misc/vscode/out/ovmDebug.js index 6a3f2d7c..58653c23 100644 --- a/misc/vscode/out/ovmDebug.js +++ b/misc/vscode/out/ovmDebug.js @@ -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; diff --git a/misc/vscode/ovmDebug.ts b/misc/vscode/ovmDebug.ts index 0fa1c54f..35ce3d53 100644 --- a/misc/vscode/ovmDebug.ts +++ b/misc/vscode/ovmDebug.ts @@ -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 }); diff --git a/shared/lib/linux_x86_64/lib/libovmwasm.so b/shared/lib/linux_x86_64/lib/libovmwasm.so index bb90f89b..09751b8a 100755 Binary files a/shared/lib/linux_x86_64/lib/libovmwasm.so and b/shared/lib/linux_x86_64/lib/libovmwasm.so differ