[llvm] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead code (PR #141616)
Carlos Alberto Enciso via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 11 08:14:53 PDT 2025
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/141616
>From 4d1a2ebcefb7a1d5cdb032db95bcc96bd33038d4 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Tue, 27 May 2025 15:44:50 +0100
Subject: [PATCH 1/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
code
https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.
llvm-debuginfo-analyzer already uses the tombstone approach
to identify dead code. Currently, the tombstone value is
evaluated as std::numeric_limits<uint64_t>::max(). Which is
wrong as it does not take into account the 'Address Byte Size'
from the Compile Unit header.
---
.../llvm/DebugInfo/LogicalView/Core/LVRange.h | 9 +-
.../DebugInfo/LogicalView/Core/LVReader.h | 7 +
.../LogicalView/Readers/LVDWARFReader.cpp | 15 +-
.../WebAssembly/Inputs/test-clang-tombstone.s | 366 ++++++++++++++++++
.../WebAssembly/wasm-crash-tombstone.test | 44 +++
5 files changed, 434 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
create mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index 07d5813e5b19b..ecd5d524a195c 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -55,11 +55,14 @@ class LLVM_ABI LVRange final : public LVObject {
LVAllocator Allocator;
LVRangesTree RangesTree;
LVRangeEntries RangeEntries;
- LVAddress Lower = MaxAddress;
+ LVAddress TombstoneAddress;
+ LVAddress Lower;
LVAddress Upper = 0;
public:
- LVRange() : LVObject(), RangesTree(Allocator) {}
+ LVRange(LVAddress Address = MaxAddress)
+ : LVObject(),
+ RangesTree(Allocator), TombstoneAddress(Address), Lower(Address) {}
LVRange(const LVRange &) = delete;
LVRange &operator=(const LVRange &) = delete;
~LVRange() = default;
@@ -76,7 +79,7 @@ class LLVM_ABI LVRange final : public LVObject {
void clear() {
RangeEntries.clear();
- Lower = MaxAddress;
+ Lower = TombstoneAddress;
Upper = 0;
}
bool empty() const { return RangeEntries.empty(); }
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index 371bffb2ed163..a3140df627848 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -156,6 +156,10 @@ class LLVM_ABI LVReader {
LVAddress LowerAddress, LVAddress UpperAddress);
LVRange *getSectionRanges(LVSectionIndex SectionIndex);
+ // Tombstone value. Assume 64 bits. The value is updated for each
+ // Compile Unit that is processed.
+ LVAddress TombstoneAddress = MaxAddress;
+
// Record Compilation Unit entry.
void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
CompileUnits.emplace(Offset, CompileUnit);
@@ -282,6 +286,9 @@ class LLVM_ABI LVReader {
return CompileUnit->getCPUType();
}
+ void setTombstoneAddress(LVAddress Address) { TombstoneAddress = Address; }
+ LVAddress getTombstoneAddress() const { return TombstoneAddress; }
+
// Access to the scopes root.
LVScopeRoot *getScopesRoot() const { return Root; }
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
index 7ff96ae90a7fd..95b7007d119bc 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
@@ -214,10 +214,11 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
}
}
if (FoundLowPC) {
- if (CurrentLowPC == MaxAddress)
+ if (CurrentLowPC == getTombstoneAddress())
CurrentElement->setIsDiscarded();
- // Consider the case of WebAssembly.
- CurrentLowPC += WasmCodeSectionOffset;
+ else
+ // Consider the case of WebAssembly.
+ CurrentLowPC += WasmCodeSectionOffset;
if (CurrentElement->isCompileUnit())
setCUBaseAddress(CurrentLowPC);
}
@@ -271,7 +272,8 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
DWARFAddressRangesVector Ranges = RangesOrError.get();
for (DWARFAddressRange &Range : Ranges) {
// This seems to be a tombstone for empty ranges.
- if (Range.LowPC == Range.HighPC)
+ if ((Range.LowPC == Range.HighPC) ||
+ (Range.LowPC = getTombstoneAddress()))
continue;
// Store the real upper limit for the address range.
if (UpdateHighAddress && Range.HighPC > 0)
@@ -629,6 +631,11 @@ Error LVDWARFReader::createScopes() {
: DwarfContext->dwo_compile_units();
for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) {
+ // Take into account the address byte size for a correct 'tombstone'
+ // value identification.
+ setTombstoneAddress(
+ dwarf::computeTombstoneAddress(CU->getAddressByteSize()));
+
// Deduction of index used for the line records.
//
// For the following test case: test.cpp
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
new file mode 100644
index 0000000000000..f7e85420b89dd
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
@@ -0,0 +1,366 @@
+ .text
+ .file "test.cpp"
+ .globaltype __stack_pointer, i32
+ .functype _Z3fooPKijb (i32, i32, i32) -> (i32)
+ .section .text._Z3fooPKijb,"",@
+ .hidden _Z3fooPKijb # -- Begin function _Z3fooPKijb
+ .globl _Z3fooPKijb
+ .type _Z3fooPKijb, at function
+_Z3fooPKijb: # @_Z3fooPKijb
+.Lfunc_begin0:
+ .file 1 "/data/projects/scripts/regression-suite/input/general" "test.cpp"
+ .loc 1 2 0 # test.cpp:2:0
+ .functype _Z3fooPKijb (i32, i32, i32) -> (i32)
+ .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32
+# %bb.0: # %entry
+ global.get __stack_pointer
+ local.set 3
+ i32.const 32
+ local.set 4
+ local.get 3
+ local.get 4
+ i32.sub
+ local.set 5
+ local.get 5
+ local.get 0
+ i32.store 24
+ local.get 5
+ local.get 1
+ i32.store 20
+ local.get 2
+ local.set 6
+ local.get 5
+ local.get 6
+ i32.store8 19
+.Ltmp0:
+ .loc 1 3 7 prologue_end # test.cpp:3:7
+ local.get 5
+ i32.load8_u 19
+ local.set 7
+.Ltmp1:
+ .loc 1 3 7 is_stmt 0 # test.cpp:3:7
+ i32.const 1
+ local.set 8
+ local.get 7
+ local.get 8
+ i32.and
+ local.set 9
+ block
+ block
+ local.get 9
+ i32.eqz
+ br_if 0 # 0: down to label1
+# %bb.1: # %if.then
+.Ltmp2:
+ .loc 1 5 19 is_stmt 1 # test.cpp:5:19
+ i32.const 7
+ local.set 10
+ local.get 5
+ local.get 10
+ i32.store 12
+ .loc 1 6 5 # test.cpp:6:5
+ i32.const 7
+ local.set 11
+ local.get 5
+ local.get 11
+ i32.store 28
+ br 1 # 1: down to label0
+.Ltmp3:
+.LBB0_2: # %if.end
+ .loc 1 0 5 is_stmt 0 # test.cpp:0:5
+ end_block # label1:
+ .loc 1 8 10 is_stmt 1 # test.cpp:8:10
+ local.get 5
+ i32.load 20
+ local.set 12
+ .loc 1 8 3 is_stmt 0 # test.cpp:8:3
+ local.get 5
+ local.get 12
+ i32.store 28
+.LBB0_3: # %return
+ .loc 1 0 3 # test.cpp:0:3
+ end_block # label0:
+ .loc 1 9 1 is_stmt 1 # test.cpp:9:1
+ local.get 5
+ i32.load 28
+ local.set 13
+ local.get 13
+ return
+ end_function
+.Ltmp4:
+.Lfunc_end0:
+ # -- End function
+ .section .debug_abbrev,"",@
+ .int8 1 # Abbreviation Code
+ .int8 17 # DW_TAG_compile_unit
+ .int8 1 # DW_CHILDREN_yes
+ .int8 37 # DW_AT_producer
+ .int8 14 # DW_FORM_strp
+ .int8 19 # DW_AT_language
+ .int8 5 # DW_FORM_data2
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 16 # DW_AT_stmt_list
+ .int8 23 # DW_FORM_sec_offset
+ .int8 27 # DW_AT_comp_dir
+ .int8 14 # DW_FORM_strp
+ .int8 17 # DW_AT_low_pc
+ .int8 1 # DW_FORM_addr
+ .int8 18 # DW_AT_high_pc
+ .int8 6 # DW_FORM_data4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 2 # Abbreviation Code
+ .int8 46 # DW_TAG_subprogram
+ .int8 1 # DW_CHILDREN_yes
+ .int8 17 # DW_AT_low_pc
+ .int8 1 # DW_FORM_addr
+ .int8 18 # DW_AT_high_pc
+ .int8 6 # DW_FORM_data4
+ .int8 64 # DW_AT_frame_base
+ .int8 24 # DW_FORM_exprloc
+ .int8 110 # DW_AT_linkage_name
+ .int8 14 # DW_FORM_strp
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 63 # DW_AT_external
+ .int8 25 # DW_FORM_flag_present
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 3 # Abbreviation Code
+ .int8 5 # DW_TAG_formal_parameter
+ .int8 0 # DW_CHILDREN_no
+ .int8 2 # DW_AT_location
+ .int8 24 # DW_FORM_exprloc
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 4 # Abbreviation Code
+ .int8 11 # DW_TAG_lexical_block
+ .int8 1 # DW_CHILDREN_yes
+ .int8 17 # DW_AT_low_pc
+ .int8 1 # DW_FORM_addr
+ .int8 18 # DW_AT_high_pc
+ .int8 6 # DW_FORM_data4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 5 # Abbreviation Code
+ .int8 52 # DW_TAG_variable
+ .int8 0 # DW_CHILDREN_no
+ .int8 2 # DW_AT_location
+ .int8 24 # DW_FORM_exprloc
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 6 # Abbreviation Code
+ .int8 22 # DW_TAG_typedef
+ .int8 0 # DW_CHILDREN_no
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 7 # Abbreviation Code
+ .int8 36 # DW_TAG_base_type
+ .int8 0 # DW_CHILDREN_no
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 62 # DW_AT_encoding
+ .int8 11 # DW_FORM_data1
+ .int8 11 # DW_AT_byte_size
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 8 # Abbreviation Code
+ .int8 15 # DW_TAG_pointer_type
+ .int8 0 # DW_CHILDREN_no
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 9 # Abbreviation Code
+ .int8 38 # DW_TAG_const_type
+ .int8 0 # DW_CHILDREN_no
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 0 # EOM(3)
+ .section .debug_info,"",@
+.Lcu_begin0:
+ .int32 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .int16 4 # DWARF version number
+ .int32 .debug_abbrev0 # Offset Into Abbrev. Section
+ .int8 4 # Address Size (in bytes)
+ .int8 1 # Abbrev [1] 0xb:0xb5 DW_TAG_compile_unit
+ .int32 .Linfo_string0 # DW_AT_producer
+ .int16 33 # DW_AT_language
+ .int32 .Linfo_string1 # DW_AT_name
+ .int32 .Lline_table_start0 # DW_AT_stmt_list
+ .int32 .Linfo_string2 # DW_AT_comp_dir
+ .int32 .Lfunc_begin0 # DW_AT_low_pc
+ .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+ .int32 0xffffffff # DW_AT_low_pc
+ .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .int8 4 # DW_AT_frame_base
+ .int8 237
+ .int8 0
+ .int8 5
+ .int8 159
+ .int32 .Linfo_string3 # DW_AT_linkage_name
+ .int32 .Linfo_string4 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 2 # DW_AT_decl_line
+ .int32 144 # DW_AT_type
+ # DW_AT_external
+ .int8 3 # Abbrev [3] 0x42:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 24
+ .int32 .Linfo_string6 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 2 # DW_AT_decl_line
+ .int32 151 # DW_AT_type
+ .int8 3 # Abbrev [3] 0x50:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 20
+ .int32 .Linfo_string8 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 2 # DW_AT_decl_line
+ .int32 172 # DW_AT_type
+ .int8 3 # Abbrev [3] 0x5e:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 19
+ .int32 .Linfo_string10 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 2 # DW_AT_decl_line
+ .int32 179 # DW_AT_type
+ .int8 4 # Abbrev [4] 0x6c:0x18 DW_TAG_lexical_block
+ .int32 .Ltmp2 # DW_AT_low_pc
+ .int32 .Ltmp3-.Ltmp2 # DW_AT_high_pc
+ .int8 5 # Abbrev [5] 0x75:0xe DW_TAG_variable
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 12
+ .int32 .Linfo_string12 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 5 # DW_AT_decl_line
+ .int32 186 # DW_AT_type
+ .int8 0 # End Of Children Mark
+ .int8 6 # Abbrev [6] 0x84:0xb DW_TAG_typedef
+ .int32 144 # DW_AT_type
+ .int32 .Linfo_string13 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 4 # DW_AT_decl_line
+ .int8 0 # End Of Children Mark
+ .int8 7 # Abbrev [7] 0x90:0x7 DW_TAG_base_type
+ .int32 .Linfo_string5 # DW_AT_name
+ .int8 5 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 6 # Abbrev [6] 0x97:0xb DW_TAG_typedef
+ .int32 162 # DW_AT_type
+ .int32 .Linfo_string7 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 1 # DW_AT_decl_line
+ .int8 8 # Abbrev [8] 0xa2:0x5 DW_TAG_pointer_type
+ .int32 167 # DW_AT_type
+ .int8 9 # Abbrev [9] 0xa7:0x5 DW_TAG_const_type
+ .int32 144 # DW_AT_type
+ .int8 7 # Abbrev [7] 0xac:0x7 DW_TAG_base_type
+ .int32 .Linfo_string9 # DW_AT_name
+ .int8 7 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 7 # Abbrev [7] 0xb3:0x7 DW_TAG_base_type
+ .int32 .Linfo_string11 # DW_AT_name
+ .int8 2 # DW_AT_encoding
+ .int8 1 # DW_AT_byte_size
+ .int8 9 # Abbrev [9] 0xba:0x5 DW_TAG_const_type
+ .int32 132 # DW_AT_type
+ .int8 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str,"S",@
+.Linfo_string0:
+ .asciz "clang version 19.0.0" # string offset=0
+.Linfo_string1:
+ .asciz "test.cpp" # string offset=111
+.Linfo_string2:
+ .asciz "general" # string offset=120
+.Linfo_string3:
+ .asciz "_Z3fooPKijb" # string offset=174
+.Linfo_string4:
+ .asciz "foo" # string offset=186
+.Linfo_string5:
+ .asciz "int" # string offset=190
+.Linfo_string6:
+ .asciz "ParamPtr" # string offset=194
+.Linfo_string7:
+ .asciz "INTPTR" # string offset=203
+.Linfo_string8:
+ .asciz "ParamUnsigned" # string offset=210
+.Linfo_string9:
+ .asciz "unsigned int" # string offset=224
+.Linfo_string10:
+ .asciz "ParamBool" # string offset=237
+.Linfo_string11:
+ .asciz "bool" # string offset=247
+.Linfo_string12:
+ .asciz "CONSTANT" # string offset=252
+.Linfo_string13:
+ .asciz "INTEGER" # string offset=261
+ .ident "clang version 19.0.0"
+ .section .custom_section.producers,"",@
+ .int8 2
+ .int8 8
+ .ascii "language"
+ .int8 1
+ .int8 14
+ .ascii "C_plus_plus_14"
+ .int8 0
+ .int8 12
+ .ascii "processed-by"
+ .int8 1
+ .int8 5
+ .ascii "clang"
+ .int8 96
+ .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+ .section .debug_str,"S",@
+ .section .custom_section.target_features,"",@
+ .int8 2
+ .int8 43
+ .int8 15
+ .ascii "mutable-globals"
+ .int8 43
+ .int8 8
+ .ascii "sign-ext"
+ .section .debug_str,"S",@
+ .section .debug_line,"",@
+.Lline_table_start0:
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
new file mode 100644
index 0000000000000..35e152c878b8c
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
@@ -0,0 +1,44 @@
+; REQUIRES: x86-registered-target
+
+; llvm-debuginfo-analyzer crashes on dead code
+; https://github.com/llvm/llvm-project/issues/136772
+
+; For the attached reproducer:
+; llvm-dwarfdump out/lzma-lzmadec.wasm --all shows:
+;
+; 0x000002b3: DW_TAG_subprogram
+; DW_AT_low_pc (dead code)
+; DW_AT_high_pc (0x00000362)
+; DW_AT_frame_base (DW_OP_WASM_location 0x0 0x6, DW_OP_stack_value)
+;
+; llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
+;
+; crashes and shows a stack dump.
+;
+; The llvm-debuginfo-analyzer crashes when producing a logical view for
+; the object file generated using the following commands:
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/test-clang-tombstone.s \
+; RUN: -o %t.test-clang-tombstone.o
+
+; llvm-debuginfo-analyzer --select-elements=Discarde \
+; --print=elements \
+; %t.test-clang-tombstone.o 2>&1 | \
+; FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: {File} '{{.*}}test-clang-tombstone.o'
+; ONE-EMPTY:
+; ONE-NEXT: {CompileUnit} 'test.cpp'
+; ONE-NEXT: 2 {Function} extern not_inlined 'foo' -> 'int'
+
+; RUN: llvm-dwarfdump --debug-info %t.test-clang-tombstone.o | \
+; RUN: FileCheck %s --check-prefix=TWO
+
+; TWO: DW_TAG_subprogram
+; TWO-NEXT: DW_AT_low_pc (dead code)
+; TWO-NEXT: DW_AT_high_pc
+; TWO-NEXT: DW_AT_frame_base
+; TWO-NEXT: DW_AT_linkage_name
+; TWO-NEXT: DW_AT_name ("foo")
>From 036b1e60efc6dcf4b8e8c202613a130bbb31cb8b Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Tue, 27 May 2025 16:21:59 +0100
Subject: [PATCH 2/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
code
https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.
Fix clang-format issue.
---
llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index ecd5d524a195c..d77cea37c638d 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -61,8 +61,8 @@ class LLVM_ABI LVRange final : public LVObject {
public:
LVRange(LVAddress Address = MaxAddress)
- : LVObject(),
- RangesTree(Allocator), TombstoneAddress(Address), Lower(Address) {}
+ : LVObject(), RangesTree(Allocator), TombstoneAddress(Address),
+ Lower(Address) {}
LVRange(const LVRange &) = delete;
LVRange &operator=(const LVRange &) = delete;
~LVRange() = default;
>From ab09f83cd56d446f02563d35ca05376e8f3dba3f Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Fri, 30 May 2025 08:27:53 +0100
Subject: [PATCH 3/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
code
https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.
Address comments from reviewers:
- Combine test and .s file.
- Introduce the concept of a meta-tombstone value, to
be able to check for an invalid tombstone value.
---
.../DebugInfo/LogicalView/Core/LVObject.h | 10 +++
.../llvm/DebugInfo/LogicalView/Core/LVRange.h | 2 +-
.../DebugInfo/LogicalView/Core/LVReader.h | 10 +--
.../LogicalView/Readers/LVCodeViewReader.h | 10 ++-
...ang-tombstone.s => wasm-crash-tombstone.s} | 63 +++++++++++++++++++
.../WebAssembly/wasm-crash-tombstone.test | 44 -------------
6 files changed, 88 insertions(+), 51 deletions(-)
rename llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/{Inputs/test-clang-tombstone.s => wasm-crash-tombstone.s} (86%)
delete mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
index ec02120e69b73..3319a608803b9 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -84,7 +84,17 @@ using LVTypes = SmallVector<LVType *, 8>;
using LVOffsets = SmallVector<LVOffset, 8>;
+// The following DWARF documents detail the 'tombstone' concept:
+// https://dwarfstd.org/issues/231013.1.html
+// https://dwarfstd.org/issues/200609.1.html
+//
+// The value of the largest representable address offset (for example,
+// 0xffffffff when the size of an address is 32 bits).
+//
+// -1 (0xffffffff) => Valid tombstone
+// -2 (0xfffffffe) => Undefined tomstone
const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max();
+const LVAddress InvalidTombstone = MaxAddress - 1;
enum class LVBinaryType { NONE, ELF, COFF };
enum class LVComparePass { Missing, Added };
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index d77cea37c638d..afa7e2a7ae8bb 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -60,7 +60,7 @@ class LLVM_ABI LVRange final : public LVObject {
LVAddress Upper = 0;
public:
- LVRange(LVAddress Address = MaxAddress)
+ LVRange(LVAddress Address = InvalidTombstone)
: LVObject(), RangesTree(Allocator), TombstoneAddress(Address),
Lower(Address) {}
LVRange(const LVRange &) = delete;
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index a3140df627848..e97d8243fd521 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -156,9 +156,8 @@ class LLVM_ABI LVReader {
LVAddress LowerAddress, LVAddress UpperAddress);
LVRange *getSectionRanges(LVSectionIndex SectionIndex);
- // Tombstone value. Assume 64 bits. The value is updated for each
- // Compile Unit that is processed.
- LVAddress TombstoneAddress = MaxAddress;
+ // The value is updated for each Compile Unit that is processed.
+ LVAddress TombstoneAddress = InvalidTombstone;
// Record Compilation Unit entry.
void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
@@ -287,7 +286,10 @@ class LLVM_ABI LVReader {
}
void setTombstoneAddress(LVAddress Address) { TombstoneAddress = Address; }
- LVAddress getTombstoneAddress() const { return TombstoneAddress; }
+ LVAddress getTombstoneAddress() const {
+ assert(TombstoneAddress != InvalidTombstone && "Invalid tombstone value");
+ return TombstoneAddress;
+ }
// Access to the scopes root.
LVScopeRoot *getScopesRoot() const { return Root; }
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h
index 4dd7c967ddc17..612c6fc68f09c 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h
@@ -193,11 +193,17 @@ class LVCodeViewReader final : public LVBinaryReader {
llvm::object::COFFObjectFile &Obj, ScopedPrinter &W,
StringRef ExePath)
: LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
- Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
+ Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {
+ // CodeView does not have the concept of 'tombstone' address.
+ setTombstoneAddress(MaxAddress);
+ }
LVCodeViewReader(StringRef Filename, StringRef FileFormatName,
llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath)
: LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
- Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
+ Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {
+ // CodeView does not have the concept of 'tombstone' address.
+ setTombstoneAddress(MaxAddress);
+ }
LVCodeViewReader(const LVCodeViewReader &) = delete;
LVCodeViewReader &operator=(const LVCodeViewReader &) = delete;
~LVCodeViewReader() = default;
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
similarity index 86%
rename from llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
rename to llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
index f7e85420b89dd..92a5e023c9464 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
@@ -1,3 +1,66 @@
+# REQUIRES: x86-registered-target
+
+# llvm-debuginfo-analyzer crashes on dead code
+# https://github.com/llvm/llvm-project/issues/136772
+
+# For the attached reproducer:
+# llvm-dwarfdump out/lzma-lzmadec.wasm --all
+#
+# shows:
+#
+# 0x000002b3: DW_TAG_subprogram
+# DW_AT_low_pc (dead code)
+# DW_AT_high_pc (0x00000362)
+# DW_AT_frame_base (DW_OP_WASM_location 0x0 0x6, DW_OP_stack_value)
+
+# llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
+#
+# crashes and shows a stack dump:
+#
+# PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/
+# and include the crash backtrace.
+# Stack dump:
+# 0. Program arguments: llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
+
+# The test-clang-tombstone.s was produced by the following steps:
+# 1) clang --target=wasm32 -S -g Inputs/test-clang.cpp
+# -o Inputs/wasm-crash-tombstone.s
+# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram, from
+# .Lfunc_begin0 to 0xffffffff to mark the function as dead code:
+#
+# .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+# .int32 .Lfunc_begin0 # DW_AT_low_pc <---------
+# .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+
+# .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+# .int32 0xffffffff # DW_AT_low_pc <---------
+# .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+
+# RUN: llvm-mc -arch=wasm32 -filetype=obj \
+# RUN: %p/wasm-crash-tombstone.s \
+# RUN: -o %t.wasm-crash-tombstone.wasm
+
+# llvm-debuginfo-analyzer --select-elements=Discarde \
+# --print=elements \
+# %t.wasm-crash-tombstone.wasm 2>&1 | \
+# FileCheck --strict-whitespace -check-prefix=ONE %s
+
+# ONE: Logical View:
+# ONE-NEXT: {File} '{{.*}}wasm-crash-tombstone.wasm'
+# ONE-EMPTY:
+# ONE-NEXT: {CompileUnit} 'test.cpp'
+# ONE-NEXT: 2 {Function} extern not_inlined 'foo' -> 'int'
+
+# RUN: llvm-dwarfdump --debug-info %t.wasm-crash-tombstone.wasm | \
+# RUN: FileCheck %s --check-prefix=TWO
+
+# TWO: DW_TAG_subprogram
+# TWO-NEXT: DW_AT_low_pc (dead code)
+# TWO-NEXT: DW_AT_high_pc
+# TWO-NEXT: DW_AT_frame_base
+# TWO-NEXT: DW_AT_linkage_name
+# TWO-NEXT: DW_AT_name ("foo")
+
.text
.file "test.cpp"
.globaltype __stack_pointer, i32
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
deleted file mode 100644
index 35e152c878b8c..0000000000000
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
+++ /dev/null
@@ -1,44 +0,0 @@
-; REQUIRES: x86-registered-target
-
-; llvm-debuginfo-analyzer crashes on dead code
-; https://github.com/llvm/llvm-project/issues/136772
-
-; For the attached reproducer:
-; llvm-dwarfdump out/lzma-lzmadec.wasm --all shows:
-;
-; 0x000002b3: DW_TAG_subprogram
-; DW_AT_low_pc (dead code)
-; DW_AT_high_pc (0x00000362)
-; DW_AT_frame_base (DW_OP_WASM_location 0x0 0x6, DW_OP_stack_value)
-;
-; llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
-;
-; crashes and shows a stack dump.
-;
-; The llvm-debuginfo-analyzer crashes when producing a logical view for
-; the object file generated using the following commands:
-
-; RUN: llvm-mc -arch=wasm32 -filetype=obj \
-; RUN: %p/Inputs/test-clang-tombstone.s \
-; RUN: -o %t.test-clang-tombstone.o
-
-; llvm-debuginfo-analyzer --select-elements=Discarde \
-; --print=elements \
-; %t.test-clang-tombstone.o 2>&1 | \
-; FileCheck --strict-whitespace -check-prefix=ONE %s
-
-; ONE: Logical View:
-; ONE-NEXT: {File} '{{.*}}test-clang-tombstone.o'
-; ONE-EMPTY:
-; ONE-NEXT: {CompileUnit} 'test.cpp'
-; ONE-NEXT: 2 {Function} extern not_inlined 'foo' -> 'int'
-
-; RUN: llvm-dwarfdump --debug-info %t.test-clang-tombstone.o | \
-; RUN: FileCheck %s --check-prefix=TWO
-
-; TWO: DW_TAG_subprogram
-; TWO-NEXT: DW_AT_low_pc (dead code)
-; TWO-NEXT: DW_AT_high_pc
-; TWO-NEXT: DW_AT_frame_base
-; TWO-NEXT: DW_AT_linkage_name
-; TWO-NEXT: DW_AT_name ("foo")
>From a563faa2c89ec2b1132c24123b9dfa519473fbbf Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Fri, 30 May 2025 08:54:57 +0100
Subject: [PATCH 4/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
code
https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.
Minor comments change in test case.
---
.../WebAssembly/wasm-crash-tombstone.s | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
index 92a5e023c9464..50adaaa9cfec4 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
@@ -22,10 +22,11 @@
# Stack dump:
# 0. Program arguments: llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
-# The test-clang-tombstone.s was produced by the following steps:
+# The test case was produced by the following steps:
+#
# 1) clang --target=wasm32 -S -g Inputs/test-clang.cpp
# -o Inputs/wasm-crash-tombstone.s
-# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram, from
+# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram:
# .Lfunc_begin0 to 0xffffffff to mark the function as dead code:
#
# .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
>From a93d7f63f3f3afae39a86ffbaaf671ab06dc29d3 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Wed, 11 Jun 2025 15:57:44 +0100
Subject: [PATCH 5/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
code
https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.
Address reviewes comments:
- Reduce the test case.
- Use std::optional to illustrate the set/unset state.
- Rebase with main branch.
---
.../DebugInfo/LogicalView/Core/LVObject.h | 2 -
.../llvm/DebugInfo/LogicalView/Core/LVRange.h | 10 +-
.../DebugInfo/LogicalView/Core/LVReader.h | 6 +-
.../WebAssembly/wasm-crash-tombstone.s | 350 ++----------------
4 files changed, 30 insertions(+), 338 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
index 3319a608803b9..42a22039c870f 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -92,9 +92,7 @@ using LVOffsets = SmallVector<LVOffset, 8>;
// 0xffffffff when the size of an address is 32 bits).
//
// -1 (0xffffffff) => Valid tombstone
-// -2 (0xfffffffe) => Undefined tomstone
const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max();
-const LVAddress InvalidTombstone = MaxAddress - 1;
enum class LVBinaryType { NONE, ELF, COFF };
enum class LVComparePass { Missing, Added };
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index afa7e2a7ae8bb..ca3e89faf5e29 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -55,14 +55,14 @@ class LLVM_ABI LVRange final : public LVObject {
LVAllocator Allocator;
LVRangesTree RangesTree;
LVRangeEntries RangeEntries;
- LVAddress TombstoneAddress;
- LVAddress Lower;
+ std::optional<LVAddress> TombstoneAddress;
+ LVAddress Lower = 0;
LVAddress Upper = 0;
public:
- LVRange(LVAddress Address = InvalidTombstone)
+ LVRange(std::optional<LVAddress> Address = std::nullopt)
: LVObject(), RangesTree(Allocator), TombstoneAddress(Address),
- Lower(Address) {}
+ Lower(Address ? Address.value() : MaxAddress) {}
LVRange(const LVRange &) = delete;
LVRange &operator=(const LVRange &) = delete;
~LVRange() = default;
@@ -79,7 +79,7 @@ class LLVM_ABI LVRange final : public LVObject {
void clear() {
RangeEntries.clear();
- Lower = TombstoneAddress;
+ Lower = TombstoneAddress ? TombstoneAddress.value() : MaxAddress;
Upper = 0;
}
bool empty() const { return RangeEntries.empty(); }
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index e97d8243fd521..20261418791d3 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -157,7 +157,7 @@ class LLVM_ABI LVReader {
LVRange *getSectionRanges(LVSectionIndex SectionIndex);
// The value is updated for each Compile Unit that is processed.
- LVAddress TombstoneAddress = InvalidTombstone;
+ std::optional<LVAddress> TombstoneAddress;
// Record Compilation Unit entry.
void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
@@ -287,8 +287,8 @@ class LLVM_ABI LVReader {
void setTombstoneAddress(LVAddress Address) { TombstoneAddress = Address; }
LVAddress getTombstoneAddress() const {
- assert(TombstoneAddress != InvalidTombstone && "Invalid tombstone value");
- return TombstoneAddress;
+ assert(TombstoneAddress && "Unset tombstone value");
+ return TombstoneAddress.value();
}
// Access to the scopes root.
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
index 50adaaa9cfec4..7d833b841af99 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
@@ -24,16 +24,20 @@
# The test case was produced by the following steps:
#
-# 1) clang --target=wasm32 -S -g Inputs/test-clang.cpp
+# // test-clang.cpp
+# void foo() {
+# }
+#
+# 1) clang --target=wasm32 -S -g test-clang.cpp
# -o Inputs/wasm-crash-tombstone.s
# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram:
# .Lfunc_begin0 to 0xffffffff to mark the function as dead code:
#
-# .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+# .int8 2 # Abbrev [2] 0x26:0x1b DW_TAG_subprogram
# .int32 .Lfunc_begin0 # DW_AT_low_pc <---------
# .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
-# .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+# .int8 2 # Abbrev [2] 0x26:0x1b DW_TAG_subprogram
# .int32 0xffffffff # DW_AT_low_pc <---------
# .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
@@ -41,16 +45,16 @@
# RUN: %p/wasm-crash-tombstone.s \
# RUN: -o %t.wasm-crash-tombstone.wasm
-# llvm-debuginfo-analyzer --select-elements=Discarde \
-# --print=elements \
-# %t.wasm-crash-tombstone.wasm 2>&1 | \
-# FileCheck --strict-whitespace -check-prefix=ONE %s
+# RUN: llvm-debuginfo-analyzer --select-elements=Discarded \
+# RUN: --print=elements \
+# RUN: %t.wasm-crash-tombstone.wasm 2>&1 | \
+# RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
# ONE: Logical View:
# ONE-NEXT: {File} '{{.*}}wasm-crash-tombstone.wasm'
# ONE-EMPTY:
-# ONE-NEXT: {CompileUnit} 'test.cpp'
-# ONE-NEXT: 2 {Function} extern not_inlined 'foo' -> 'int'
+# ONE-NEXT: {CompileUnit} 'test-clang.cpp'
+# ONE-NEXT: {Function} not_inlined 'foo' -> 'void'
# RUN: llvm-dwarfdump --debug-info %t.wasm-crash-tombstone.wasm | \
# RUN: FileCheck %s --check-prefix=TWO
@@ -58,116 +62,25 @@
# TWO: DW_TAG_subprogram
# TWO-NEXT: DW_AT_low_pc (dead code)
# TWO-NEXT: DW_AT_high_pc
-# TWO-NEXT: DW_AT_frame_base
-# TWO-NEXT: DW_AT_linkage_name
# TWO-NEXT: DW_AT_name ("foo")
.text
- .file "test.cpp"
- .globaltype __stack_pointer, i32
- .functype _Z3fooPKijb (i32, i32, i32) -> (i32)
- .section .text._Z3fooPKijb,"",@
- .hidden _Z3fooPKijb # -- Begin function _Z3fooPKijb
- .globl _Z3fooPKijb
- .type _Z3fooPKijb, at function
-_Z3fooPKijb: # @_Z3fooPKijb
+ .file "test-clang.cpp"
+ .functype _Z3foov () -> ()
+ .section .text._Z3foov,"",@
+_Z3foov: # @_Z3foov
.Lfunc_begin0:
- .file 1 "/data/projects/scripts/regression-suite/input/general" "test.cpp"
- .loc 1 2 0 # test.cpp:2:0
- .functype _Z3fooPKijb (i32, i32, i32) -> (i32)
- .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32
-# %bb.0: # %entry
- global.get __stack_pointer
- local.set 3
- i32.const 32
- local.set 4
- local.get 3
- local.get 4
- i32.sub
- local.set 5
- local.get 5
- local.get 0
- i32.store 24
- local.get 5
- local.get 1
- i32.store 20
- local.get 2
- local.set 6
- local.get 5
- local.get 6
- i32.store8 19
-.Ltmp0:
- .loc 1 3 7 prologue_end # test.cpp:3:7
- local.get 5
- i32.load8_u 19
- local.set 7
-.Ltmp1:
- .loc 1 3 7 is_stmt 0 # test.cpp:3:7
- i32.const 1
- local.set 8
- local.get 7
- local.get 8
- i32.and
- local.set 9
- block
- block
- local.get 9
- i32.eqz
- br_if 0 # 0: down to label1
-# %bb.1: # %if.then
-.Ltmp2:
- .loc 1 5 19 is_stmt 1 # test.cpp:5:19
- i32.const 7
- local.set 10
- local.get 5
- local.get 10
- i32.store 12
- .loc 1 6 5 # test.cpp:6:5
- i32.const 7
- local.set 11
- local.get 5
- local.get 11
- i32.store 28
- br 1 # 1: down to label0
-.Ltmp3:
-.LBB0_2: # %if.end
- .loc 1 0 5 is_stmt 0 # test.cpp:0:5
- end_block # label1:
- .loc 1 8 10 is_stmt 1 # test.cpp:8:10
- local.get 5
- i32.load 20
- local.set 12
- .loc 1 8 3 is_stmt 0 # test.cpp:8:3
- local.get 5
- local.get 12
- i32.store 28
-.LBB0_3: # %return
- .loc 1 0 3 # test.cpp:0:3
- end_block # label0:
- .loc 1 9 1 is_stmt 1 # test.cpp:9:1
- local.get 5
- i32.load 28
- local.set 13
- local.get 13
+ .functype _Z3foov () -> ()
return
end_function
-.Ltmp4:
.Lfunc_end0:
# -- End function
.section .debug_abbrev,"",@
.int8 1 # Abbreviation Code
.int8 17 # DW_TAG_compile_unit
.int8 1 # DW_CHILDREN_yes
- .int8 37 # DW_AT_producer
- .int8 14 # DW_FORM_strp
- .int8 19 # DW_AT_language
- .int8 5 # DW_FORM_data2
.int8 3 # DW_AT_name
.int8 14 # DW_FORM_strp
- .int8 16 # DW_AT_stmt_list
- .int8 23 # DW_FORM_sec_offset
- .int8 27 # DW_AT_comp_dir
- .int8 14 # DW_FORM_strp
.int8 17 # DW_AT_low_pc
.int8 1 # DW_FORM_addr
.int8 18 # DW_AT_high_pc
@@ -176,102 +89,13 @@ _Z3fooPKijb: # @_Z3fooPKijb
.int8 0 # EOM(2)
.int8 2 # Abbreviation Code
.int8 46 # DW_TAG_subprogram
- .int8 1 # DW_CHILDREN_yes
- .int8 17 # DW_AT_low_pc
- .int8 1 # DW_FORM_addr
- .int8 18 # DW_AT_high_pc
- .int8 6 # DW_FORM_data4
- .int8 64 # DW_AT_frame_base
- .int8 24 # DW_FORM_exprloc
- .int8 110 # DW_AT_linkage_name
- .int8 14 # DW_FORM_strp
- .int8 3 # DW_AT_name
- .int8 14 # DW_FORM_strp
- .int8 58 # DW_AT_decl_file
- .int8 11 # DW_FORM_data1
- .int8 59 # DW_AT_decl_line
- .int8 11 # DW_FORM_data1
- .int8 73 # DW_AT_type
- .int8 19 # DW_FORM_ref4
- .int8 63 # DW_AT_external
- .int8 25 # DW_FORM_flag_present
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 3 # Abbreviation Code
- .int8 5 # DW_TAG_formal_parameter
.int8 0 # DW_CHILDREN_no
- .int8 2 # DW_AT_location
- .int8 24 # DW_FORM_exprloc
- .int8 3 # DW_AT_name
- .int8 14 # DW_FORM_strp
- .int8 58 # DW_AT_decl_file
- .int8 11 # DW_FORM_data1
- .int8 59 # DW_AT_decl_line
- .int8 11 # DW_FORM_data1
- .int8 73 # DW_AT_type
- .int8 19 # DW_FORM_ref4
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 4 # Abbreviation Code
- .int8 11 # DW_TAG_lexical_block
- .int8 1 # DW_CHILDREN_yes
.int8 17 # DW_AT_low_pc
.int8 1 # DW_FORM_addr
.int8 18 # DW_AT_high_pc
.int8 6 # DW_FORM_data4
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 5 # Abbreviation Code
- .int8 52 # DW_TAG_variable
- .int8 0 # DW_CHILDREN_no
- .int8 2 # DW_AT_location
- .int8 24 # DW_FORM_exprloc
.int8 3 # DW_AT_name
.int8 14 # DW_FORM_strp
- .int8 58 # DW_AT_decl_file
- .int8 11 # DW_FORM_data1
- .int8 59 # DW_AT_decl_line
- .int8 11 # DW_FORM_data1
- .int8 73 # DW_AT_type
- .int8 19 # DW_FORM_ref4
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 6 # Abbreviation Code
- .int8 22 # DW_TAG_typedef
- .int8 0 # DW_CHILDREN_no
- .int8 73 # DW_AT_type
- .int8 19 # DW_FORM_ref4
- .int8 3 # DW_AT_name
- .int8 14 # DW_FORM_strp
- .int8 58 # DW_AT_decl_file
- .int8 11 # DW_FORM_data1
- .int8 59 # DW_AT_decl_line
- .int8 11 # DW_FORM_data1
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 7 # Abbreviation Code
- .int8 36 # DW_TAG_base_type
- .int8 0 # DW_CHILDREN_no
- .int8 3 # DW_AT_name
- .int8 14 # DW_FORM_strp
- .int8 62 # DW_AT_encoding
- .int8 11 # DW_FORM_data1
- .int8 11 # DW_AT_byte_size
- .int8 11 # DW_FORM_data1
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 8 # Abbreviation Code
- .int8 15 # DW_TAG_pointer_type
- .int8 0 # DW_CHILDREN_no
- .int8 73 # DW_AT_type
- .int8 19 # DW_FORM_ref4
- .int8 0 # EOM(1)
- .int8 0 # EOM(2)
- .int8 9 # Abbreviation Code
- .int8 38 # DW_TAG_const_type
- .int8 0 # DW_CHILDREN_no
- .int8 73 # DW_AT_type
- .int8 19 # DW_FORM_ref4
.int8 0 # EOM(1)
.int8 0 # EOM(2)
.int8 0 # EOM(3)
@@ -282,149 +106,19 @@ _Z3fooPKijb: # @_Z3fooPKijb
.int16 4 # DWARF version number
.int32 .debug_abbrev0 # Offset Into Abbrev. Section
.int8 4 # Address Size (in bytes)
- .int8 1 # Abbrev [1] 0xb:0xb5 DW_TAG_compile_unit
- .int32 .Linfo_string0 # DW_AT_producer
- .int16 33 # DW_AT_language
+ .int8 1 # Abbrev [1] 0xb:0x37 DW_TAG_compile_unit
.int32 .Linfo_string1 # DW_AT_name
- .int32 .Lline_table_start0 # DW_AT_stmt_list
- .int32 .Linfo_string2 # DW_AT_comp_dir
.int32 .Lfunc_begin0 # DW_AT_low_pc
.int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+ .int8 2 # Abbrev [2] 0x26:0x1b DW_TAG_subprogram
.int32 0xffffffff # DW_AT_low_pc
.int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
- .int8 4 # DW_AT_frame_base
- .int8 237
- .int8 0
- .int8 5
- .int8 159
- .int32 .Linfo_string3 # DW_AT_linkage_name
.int32 .Linfo_string4 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 2 # DW_AT_decl_line
- .int32 144 # DW_AT_type
- # DW_AT_external
- .int8 3 # Abbrev [3] 0x42:0xe DW_TAG_formal_parameter
- .int8 2 # DW_AT_location
- .int8 145
- .int8 24
- .int32 .Linfo_string6 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 2 # DW_AT_decl_line
- .int32 151 # DW_AT_type
- .int8 3 # Abbrev [3] 0x50:0xe DW_TAG_formal_parameter
- .int8 2 # DW_AT_location
- .int8 145
- .int8 20
- .int32 .Linfo_string8 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 2 # DW_AT_decl_line
- .int32 172 # DW_AT_type
- .int8 3 # Abbrev [3] 0x5e:0xe DW_TAG_formal_parameter
- .int8 2 # DW_AT_location
- .int8 145
- .int8 19
- .int32 .Linfo_string10 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 2 # DW_AT_decl_line
- .int32 179 # DW_AT_type
- .int8 4 # Abbrev [4] 0x6c:0x18 DW_TAG_lexical_block
- .int32 .Ltmp2 # DW_AT_low_pc
- .int32 .Ltmp3-.Ltmp2 # DW_AT_high_pc
- .int8 5 # Abbrev [5] 0x75:0xe DW_TAG_variable
- .int8 2 # DW_AT_location
- .int8 145
- .int8 12
- .int32 .Linfo_string12 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 5 # DW_AT_decl_line
- .int32 186 # DW_AT_type
- .int8 0 # End Of Children Mark
- .int8 6 # Abbrev [6] 0x84:0xb DW_TAG_typedef
- .int32 144 # DW_AT_type
- .int32 .Linfo_string13 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 4 # DW_AT_decl_line
- .int8 0 # End Of Children Mark
- .int8 7 # Abbrev [7] 0x90:0x7 DW_TAG_base_type
- .int32 .Linfo_string5 # DW_AT_name
- .int8 5 # DW_AT_encoding
- .int8 4 # DW_AT_byte_size
- .int8 6 # Abbrev [6] 0x97:0xb DW_TAG_typedef
- .int32 162 # DW_AT_type
- .int32 .Linfo_string7 # DW_AT_name
- .int8 1 # DW_AT_decl_file
- .int8 1 # DW_AT_decl_line
- .int8 8 # Abbrev [8] 0xa2:0x5 DW_TAG_pointer_type
- .int32 167 # DW_AT_type
- .int8 9 # Abbrev [9] 0xa7:0x5 DW_TAG_const_type
- .int32 144 # DW_AT_type
- .int8 7 # Abbrev [7] 0xac:0x7 DW_TAG_base_type
- .int32 .Linfo_string9 # DW_AT_name
- .int8 7 # DW_AT_encoding
- .int8 4 # DW_AT_byte_size
- .int8 7 # Abbrev [7] 0xb3:0x7 DW_TAG_base_type
- .int32 .Linfo_string11 # DW_AT_name
- .int8 2 # DW_AT_encoding
- .int8 1 # DW_AT_byte_size
- .int8 9 # Abbrev [9] 0xba:0x5 DW_TAG_const_type
- .int32 132 # DW_AT_type
.int8 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_str,"S",@
-.Linfo_string0:
- .asciz "clang version 19.0.0" # string offset=0
.Linfo_string1:
- .asciz "test.cpp" # string offset=111
-.Linfo_string2:
- .asciz "general" # string offset=120
-.Linfo_string3:
- .asciz "_Z3fooPKijb" # string offset=174
+ .asciz "test-clang.cpp" # string offset=176
.Linfo_string4:
- .asciz "foo" # string offset=186
-.Linfo_string5:
- .asciz "int" # string offset=190
-.Linfo_string6:
- .asciz "ParamPtr" # string offset=194
-.Linfo_string7:
- .asciz "INTPTR" # string offset=203
-.Linfo_string8:
- .asciz "ParamUnsigned" # string offset=210
-.Linfo_string9:
- .asciz "unsigned int" # string offset=224
-.Linfo_string10:
- .asciz "ParamBool" # string offset=237
-.Linfo_string11:
- .asciz "bool" # string offset=247
-.Linfo_string12:
- .asciz "CONSTANT" # string offset=252
-.Linfo_string13:
- .asciz "INTEGER" # string offset=261
+ .asciz "foo" # string offset=241
.ident "clang version 19.0.0"
- .section .custom_section.producers,"",@
- .int8 2
- .int8 8
- .ascii "language"
- .int8 1
- .int8 14
- .ascii "C_plus_plus_14"
- .int8 0
- .int8 12
- .ascii "processed-by"
- .int8 1
- .int8 5
- .ascii "clang"
- .int8 96
- .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
- .section .debug_str,"S",@
- .section .custom_section.target_features,"",@
- .int8 2
- .int8 43
- .int8 15
- .ascii "mutable-globals"
- .int8 43
- .int8 8
- .ascii "sign-ext"
- .section .debug_str,"S",@
- .section .debug_line,"",@
-.Lline_table_start0:
More information about the llvm-commits
mailing list