summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Print.cpp21
-rw-r--r--src/support/small_vector.h24
-rw-r--r--src/wasm-binary.h8
-rw-r--r--src/wasm.h21
-rw-r--r--src/wasm/wasm-binary.cpp44
-rw-r--r--src/wasm/wasm-debug.cpp5
-rw-r--r--src/wasm/wasm-stack.cpp7
-rw-r--r--test/passes/dwarf_with_exceptions.bin.txt544
-rw-r--r--test/passes/dwarf_with_exceptions.passes1
-rwxr-xr-xtest/passes/dwarf_with_exceptions.wasmbin0 -> 1072 bytes
10 files changed, 630 insertions, 45 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 53049943a..7b35701d4 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1902,6 +1902,21 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
}
}
+ // 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<PrintSExpression>::visit(curr);
@@ -2020,6 +2035,10 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
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();
@@ -2380,6 +2399,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
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();
@@ -2389,6 +2409,7 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
}
if (curr->hasCatchAll()) {
doIndent(o, indent);
+ printDebugDelimiterLocation(curr, curr->catchEvents.size());
o << "(catch_all";
incIndent();
maybePrintImplicitBlock(curr->catchBodies.back(), true);
diff --git a/src/support/small_vector.h b/src/support/small_vector.h
index 2e65eda41..8ab10c05b 100644
--- a/src/support/small_vector.h
+++ b/src/support/small_vector.h
@@ -181,6 +181,30 @@ public:
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<typename T, size_t N>
+struct ZeroInitSmallVector : public SmallVector<T, N> {
+ T& operator[](size_t i) {
+ if (i >= this->size()) {
+ resize(i + 1);
+ }
+ return SmallVector<T, N>::operator[](i);
+ }
+
+ const T& operator[](size_t i) const {
+ return const_cast<ZeroInitSmallVector<T, N>&>(*this)[i];
+ }
+
+ void resize(size_t newSize) {
+ auto oldSize = this->size();
+ SmallVector<T, N>::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 8f4946786..a495300dc 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1177,9 +1177,7 @@ public:
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);
@@ -1406,10 +1404,6 @@ public:
// 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(BinaryLocations::DelimiterId 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.h b/src/wasm.h
index 0b7a09a3c..7090aeff1 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1530,20 +1530,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<BinaryLocation, 1> {
- 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<BinaryLocation, 1>;
+
+ enum DelimiterId : size_t { Else = 0, Invalid = size_t(-1) };
- enum DelimiterId { Else = 0, Catch = 0, Invalid = -1 };
std::unordered_map<Expression*, DelimiterLocations> 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 cc289e7ec..bf71d3a4d 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();
}
@@ -2836,13 +2837,30 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
}
break;
case BinaryConsts::Else:
+ case BinaryConsts::Catch: {
curr = nullptr;
- continueControlFlow(BinaryLocations::Else, startPos);
- break;
- case BinaryConsts::Catch:
- curr = nullptr;
- continueControlFlow(BinaryLocations::Catch, startPos);
+ if (DWARF && currFunction) {
+ assert(!controlFlowStack.empty());
+ auto currControlFlow = controlFlowStack.back();
+ BinaryLocation delimiterId;
+ // Else and CatchAll have the same binary ID, so differentiate them
+ // using the control flow stack.
+ static_assert(BinaryConsts::CatchAll == BinaryConsts::Else,
+ "Else and CatchAll should have identical codes");
+ if (currControlFlow->is<If>()) {
+ 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();
+ }
+ currFunction->delimiterLocations[currControlFlow][delimiterId] =
+ startPos - codeSectionLocation;
+ }
break;
+ }
case BinaryConsts::RefNull:
visitRefNull((curr = allocator.alloc<RefNull>())->cast<RefNull>());
break;
@@ -3102,18 +3120,6 @@ void WasmBinaryBuilder::startControlFlow(Expression* curr) {
}
}
-void WasmBinaryBuilder::continueControlFlow(BinaryLocations::DelimiterId 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) {
diff --git a/src/wasm/wasm-debug.cpp b/src/wasm/wasm-debug.cpp
index 52baaf24d..2c5ed9515 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<BinaryLocation, DelimiterInfo> delimiterMap;
@@ -414,8 +414,7 @@ private:
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 8a5726f1f..fae9da140 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1887,9 +1887,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]));
@@ -1899,7 +1898,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);
}
diff --git a/test/passes/dwarf_with_exceptions.bin.txt b/test/passes/dwarf_with_exceptions.bin.txt
new file mode 100644
index 000000000..324e1d44d
--- /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: 0x4a
+ (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: 0x63
+ (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: 0x2c
+ (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: 0x39
+ (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 000000000..a85a46b5e
--- /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 000000000..c5ab0000c
--- /dev/null
+++ b/test/passes/dwarf_with_exceptions.wasm
Binary files differ