diff options
-rw-r--r-- | src/compiler-support.h | 6 | ||||
-rw-r--r-- | src/s2wasm.h | 96 | ||||
-rw-r--r-- | test/dot_s/debug.s | 307 | ||||
-rw-r--r-- | test/dot_s/debug.wast | 51 |
4 files changed, 448 insertions, 12 deletions
diff --git a/src/compiler-support.h b/src/compiler-support.h index 9e298b278..bf2885993 100644 --- a/src/compiler-support.h +++ b/src/compiler-support.h @@ -36,4 +36,10 @@ # define WASM_UNREACHABLE() abort() #endif +// The code might contain TODOs or stubs that read some values but do nothing +// with them. The compiler might fail with [-Werror,-Wunused-variable]. +// The WASM_UNUSED(varible) is a wrapper that helps to suppress the error. +#define WASM_UNUSED(expr) \ + do { if (sizeof expr) { (void)0; } } while (0) + #endif // wasm_compiler_support_h diff --git a/src/s2wasm.h b/src/s2wasm.h index c0ab0998b..2228ae900 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -101,6 +101,10 @@ class S2WasmBuilder { abort(); \ } + bool peek(const char *pattern) { + return strncmp(s, pattern, strlen(pattern)) == 0; + } + // match and skip the pattern, if matched bool match(const char *pattern) { size_t size = strlen(pattern); @@ -396,17 +400,19 @@ class S2WasmBuilder { else if (match("ident")) {} else if (match("section")) parseToplevelSection(); else if (match("align") || match("p2align")) s = strchr(s, '\n'); - else if (match("Lfunc_end")) { - // skip the next line, which has a .size we can ignore - s = strstr(s, ".size"); - s = strchr(s, '\n'); - } else if (match("globl")) parseGlobl(); + else if (match("globl")) parseGlobl(); else abort_on("process"); } } void parseToplevelSection() { auto section = getCommaSeparated(); + // Skipping .debug_ sections + if (!strncmp(section.c_str(), ".debug_", strlen(".debug_"))) { + const char *next = strstr(s, ".section"); + s = !next ? s + strlen(s) : next; + return; + } // Initializers are anything in a section whose name begins with .init_array if (!strncmp(section.c_str(), ".init_array", strlen(".init_array") - 1)) { parseInitializer(); @@ -449,7 +455,16 @@ class S2WasmBuilder { } void parseFile() { - assert(*s == '"'); + if (*s != '"') { + // TODO: optimize, see recordFile below + size_t fileId = getInt(); + skipWhitespace(); + auto quoted = getQuoted(); + WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted + s = strchr(s, '\n'); + return; + } + // '.file' without first index argument points to bc-file s++; std::string filename; while (*s != '"') { @@ -457,7 +472,7 @@ class S2WasmBuilder { s++; } s++; - // TODO: use the filename? + WASM_UNUSED(filename); // TODO: use the filename } void parseGlobl() { @@ -485,11 +500,31 @@ class S2WasmBuilder { mustMatch(":"); - if (match(".Lfunc_begin")) { + auto recordFile = [&]() { + if (debug) dump("file"); + size_t fileId = getInt(); + skipWhitespace(); + auto quoted = getQuoted(); + WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted s = strchr(s, '\n'); - s++; + }; + auto recordLoc = [&]() { + if (debug) dump("loc"); + size_t fileId = getInt(); skipWhitespace(); - } + size_t row = getInt(); + skipWhitespace(); + size_t column = getInt(); + WASM_UNUSED(fileId); WASM_UNUSED(row); WASM_UNUSED(column); // TODO: use the fileId, row and column + s = strchr(s, '\n'); + }; + auto recordLabel = [&]() { + if (debug) dump("label"); + Name label = getStrToSep(); + // TODO: track and create map of labels and their ranges for our AST + WASM_UNUSED(label); + s = strchr(s, '\n'); + }; unsigned nextId = 0; auto getNextId = [&nextId]() { @@ -523,6 +558,15 @@ class S2WasmBuilder { skipWhitespace(); if (!match(",")) break; } + } else if (match(".file")) { + recordFile(); + skipWhitespace(); + } else if (match(".loc")) { + recordLoc(); + skipWhitespace(); + } else if (peek(".Lfunc_begin")) { + recordLabel(); + skipWhitespace(); } else break; } Function* func = builder.makeFunction(name, std::move(params), resultType, std::move(vars)); @@ -644,6 +688,7 @@ class S2WasmBuilder { auto curr = allocator->alloc<Unary>(); curr->op = op; curr->value = getInput(); + curr->type = type; curr->finalize(); setOutput(curr, assign); }; @@ -935,8 +980,13 @@ class S2WasmBuilder { } else if (match("end_block")) { bstack.back()->cast<Block>()->finalize(); bstack.pop_back(); - } else if (match(".LBB")) { - s = strchr(s, '\n'); + } else if (peek(".LBB")) { + // FIXME legacy tests: it can be leftover from "loop" or "block", but it can be a label too + auto p = s; + while (*p && *p != ':' && *p != '#' && *p != '\n') p++; + if (*p == ':') { // it's a label + recordLabel(); + } else s = strchr(s, '\n'); } else if (match("loop")) { auto curr = allocator->alloc<Loop>(); addToBlock(curr); @@ -997,8 +1047,30 @@ class S2WasmBuilder { makeHost(CurrentMemory); } else if (match("grow_memory")) { makeHost1(GrowMemory); + } else if (peek(".Lfunc_end")) { + // TODO fix handwritten tests to have .endfunc + recordLabel(); + // skip the next line, which has a .size we can ignore + s = strstr(s, ".size"); + s = strchr(s, '\n'); + break; // the function is done } else if (match(".endfunc")) { + skipWhitespace(); + // getting all labels at the end of function + while (peek(".L") && strchr(s, ':') < strchr(s, '\n')) { + recordLabel(); + skipWhitespace(); + } + // skip the next line, which has a .size we can ignore + s = strstr(s, ".size"); + s = strchr(s, '\n'); break; // the function is done + } else if (match(".file")) { + recordFile(); + } else if (match(".loc")) { + recordLoc(); + } else if (peek(".L") && strchr(s, ':') < strchr(s, '\n')) { + recordLabel(); } else { abort_on("function element"); } diff --git a/test/dot_s/debug.s b/test/dot_s/debug.s new file mode 100644 index 000000000..045b1ddad --- /dev/null +++ b/test/dot_s/debug.s @@ -0,0 +1,307 @@ + .text + .file "fib.bc" + .hidden fib + .globl fib + .type fib,@function +fib: +.Lfunc_begin0: + .file 1 "fib.c" + .loc 1 1 0 + .param i32 + .result i32 + .local i32, i32, i32, i32 +.Ltmp0: + i32.const $3=, 0 +.Ltmp1: + i32.const $2=, -1 + i32.const $4=, 1 +.LBB0_1: + loop + i32.const $push1=, 1 +.Ltmp2: + .loc 1 3 17 prologue_end discriminator 1 + i32.add $2=, $2, $pop1 + .loc 1 3 3 is_stmt 0 discriminator 1 + i32.ge_s $push0=, $2, $0 + br_if 1, $pop0 +.Ltmp3: + .loc 1 4 11 is_stmt 1 + i32.add $1=, $4, $3 +.Ltmp4: + copy_local $3=, $4 + copy_local $4=, $1 + br 0 +.Ltmp5: +.LBB0_3: + end_loop +.Ltmp6: + .loc 1 6 3 + return $4 +.Ltmp7: + .endfunc +.Lfunc_end0: + .size fib, .Lfunc_end0-fib + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 3.9.0 (trunk 266025)" +.Linfo_string1: + .asciz "fib.c" +.Linfo_string2: + .asciz "/Users/yury/llvmwasm" +.Linfo_string3: + .asciz "fib" +.Linfo_string4: + .asciz "int" +.Linfo_string5: + .asciz "n" +.Linfo_string6: + .asciz "a" +.Linfo_string7: + .asciz "b" +.Linfo_string8: + .asciz "i" +.Linfo_string9: + .asciz "t" + .section .debug_loc,"",@progbits +.Ldebug_loc0: + .int32 .Lfunc_begin0-.Lfunc_begin0 + .int32 .Lfunc_end0-.Lfunc_begin0 + .int16 1 + .int8 150 + .int32 0 + .int32 0 +.Ldebug_loc1: + .int32 .Ltmp0-.Lfunc_begin0 + .int32 .Ltmp6-.Lfunc_begin0 + .int16 3 + .int8 17 + .int8 0 + .int8 159 + .int32 .Ltmp6-.Lfunc_begin0 + .int32 .Lfunc_end0-.Lfunc_begin0 + .int16 1 + .int8 150 + .int32 0 + .int32 0 +.Ldebug_loc2: + .int32 .Ltmp0-.Lfunc_begin0 + .int32 .Ltmp4-.Lfunc_begin0 + .int16 3 + .int8 17 + .int8 1 + .int8 159 + .int32 .Ltmp4-.Lfunc_begin0 + .int32 .Lfunc_end0-.Lfunc_begin0 + .int16 1 + .int8 150 + .int32 0 + .int32 0 +.Ldebug_loc3: + .int32 .Ltmp4-.Lfunc_begin0 + .int32 .Lfunc_end0-.Lfunc_begin0 + .int16 1 + .int8 150 + .int32 0 + .int32 0 + .section .debug_abbrev,"",@progbits +.Lsection_abbrev: + .int8 1 + .int8 17 + .int8 1 + .int8 37 + .int8 14 + .int8 19 + .int8 5 + .int8 3 + .int8 14 + .int8 16 + .int8 23 + .int8 27 + .int8 14 + .ascii "\341\177" + .int8 25 + .int8 17 + .int8 1 + .int8 18 + .int8 6 + .int8 0 + .int8 0 + .int8 2 + .int8 46 + .int8 1 + .int8 17 + .int8 1 + .int8 18 + .int8 6 + .ascii "\347\177" + .int8 25 + .int8 64 + .int8 24 + .int8 3 + .int8 14 + .int8 58 + .int8 11 + .int8 59 + .int8 11 + .int8 39 + .int8 25 + .int8 73 + .int8 19 + .int8 63 + .int8 25 + .ascii "\341\177" + .int8 25 + .int8 0 + .int8 0 + .int8 3 + .int8 5 + .int8 0 + .int8 2 + .int8 23 + .int8 3 + .int8 14 + .int8 58 + .int8 11 + .int8 59 + .int8 11 + .int8 73 + .int8 19 + .int8 0 + .int8 0 + .int8 4 + .int8 52 + .int8 0 + .int8 2 + .int8 23 + .int8 3 + .int8 14 + .int8 58 + .int8 11 + .int8 59 + .int8 11 + .int8 73 + .int8 19 + .int8 0 + .int8 0 + .int8 5 + .int8 52 + .int8 0 + .int8 28 + .int8 13 + .int8 3 + .int8 14 + .int8 58 + .int8 11 + .int8 59 + .int8 11 + .int8 73 + .int8 19 + .int8 0 + .int8 0 + .int8 6 + .int8 36 + .int8 0 + .int8 3 + .int8 14 + .int8 62 + .int8 11 + .int8 11 + .int8 11 + .int8 0 + .int8 0 + .int8 0 + .section .debug_info,"",@progbits +.Lsection_info: +.Lcu_begin0: + .int32 135 + .int16 4 + .int32 .Lsection_abbrev + .int8 4 + .int8 1 + .int32 .Linfo_string0 + .int16 12 + .int32 .Linfo_string1 + .int32 .Lline_table_start0 + .int32 .Linfo_string2 + + .int32 .Lfunc_begin0 + .int32 .Lfunc_end0-.Lfunc_begin0 + .int8 2 + .int32 .Lfunc_begin0 + .int32 .Lfunc_end0-.Lfunc_begin0 + + .int8 0 + .int32 .Linfo_string3 + .int8 1 + .int8 1 + + .int32 131 + + + .int8 3 + .int32 .Ldebug_loc0 + .int32 .Linfo_string5 + .int8 1 + .int8 1 + .int32 131 + .int8 4 + .int32 .Ldebug_loc1 + .int32 .Linfo_string6 + .int8 1 + .int8 2 + .int32 131 + .int8 4 + .int32 .Ldebug_loc2 + .int32 .Linfo_string7 + .int8 1 + .int8 2 + .int32 131 + .int8 5 + .int8 0 + .int32 .Linfo_string8 + .int8 1 + .int8 2 + .int32 131 + .int8 4 + .int32 .Ldebug_loc3 + .int32 .Linfo_string9 + .int8 1 + .int8 2 + .int32 131 + .int8 0 + .int8 6 + .int32 .Linfo_string4 + .int8 5 + .int8 4 + .int8 0 + .section .debug_ranges,"",@progbits +.Ldebug_range: + .section .debug_macinfo,"",@progbits +.Ldebug_macinfo: +.Lcu_macro_begin0: + .int8 0 + .section .debug_pubnames,"",@progbits + .int32 .LpubNames_end0-.LpubNames_begin0 +.LpubNames_begin0: + .int16 2 + .int32 .Lcu_begin0 + .int32 139 + .int32 38 + .asciz "fib" + .int32 0 +.LpubNames_end0: + .section .debug_pubtypes,"",@progbits + .int32 .LpubTypes_end0-.LpubTypes_begin0 +.LpubTypes_begin0: + .int16 2 + .int32 .Lcu_begin0 + .int32 139 + .int32 131 + .asciz "int" + .int32 0 +.LpubTypes_end0: + + .ident "clang version 3.9.0 (trunk 266025)" + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/test/dot_s/debug.wast b/test/dot_s/debug.wast new file mode 100644 index 000000000..3a859fd0d --- /dev/null +++ b/test/dot_s/debug.wast @@ -0,0 +1,51 @@ +(module + (memory 1) + (export "memory" memory) + (export "fib" $fib) + (func $fib (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (set_local $3 + (i32.const 0) + ) + (set_local $2 + (i32.const -1) + ) + (set_local $4 + (i32.const 1) + ) + (loop $label$1 $label$0 + (set_local $2 + (i32.add + (get_local $2) + (i32.const 1) + ) + ) + (br_if $label$1 + (i32.ge_s + (get_local $2) + (get_local $0) + ) + ) + (set_local $1 + (i32.add + (get_local $4) + (get_local $3) + ) + ) + (set_local $3 + (get_local $4) + ) + (set_local $4 + (get_local $1) + ) + (br $label$0) + ) + (return + (get_local $4) + ) + ) +) +;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [] } |