fixed major issue with debugger
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 18 Sep 2022 21:13:11 +0000 (16:13 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 18 Sep 2022 21:13:11 +0000 (16:13 -0500)
compiler/include/wasm_emit.h
compiler/src/wasm_emit.c
interpreter/src/vm/code_builder.c
interpreter/src/vm/vm.c
misc/vscode/onyx-0.0.3.vsix
misc/vscode/out/ovmDebug.js
misc/vscode/ovmDebug.ts
misc/vscode/package.json

index 3a79e5494d1613cab741706cfed1fec18f410da7..d057f5a96905ccc339933bab335fc5b67fbcb59f 100644 (file)
@@ -810,7 +810,7 @@ typedef struct DebugFuncContext {
     u32 file_id;
     u32 line;
     u32 op_offset;
-    u32 stack_ptr_idx;
+    u64 stack_ptr_idx;
 
     u32 name_length;
     char *name;
index 83427bf307aa3dfbc4e66672ef726634c27e057f..8c7fd5df758feec471045905a494be246ce36f77 100644 (file)
@@ -391,6 +391,14 @@ static void debug_begin_function(OnyxWasmModule *mod, u32 func_idx, OnyxToken *t
     debug_set_position(mod, token);
 }
 
+static void debug_function_set_ptr_idx(OnyxWasmModule *mod, u32 func_idx, u64 ptr_idx) {
+    bh_arr_each(DebugFuncContext, func, mod->debug_context->funcs) {
+        if (func->func_index == func_idx) {
+            func->stack_ptr_idx = ptr_idx;
+        }
+    }
+}
+
 static void debug_end_function(OnyxWasmModule *mod) {
     bh_buffer_write_byte(&mod->debug_context->op_buffer, DOT_POPF);
     bh_buffer_write_byte(&mod->debug_context->op_buffer, DOT_END);
@@ -415,6 +423,7 @@ static void debug_leave_symbol_frame(OnyxWasmModule *mod) {
 #define debug_set_position(mod, token) (void)0
 #define debug_emit_instruction(mod, token) (void)0
 #define debug_begin_function(mod, idx, token, name) (void)0
+#define debug_function_set_ptr_idx(mod, func_idx, ptr_idx) (void)0
 #define debug_end_function(mod) (void)0
 #define debug_enter_symbol_frame(mod) (void)0
 #define debug_leave_symbol_frame(mod) (void)0
@@ -3815,6 +3824,7 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
         // 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);
 
         // Generate code
         emit_function_body(mod, &wasm_func.code, fd);
index ec84b47335d95a911e4ca5c1be24d242f3efb408..eb27a810bb19447ac41787607f1e20ebe45dbacc 100644 (file)
@@ -123,6 +123,18 @@ void ovm_code_builder_patch_else(ovm_code_builder_t *builder, label_target_t if_
 }
 
 void ovm_code_builder_add_nop(ovm_code_builder_t *builder) {
+    //
+    // If debugging info was not present in the binary,
+    // do not create NOP instructions. NOP instructions are
+    // normally used as placeholders / special instructions
+    // to signify something weird happened, such as an expanded
+    // macro or operator overload. When this happens, it is
+    // nice to have the correct location in the source tree
+    // so you don't magically jump from one place to another.
+    // HOWEVER, if there is no debug info, then this is not
+    // a concern, and NOPs can be ommited.
+    if (builder->debug_builder->data == NULL) return;
+
     ovm_instr_t nop = {0};
     nop.full_instr = OVMI_NOP;
 
index 28a42627bc63f30f884d517a761693e77da44186..aa7e8d328ebfb0ab8196c530298d3b0cac64e51e 100644 (file)
@@ -675,19 +675,6 @@ ovm_value_t ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t
     ovm_value_t tmp_val;
 
     while (state->pc < bh_arr_length(program->code)) {
-        // This will become the line change detection
-        // debug_loc_info_t loc_info;
-        // debug_info_lookup_location(engine->debug->info, state->pc, &loc_info);
-        // if (loc_info.file_id != last_file || loc_info.line != last_line) {
-        //     last_file = loc_info.file_id;
-        //     last_line = loc_info.line;
-
-        //     debug_file_info_t file_info;
-        //     debug_info_lookup_file(engine->debug->info, last_file, &file_info);
-        //     
-        //     printf("(%d, %d) %s:%d\n", last_file, last_line, file_info.name, last_line);
-        // }
-        
 #ifdef OVM_VERBOSE
         ovm_program_print_instructions(program, state->pc, 1);
 #endif
index ba5d515741443ee98170ced23e95ad19a20ca45e..59266f93afb96a379bfed50b1bbaab1e71581d9e 100644 (file)
Binary files a/misc/vscode/onyx-0.0.3.vsix and b/misc/vscode/onyx-0.0.3.vsix differ
index 5c66268d0534c21c0d18db884a645f3254c9fc89..5fdde9ed53f76a5cda50df25b9487ff022be3a9f 100644 (file)
@@ -188,14 +188,30 @@ class OVMDebugSession extends debugadapter_1.LoggingDebugSession {
         });
     }
     launchRequest(response, args, request) {
-        this.running_process = child_process.spawn("onyx-run", ["--debug", args.wasmFile], {
-            "cwd": args.workingDir,
-        });
-        this.running_process.stdout.setEncoding("utf-8");
-        this.running_process.stdout.on("data", (chunk) => {
-            this.sendEvent(new debugadapter_1.OutputEvent(chunk, "console"));
+        return __awaiter(this, void 0, void 0, function* () {
+            if (args.wasmFile) {
+                this.running_process = child_process.spawn("onyx-run", ["--debug", args.wasmFile], {
+                    "cwd": args.workingDir,
+                });
+            }
+            else if (args.onyxFiles) {
+                this.running_process = child_process.spawn("onyx", ["run", "--debug", ...args.onyxFiles], {
+                    "cwd": args.workingDir,
+                });
+            }
+            else {
+                this.sendErrorResponse(response, {
+                    format: "Expected either wasmFile or onyxFiles in launch configuration.",
+                    id: 1
+                });
+                return;
+            }
+            this.running_process.stdout.setEncoding("utf-8");
+            this.running_process.stdout.on("data", (chunk) => {
+                this.sendEvent(new debugadapter_1.OutputEvent(chunk, "console"));
+            });
+            this.attachRequest(response, { "socketPath": "/tmp/ovm-debug.0000", "stopOnEntry": args.stopOnEntry });
         });
-        this.attachRequest(response, { "socketPath": "/tmp/ovm-debug.0000", "stopOnEntry": args.stopOnEntry });
     }
     attachRequest(response, args, request) {
         return __awaiter(this, void 0, void 0, function* () {
@@ -279,6 +295,8 @@ class OVMDebugger extends EventEmitter {
         });
     }
     pause(thread_id = 0xffffffff) {
+        if (this.client == null)
+            return;
         let data = new ArrayBuffer(12);
         let view = new DataView(data);
         let cmd_id = this.next_command_id;
@@ -289,6 +307,8 @@ class OVMDebugger extends EventEmitter {
         this.pending_responses[cmd_id] = OVMCommand.PAUSE;
     }
     resume(thread_id = 0xffffffff) {
+        if (this.client == null)
+            return;
         let data = new ArrayBuffer(12);
         let view = new DataView(data);
         let cmd_id = this.next_command_id;
@@ -300,6 +320,8 @@ class OVMDebugger extends EventEmitter {
     }
     set_breakpoint(filename, line) {
         return __awaiter(this, void 0, void 0, function* () {
+            if (this.client == null)
+                return Promise.resolve({});
             let data = new ArrayBuffer(16 + filename.length);
             let view = new DataView(data);
             let cmd_id = this.next_command_id;
@@ -317,6 +339,8 @@ class OVMDebugger extends EventEmitter {
     }
     remove_breakpoints_in_file(filename) {
         return __awaiter(this, void 0, void 0, function* () {
+            if (this.client == null)
+                return Promise.resolve(false);
             let data = new ArrayBuffer(12 + filename.length);
             let view = new DataView(data);
             let cmd_id = this.next_command_id;
@@ -332,6 +356,8 @@ class OVMDebugger extends EventEmitter {
         });
     }
     step(granularity, thread_id) {
+        if (this.client == null)
+            return;
         let data = new ArrayBuffer(16);
         let view = new DataView(data);
         let cmd_id = this.next_command_id;
@@ -356,6 +382,8 @@ class OVMDebugger extends EventEmitter {
         this.pending_responses[cmd_id] = OVMCommand.STEP;
     }
     trace(thread_id) {
+        if (this.client == null)
+            return Promise.resolve([]);
         let data = new ArrayBuffer(12);
         let view = new DataView(data);
         let cmd_id = this.next_command_id;
@@ -367,6 +395,8 @@ class OVMDebugger extends EventEmitter {
         return this.preparePromise(cmd_id);
     }
     threads() {
+        if (this.client == null)
+            return Promise.resolve([]);
         let data = new ArrayBuffer(8);
         let view = new DataView(data);
         let cmd_id = this.next_command_id;
@@ -377,6 +407,8 @@ class OVMDebugger extends EventEmitter {
         return this.preparePromise(cmd_id);
     }
     variables(frame_index, thread_id) {
+        if (this.client == null)
+            return Promise.resolve([]);
         let data = new ArrayBuffer(16);
         let view = new DataView(data);
         let cmd_id = this.next_command_id;
index 08d85494d69481689c1ff32c3bc4b7c9ee3ae639..f646927f8f1fb0e35a9dac9c8f48c2ffbf9eebcd 100644 (file)
@@ -12,6 +12,7 @@ import { Subject } from "await-notify";
 import * as net from "node:net";
 import * as child_process from "node:child_process";
 import { ChildProcess } from 'node:child_process';
+import { openStdin } from 'node:process';
 
 
 interface IOVMAttachRequestArguments extends DebugProtocol.AttachRequestArguments {
@@ -20,7 +21,8 @@ interface IOVMAttachRequestArguments extends DebugProtocol.AttachRequestArgument
 }
 
 interface IOVMLaunchRequestArguments extends DebugProtocol.AttachRequestArguments {
-    wasmFile: string;
+    wasmFile?: string;
+    onyxFiles?: [string];
        workingDir: string;
     stopOnEntry?: boolean;
 }
@@ -257,10 +259,25 @@ export class OVMDebugSession extends LoggingDebugSession {
                this.sendResponse(response);
        }
 
-    protected launchRequest(response: DebugProtocol.LaunchResponse, args: IOVMLaunchRequestArguments, request?: DebugProtocol.Request): void {
-               this.running_process = child_process.spawn("onyx-run", ["--debug", args.wasmFile], {
-                       "cwd": args.workingDir, 
-               });
+    protected async launchRequest(response: DebugProtocol.LaunchResponse, args: IOVMLaunchRequestArguments, request?: DebugProtocol.Request): Promise<void> {
+               if (args.wasmFile) {
+                       this.running_process = child_process.spawn("onyx-run", ["--debug", args.wasmFile], {
+                               "cwd": args.workingDir, 
+                       });
+
+               } else if (args.onyxFiles) {
+                       this.running_process = child_process.spawn("onyx", ["run", "--debug", ...args.onyxFiles], {
+                               "cwd": args.workingDir,
+                       });
+
+               } else {
+                       this.sendErrorResponse(response, {
+                               format: "Expected either wasmFile or onyxFiles in launch configuration.",
+                               id: 1
+                       } as DebugProtocol.Message);
+
+                       return;
+               }
 
                this.running_process.stdout.setEncoding("utf-8");
                this.running_process.stdout.on("data", (chunk) => {
@@ -398,6 +415,8 @@ class OVMDebugger extends EventEmitter {
        }
 
        pause(thread_id: number = 0xffffffff): void {
+               if (this.client == null) return;
+
         let data = new ArrayBuffer(12);
         let view = new DataView(data);
 
@@ -413,6 +432,8 @@ class OVMDebugger extends EventEmitter {
        }
 
     resume(thread_id: number = 0xffffffff): void {
+               if (this.client == null) return;
+
         let data = new ArrayBuffer(12);
         let view = new DataView(data);
 
@@ -428,6 +449,8 @@ class OVMDebugger extends EventEmitter {
     }
 
     async set_breakpoint(filename: string, line: number): Promise<IBreakpointValidation> {
+               if (this.client == null) return Promise.resolve({} as IBreakpointValidation);
+
         let data = new ArrayBuffer(16+filename.length);
         let view = new DataView(data);
 
@@ -450,6 +473,8 @@ class OVMDebugger extends EventEmitter {
     }
        
        async remove_breakpoints_in_file(filename: string): Promise<boolean> {
+               if (this.client == null) return Promise.resolve(false);
+
         let data = new ArrayBuffer(12+filename.length);
         let view = new DataView(data);
 
@@ -471,6 +496,8 @@ class OVMDebugger extends EventEmitter {
        }
 
        step(granularity: "line" | "instruction" | "over" | "out", thread_id: number): void {
+               if (this.client == null) return;
+
         let data = new ArrayBuffer(16);
         let view = new DataView(data);
 
@@ -493,6 +520,8 @@ class OVMDebugger extends EventEmitter {
        }
 
        trace(thread_id: number): Promise<IFileLocation[]> {
+               if (this.client == null) return Promise.resolve([]);
+
         let data = new ArrayBuffer(12);
         let view = new DataView(data);
 
@@ -510,6 +539,8 @@ class OVMDebugger extends EventEmitter {
        }
 
        threads(): Promise<IThreadInfo[]> {
+               if (this.client == null) return Promise.resolve([]);
+
         let data = new ArrayBuffer(8);
         let view = new DataView(data);
 
@@ -526,6 +557,8 @@ class OVMDebugger extends EventEmitter {
        }
 
        variables(frame_index: number, thread_id: number): Promise<IVariableInfo[]> {
+               if (this.client == null) return Promise.resolve([]);
+
         let data = new ArrayBuffer(16);
         let view = new DataView(data);
 
index 8ad40eaa518f62ec6de7adbf0fa2a8ace701f886..7bbd3ff0f2cffe782dd465a7d12dc288a16a06af 100644 (file)
@@ -14,6 +14,9 @@
     "activationEvents": [
         "onLanguage:onyx"
     ],
+    "repository": {
+        "url": "https://github.com/onyx-lang/onyx"
+    },
     "icon": "logo.png",
     "main": "./out/extension.js",
     "contributes": {
                                 "description": "The WASM file for debugging, compiled with the --debug flag.",
                                 "default": "out.wasm"
                             },
+                            "onyxFiles": {
+                                "type": "array",
+                                "description": "The Onyx files for compiling.",
+                                "default": "[]"
+                            },
                             "workingDir": {
                                 "type": "string",
                                 "description": "The working directory for the execution",
                 },
                 "initialConfigurations": [
                     {
+                        "name": "Onyx Attach",
                         "type": "onyx",
                         "request": "attach",
-                        "stopOnEntry": true
+                        "stopOnEntry": true,
+                        "socketPath": "/tmp/ovm-debug.0000"
                     },
                     {
+                        "name": "Onyx Launch",
                         "type": "onyx",
                         "request": "launch",
                         "wasmFile": "out.wasm",