bugfixes with debug info emitted
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 Aug 2022 03:12:35 +0000 (22:12 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 2 Aug 2022 03:12:35 +0000 (22:12 -0500)
include/astnodes.h
include/bh.h
include/wasm_emit.h
lib/linux_x86_64/lib/libovmwasm.so
src/astnodes.c
src/checker.c
src/onyx.c
src/wasm_emit.c
src/wasm_output.h
src/wasm_runtime.c

index 6214b4b76262d151ad9f89f927396beeaa72afd1..45a665676c8be0ef611b6001240cfb9ba4f9bb3c 100644 (file)
@@ -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;
 };
index 536ab38b7d83b2b43e821a40b7d848f01894201d..b9f008ddd563fa1f74bd9d9640aef2616f3b0b32 100644 (file)
@@ -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);
index d2c6039137f45f4c3c527a9532fda477d4d60dce..84a69fb817827223be73824b5b7f5c3ed257a3fb 100644 (file)
@@ -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;
index 1a53a55a0f180bd02da557de307f60bc485d76ab..82f3fa282fee4abea9e8086ae5b5c27fb7c51af2 100755 (executable)
Binary files a/lib/linux_x86_64/lib/libovmwasm.so and b/lib/linux_x86_64/lib/libovmwasm.so differ
index c2ca3f0725011dc59dea22b8a399be34fd09b5fa..63803c61e3ccd52d343403047df3060d459302bf 100644 (file)
@@ -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);
 
index 6dd82e7a5153acee15fa9efc7f5eb885423176b6..6ed77a31b7976df09446c691c0c841e24481d07f 100644 (file)
@@ -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);
index 40ce30973f1549d37a912f482950617f62245d0c..4b5957dab3688d7478d18108d008541a46cc6915 100644 (file)
@@ -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;
 }
 
index a6482f74d16de2546f81247f4eb0e596228a4aae..a1df61e357c705107dd70a62f79dd00e342e60da 100644 (file)
@@ -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);
index c7b4e7dd5316bd91d8133b114f7caf2bf5621a2a..db15efb51f49ca085bd6fef1212fc19c5f45317a 100644 (file)
@@ -777,12 +777,13 @@ static i32 output_ovm_debug_sections(OnyxWasmModule* module, bh_buffer* buff) {
 
         output_custom_section_name("ovm_debug_files", &section_buff);
 
-        i32 file_count = shlenu(ctx->file_ids);
+        i32 file_count = shlenu(ctx->file_info);
         output_unsigned_integer(file_count, &section_buff);
 
         fori (i, 0, file_count) {
-            Table(u32) entry = (void *) &ctx->file_ids[i];
-            output_unsigned_integer(entry->value, &section_buff);
+            Table(DebugFileInfo) entry = (void *) &ctx->file_info[i];
+            output_unsigned_integer(entry->value.file_id, &section_buff);
+            output_unsigned_integer(entry->value.line_count, &section_buff);
             output_name(entry->key, strlen(entry->key), &section_buff);
         }
 
index b3551ea81e95605818390d85496d407dd72e2bad..1818f4d0e41c28bd72fd9ee965b03192492ac81b 100644 (file)
     #include <sys/wait.h>
     #include <dlfcn.h>
 #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);