u32 file_id;
u32 line;
u32 op_offset;
- u32 stack_ptr_idx;
+ u64 stack_ptr_idx;
u32 name_length;
char *name;
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);
#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
// 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);
}
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;
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
});
}
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* () {
});
}
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;
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;
}
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;
}
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;
});
}
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;
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;
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;
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;
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 {
}
interface IOVMLaunchRequestArguments extends DebugProtocol.AttachRequestArguments {
- wasmFile: string;
+ wasmFile?: string;
+ onyxFiles?: [string];
workingDir: string;
stopOnEntry?: boolean;
}
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) => {
}
pause(thread_id: number = 0xffffffff): void {
+ if (this.client == null) return;
+
let data = new ArrayBuffer(12);
let view = new DataView(data);
}
resume(thread_id: number = 0xffffffff): void {
+ if (this.client == null) return;
+
let data = new ArrayBuffer(12);
let view = new DataView(data);
}
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);
}
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);
}
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);
}
trace(thread_id: number): Promise<IFileLocation[]> {
+ if (this.client == null) return Promise.resolve([]);
+
let data = new ArrayBuffer(12);
let view = new DataView(data);
}
threads(): Promise<IThreadInfo[]> {
+ if (this.client == null) return Promise.resolve([]);
+
let data = new ArrayBuffer(8);
let view = new DataView(data);
}
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);
"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",