From: Brendan Hansen Date: Tue, 2 Aug 2022 03:12:35 +0000 (-0500) Subject: bugfixes with debug info emitted X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=7e616fbb2bebe3df182a25223be6c0710527eba4;p=onyx.git bugfixes with debug info emitted --- diff --git a/include/astnodes.h b/include/astnodes.h index 6214b4b7..45a66567 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -1541,6 +1541,8 @@ struct CompileOptions { const char* target_file; const char* documentation_file; + b32 debug_enabled; + i32 passthrough_argument_count; char** passthrough_argument_data; }; diff --git a/include/bh.h b/include/bh.h index 536ab38b..b9f008dd 100644 --- a/include/bh.h +++ b/include/bh.h @@ -356,6 +356,7 @@ typedef struct bh_file_contents { const char *filename; isize length; void* data; + isize line_count; } bh_file_contents; bh_file_error bh_file_get_standard(bh_file* file, bh_file_standard stand); @@ -1606,7 +1607,7 @@ bh_file_contents bh_file_read_contents_bh_file(bh_allocator alloc, bh_file* file bh_file_contents fc = { .allocator = alloc, .filename = bh_strdup(alloc, (char *) file->filename), - .length = 0, .data = NULL + .length = 0, .data = NULL, .line_count = 0, }; isize size = bh_file_size(file); diff --git a/include/wasm_emit.h b/include/wasm_emit.h index d2c60391..84a69fb8 100644 --- a/include/wasm_emit.h +++ b/include/wasm_emit.h @@ -814,10 +814,15 @@ typedef struct DebugFuncContext { char *name; } DebugFuncContext; +typedef struct DebugFileInfo { + u32 file_id; + u32 line_count; +} DebugFileInfo; + typedef struct DebugContext { bh_allocator allocator; - Table(u32) file_ids; + Table(DebugFileInfo) file_info; u32 next_file_id; bh_arr(DebugFuncContext) funcs; diff --git a/lib/linux_x86_64/lib/libovmwasm.so b/lib/linux_x86_64/lib/libovmwasm.so index 1a53a55a..82f3fa28 100755 Binary files a/lib/linux_x86_64/lib/libovmwasm.so and b/lib/linux_x86_64/lib/libovmwasm.so differ diff --git a/src/astnodes.c b/src/astnodes.c index c2ca3f07..63803c61 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -881,6 +881,10 @@ Type* resolve_expression_type(AstTyped* node) { node->type = &basic_types[Basic_Kind_Void]; } + if (node->kind == Ast_Kind_Macro) { + return resolve_expression_type((AstTyped *) ((AstMacro *) node)->body); + } + if (node->type == NULL) node->type = type_build_from_ast(context.ast_alloc, node->type_node); diff --git a/src/checker.c b/src/checker.c index 6dd82e7a..6ed77a31 100644 --- a/src/checker.c +++ b/src/checker.c @@ -816,6 +816,10 @@ CheckStatus check_binaryop_assignment(AstBinaryOp** pbinop) { YIELD(binop->token->pos, "Waiting for type to be constructed on left hand side."); } + // NOTE: There is a subtlety here. You cannot use the result of `resolve_expression_type` directly, + // as in some cases (especially with macros and polyprocs), the result is not "correct". The result + // makes them appears as though they are runtime-known values, which they are not. Using the following + // pattern does prevent this issue. resolve_expression_type(binop->right); Type* right_type = get_expression_type(binop->right); diff --git a/src/onyx.c b/src/onyx.c index 40ce3097..4b5957da 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -81,6 +81,8 @@ static CompileOptions compile_opts_parse(bh_allocator alloc, int argc, char *arg .documentation_file = NULL, + .debug_enabled = 0, + .passthrough_argument_count = 0, .passthrough_argument_data = NULL, }; @@ -172,6 +174,9 @@ static CompileOptions compile_opts_parse(bh_allocator alloc, int argc, char *arg else if (!strcmp(argv[i], "--doc")) { options.documentation_file = argv[++i]; } + else if (!strcmp(argv[i], "--debug")) { + options.debug_enabled = 1; + } else if (!strcmp(argv[i], "--")) { options.passthrough_argument_count = argc - i - 1; options.passthrough_argument_data = &argv[i + 1]; @@ -321,6 +326,8 @@ static void parse_source_file(bh_file_contents* file_contents) { OnyxTokenizer tokenizer = onyx_tokenizer_create(context.token_alloc, file_contents); onyx_lex_tokens(&tokenizer); + file_contents->line_count = tokenizer.line_number; + OnyxParser parser = onyx_parser_create(context.ast_alloc, &tokenizer); onyx_parse(&parser); onyx_parser_free(&parser); @@ -350,7 +357,7 @@ static b32 process_source_file(char* filename, OnyxFilePos error_pos) { if (context.options->verbose_output == 2) bh_printf("Processing source file: %s (%d bytes)\n", file.filename, fc.length); - parse_source_file(&fc); + parse_source_file(&bh_arr_last(context.loaded_files)); return 1; } diff --git a/src/wasm_emit.c b/src/wasm_emit.c index a6482f74..a1df61e3 100644 --- a/src/wasm_emit.c +++ b/src/wasm_emit.c @@ -222,15 +222,23 @@ static inline b32 should_emit_function(AstFunction* fd) { static u32 debug_get_file_id(OnyxWasmModule *mod, const char *name) { assert(mod && mod->debug_context); - i32 index = shgeti(mod->debug_context->file_ids, name); + i32 index = shgeti(mod->debug_context->file_info, name); if (index == -1) { u32 id = mod->debug_context->next_file_id++; - shput(mod->debug_context->file_ids, name, id); + DebugFileInfo file_info; + file_info.file_id = id; + + bh_arr_each(bh_file_contents, fc, context.loaded_files) { + if (!strcmp(fc->filename, name)) { + file_info.line_count = fc->line_count; + } + } + shput(mod->debug_context->file_info, name, file_info); return id; } - return mod->debug_context->file_ids[index].value; + return mod->debug_context->file_info[index].value.file_id; } static void debug_set_position(OnyxWasmModule *mod, OnyxToken *token) { @@ -349,6 +357,7 @@ 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); mod->debug_context->last_op_was_rep = 0; + mod->debug_context->last_token = NULL; } #else @@ -380,15 +389,17 @@ enum StructuredBlockType { }; #ifdef ENABLE_DEBUG_INFO - #define WI(token, instr) (debug_emit_instruction(mod, token), bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }))) + #define WI(token, instr) (debug_emit_instruction(mod, token), bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }))) #define WID(token, instr, data) (debug_emit_instruction(mod, token), bh_arr_push(code, ((WasmInstruction){ instr, data }))) #define WIL(token, instr, data) (debug_emit_instruction(mod, token), bh_arr_push(code, ((WasmInstruction){ instr, { .l = data } }))) #define WIP(token, instr, data) (debug_emit_instruction(mod, token), bh_arr_push(code, ((WasmInstruction){ instr, { .p = data } }))) + #define WIR(token, full_instr) (debug_emit_instruction(mod, token), bh_arr_push(code, full_instr)) #else #define WI(token, instr) (bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }))) #define WID(token, instr, data) (bh_arr_push(code, ((WasmInstruction){ instr, data }))) #define WIL(token, instr, data) (bh_arr_push(code, ((WasmInstruction){ instr, { .l = data } }))) #define WIP(token, instr, data) (bh_arr_push(code, ((WasmInstruction){ instr, { .p = data } }))) + #define WIR(token, full_instr) (bh_arr_push(code, full_instr)) #endif #define EMIT_FUNC(kind, ...) static void emit_ ## kind (OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, __VA_ARGS__) @@ -1545,7 +1556,7 @@ EMIT_FUNC(deferred_stmt, DeferredStmt deferred_stmt) { case Deferred_Stmt_Node: emit_statement(mod, &code, deferred_stmt.stmt); break; case Deferred_Stmt_Code: { fori (i, 0, deferred_stmt.instruction_count) { - bh_arr_push(code, deferred_stmt.instructions[i]); + WIR(NULL, deferred_stmt.instructions[i]); } break; } @@ -1906,13 +1917,13 @@ EMIT_FUNC(call, AstCall* call) { if (call->callee->kind == Ast_Kind_Function) { i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) call->callee); - bh_arr_push(code, ((WasmInstruction){ WI_CALL, func_idx })); + WIL(NULL, WI_CALL, func_idx); } else { emit_expression(mod, &code, call->callee); i32 type_idx = generate_type_idx(mod, call->callee->type); - WID(call_token, WI_CALL_INDIRECT, ((WasmInstructionData) { type_idx, 0x00 })); + WID(NULL, WI_CALL_INDIRECT, ((WasmInstructionData) { type_idx, 0x00 })); } if (reserve_size > 0) { @@ -2465,9 +2476,9 @@ EMIT_FUNC(memory_reservation_location, AstMemRes* memres) { if (memres->threadlocal) { u64 tls_base_idx = bh_imap_get(&mod->index_map, (u64) &builtin_tls_base); - WID(memres->token, WI_PTR_CONST, memres->tls_offset); - WIL(memres->token, WI_GLOBAL_GET, tls_base_idx); - WI(memres->token, WI_PTR_ADD); + WID(NULL, WI_PTR_CONST, memres->tls_offset); + WIL(NULL, WI_GLOBAL_GET, tls_base_idx); + WI(NULL, WI_PTR_ADD); } else { // :ProperLinking @@ -2971,7 +2982,7 @@ EMIT_FUNC(expression, AstTyped* expr) { instr.data.d = lit->value.d; } - bh_arr_push(code, instr); + WIR(NULL, instr); break; } @@ -3588,7 +3599,7 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) { wasm_func.type_idx = type_idx; wasm_func.location = fd->token; - bh_arr_new(mod->allocator, wasm_func.code, 4); + bh_arr_new(mod->allocator, wasm_func.code, 16); i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd); mod->current_func_idx = func_idx; @@ -3653,6 +3664,11 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) { bh_arr_clear(mod->stack_leave_patches); + debug_emit_instruction(mod, fd->token); + debug_emit_instruction(mod, fd->token); + debug_emit_instruction(mod, fd->token); + debug_emit_instruction(mod, fd->token); + debug_emit_instruction(mod, fd->token); bh_arr_insert_end(wasm_func.code, 5); fori (i, 0, 5) wasm_func.code[i] = (WasmInstruction) { WI_NOP, 0 }; @@ -4196,7 +4212,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { module.debug_context->next_file_id = 0; module.debug_context->last_token = NULL; - sh_new_arena(module.debug_context->file_ids); + sh_new_arena(module.debug_context->file_info); bh_arr_new(global_heap_allocator, module.debug_context->funcs, 16); bh_buffer_init(&module.debug_context->op_buffer, global_heap_allocator, 1024); diff --git a/src/wasm_output.h b/src/wasm_output.h index c7b4e7dd..db15efb5 100644 --- a/src/wasm_output.h +++ b/src/wasm_output.h @@ -777,12 +777,13 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) { output_custom_section_name("ovm_debug_files", §ion_buff); - i32 file_count = shlenu(ctx->file_ids); + i32 file_count = shlenu(ctx->file_info); output_unsigned_integer(file_count, §ion_buff); fori (i, 0, file_count) { - Table(u32) entry = (void *) &ctx->file_ids[i]; - output_unsigned_integer(entry->value, §ion_buff); + Table(DebugFileInfo) entry = (void *) &ctx->file_info[i]; + output_unsigned_integer(entry->value.file_id, §ion_buff); + output_unsigned_integer(entry->value.line_count, §ion_buff); output_name(entry->key, strlen(entry->key), §ion_buff); } diff --git a/src/wasm_runtime.c b/src/wasm_runtime.c index b3551ea8..1818f4d0 100644 --- a/src/wasm_runtime.c +++ b/src/wasm_runtime.c @@ -14,10 +14,6 @@ #include #include #endif -// -// #ifndef WASMER_VERSION -// #error "Currently, building the Onyx compiler with built-in execution support requires the Wasmer library to be compiled and linked." -// #endif static wasm_config_t* wasm_config; static wasm_engine_t* wasm_engine; @@ -236,7 +232,16 @@ b32 onyx_run_wasm(bh_buffer wasm_bytes, int argc, char *argv[]) { wasm_config = wasm_config_new(); if (!wasm_config) goto error_handling; +#ifdef USE_OVM_DEBUGGER + void wasm_config_enable_debug(wasm_config_t *config, int value); + wasm_config_enable_debug(wasm_config, context.options->debug_enabled); +#endif + #ifndef USE_OVM_DEBUGGER + if (context.options->debug_enabled) { + printf("Warning: --debug does nothing if libovmwasm.so is not being used!\n"); + } + // Prefer the LLVM compile because it is faster. This should be configurable from the command line and/or a top-level directive. if (wasmer_is_compiler_available(LLVM)) { wasm_config_set_compiler(wasm_config, LLVM);