From 84a34aa82fe5879fc6d072550827e2668bbab19f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Jan 2021 14:56:23 -0800 Subject: [PATCH 01/11] ndebug --- src/support/small_vector.h | 24 ++++++++++++++++++++++++ src/wasm-binary.h | 6 ++---- src/wasm.h | 21 ++++++++------------- src/wasm/wasm-binary.cpp | 18 ++++++++++++------ src/wasm/wasm-debug.cpp | 5 ++--- src/wasm/wasm-stack.cpp | 7 ++++--- 6 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/support/small_vector.h b/src/support/small_vector.h index 2e65eda419e..8ab10c05be9 100644 --- a/src/support/small_vector.h +++ b/src/support/small_vector.h @@ -181,6 +181,30 @@ template class SmallVector { ConstIterator end() const { return ConstIterator(this, size()); } }; +// A SmallVector for which some values may be read before they are written, and +// in that case they have the value zero. +template +struct ZeroInitSmallVector : public SmallVector { + T& operator[](size_t i) { + if (i >= this->size()) { + resize(i + 1); + } + return SmallVector::operator[](i); + } + + const T& operator[](size_t i) const { + return const_cast&>(*this)[i]; + } + + void resize(size_t newSize) { + auto oldSize = this->size(); + SmallVector::resize(newSize); + for (size_t i = oldSize; i < this->size(); i++) { + (*this)[i] = 0; + } + } +}; + } // namespace wasm #endif // wasm_support_small_vector_h diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ea18fdf67b8..70eed361919 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1171,9 +1171,7 @@ class WasmBinaryWriter { void writeDebugLocation(const Function::DebugLocation& loc); void writeDebugLocation(Expression* curr, Function* func); void writeDebugLocationEnd(Expression* curr, Function* func); - void writeExtraDebugLocation(Expression* curr, - Function* func, - BinaryLocations::DelimiterId id); + void writeExtraDebugLocation(Expression* curr, Function* func, size_t id); // helpers void writeInlineString(const char* name); @@ -1378,7 +1376,7 @@ class WasmBinaryBuilder { // Called when we parse a later part of a control flow structure, like "end" // or "else". - void continueControlFlow(BinaryLocations::DelimiterId id, BinaryLocation pos); + void continueControlFlow(size_t id, BinaryLocation pos); // set when we know code is unreachable in the sense of the wasm spec: we are // in a block and after an unreachable element. this helps parse stacky wasm diff --git a/src/wasm.h b/src/wasm.h index eeccd7be033..c07bc82c5ad 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1539,20 +1539,15 @@ struct BinaryLocations { // Track the extra delimiter positions that some instructions, in particular // control flow, have, like 'end' for loop and block. We keep these in a // separate map because they are rare and we optimize for the storage space - // for the common type of instruction which just needs a Span. We implement - // this as a simple array with one element at the moment (more elements may - // be necessary in the future). - // TODO: If we are sure we won't need more, make this a single value? - struct DelimiterLocations : public std::array { - DelimiterLocations() { - // Ensure zero-initialization. - for (auto& item : *this) { - item = 0; - } - } - }; + // for the common type of instruction which just needs a Span. + // For "else" (from an if) we use index 0, and for catch (from a try) we use + // indexes 0 and above. + // We use automatic zero-initialization here because that indicates a "null" + // debug value, indicating the information is not present. + using DelimiterLocations = ZeroInitSmallVector; + + enum DelimiterId : size_t { Else = 0, Invalid = size_t(-1) }; - enum DelimiterId { Else = 0, Catch = 0, Invalid = -1 }; std::unordered_map delimiters; // DWARF debug info can refer to multiple interesting positions in a function. diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 9b4794997b8..bdc9ff1b9a9 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -915,8 +915,9 @@ void WasmBinaryWriter::writeDebugLocationEnd(Expression* curr, Function* func) { } } -void WasmBinaryWriter::writeExtraDebugLocation( - Expression* curr, Function* func, BinaryLocations::DelimiterId id) { +void WasmBinaryWriter::writeExtraDebugLocation(Expression* curr, + Function* func, + size_t id) { if (func && !func->expressionLocations.empty()) { binaryLocations.delimiters[curr][id] = o.size(); } @@ -2830,10 +2831,16 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { curr = nullptr; continueControlFlow(BinaryLocations::Else, startPos); break; - case BinaryConsts::Catch: + case BinaryConsts::Catch: { curr = nullptr; - continueControlFlow(BinaryLocations::Catch, startPos); + // The new catch is appended at the end of the list of debug delimiters + // for this instruction. + auto currControlFlow = controlFlowStack.back(); + auto delimiterId = + currFunction->delimiterLocations[currControlFlow].size(); + continueControlFlow(delimiterId, startPos); break; + } case BinaryConsts::RefNull: visitRefNull((curr = allocator.alloc())->cast()); break; @@ -3062,8 +3069,7 @@ void WasmBinaryBuilder::startControlFlow(Expression* curr) { } } -void WasmBinaryBuilder::continueControlFlow(BinaryLocations::DelimiterId id, - BinaryLocation pos) { +void WasmBinaryBuilder::continueControlFlow(size_t id, BinaryLocation pos) { if (DWARF && currFunction) { assert(!controlFlowStack.empty()); auto currControlFlow = controlFlowStack.back(); diff --git a/src/wasm/wasm-debug.cpp b/src/wasm/wasm-debug.cpp index 52baaf24d9d..2c5ed95151f 100644 --- a/src/wasm/wasm-debug.cpp +++ b/src/wasm/wasm-debug.cpp @@ -361,7 +361,7 @@ struct AddrExprMap { // bloat the common case which is represented in the earlier maps. struct DelimiterInfo { Expression* expr; - BinaryLocations::DelimiterId id; + size_t id; }; std::unordered_map delimiterMap; @@ -414,8 +414,7 @@ struct AddrExprMap { for (Index i = 0; i < delimiter.size(); i++) { if (delimiter[i] != 0) { assert(delimiterMap.count(delimiter[i]) == 0); - delimiterMap[delimiter[i]] = - DelimiterInfo{expr, BinaryLocations::DelimiterId(i)}; + delimiterMap[delimiter[i]] = DelimiterInfo{expr, i}; } } } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index c96ceabb6c3..cd06cc1d713 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1863,9 +1863,8 @@ void BinaryInstWriter::emitCatch(Try* curr, Index i) { assert(!breakStack.empty()); breakStack.pop_back(); breakStack.emplace_back(IMPOSSIBLE_CONTINUE); - // TODO Fix handling of BinaryLocations for the new EH spec if (func && !sourceMap) { - parent.writeExtraDebugLocation(curr, func, BinaryLocations::Catch); + parent.writeExtraDebugLocation(curr, func, i); } o << int8_t(BinaryConsts::Catch) << U32LEB(parent.getEventIndex(curr->catchEvents[i])); @@ -1875,7 +1874,9 @@ void BinaryInstWriter::emitCatchAll(Try* curr) { assert(!breakStack.empty()); breakStack.pop_back(); breakStack.emplace_back(IMPOSSIBLE_CONTINUE); - // TODO Fix handling of BinaryLocations for the new EH spec + if (func && !sourceMap) { + parent.writeExtraDebugLocation(curr, func, curr->catchBodies.size()); + } o << int8_t(BinaryConsts::CatchAll); } From 49908430b97477cb5bb85a69e09f4475401fdb6b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Jan 2021 10:21:25 -0800 Subject: [PATCH 02/11] better --- src/wasm-binary.h | 4 ---- src/wasm/wasm-binary.cpp | 34 ++++++++++++++++------------------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 70eed361919..5ff50699d96 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1374,10 +1374,6 @@ class WasmBinaryBuilder { // Called when we parse the beginning of a control flow structure. void startControlFlow(Expression* curr); - // Called when we parse a later part of a control flow structure, like "end" - // or "else". - void continueControlFlow(size_t id, BinaryLocation pos); - // set when we know code is unreachable in the sense of the wasm spec: we are // in a block and after an unreachable element. this helps parse stacky wasm // code, which can be unsuitable for our IR when unreachable. diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index bdc9ff1b9a9..21e221108f0 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2829,16 +2829,25 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { break; case BinaryConsts::Else: curr = nullptr; - continueControlFlow(BinaryLocations::Else, startPos); + if (DWARF && currFunction) { + assert(!controlFlowStack.empty()); + auto currControlFlow = controlFlowStack.back(); + currFunction->delimiterLocations[currControlFlow][BinaryLocations::Else] = + startPos - codeSectionLocation; + } break; case BinaryConsts::Catch: { curr = nullptr; - // The new catch is appended at the end of the list of debug delimiters - // for this instruction. - auto currControlFlow = controlFlowStack.back(); - auto delimiterId = - currFunction->delimiterLocations[currControlFlow].size(); - continueControlFlow(delimiterId, startPos); + if (DWARF && currFunction) { + assert(!controlFlowStack.empty()); + auto currControlFlow = controlFlowStack.back(); + // The new catch is appended at the end of the list of debug delimiters + // for this instruction. + auto delimiterId = + currFunction->delimiterLocations[currControlFlow].size(); + currFunction->delimiterLocations[currControlFlow][delimiterId] = + startPos - codeSectionLocation; + } break; } case BinaryConsts::RefNull: @@ -3069,17 +3078,6 @@ void WasmBinaryBuilder::startControlFlow(Expression* curr) { } } -void WasmBinaryBuilder::continueControlFlow(size_t id, BinaryLocation pos) { - if (DWARF && currFunction) { - assert(!controlFlowStack.empty()); - auto currControlFlow = controlFlowStack.back(); - // We are called after parsing the byte, so we need to subtract one to - // get its position. - currFunction->delimiterLocations[currControlFlow][id] = - pos - codeSectionLocation; - } -} - void WasmBinaryBuilder::pushBlockElements(Block* curr, Type type, size_t start) { From af57d4ea9e2d3d95f360b2a71de3621916e5a471 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Jan 2021 10:21:34 -0800 Subject: [PATCH 03/11] format --- src/wasm/wasm-binary.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 21e221108f0..b501cb73b8f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2832,7 +2832,8 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (DWARF && currFunction) { assert(!controlFlowStack.empty()); auto currControlFlow = controlFlowStack.back(); - currFunction->delimiterLocations[currControlFlow][BinaryLocations::Else] = + currFunction + ->delimiterLocations[currControlFlow][BinaryLocations::Else] = startPos - codeSectionLocation; } break; From a2112689235dfc038d62850e56080967c5e5ef0c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 19 Jan 2021 18:26:46 +0000 Subject: [PATCH 04/11] Update src/wasm/wasm-binary.cpp [ci skip] Co-authored-by: Heejin Ahn --- src/wasm/wasm-binary.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index b501cb73b8f..15fae74525f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2837,7 +2837,8 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { startPos - codeSectionLocation; } break; - case BinaryConsts::Catch: { + case BinaryConsts::Catch: + case BinaryConsts::CatchAll: { curr = nullptr; if (DWARF && currFunction) { assert(!controlFlowStack.empty()); From c1cc7544609c9efcd9efa1d59ae47c4577c5823a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 19 Jan 2021 10:48:39 -0800 Subject: [PATCH 05/11] finish test --- src/passes/Print.cpp | 17 + src/wasm/wasm-binary.cpp | 5 +- test/passes/dwarf_with_exceptions.bin.txt | 544 ++++++++++++++++++++++ test/passes/dwarf_with_exceptions.passes | 1 + test/passes/dwarf_with_exceptions.wasm | Bin 0 -> 1072 bytes 5 files changed, 565 insertions(+), 2 deletions(-) create mode 100644 test/passes/dwarf_with_exceptions.bin.txt create mode 100644 test/passes/dwarf_with_exceptions.passes create mode 100755 test/passes/dwarf_with_exceptions.wasm diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index b6da2986171..afdea42e5e4 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1890,6 +1890,21 @@ struct PrintSExpression : public OverriddenVisitor { } } + // Prints debug info for a delimiter in an expression. + void printDebugDelimiterLocation(Expression* curr, Index i) { + if (currFunction && debugInfo) { + auto iter = currFunction->delimiterLocations.find(curr); + if (iter != currFunction->delimiterLocations.end()) { + auto& locations = iter->second; + Colors::grey(o); + o << ";; code offset: 0x" << std::hex << locations[i] << std::dec + << '\n'; + restoreNormalColor(o); + doIndent(o, indent); + } + } + } + void visit(Expression* curr) { printDebugLocation(curr); OverriddenVisitor::visit(curr); @@ -2368,6 +2383,7 @@ struct PrintSExpression : public OverriddenVisitor { o << "\n"; for (size_t i = 0; i < curr->catchEvents.size(); i++) { doIndent(o, indent); + printDebugDelimiterLocation(curr, i); o << "(catch "; printName(curr->catchEvents[i], o); incIndent(); @@ -2377,6 +2393,7 @@ struct PrintSExpression : public OverriddenVisitor { } if (curr->hasCatchAll()) { doIndent(o, indent); + printDebugDelimiterLocation(curr, curr->catchEvents.size()); o << "(catch_all"; incIndent(); maybePrintImplicitBlock(curr->catchBodies.back(), true); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 15fae74525f..c98d0b13a97 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2837,8 +2837,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { startPos - codeSectionLocation; } break; - case BinaryConsts::Catch: - case BinaryConsts::CatchAll: { + case BinaryConsts::Catch: { + // TODO: add CatchAll, but the value of the constant is identical to Else + // case BinaryConsts::CatchAll: { curr = nullptr; if (DWARF && currFunction) { assert(!controlFlowStack.empty()); diff --git a/test/passes/dwarf_with_exceptions.bin.txt b/test/passes/dwarf_with_exceptions.bin.txt new file mode 100644 index 00000000000..9bf00fbb637 --- /dev/null +++ b/test/passes/dwarf_with_exceptions.bin.txt @@ -0,0 +1,544 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "foo" (func $foo)) + (import "env" "__cxa_begin_catch" (func $__cxa_begin_catch (param i32) (result i32))) + (import "env" "__cxa_end_catch" (func $__cxa_end_catch)) + (import "env" "_ZSt9terminatev" (func $std::terminate\28\29)) + (memory $0 2) + (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66560)) + (event $event$0 (attr 0) (param i32)) + (export "memory" (memory $0)) + (func $__wasm_call_ctors + ) + (func $test_debuginfo + (local $0 i32) + (local $1 i32) + ;; code offset: 0xe + (local.set $0 + ;; code offset: 0x8 + (global.get $global$0) + ) + ;; code offset: 0x10 + (try + (do + ;; code offset: 0x12 + (call $foo) + ) + ;; code offset: 0x18 + (catch $event$0 + ;; code offset: 0x1e + (local.set $1 + (pop i32) + ) + ;; code offset: 0x22 + (global.set $global$0 + ;; code offset: 0x20 + (local.get $0) + ) + ;; code offset: 0x30 + (drop + ;; code offset: 0x2a + (call $__cxa_begin_catch + ;; code offset: 0x28 + (local.get $1) + ) + ) + ;; code offset: 0x31 + (try + (do + ;; code offset: 0x33 + (call $foo) + ;; code offset: 0x3b + (global.set $global$0 + ;; code offset: 0x39 + (local.get $0) + ) + ) + ;; code offset: 0x41 + (catch_all + ;; code offset: 0x42 + (try + (do + ;; code offset: 0x44 + (call $__cxa_end_catch) + ) + ;; code offset: 0x63 + (catch $event$0 + ;; code offset: 0x50 + (local.set $1 + (pop i32) + ) + ;; code offset: 0x54 + (global.set $global$0 + ;; code offset: 0x52 + (local.get $0) + ) + ;; code offset: 0x5c + (call $__clang_call_terminate + ;; code offset: 0x5a + (local.get $1) + ) + ;; code offset: 0x62 + (unreachable) + ) + ;; code offset: 0x0 + (catch_all + ;; code offset: 0x64 + (call $std::terminate\28\29) + ;; code offset: 0x6a + (unreachable) + ) + ) + ;; code offset: 0x6c + (rethrow 0) + ) + ) + ;; code offset: 0x6f + (call $__cxa_end_catch) + ) + ) + ) + (func $__clang_call_terminate (param $0 i32) + ;; code offset: 0x81 + (drop + ;; code offset: 0x7b + (call $__cxa_begin_catch + ;; code offset: 0x79 + (local.get $0) + ) + ) + ;; code offset: 0x82 + (call $std::terminate\28\29) + ;; code offset: 0x88 + (unreachable) + ) + ;; custom section ".debug_info", size 63 + ;; custom section ".debug_abbrev", size 41 + ;; custom section ".debug_line", size 92 + ;; custom section ".debug_str", size 194 + ;; custom section "producers", size 137 +) +DWARF debug info +================ + +Contains section .debug_info (63 bytes) +Contains section .debug_abbrev (41 bytes) +Contains section .debug_line (92 bytes) +Contains section .debug_str (194 bytes) + +.debug_abbrev contents: +Abbrev table for offset: 0x00000000 +[1] DW_TAG_compile_unit DW_CHILDREN_yes + DW_AT_producer DW_FORM_strp + DW_AT_language DW_FORM_data2 + DW_AT_name DW_FORM_strp + DW_AT_stmt_list DW_FORM_sec_offset + DW_AT_comp_dir DW_FORM_strp + DW_AT_low_pc DW_FORM_addr + DW_AT_high_pc DW_FORM_data4 + +[2] DW_TAG_subprogram DW_CHILDREN_no + DW_AT_low_pc DW_FORM_addr + DW_AT_high_pc DW_FORM_data4 + DW_AT_frame_base DW_FORM_exprloc + DW_AT_linkage_name DW_FORM_strp + DW_AT_name DW_FORM_strp + DW_AT_decl_file DW_FORM_data1 + DW_AT_decl_line DW_FORM_data1 + DW_AT_external DW_FORM_flag_present + + +.debug_info contents: +0x00000000: Compile Unit: length = 0x0000003b version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000003f) + +0x0000000b: DW_TAG_compile_unit [1] * + DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = "clang version 12.0.0 (https://github.com/aheejin/llvm-project e74a5010a507b737fcbd40e87cde358f2c9fc812)") + DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus_14) + DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000068] = "test.cpp") + DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) + DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000071] = "/usr/local/google/home/aheejin/llvm-git/llvm/tw") + DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) + DW_AT_high_pc [DW_FORM_data4] (0x00000072) + +0x00000026: DW_TAG_subprogram [2] + DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) + DW_AT_high_pc [DW_FORM_data4] (0x00000072) + DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x0 +0, DW_OP_stack_value) + DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000a1] = "test_debuginfo") + DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000b0] = "test_terminatepad") + DW_AT_decl_file [DW_FORM_data1] ("/usr/local/google/home/aheejin/llvm-git/llvm/tw/test.cpp") + DW_AT_decl_line [DW_FORM_data1] (2) + DW_AT_external [DW_FORM_flag_present] (true) + +0x0000003e: NULL + +.debug_line contents: +debug_line[0x00000000] +Line table prologue: + total_length: 0x00000058 + version: 4 + prologue_length: 0x00000020 + min_inst_length: 1 +max_ops_per_inst: 1 + default_is_stmt: 1 + line_base: -5 + line_range: 14 + opcode_base: 13 +standard_opcode_lengths[DW_LNS_copy] = 0 +standard_opcode_lengths[DW_LNS_advance_pc] = 1 +standard_opcode_lengths[DW_LNS_advance_line] = 1 +standard_opcode_lengths[DW_LNS_set_file] = 1 +standard_opcode_lengths[DW_LNS_set_column] = 1 +standard_opcode_lengths[DW_LNS_negate_stmt] = 0 +standard_opcode_lengths[DW_LNS_set_basic_block] = 0 +standard_opcode_lengths[DW_LNS_const_add_pc] = 0 +standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1 +standard_opcode_lengths[DW_LNS_set_prologue_end] = 0 +standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 +standard_opcode_lengths[DW_LNS_set_isa] = 1 +file_names[ 1]: + name: "test.cpp" + dir_index: 0 + mod_time: 0x00000000 + length: 0x00000000 +0x0000002a: 00 DW_LNE_set_address (0x0000000000000005) +0x00000031: 13 address += 0, line += 1 + 0x0000000000000005 2 0 1 0 0 is_stmt + +0x00000032: 05 DW_LNS_set_column (5) +0x00000034: 0a DW_LNS_set_prologue_end +0x00000035: ae address += 11, line += 2 + 0x0000000000000010 4 5 1 0 0 is_stmt prologue_end + +0x00000036: 05 DW_LNS_set_column (3) +0x00000038: 83 address += 8, line += 1 + 0x0000000000000018 5 3 1 0 0 is_stmt + +0x00000039: 05 DW_LNS_set_column (5) +0x0000003b: 08 DW_LNS_const_add_pc (0x0000000000000011) +0x0000003c: 83 address += 8, line += 1 + 0x0000000000000031 6 5 1 0 0 is_stmt + +0x0000003d: 06 DW_LNS_negate_stmt +0x0000003e: 03 DW_LNS_advance_line (0) +0x00000040: 82 address += 8, line += 0 + 0x0000000000000039 0 5 1 0 0 + +0x00000041: 05 DW_LNS_set_column (3) +0x00000043: 06 DW_LNS_negate_stmt +0x00000044: 89 address += 8, line += 7 + 0x0000000000000041 7 3 1 0 0 is_stmt + +0x00000045: 06 DW_LNS_negate_stmt +0x00000046: 03 DW_LNS_advance_line (0) +0x00000048: 02 DW_LNS_advance_pc (42) +0x0000004a: 01 DW_LNS_copy + 0x000000000000006b 0 3 1 0 0 + + +0x0000004b: 27 address += 1, line += 7 + 0x000000000000006c 7 3 1 0 0 + +0x0000004c: 03 DW_LNS_advance_line (0) +0x0000004e: 2e address += 2, line += 0 + 0x000000000000006e 0 3 1 0 0 + +0x0000004f: 27 address += 1, line += 7 + 0x000000000000006f 7 3 1 0 0 + +0x00000050: 03 DW_LNS_advance_line (0) +0x00000052: 66 address += 6, line += 0 + 0x0000000000000075 0 3 1 0 0 + +0x00000053: 05 DW_LNS_set_column (1) +0x00000055: 06 DW_LNS_negate_stmt +0x00000056: 28 address += 1, line += 8 + 0x0000000000000076 8 1 1 0 0 is_stmt + +0x00000057: 02 DW_LNS_advance_pc (1) +0x00000059: 00 DW_LNE_end_sequence + 0x0000000000000077 8 1 1 0 0 is_stmt end_sequence + + +.debug_str contents: +0x00000000: "clang version 12.0.0 (https://github.com/aheejin/llvm-project e74a5010a507b737fcbd40e87cde358f2c9fc812)" +0x00000068: "test.cpp" +0x00000071: "/usr/local/google/home/aheejin/llvm-git/llvm/tw" +0x000000a1: "test_debuginfo" +0x000000b0: "test_terminatepad" +DWARF debug info +================ + +Contains section .debug_info (63 bytes) +Contains section .debug_abbrev (41 bytes) +Contains section .debug_line (145 bytes) +Contains section .debug_str (194 bytes) + +.debug_abbrev contents: +Abbrev table for offset: 0x00000000 +[1] DW_TAG_compile_unit DW_CHILDREN_yes + DW_AT_producer DW_FORM_strp + DW_AT_language DW_FORM_data2 + DW_AT_name DW_FORM_strp + DW_AT_stmt_list DW_FORM_sec_offset + DW_AT_comp_dir DW_FORM_strp + DW_AT_low_pc DW_FORM_addr + DW_AT_high_pc DW_FORM_data4 + +[2] DW_TAG_subprogram DW_CHILDREN_no + DW_AT_low_pc DW_FORM_addr + DW_AT_high_pc DW_FORM_data4 + DW_AT_frame_base DW_FORM_exprloc + DW_AT_linkage_name DW_FORM_strp + DW_AT_name DW_FORM_strp + DW_AT_decl_file DW_FORM_data1 + DW_AT_decl_line DW_FORM_data1 + DW_AT_external DW_FORM_flag_present + + +.debug_info contents: +0x00000000: Compile Unit: length = 0x0000003b version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000003f) + +0x0000000b: DW_TAG_compile_unit [1] * + DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = "clang version 12.0.0 (https://github.com/aheejin/llvm-project e74a5010a507b737fcbd40e87cde358f2c9fc812)") + DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus_14) + DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000068] = "test.cpp") + DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) + DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000071] = "/usr/local/google/home/aheejin/llvm-git/llvm/tw") + DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) + DW_AT_high_pc [DW_FORM_data4] (0x00000040) + +0x00000026: DW_TAG_subprogram [2] + DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) + DW_AT_high_pc [DW_FORM_data4] (0x00000040) + DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x0 +0, DW_OP_stack_value) + DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x000000a1] = "test_debuginfo") + DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000b0] = "test_terminatepad") + DW_AT_decl_file [DW_FORM_data1] ("/usr/local/google/home/aheejin/llvm-git/llvm/tw/test.cpp") + DW_AT_decl_line [DW_FORM_data1] (2) + DW_AT_external [DW_FORM_flag_present] (true) + +0x0000003e: NULL + +.debug_line contents: +debug_line[0x00000000] +Line table prologue: + total_length: 0x0000008d + version: 4 + prologue_length: 0x00000020 + min_inst_length: 1 +max_ops_per_inst: 1 + default_is_stmt: 1 + line_base: -5 + line_range: 14 + opcode_base: 13 +standard_opcode_lengths[DW_LNS_copy] = 0 +standard_opcode_lengths[DW_LNS_advance_pc] = 1 +standard_opcode_lengths[DW_LNS_advance_line] = 1 +standard_opcode_lengths[DW_LNS_set_file] = 1 +standard_opcode_lengths[DW_LNS_set_column] = 1 +standard_opcode_lengths[DW_LNS_negate_stmt] = 0 +standard_opcode_lengths[DW_LNS_set_basic_block] = 0 +standard_opcode_lengths[DW_LNS_const_add_pc] = 0 +standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1 +standard_opcode_lengths[DW_LNS_set_prologue_end] = 0 +standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 +standard_opcode_lengths[DW_LNS_set_isa] = 1 +file_names[ 1]: + name: "test.cpp" + dir_index: 0 + mod_time: 0x00000000 + length: 0x00000000 +0x0000002a: 00 DW_LNE_set_address (0x0000000000000005) +0x00000031: 03 DW_LNS_advance_line (2) +0x00000033: 01 DW_LNS_copy + 0x0000000000000005 2 0 1 0 0 is_stmt + + +0x00000034: 00 DW_LNE_set_address (0x000000000000000e) +0x0000003b: 03 DW_LNS_advance_line (4) +0x0000003d: 05 DW_LNS_set_column (5) +0x0000003f: 0a DW_LNS_set_prologue_end +0x00000040: 01 DW_LNS_copy + 0x000000000000000e 4 5 1 0 0 is_stmt prologue_end + + +0x00000041: 00 DW_LNE_set_address (0x0000000000000012) +0x00000048: 03 DW_LNS_advance_line (5) +0x0000004a: 05 DW_LNS_set_column (3) +0x0000004c: 01 DW_LNS_copy + 0x0000000000000012 5 3 1 0 0 is_stmt + + +0x0000004d: 00 DW_LNE_set_address (0x000000000000001f) +0x00000054: 03 DW_LNS_advance_line (6) +0x00000056: 05 DW_LNS_set_column (5) +0x00000058: 01 DW_LNS_copy + 0x000000000000001f 6 5 1 0 0 is_stmt + + +0x00000059: 00 DW_LNE_set_address (0x000000000000003e) +0x00000060: 03 DW_LNS_advance_line (7) +0x00000062: 05 DW_LNS_set_column (3) +0x00000064: 06 DW_LNS_negate_stmt +0x00000065: 01 DW_LNS_copy + 0x000000000000003e 7 3 1 0 0 + + +0x00000066: 00 DW_LNE_set_address (0x0000000000000041) +0x0000006d: 01 DW_LNS_copy + 0x0000000000000041 7 3 1 0 0 + + +0x0000006e: 00 DW_LNE_set_address (0x0000000000000044) +0x00000075: 03 DW_LNS_advance_line (8) +0x00000077: 05 DW_LNS_set_column (1) +0x00000079: 06 DW_LNS_negate_stmt +0x0000007a: 01 DW_LNS_copy + 0x0000000000000044 8 1 1 0 0 is_stmt + + +0x0000007b: 00 DW_LNE_set_address (0x0000000000000045) +0x00000082: 01 DW_LNS_copy + 0x0000000000000045 8 1 1 0 0 is_stmt + + +0x00000083: 00 DW_LNE_set_address (0x00000000ffffff61) +0x0000008a: 03 DW_LNS_advance_line (7) +0x0000008c: 05 DW_LNS_set_column (3) +0x0000008e: 00 DW_LNE_end_sequence + 0x00000000ffffff61 7 3 1 0 0 is_stmt end_sequence + + +.debug_str contents: +0x00000000: "clang version 12.0.0 (https://github.com/aheejin/llvm-project e74a5010a507b737fcbd40e87cde358f2c9fc812)" +0x00000068: "test.cpp" +0x00000071: "/usr/local/google/home/aheejin/llvm-git/llvm/tw" +0x000000a1: "test_debuginfo" +0x000000b0: "test_terminatepad" +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "foo" (func $foo)) + (import "env" "__cxa_begin_catch" (func $__cxa_begin_catch (param i32) (result i32))) + (import "env" "__cxa_end_catch" (func $__cxa_end_catch)) + (import "env" "_ZSt9terminatev" (func $std::terminate\28\29)) + (memory $0 2) + (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66560)) + (event $event$0 (attr 0) (param i32)) + (export "memory" (memory $0)) + (func $__wasm_call_ctors + ) + (func $test_debuginfo + (local $0 i32) + (local $1 i32) + ;; code offset: 0xc + (local.set $0 + ;; code offset: 0xa + (global.get $global$0) + ) + ;; code offset: 0xe + (try + (do + ;; code offset: 0x10 + (call $foo) + ) + ;; code offset: 0x12 + (catch $event$0 + ;; code offset: 0x14 + (local.set $1 + (pop i32) + ) + ;; code offset: 0x18 + (global.set $global$0 + ;; code offset: 0x16 + (local.get $0) + ) + ;; code offset: 0x1e + (drop + ;; code offset: 0x1c + (call $__cxa_begin_catch + ;; code offset: 0x1a + (local.get $1) + ) + ) + ;; code offset: 0x1f + (try + (do + ;; code offset: 0x21 + (call $foo) + ;; code offset: 0x25 + (global.set $global$0 + ;; code offset: 0x23 + (local.get $0) + ) + ) + ;; code offset: 0x27 + (catch_all + ;; code offset: 0x28 + (try + (do + ;; code offset: 0x2a + (call $__cxa_end_catch) + ) + ;; code offset: 0x39 + (catch $event$0 + ;; code offset: 0x2e + (local.set $1 + (pop i32) + ) + ;; code offset: 0x32 + (global.set $global$0 + ;; code offset: 0x30 + (local.get $0) + ) + ;; code offset: 0x36 + (call $__clang_call_terminate + ;; code offset: 0x34 + (local.get $1) + ) + ;; code offset: 0x38 + (unreachable) + ) + ;; code offset: 0x0 + (catch_all + ;; code offset: 0x3a + (call $std::terminate\28\29) + ;; code offset: 0x3c + (unreachable) + ) + ) + ;; code offset: 0x3e + (rethrow 0) + ) + ) + ;; code offset: 0x41 + (call $__cxa_end_catch) + ) + ) + ) + (func $__clang_call_terminate (param $0 i32) + ;; code offset: 0x4b + (drop + ;; code offset: 0x49 + (call $__cxa_begin_catch + ;; code offset: 0x47 + (local.get $0) + ) + ) + ;; code offset: 0x4c + (call $std::terminate\28\29) + ;; code offset: 0x4e + (unreachable) + ) + ;; custom section ".debug_info", size 63 + ;; custom section ".debug_abbrev", size 41 + ;; custom section ".debug_line", size 145 + ;; custom section ".debug_str", size 194 + ;; custom section "producers", size 137 +) diff --git a/test/passes/dwarf_with_exceptions.passes b/test/passes/dwarf_with_exceptions.passes new file mode 100644 index 00000000000..a85a46b5ebd --- /dev/null +++ b/test/passes/dwarf_with_exceptions.passes @@ -0,0 +1 @@ +print_dwarfdump_roundtrip_dwarfdump_g diff --git a/test/passes/dwarf_with_exceptions.wasm b/test/passes/dwarf_with_exceptions.wasm new file mode 100755 index 0000000000000000000000000000000000000000..c5ab0000c2c724bc05c90e58069a081335e67b0e GIT binary patch literal 1072 zcmcIjOK;Oa5T5m`ZA_iCm3Ur)0MSwZJC$G9o3!CTODiGZ z$`3&N0mL8Sr|=87FzY0(cwAX&W@l%=`DQdb3vQV(0AP#iOMsW`m>rV><%yXmVdMk9@dGS>23M`UA>IxhYho%B3n$B{@n65HV z7Ns)gDdWSF_nJ9ZV@85WR*V&>ePpTvX2F!>TPL*OCK&sT%9@*;SrcwoR+BZ}O2qXU zV0NLC<5b@KBjTO(gWfo+c5?yD3Dh)~p$SvM*)2Ra+dg{3&>5sbwg&(j32E6jsw|Ql ztyd&ENkO8_4DAQN=P%^>M#2<;-r|(Z^}GT{Y>C~mR&>>BT)AN_v1Nl|+aQhotEr`0 zeRI!zaE)RinpF`GQhY`ZjY=g>#(r9ha+BqdFc4UZHqUc9)6%P2R&>4gRaeh+eg4c) zU!Ur#@xf5X$~|^h9k)pWof)eNBO>_DYSS7^QSjJJ!{!K!a*(CX?nb-Q?le~;A@Z_s z+u=Y&L$A%V#C9XZgF$M?@hEBKMRtH(G_kkkZg;vJQa!J?*$cSmZ*_2|$9>$~-U&AN zZoqfC8*3Lu+rzT3 Date: Tue, 19 Jan 2021 14:31:51 -0800 Subject: [PATCH 06/11] ifs too --- src/passes/Print.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index afdea42e5e4..f31687f1106 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2023,6 +2023,10 @@ struct PrintSExpression : public OverriddenVisitor { printFullLine(curr->condition); maybePrintImplicitBlock(curr->ifTrue, false); if (curr->ifFalse) { + // Note: debug info here is not used as LLVM does not emit ifs, and since + // LLVM is the main source of DWARF, effectively we never encounter ifs + // with DWARF. + printDebugDelimiterLocation(curr, BinaryLocations::Else); maybePrintImplicitBlock(curr->ifFalse, false); } decIndent(); From 40276eb1fbc980fde11d0d1e2512db0f892c2d60 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 22 Jan 2021 12:37:36 -0800 Subject: [PATCH 07/11] work --- src/wasm/wasm-binary.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index ece63de7747..96d68f9d551 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2837,27 +2837,23 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { } break; case BinaryConsts::Else: - curr = nullptr; - if (DWARF && currFunction) { - assert(!controlFlowStack.empty()); - auto currControlFlow = controlFlowStack.back(); - currFunction - ->delimiterLocations[currControlFlow][BinaryLocations::Else] = - startPos - codeSectionLocation; - } - break; case BinaryConsts::Catch: { - // TODO: add CatchAll, but the value of the constant is identical to Else - // case BinaryConsts::CatchAll: { curr = nullptr; if (DWARF && currFunction) { assert(!controlFlowStack.empty()); auto currControlFlow = controlFlowStack.back(); - // The new catch is appended at the end of the list of debug delimiters - // for this instruction. - auto delimiterId = - currFunction->delimiterLocations[currControlFlow].size(); - currFunction->delimiterLocations[currControlFlow][delimiterId] = + BinaryLocation delimiterId; + // Else and CatchAll have the same binary ID, so differentiate them + // using the control flow stack. + static_assert(BinaryConsts::CatchAll == BinaryConsts::Else); + if (currControlFlow->is()) { + delimiterId = BinaryLocations::Else; + } else { + delimiterId = + currFunction->delimiterLocations[currControlFlow].size(); + } + currFunction + ->delimiterLocations[currControlFlow][delimiterId] = startPos - codeSectionLocation; } break; From 3cfaf96906fc7d964be8b8baa55b51cae273cf3f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 22 Jan 2021 12:37:47 -0800 Subject: [PATCH 08/11] format --- src/wasm/wasm-binary.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 96d68f9d551..0cf11706f1f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2850,10 +2850,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { delimiterId = BinaryLocations::Else; } else { delimiterId = - currFunction->delimiterLocations[currControlFlow].size(); + currFunction->delimiterLocations[currControlFlow].size(); } - currFunction - ->delimiterLocations[currControlFlow][delimiterId] = + currFunction->delimiterLocations[currControlFlow][delimiterId] = startPos - codeSectionLocation; } break; From a9d679d676c0ff9b267eb6c4738f0156c9ef5bfb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 22 Jan 2021 12:39:06 -0800 Subject: [PATCH 09/11] comment --- src/wasm/wasm-binary.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 0cf11706f1f..1a42f6dde13 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2849,6 +2849,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (currControlFlow->is()) { delimiterId = BinaryLocations::Else; } else { + // Both Catch and CatchAll can simply append to the list as we go, as + // we visit them in the right order in the binary, and like the binary + // we store the CatchAll at the end. delimiterId = currFunction->delimiterLocations[currControlFlow].size(); } From 8b11e5f10de0979fdb2846c5abb2128c55cd4b6b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 22 Jan 2021 12:45:18 -0800 Subject: [PATCH 10/11] test update --- test/passes/dwarf_with_exceptions.bin.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/passes/dwarf_with_exceptions.bin.txt b/test/passes/dwarf_with_exceptions.bin.txt index 9bf00fbb637..324e1d44d57 100644 --- a/test/passes/dwarf_with_exceptions.bin.txt +++ b/test/passes/dwarf_with_exceptions.bin.txt @@ -65,7 +65,7 @@ ;; code offset: 0x44 (call $__cxa_end_catch) ) - ;; code offset: 0x63 + ;; code offset: 0x4a (catch $event$0 ;; code offset: 0x50 (local.set $1 @@ -84,7 +84,7 @@ ;; code offset: 0x62 (unreachable) ) - ;; code offset: 0x0 + ;; code offset: 0x63 (catch_all ;; code offset: 0x64 (call $std::terminate\28\29) @@ -486,7 +486,7 @@ file_names[ 1]: ;; code offset: 0x2a (call $__cxa_end_catch) ) - ;; code offset: 0x39 + ;; code offset: 0x2c (catch $event$0 ;; code offset: 0x2e (local.set $1 @@ -505,7 +505,7 @@ file_names[ 1]: ;; code offset: 0x38 (unreachable) ) - ;; code offset: 0x0 + ;; code offset: 0x39 (catch_all ;; code offset: 0x3a (call $std::terminate\28\29) From 279783463cb67416cb1cf68a392e79321585ea74 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 22 Jan 2021 13:17:14 -0800 Subject: [PATCH 11/11] fix --- src/wasm/wasm-binary.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 1a42f6dde13..bf71d3a4dfa 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2845,7 +2845,8 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { BinaryLocation delimiterId; // Else and CatchAll have the same binary ID, so differentiate them // using the control flow stack. - static_assert(BinaryConsts::CatchAll == BinaryConsts::Else); + static_assert(BinaryConsts::CatchAll == BinaryConsts::Else, + "Else and CatchAll should have identical codes"); if (currControlFlow->is()) { delimiterId = BinaryLocations::Else; } else {