[llvm] b19cfb9 - [llvm-debuginfo-analyzer] Add support for WebAssembly binary format. (#82588)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 14 03:03:22 PDT 2024
Author: Carlos Alberto Enciso
Date: 2024-03-14T10:03:18Z
New Revision: b19cfb9175223d3e1bb3ef6d49ccd26d0104906c
URL: https://github.com/llvm/llvm-project/commit/b19cfb9175223d3e1bb3ef6d49ccd26d0104906c
DIFF: https://github.com/llvm/llvm-project/commit/b19cfb9175223d3e1bb3ef6d49ccd26d0104906c.diff
LOG: [llvm-debuginfo-analyzer] Add support for WebAssembly binary format. (#82588)
Add support for the WebAssembly binary format and be able to generate
logical views.
https://github.com/llvm/llvm-project/issues/69181
The README.txt includes information about how to build the test cases.
Added:
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world.cpp
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860.cpp
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884.cpp
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466.cpp
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.s
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test.cpp
llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt
Modified:
llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h
llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
index a78066a5eea37e..00c070cedb479c 100644
--- a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
+++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst
@@ -16,7 +16,7 @@ DESCRIPTION
binary object files and prints their contents in a logical view, which
is a human readable representation that closely matches the structure
of the original user source code. Supported object file formats include
-ELF, Mach-O, PDB and COFF.
+ELF, Mach-O, WebAssembly, PDB and COFF.
The **logical view** abstracts the complexity associated with the
diff erent low-level representations of the debugging information that
@@ -468,8 +468,9 @@ If the <pattern> criteria is too general, a more selective option can
be specified to target a particular category of elements:
lines (:option:`--select-lines`), scopes (:option:`--select-scopes`),
symbols (:option:`--select-symbols`) and types (:option:`--select-types`).
+
These options require knowledge of the debug information format (DWARF,
-CodeView, COFF), as the given **kind** describes a very specific type
+CodeView), as the given **kind** describes a very specific type
of element.
LINES
@@ -598,7 +599,7 @@ When comparing logical views created from
diff erent debug formats, its
accuracy depends on how close the debug information represents the
user code. For instance, a logical view created from a binary file with
DWARF debug information may include more detailed data than a logical
-view created from a binary file with CodeView/COFF debug information.
+view created from a binary file with CodeView debug information.
The following options describe the elements to compare.
@@ -1952,6 +1953,315 @@ The **{Coverage}** and **{Location}** attributes describe the debug
location and coverage for logical symbols. For optimized code, the
coverage value decreases and it affects the program debuggability.
+WEBASSEMBLY SUPPORT
+~~~~~~~~~~~~~~~~~~~
+The below example is used to show the WebAssembly output generated by
+:program:`llvm-debuginfo-analyzer`. We compiled the example for a
+WebAssembly 32-bit target with Clang (-O0 -g --target=wasm32):
+
+.. code-block:: c++
+
+ 1 using INTPTR = const int *;
+ 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+ 3 if (ParamBool) {
+ 4 typedef int INTEGER;
+ 5 const INTEGER CONSTANT = 7;
+ 6 return CONSTANT;
+ 7 }
+ 8 return ParamUnsigned;
+ 9 }
+
+PRINT BASIC DETAILS
+^^^^^^^^^^^^^^^^^^^
+The following command prints basic details for all the logical elements
+sorted by the debug information internal offset; it includes its lexical
+level and debug info format.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level,format
+ --output-sort=offset
+ --print=scopes,symbols,types,lines,instructions
+ test-clang.wasm
+
+or
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level,format
+ --output-sort=offset
+ --print=elements
+ test-clang.wasm
+
+Each row represents an element that is present within the debug
+information. The first column represents the scope level, followed by
+the associated line number (if any), and finally the description of
+the element.
+
+.. code-block:: none
+
+ Logical View:
+ [000] {File} 'test-clang.wasm' -> WASM
+
+ [001] {CompileUnit} 'test.cpp'
+ [002] 2 {Function} extern not_inlined 'foo' -> 'int'
+ [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
+ [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
+ [003] 2 {Parameter} 'ParamBool' -> 'bool'
+ [003] {Block}
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+ [004] 5 {Line}
+ [004] {Code} 'i32.const 7'
+ [004] {Code} 'local.set 10'
+ [004] {Code} 'local.get 5'
+ [004] {Code} 'local.get 10'
+ [004] {Code} 'i32.store 12'
+ [004] 6 {Line}
+ [004] {Code} 'i32.const 7'
+ [004] {Code} 'local.set 11'
+ [004] {Code} 'local.get 5'
+ [004] {Code} 'local.get 11'
+ [004] {Code} 'i32.store 28'
+ [004] {Code} 'br 1'
+ [004] - {Line}
+ [004] {Code} 'end'
+ [003] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [003] 2 {Line}
+ [003] {Code} 'nop'
+ [003] {Code} 'end'
+ [003] {Code} 'i64.div_s'
+ [003] {Code} 'global.get 0'
+ [003] {Code} 'local.set 3'
+ [003] {Code} 'i32.const 32'
+ [003] {Code} 'local.set 4'
+ [003] {Code} 'local.get 3'
+ [003] {Code} 'local.get 4'
+ [003] {Code} 'i32.sub'
+ [003] {Code} 'local.set 5'
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 0'
+ [003] {Code} 'i32.store 24'
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 1'
+ [003] {Code} 'i32.store 20'
+ [003] {Code} 'local.get 2'
+ [003] {Code} 'local.set 6'
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 6'
+ [003] {Code} 'i32.store8 19'
+ [003] 3 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'i32.load8_u 19'
+ [003] {Code} 'local.set 7'
+ [003] 3 {Line}
+ [003] {Code} 'i32.const 1'
+ [003] {Code} 'local.set 8'
+ [003] {Code} 'local.get 7'
+ [003] {Code} 'local.get 8'
+ [003] {Code} 'i32.and'
+ [003] {Code} 'local.set 9'
+ [003] {Code} 'block'
+ [003] {Code} 'block'
+ [003] {Code} 'local.get 9'
+ [003] {Code} 'i32.eqz'
+ [003] {Code} 'br_if 0'
+ [003] 8 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'i32.load 20'
+ [003] {Code} 'local.set 12'
+ [003] 8 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'local.get 12'
+ [003] {Code} 'i32.store 28'
+ [003] - {Line}
+ [003] {Code} 'end'
+ [003] 9 {Line}
+ [003] {Code} 'local.get 5'
+ [003] {Code} 'i32.load 28'
+ [003] {Code} 'local.set 13'
+ [003] {Code} 'local.get 13'
+ [003] {Code} 'return'
+ [003] {Code} 'end'
+ [003] 9 {Line}
+ [003] {Code} 'unreachable'
+ [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
+
+SELECT LOGICAL ELEMENTS
+^^^^^^^^^^^^^^^^^^^^^^^
+The following prints all *instructions*, *symbols* and *types* that
+contain **'block'** or **'.store'** in their names or types, using a tab
+layout and given the number of matches.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --select-nocase --select-regex
+ --select=BLOCK --select=.store
+ --report=list
+ --print=symbols,types,instructions,summary
+ test-clang.wasm
+
+ Logical View:
+ [000] {File} 'test-clang.wasm'
+
+ [001] {CompileUnit} 'test.cpp'
+ [003] {Code} 'block'
+ [003] {Code} 'block'
+ [004] {Code} 'i32.store 12'
+ [003] {Code} 'i32.store 20'
+ [003] {Code} 'i32.store 24'
+ [004] {Code} 'i32.store 28'
+ [003] {Code} 'i32.store 28'
+ [003] {Code} 'i32.store8 19'
+
+ -----------------------------
+ Element Total Printed
+ -----------------------------
+ Scopes 3 0
+ Symbols 4 0
+ Types 2 0
+ Lines 62 8
+ -----------------------------
+ Total 71 8
+
+COMPARISON MODE
+^^^^^^^^^^^^^^^
+Given the previous example we found the above debug information issue
+(related to the previous invalid scope location for the **'typedef int
+INTEGER'**) by comparing against another compiler.
+
+Using GCC to generate test-dwarf-gcc.o, we can apply a selection pattern
+with the printing mode to obtain the following logical view output.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --select-regex --select-nocase --select=INTe
+ --report=list
+ --print=symbols,types
+ test-clang.wasm test-dwarf-gcc.o
+
+ Logical View:
+ [000] {File} 'test-clang.wasm'
+
+ [001] {CompileUnit} 'test.cpp'
+ [003] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+
+ Logical View:
+ [000] {File} 'test-dwarf-gcc.o'
+
+ [001] {CompileUnit} 'test.cpp'
+ [004] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+
+The output shows that both objects contain the same elements. But the
+**'typedef INTEGER'** is located at
diff erent scope level. The GCC
+generated object, shows **'4'**, which is the correct value.
+
+There are 2 comparison methods: logical view and logical elements.
+
+LOGICAL VIEW
+""""""""""""
+It compares the logical view as a whole unit; for a match, each compared
+logical element must have the same parents and children.
+
+The output shows in view form the **missing (-), added (+)** elements,
+giving more context by swapping the reference and target object files.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --compare=types
+ --report=view
+ --print=symbols,types
+ test-clang.wasm test-dwarf-gcc.o
+
+ Reference: 'test-clang.wasm'
+ Target: 'test-dwarf-gcc.o'
+
+ Logical View:
+ [000] {File} 'test-clang.wasm'
+
+ [001] {CompileUnit} 'test.cpp'
+ [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
+ [002] 2 {Function} extern not_inlined 'foo' -> 'int'
+ [003] {Block}
+ [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+ +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+ [003] 2 {Parameter} 'ParamBool' -> 'bool'
+ [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
+ [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
+ -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+The output shows the merging view path (reference and target) with the
+missing and added elements.
+
+LOGICAL ELEMENTS
+""""""""""""""""
+It compares individual logical elements without considering if their
+parents are the same. For both comparison methods, the equal criteria
+includes the name, source code location, type, lexical scope level.
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --compare=types
+ --report=list
+ --print=symbols,types,summary
+ test-clang.wasm test-dwarf-gcc.o
+
+ Reference: 'test-clang.wasm'
+ Target: 'test-dwarf-gcc.o'
+
+ (1) Missing Types:
+ -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ (1) Added Types:
+ +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ ----------------------------------------
+ Element Expected Missing Added
+ ----------------------------------------
+ Scopes 4 0 0
+ Symbols 0 0 0
+ Types 2 1 1
+ Lines 0 0 0
+ ----------------------------------------
+ Total 6 1 1
+
+Changing the *Reference* and *Target* order:
+
+.. code-block:: none
+
+ llvm-debuginfo-analyzer --attribute=level
+ --compare=types
+ --report=list
+ --print=symbols,types,summary
+ test-dwarf-gcc.o test-clang.wasm
+
+ Reference: 'test-dwarf-gcc.o'
+ Target: 'test-clang.wasm'
+
+ (1) Missing Types:
+ -[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ (1) Added Types:
+ +[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+ ----------------------------------------
+ Element Expected Missing Added
+ ----------------------------------------
+ Scopes 4 0 0
+ Symbols 0 0 0
+ Types 2 1 1
+ Lines 0 0 0
+ ----------------------------------------
+ Total 6 1 1
+
+As the *Reference* and *Target* are switched, the *Added Types* from
+the first case now are listed as *Missing Types*.
+
EXIT STATUS
-----------
:program:`llvm-debuginfo-analyzer` returns 0 if the input files were
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h
index a66cf4608823be..f76f2ecd3e2121 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h
@@ -122,6 +122,48 @@ class LVBinaryReader : public LVReader {
std::unique_ptr<MCContext> MC;
std::unique_ptr<MCInstPrinter> MIP;
+ // https://yurydelendik.github.io/webassembly-dwarf/
+ // 2. Consuming and Generating DWARF for WebAssembly Code
+ // Note: Some DWARF constructs don't map one-to-one onto WebAssembly
+ // constructs. We strive to enumerate and resolve any ambiguities here.
+ //
+ // 2.1. Code Addresses
+ // Note: DWARF associates various bits of debug info
+ // with particular locations in the program via its code address (instruction
+ // pointer or PC). However, WebAssembly's linear memory address space does not
+ // contain WebAssembly instructions.
+ //
+ // Wherever a code address (see 2.17 of [DWARF]) is used in DWARF for
+ // WebAssembly, it must be the offset of an instruction relative within the
+ // Code section of the WebAssembly file. The DWARF is considered malformed if
+ // a PC offset is between instruction boundaries within the Code section.
+ //
+ // Note: It is expected that a DWARF consumer does not know how to decode
+ // WebAssembly instructions. The instruction pointer is selected as the offset
+ // in the binary file of the first byte of the instruction, and it is
+ // consistent with the WebAssembly Web API conventions definition of the code
+ // location.
+ //
+ // EXAMPLE: .DEBUG_LINE INSTRUCTION POINTERS
+ // The .debug_line DWARF section maps instruction pointers to source
+ // locations. With WebAssembly, the .debug_line section maps Code
+ // section-relative instruction offsets to source locations.
+ //
+ // EXAMPLE: DW_AT_* ATTRIBUTES
+ // For entities with a single associated code address, DWARF uses
+ // the DW_AT_low_pc attribute to specify the associated code address value.
+ // For WebAssembly, the DW_AT_low_pc's value is a Code section-relative
+ // instruction offset.
+ //
+ // For entities with a single contiguous range of code, DWARF uses a
+ // pair of DW_AT_low_pc and DW_AT_high_pc attributes to specify the associated
+ // contiguous range of code address values. For WebAssembly, these attributes
+ // are Code section-relative instruction offsets.
+ //
+ // For entities with multiple ranges of code, DWARF uses the DW_AT_ranges
+ // attribute, which refers to the array located at the .debug_ranges section.
+ LVAddress WasmCodeSectionOffset = 0;
+
// Loads all info for the architecture of the provided object file.
Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures);
diff --git a/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp b/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
index 5f82f816dc19d5..16c4fbed1423fb 100644
--- a/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
@@ -48,7 +48,7 @@ Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers,
return std::make_unique<LVCodeViewReader>(Filename, FileFormatName,
*COFF, W, ExePath);
}
- if (Obj.isELF() || Obj.isMachO())
+ if (Obj.isELF() || Obj.isMachO() || Obj.isWasm())
return std::make_unique<LVELFReader>(Filename, FileFormatName, Obj, W);
}
if (isa<PDBFile *>(Input)) {
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
index a0cd8b7839cf7a..2d46414a6986ac 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
@@ -146,6 +146,30 @@ bool LVBinaryReader::getSymbolTableIsComdat(StringRef Name) {
void LVBinaryReader::mapVirtualAddress(const object::ObjectFile &Obj) {
for (const object::SectionRef &Section : Obj.sections()) {
+ LLVM_DEBUG({
+ Expected<StringRef> SectionNameOrErr = Section.getName();
+ StringRef Name;
+ if (!SectionNameOrErr)
+ consumeError(SectionNameOrErr.takeError());
+ else
+ Name = *SectionNameOrErr;
+ dbgs() << "Index: " << format_decimal(Section.getIndex(), 3) << ", "
+ << "Address: " << hexValue(Section.getAddress()) << ", "
+ << "Size: " << hexValue(Section.getSize()) << ", "
+ << "Name: " << Name << "\n";
+ dbgs() << "isCompressed: " << Section.isCompressed() << ", "
+ << "isText: " << Section.isText() << ", "
+ << "isData: " << Section.isData() << ", "
+ << "isBSS: " << Section.isBSS() << ", "
+ << "isVirtual: " << Section.isVirtual() << "\n";
+ dbgs() << "isBitcode: " << Section.isBitcode() << ", "
+ << "isStripped: " << Section.isStripped() << ", "
+ << "isBerkeleyText: " << Section.isBerkeleyText() << ", "
+ << "isBerkeleyData: " << Section.isBerkeleyData() << ", "
+ << "isDebugSection: " << Section.isDebugSection() << "\n";
+ dbgs() << "\n";
+ });
+
if (!Section.isText() || Section.isVirtual() || !Section.getSize())
continue;
@@ -161,8 +185,14 @@ void LVBinaryReader::mapVirtualAddress(const object::ObjectFile &Obj) {
continue;
}
if ((*SectionNameOrErr).equals(".text") ||
- (*SectionNameOrErr).equals(".code"))
+ (*SectionNameOrErr).equals("CODE") ||
+ (*SectionNameOrErr).equals(".code")) {
DotTextSectionIndex = Section.getIndex();
+ // If the object is WebAssembly, update the address offset that
+ // will be added to DWARF DW_AT_* attributes.
+ if (Obj.isWasm())
+ WasmCodeSectionOffset = Section.getAddress();
+ }
}
// Process the symbol table.
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp
index 4469092099daca..6bdcbc0ab641b0 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
//
// This implements the LVELFReader class.
-// It supports ELF and Mach-O formats.
+// It supports ELF, Mach-O and Wasm binary formats.
//
//===----------------------------------------------------------------------===//
@@ -415,6 +415,8 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr,
if (FoundLowPC) {
if (CurrentLowPC == MaxAddress)
CurrentElement->setIsDiscarded();
+ // Consider the case of WebAssembly.
+ CurrentLowPC += WasmCodeSectionOffset;
if (CurrentElement->isCompileUnit())
setCUBaseAddress(CurrentLowPC);
}
@@ -429,10 +431,17 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr,
CurrentHighPC = *Address;
if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant())
// High PC is an offset from LowPC.
- CurrentHighPC = CurrentLowPC + *Offset;
+ // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as
+ // the CurrentLowPC has already that offset added. Basically, use the
+ // original DW_AT_loc_pc value.
+ CurrentHighPC =
+ (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) +
+ *Offset;
// Store the real upper limit for the address range.
if (UpdateHighAddress && CurrentHighPC > 0)
--CurrentHighPC;
+ // Consider the case of WebAssembly.
+ CurrentHighPC += WasmCodeSectionOffset;
if (CurrentElement->isCompileUnit())
setCUHighAddress(CurrentHighPC);
}
@@ -466,6 +475,9 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr,
// Store the real upper limit for the address range.
if (UpdateHighAddress && Range.HighPC > 0)
--Range.HighPC;
+ // Consider the case of WebAssembly.
+ Range.LowPC += WasmCodeSectionOffset;
+ Range.HighPC += WasmCodeSectionOffset;
// Add the pair of addresses.
CurrentScope->addObject(Range.LowPC, Range.HighPC);
// If the scope is the CU, do not update the ranges set.
@@ -735,7 +747,8 @@ void LVELFReader::createLineAndFileRecords(
// and they will be released when its scope parent is deleted.
LVLineDebug *Line = createLineDebug();
CULines.push_back(Line);
- Line->setAddress(Row.Address.Address);
+ // Consider the case of WebAssembly.
+ Line->setAddress(Row.Address.Address + WasmCodeSectionOffset);
Line->setFilename(
CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File));
Line->setLineNumber(Row.Line);
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test
new file mode 100644
index 00000000000000..f52c9c7cc71641
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test
@@ -0,0 +1,106 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 1 - General options
+
+; test.cpp
+; 1 using INTPTR = const int *;
+; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+; 3 if (ParamBool) {
+; 4 typedef int INTEGER;
+; 5 const INTEGER CONSTANT = 7;
+; 6 return CONSTANT;
+; 7 }
+; 8 return ParamUnsigned;
+; 9 }
+
+; Compare mode - Logical view.
+; The output shows in view form the 'missing (-), added (+)' elements,
+; giving more context by swapping the reference and target object files.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level \
+; RUN: --compare=types \
+; RUN: --report=view \
+; RUN: --print=symbols,types \
+; RUN: %t.test-clang.o \
+; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Reference: '{{.*}}test-clang.o'
+; ONE-NEXT: Target: 'test-dwarf-gcc.o'
+; ONE-EMPTY:
+; ONE-NEXT: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}test-clang.o'
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'test.cpp'
+; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
+; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int'
+; ONE-NEXT: [003] {Block}
+; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+; ONE-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool'
+; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
+; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
+; ONE-NEXT: -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+
+; Compare mode - Logical elements.
+; The output shows in tabular form the 'missing (-), added (+)' elements,
+; giving more context by swapping the reference and target object files.
+
+; RUN: llvm-debuginfo-analyzer --attribute=level \
+; RUN: --compare=types \
+; RUN: --report=list \
+; RUN: --print=symbols,types,summary \
+; RUN: %t.test-clang.o \
+; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s
+
+; TWO: Reference: '{{.*}}test-clang.o'
+; TWO-NEXT: Target: 'test-dwarf-gcc.o'
+; TWO-EMPTY:
+; TWO-NEXT: (1) Missing Types:
+; TWO-NEXT: -[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+; TWO-EMPTY:
+; TWO-NEXT: (1) Added Types:
+; TWO-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+; TWO-EMPTY:
+; TWO-NEXT: ----------------------------------------
+; TWO-NEXT: Element Expected Missing Added
+; TWO-NEXT: ----------------------------------------
+; TWO-NEXT: Scopes 4 0 0
+; TWO-NEXT: Symbols 0 0 0
+; TWO-NEXT: Types 2 1 1
+; TWO-NEXT: Lines 0 0 0
+; TWO-NEXT: ----------------------------------------
+; TWO-NEXT: Total 6 1 1
+
+; Changing the 'Reference' and 'Target' order:
+
+; RUN: llvm-debuginfo-analyzer --attribute=level \
+; RUN: --compare=types \
+; RUN: --report=list \
+; RUN: --print=symbols,types,summary \
+; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o \
+; RUN: %t.test-clang.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=THR %s
+
+; THR: Reference: 'test-dwarf-gcc.o'
+; THR-NEXT: Target: '{{.*}}test-clang.o'
+; THR-EMPTY:
+; THR-NEXT: (1) Missing Types:
+; THR-NEXT: -[004] 4 {TypeAlias} 'INTEGER' -> 'int'
+; THR-EMPTY:
+; THR-NEXT: (1) Added Types:
+; THR-NEXT: +[003] 4 {TypeAlias} 'INTEGER' -> 'int'
+; THR-EMPTY:
+; THR-NEXT: ----------------------------------------
+; THR-NEXT: Element Expected Missing Added
+; THR-NEXT: ----------------------------------------
+; THR-NEXT: Scopes 4 0 0
+; THR-NEXT: Symbols 0 0 0
+; THR-NEXT: Types 2 1 1
+; THR-NEXT: Lines 0 0 0
+; THR-NEXT: ----------------------------------------
+; THR-NEXT: Total 6 1 1
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test
new file mode 100644
index 00000000000000..49270865633309
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test
@@ -0,0 +1,120 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 1 - General options.
+
+; test.cpp
+; 1 using INTPTR = const int *;
+; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+; 3 if (ParamBool) {
+; 4 typedef int INTEGER;
+; 5 const INTEGER CONSTANT = 7;
+; 6 return CONSTANT;
+; 7 }
+; 8 return ParamUnsigned;
+; 9 }
+
+; Print basic details.
+; The following command prints basic details for all the logical elements
+; sorted by the debug information internal offset; it includes its lexical
+; level and debug info format.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format \
+; RUN: --output-sort=offset \
+; RUN: --print=scopes,symbols,types,lines,instructions \
+; RUN: %t.test-clang.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format \
+; RUN: --output-sort=offset \
+; RUN: --print=elements \
+; RUN: %t.test-clang.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}test-clang.o' -> WASM
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'test.cpp'
+; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int'
+; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
+; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'
+; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool'
+; ONE-NEXT: [003] {Block}
+; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+; ONE-NEXT: [004] 5 {Line}
+; ONE-NEXT: [004] {Code} 'i32.const 7'
+; ONE-NEXT: [004] {Code} 'local.set 10'
+; ONE-NEXT: [004] {Code} 'local.get 5'
+; ONE-NEXT: [004] {Code} 'local.get 10'
+; ONE-NEXT: [004] {Code} 'i32.store 12'
+; ONE-NEXT: [004] 6 {Line}
+; ONE-NEXT: [004] {Code} 'i32.const 7'
+; ONE-NEXT: [004] {Code} 'local.set 11'
+; ONE-NEXT: [004] {Code} 'local.get 5'
+; ONE-NEXT: [004] {Code} 'local.get 11'
+; ONE-NEXT: [004] {Code} 'i32.store 28'
+; ONE-NEXT: [004] {Code} 'br 1'
+; ONE-NEXT: [004] - {Line}
+; ONE-NEXT: [004] {Code} 'end'
+; ONE-NEXT: [003] 4 {TypeAlias} 'INTEGER' -> 'int'
+; ONE-NEXT: [003] 2 {Line}
+; ONE-NEXT: [003] {Code} 'nop'
+; ONE-NEXT: [003] {Code} 'end'
+; ONE-NEXT: [003] {Code} 'i64.div_s'
+; ONE-NEXT: [003] {Code} 'global.get 0'
+; ONE-NEXT: [003] {Code} 'local.set 3'
+; ONE-NEXT: [003] {Code} 'i32.const 32'
+; ONE-NEXT: [003] {Code} 'local.set 4'
+; ONE-NEXT: [003] {Code} 'local.get 3'
+; ONE-NEXT: [003] {Code} 'local.get 4'
+; ONE-NEXT: [003] {Code} 'i32.sub'
+; ONE-NEXT: [003] {Code} 'local.set 5'
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'local.get 0'
+; ONE-NEXT: [003] {Code} 'i32.store 24'
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'local.get 1'
+; ONE-NEXT: [003] {Code} 'i32.store 20'
+; ONE-NEXT: [003] {Code} 'local.get 2'
+; ONE-NEXT: [003] {Code} 'local.set 6'
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'local.get 6'
+; ONE-NEXT: [003] {Code} 'i32.store8 19'
+; ONE-NEXT: [003] 3 {Line}
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'i32.load8_u 19'
+; ONE-NEXT: [003] {Code} 'local.set 7'
+; ONE-NEXT: [003] 3 {Line}
+; ONE-NEXT: [003] {Code} 'i32.const 1'
+; ONE-NEXT: [003] {Code} 'local.set 8'
+; ONE-NEXT: [003] {Code} 'local.get 7'
+; ONE-NEXT: [003] {Code} 'local.get 8'
+; ONE-NEXT: [003] {Code} 'i32.and'
+; ONE-NEXT: [003] {Code} 'local.set 9'
+; ONE-NEXT: [003] {Code} 'block'
+; ONE-NEXT: [003] {Code} 'block'
+; ONE-NEXT: [003] {Code} 'local.get 9'
+; ONE-NEXT: [003] {Code} 'i32.eqz'
+; ONE-NEXT: [003] {Code} 'br_if 0'
+; ONE-NEXT: [003] 8 {Line}
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'i32.load 20'
+; ONE-NEXT: [003] {Code} 'local.set 12'
+; ONE-NEXT: [003] 8 {Line}
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'local.get 12'
+; ONE-NEXT: [003] {Code} 'i32.store 28'
+; ONE-NEXT: [003] - {Line}
+; ONE-NEXT: [003] {Code} 'end'
+; ONE-NEXT: [003] 9 {Line}
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'i32.load 28'
+; ONE-NEXT: [003] {Code} 'local.set 13'
+; ONE-NEXT: [003] {Code} 'local.get 13'
+; ONE-NEXT: [003] {Code} 'return'
+; ONE-NEXT: [003] {Code} 'end'
+; ONE-NEXT: [003] 9 {Line}
+; ONE-NEXT: [003] {Code} 'unreachable'
+; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test
new file mode 100644
index 00000000000000..f50cc2d291a5b9
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test
@@ -0,0 +1,76 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 1 - General options
+
+; test.cpp
+; 1 using INTPTR = const int *;
+; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+; 3 if (ParamBool) {
+; 4 typedef int INTEGER;
+; 5 const INTEGER CONSTANT = 7;
+; 6 return CONSTANT;
+; 7 }
+; 8 return ParamUnsigned;
+; 9 }
+
+; Select logical elements.
+; The following prints all 'instructions', 'symbols' and 'types' that
+; contain 'BLOCK' or '.store' in their names or types, using a tab layout
+; and given the number of matches.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level \
+; RUN: --select-nocase --select-regex \
+; RUN: --select=BLOCK --select=.store \
+; RUN: --report=list \
+; RUN: --print=symbols,types,instructions,summary \
+; RUN: %t.test-clang.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}test-clang.o'
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'test.cpp'
+; ONE-NEXT: [003] {Code} 'block'
+; ONE-NEXT: [003] {Code} 'block'
+; ONE-NEXT: [004] {Code} 'i32.store 12'
+; ONE-NEXT: [003] {Code} 'i32.store 20'
+; ONE-NEXT: [003] {Code} 'i32.store 24'
+; ONE-NEXT: [004] {Code} 'i32.store 28'
+; ONE-NEXT: [003] {Code} 'i32.store 28'
+; ONE-NEXT: [003] {Code} 'i32.store8 19'
+; ONE-EMPTY:
+; ONE-NEXT: -----------------------------
+; ONE-NEXT: Element Total Printed
+; ONE-NEXT: -----------------------------
+; ONE-NEXT: Scopes 3 0
+; ONE-NEXT: Symbols 4 0
+; ONE-NEXT: Types 2 0
+; ONE-NEXT: Lines 62 8
+; ONE-NEXT: -----------------------------
+; ONE-NEXT: Total 71 8
+
+; RUN: llvm-debuginfo-analyzer --attribute=level \
+; RUN: --select-regex --select-nocase \
+; RUN: --select=INTe \
+; RUN: --report=list \
+; RUN: --print=symbols,types \
+; RUN: %t.test-clang.o \
+; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s
+
+; TWO: Logical View:
+; TWO-NEXT: [000] {File} '{{.*}}test-clang.o'
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'test.cpp'
+; TWO-NEXT: [003] 4 {TypeAlias} 'INTEGER' -> 'int'
+; TWO-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
+; TWO-EMPTY:
+; TWO-NEXT: Logical View:
+; TWO-NEXT: [000] {File} 'test-dwarf-gcc.o'
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'test.cpp'
+; TWO-NEXT: [004] 4 {TypeAlias} 'INTEGER' -> 'int'
+; TWO-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test
new file mode 100644
index 00000000000000..101f6abdc96b63
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test
@@ -0,0 +1,74 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 2 - Assembler instructions.
+
+; hello-world.cpp
+; 1 extern int printf(const char * format, ... );
+; 2
+; 3 int main()
+; 4 {
+; 5 printf("Hello, World\n");
+; 6 return 0;
+; 7 }
+
+; Logical lines.
+; The logical views shows the intermixed lines and assembler instructions,
+; allowing to compare the code generated by the
diff erent toolchains.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/hello-world-clang.s -o %t.hello-world-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \
+; RUN: --print=lines,instructions \
+; RUN: %t.hello-world-clang.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}hello-world-clang.o' -> WASM
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'hello-world.cpp'
+; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}'
+; ONE-NEXT: [002] 3 {Function} extern not_inlined 'main' -> 'int'
+; ONE-NEXT: [003] 4 {Line}
+; ONE-NEXT: [003] {Code} 'nop'
+; ONE-NEXT: [003] {Code} 'rethrow 127'
+; ONE-NEXT: [003] {Code} 'global.get 0'
+; ONE-NEXT: [003] {Code} 'local.set 0'
+; ONE-NEXT: [003] {Code} 'i32.const 16'
+; ONE-NEXT: [003] {Code} 'local.set 1'
+; ONE-NEXT: [003] {Code} 'local.get 0'
+; ONE-NEXT: [003] {Code} 'local.get 1'
+; ONE-NEXT: [003] {Code} 'i32.sub'
+; ONE-NEXT: [003] {Code} 'local.set 2'
+; ONE-NEXT: [003] {Code} 'local.get 2'
+; ONE-NEXT: [003] {Code} 'global.set 0'
+; ONE-NEXT: [003] {Code} 'i32.const 0'
+; ONE-NEXT: [003] {Code} 'local.set 3'
+; ONE-NEXT: [003] {Code} 'local.get 2'
+; ONE-NEXT: [003] {Code} 'local.get 3'
+; ONE-NEXT: [003] {Code} 'i32.store 12'
+; ONE-NEXT: [003] 5 {Line}
+; ONE-NEXT: [003] {Code} 'i32.const 0'
+; ONE-NEXT: [003] {Code} 'local.set 4'
+; ONE-NEXT: [003] {Code} 'i32.const 0'
+; ONE-NEXT: [003] {Code} 'local.set 5'
+; ONE-NEXT: [003] {Code} 'local.get 4'
+; ONE-NEXT: [003] {Code} 'local.get 5'
+; ONE-NEXT: [003] {Code} 'call 0'
+; ONE-NEXT: [003] {Code} 'drop'
+; ONE-NEXT: [003] 6 {Line}
+; ONE-NEXT: [003] {Code} 'i32.const 0'
+; ONE-NEXT: [003] {Code} 'local.set 6'
+; ONE-NEXT: [003] {Code} 'i32.const 16'
+; ONE-NEXT: [003] {Code} 'local.set 7'
+; ONE-NEXT: [003] {Code} 'local.get 2'
+; ONE-NEXT: [003] {Code} 'local.get 7'
+; ONE-NEXT: [003] {Code} 'i32.add'
+; ONE-NEXT: [003] {Code} 'local.set 8'
+; ONE-NEXT: [003] {Code} 'local.get 8'
+; ONE-NEXT: [003] {Code} 'global.set 0'
+; ONE-NEXT: [003] {Code} 'local.get 6'
+; ONE-NEXT: [003] {Code} 'return'
+; ONE-NEXT: [003] {Code} 'end'
+; ONE-NEXT: [003] 6 {Line}
+; ONE-NEXT: [003] {Code} 'return'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test
new file mode 100644
index 00000000000000..eb05ecae8ccf61
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test
@@ -0,0 +1,135 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 3 - Incorrect lexical scope for typedef.
+
+; pr-44884.cpp
+; 1 int bar(float Input) { return (int)Input; }
+; 2
+; 3 unsigned foo(char Param) {
+; 4 typedef int INT; // ** Definition for INT **
+; 5 INT Value = Param;
+; 6 {
+; 7 typedef float FLOAT; // ** Definition for FLOAT **
+; 8 {
+; 9 FLOAT Added = Value + Param;
+; 10 Value = bar(Added);
+; 11 }
+; 12 }
+; 13 return Value + Param;
+; 14 }
+
+; The lines 4 and 7 contains 2 typedefs, defined at
diff erent lexical
+; scopes.
+
+; The above test is used to illustrates a scope issue found in the
+; Clang compiler.
+; PR44884: https://bugs.llvm.org/show_bug.cgi?id=44884
+; PR44229: https://github.com/llvm/llvm-project/issues/44229
+
+; In the following logical views, we can see that the Clang compiler
+; emits both typedefs at the same lexical scope (3), which is wrong.
+; GCC emit correct lexical scope for both typedefs.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/pr-44884-clang.s -o %t.pr-44884-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \
+; RUN: --output-sort=kind \
+; RUN: --print=symbols,types,lines \
+; RUN: %t.pr-44884-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-44884-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}pr-44884-clang.o' -> WASM
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'pr-44884.cpp'
+; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}'
+; ONE-NEXT: [002] 1 {Function} extern not_inlined 'bar' -> 'int'
+; ONE-NEXT: [003] 1 {Parameter} 'Input' -> 'float'
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] - {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] - {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int'
+; ONE-NEXT: [003] {Block}
+; ONE-NEXT: [004] 9 {Variable} 'Added' -> 'FLOAT'
+; ONE-NEXT: [004] 9 {Line}
+; ONE-NEXT: [004] 9 {Line}
+; ONE-NEXT: [004] 9 {Line}
+; ONE-NEXT: [004] 9 {Line}
+; ONE-NEXT: [004] 9 {Line}
+; ONE-NEXT: [004] 10 {Line}
+; ONE-NEXT: [004] 10 {Line}
+; ONE-NEXT: [004] 10 {Line}
+; ONE-NEXT: [004] 13 {Line}
+; ONE-NEXT: [003] 3 {Parameter} 'Param' -> 'char'
+; ONE-NEXT: [003] 7 {TypeAlias} 'FLOAT' -> 'float'
+; ONE-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int'
+; ONE-NEXT: [003] 5 {Variable} 'Value' -> 'INT'
+; ONE-NEXT: [003] 3 {Line}
+; ONE-NEXT: [003] 5 {Line}
+; ONE-NEXT: [003] 5 {Line}
+; ONE-NEXT: [003] 13 {Line}
+; ONE-NEXT: [003] 13 {Line}
+; ONE-NEXT: [003] 13 {Line}
+; ONE-NEXT: [003] 13 {Line}
+; ONE-EMPTY:
+; ONE-NEXT: Logical View:
+; ONE-NEXT: [000] {File} 'pr-44884-dwarf-gcc.o' -> elf64-x86-64
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'pr-44884.cpp'
+; ONE-NEXT: [002] {Producer} 'GNU C++14 10.3.0 {{.*}}'
+; ONE-NEXT: [002] 1 {Function} extern not_inlined 'bar' -> 'int'
+; ONE-NEXT: [003] 1 {Parameter} 'Input' -> 'float'
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [003] 1 {Line}
+; ONE-NEXT: [002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int'
+; ONE-NEXT: [003] {Block}
+; ONE-NEXT: [004] {Block}
+; ONE-NEXT: [005] 9 {Variable} 'Added' -> 'FLOAT'
+; ONE-NEXT: [005] 9 {Line}
+; ONE-NEXT: [005] 9 {Line}
+; ONE-NEXT: [005] 9 {Line}
+; ONE-NEXT: [005] 10 {Line}
+; ONE-NEXT: [005] 13 {Line}
+; ONE-NEXT: [004] 7 {TypeAlias} 'FLOAT' -> 'float'
+; ONE-NEXT: [003] 3 {Parameter} 'Param' -> 'char'
+; ONE-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int'
+; ONE-NEXT: [003] 5 {Variable} 'Value' -> 'INT'
+; ONE-NEXT: [003] 3 {Line}
+; ONE-NEXT: [003] 5 {Line}
+; ONE-NEXT: [003] 13 {Line}
+; ONE-NEXT: [003] 14 {Line}
+; ONE-NEXT: [003] 14 {Line}
+
+; Using the selection facilities, we can produce a simple tabular
+; output showing just the logical types that are 'Typedef'.
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format \
+; RUN: --output-sort=name \
+; RUN: --select-types=Typedef \
+; RUN: --report=list \
+; RUN: --print=types \
+; RUN: %t.pr-44884-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-44884-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s
+
+; TWO: Logical View:
+; TWO-NEXT: [000] {File} '{{.*}}pr-44884-clang.o' -> WASM
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'pr-44884.cpp'
+; TWO-NEXT: [003] 7 {TypeAlias} 'FLOAT' -> 'float'
+; TWO-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int'
+; TWO-EMPTY:
+; TWO-NEXT: Logical View:
+; TWO-NEXT: [000] {File} 'pr-44884-dwarf-gcc.o' -> elf64-x86-64
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'pr-44884.cpp'
+; TWO-NEXT: [004] 7 {TypeAlias} 'FLOAT' -> 'float'
+; TWO-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test
new file mode 100644
index 00000000000000..cafa51c41966c5
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test
@@ -0,0 +1,130 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 4 - Missing nested enumerations.
+
+; pr-46466.cpp
+; 1 struct Struct {
+; 2 union Union {
+; 3 enum NestedEnum { RED, BLUE };
+; 4 };
+; 5 Union U;
+; 6 };
+; 7
+; 8 Struct S;
+; 9 int test() {
+; 10 return S.U.BLUE;
+; 11 }
+
+; The above test is used to illustrate a scope issue found in the Clang
+; compiler.
+; PR46466: https://bugs.llvm.org/show_bug.cgi?id=46466
+; PR45811: https://github.com/llvm/llvm-project/issues/45811
+
+; In the following logical views, we can see that the DWARF debug
+; information generated by the Clang compiler does not include any
+; references to the enumerators 'RED' and 'BLUE'. The DWARF generated
+; by GCC, does include such references.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/pr-46466-clang.s -o %t.pr-46466-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \
+; RUN: --output-sort=name \
+; RUN: --print=symbols,types \
+; RUN: %t.pr-46466-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-46466-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}pr-46466-clang.o' -> WASM
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'pr-46466.cpp'
+; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}'
+; ONE-NEXT: [002] 8 {Variable} extern 'S' -> 'Struct'
+; ONE-NEXT: [002] 1 {Struct} 'Struct'
+; ONE-NEXT: [003] 5 {Member} public 'U' -> 'Union'
+; ONE-EMPTY:
+; ONE-NEXT: Logical View:
+; ONE-NEXT: [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'pr-46466.cpp'
+; ONE-NEXT: [002] {Producer} 'GNU C++14 10.3.0 {{.*}}'
+; ONE-NEXT: [002] 8 {Variable} extern 'S' -> 'Struct'
+; ONE-NEXT: [002] 1 {Struct} 'Struct'
+; ONE-NEXT: [003] 5 {Member} public 'U' -> 'Union'
+; ONE-NEXT: [003] 2 {Union} 'Union'
+; ONE-NEXT: [004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int'
+; ONE-NEXT: [005] {Enumerator} 'BLUE' = '0x1'
+; ONE-NEXT: [005] {Enumerator} 'RED' = '0x0'
+
+; Using the selection facilities, we can produce a logical view
+; showing just the logical types that are 'Enumerator' and its
+; parents. The logical view is sorted by the types name.
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format \
+; RUN: --output-sort=name \
+; RUN: --select-types=Enumerator \
+; RUN: --report=parents \
+; RUN: --print=types \
+; RUN: %t.pr-46466-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-46466-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s
+
+; TWO: Logical View:
+; TWO-NEXT: [000] {File} '{{.*}}pr-46466-clang.o' -> WASM
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'pr-46466.cpp'
+; TWO-EMPTY:
+; TWO-NEXT: Logical View:
+; TWO-NEXT: [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'pr-46466.cpp'
+; TWO-NEXT: [002] 1 {Struct} 'Struct'
+; TWO-NEXT: [003] 2 {Union} 'Union'
+; TWO-NEXT: [004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int'
+; TWO-NEXT: [005] {Enumerator} 'BLUE' = '0x1'
+; TWO-NEXT: [005] {Enumerator} 'RED' = '0x0'
+
+; Using the selection facilities, we can produce a simple tabular output
+; including a summary for the logical types that are 'Enumerator'. The
+; logical view is sorted by the types name.
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format \
+; RUN: --output-sort=name \
+; RUN: --select-types=Enumerator \
+; RUN: --print=types,summary \
+; RUN: %t.pr-46466-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-46466-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=THR %s
+
+; THR: Logical View:
+; THR-NEXT: [000] {File} '{{.*}}pr-46466-clang.o' -> WASM
+; THR-EMPTY:
+; THR-NEXT: [001] {CompileUnit} 'pr-46466.cpp'
+; THR-EMPTY:
+; THR-NEXT: -----------------------------
+; THR-NEXT: Element Total Printed
+; THR-NEXT: -----------------------------
+; THR-NEXT: Scopes 4 0
+; THR-NEXT: Symbols 0 0
+; THR-NEXT: Types 0 0
+; THR-NEXT: Lines 0 0
+; THR-NEXT: -----------------------------
+; THR-NEXT: Total 4 0
+; THR-EMPTY:
+; THR-NEXT: Logical View:
+; THR-NEXT: [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64
+; THR-EMPTY:
+; THR-NEXT: [001] {CompileUnit} 'pr-46466.cpp'
+; THR-NEXT: [005] {Enumerator} 'BLUE' = '0x1'
+; THR-NEXT: [005] {Enumerator} 'RED' = '0x0'
+; THR-EMPTY:
+; THR-NEXT: -----------------------------
+; THR-NEXT: Element Total Printed
+; THR-NEXT: -----------------------------
+; THR-NEXT: Scopes 5 0
+; THR-NEXT: Symbols 0 0
+; THR-NEXT: Types 2 2
+; THR-NEXT: Lines 0 0
+; THR-NEXT: -----------------------------
+; THR-NEXT: Total 7 2
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test
new file mode 100644
index 00000000000000..4348161f8c5bad
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test
@@ -0,0 +1,114 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 5 - Incorrect lexical scope variable.
+
+; pr-43860.cpp
+; 1 #include "definitions.h"
+; 2 forceinline int InlineFunction(int Param) {
+; 3 int Var_1 = Param;
+; 4 {
+; 5 int Var_2 = Param + Var_1;
+; 6 Var_1 = Var_2;
+; 7 }
+; 8 return Var_1;
+; 9 }
+; 10
+; 11 int test(int Param_1, int Param_2) {
+; 12 int A = Param_1;
+; 13 A += InlineFunction(Param_2);
+; 14 return A;
+; 15 }
+
+; The above test is used to illustrate a variable issue found in the
+; Clang compiler.
+; PR43860: https://bugs.llvm.org/show_bug.cgi?id=43860
+; PR43205: https://github.com/llvm/llvm-project/issues/43205
+
+; In the following logical views, we can see that the DWARF debug
+; information generated by the Clang compiler shows the variables
+; 'Var_1' and 'Var_2' are at the same lexical scope (4) in the function
+; 'InlineFuction'.
+; The DWARF generated by GCC/Clang show those variables at the correct
+; lexical scope: '3' and '4' respectively.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/pr-43860-clang.s -o %t.pr-43860-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \
+; RUN: --output-sort=name \
+; RUN: --print=symbols \
+; RUN: %t.pr-43860-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-43860-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [000] {File} '{{.*}}pr-43860-clang.o' -> WASM
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'pr-43860.cpp'
+; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}'
+; ONE-NEXT: [002] 2 {Function} extern inlined 'InlineFunction' -> 'int'
+; ONE-NEXT: [003] {Block}
+; ONE-NEXT: [004] 5 {Variable} 'Var_2' -> 'int'
+; ONE-NEXT: [003] 2 {Parameter} 'Param' -> 'int'
+; ONE-NEXT: [003] 3 {Variable} 'Var_1' -> 'int'
+; ONE-NEXT: [002] 11 {Function} extern not_inlined 'test' -> 'int'
+; ONE-NEXT: [003] 12 {Variable} 'A' -> 'int'
+; ONE-NEXT: [003] 13 {InlinedFunction} inlined 'InlineFunction' -> 'int'
+; ONE-NEXT: [004] {Block}
+; ONE-NEXT: [005] {Variable} 'Var_2' -> 'int'
+; ONE-NEXT: [004] {Parameter} 'Param' -> 'int'
+; ONE-NEXT: [004] {Variable} 'Var_1' -> 'int'
+; ONE-NEXT: [003] 11 {Parameter} 'Param_1' -> 'int'
+; ONE-NEXT: [003] 11 {Parameter} 'Param_2' -> 'int'
+; ONE-EMPTY:
+; ONE-NEXT: Logical View:
+; ONE-NEXT: [000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
+; ONE-EMPTY:
+; ONE-NEXT: [001] {CompileUnit} 'pr-43860.cpp'
+; ONE-NEXT: [002] {Producer} 'GNU C++14 10.3.0 {{.*}}'
+; ONE-NEXT: [002] 2 {Function} extern declared_inlined 'InlineFunction' -> 'int'
+; ONE-NEXT: [003] {Block}
+; ONE-NEXT: [004] 5 {Variable} 'Var_2' -> 'int'
+; ONE-NEXT: [003] 2 {Parameter} 'Param' -> 'int'
+; ONE-NEXT: [003] 3 {Variable} 'Var_1' -> 'int'
+; ONE-NEXT: [002] 11 {Function} extern not_inlined 'test' -> 'int'
+; ONE-NEXT: [003] 12 {Variable} 'A' -> 'int'
+; ONE-NEXT: [003] 13 {InlinedFunction} declared_inlined 'InlineFunction' -> 'int'
+; ONE-NEXT: [004] {Block}
+; ONE-NEXT: [005] {Variable} 'Var_2' -> 'int'
+; ONE-NEXT: [004] {Parameter} 'Param' -> 'int'
+; ONE-NEXT: [004] {Variable} 'Var_1' -> 'int'
+; ONE-NEXT: [003] 11 {Parameter} 'Param_1' -> 'int'
+; ONE-NEXT: [003] 11 {Parameter} 'Param_2' -> 'int'
+
+; Using the selection facilities, we can produce a simple tabular output
+; showing just the logical elements that have in their name the 'var'
+; pattern. The logical view is sorted by the variables name.
+
+; RUN: llvm-debuginfo-analyzer --attribute=level,format \
+; RUN: --output-sort=name \
+; RUN: --select-regex --select-nocase \
+; RUN: --select=Var \
+; RUN: --report=list \
+; RUN: --print=symbols \
+; RUN: %t.pr-43860-clang.o \
+; RUN: %p/../DWARF/Inputs/pr-43860-dwarf-gcc.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s
+
+; TWO: Logical View:
+; TWO-NEXT: [000] {File} '{{.*}}pr-43860-clang.o' -> WASM
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'pr-43860.cpp'
+; TWO-NEXT: [004] {Variable} 'Var_1' -> 'int'
+; TWO-NEXT: [003] 3 {Variable} 'Var_1' -> 'int'
+; TWO-NEXT: [005] {Variable} 'Var_2' -> 'int'
+; TWO-NEXT: [004] 5 {Variable} 'Var_2' -> 'int'
+; TWO-EMPTY:
+; TWO-NEXT: Logical View:
+; TWO-NEXT: [000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64
+; TWO-EMPTY:
+; TWO-NEXT: [001] {CompileUnit} 'pr-43860.cpp'
+; TWO-NEXT: [004] {Variable} 'Var_1' -> 'int'
+; TWO-NEXT: [003] 3 {Variable} 'Var_1' -> 'int'
+; TWO-NEXT: [005] {Variable} 'Var_2' -> 'int'
+; TWO-NEXT: [004] 5 {Variable} 'Var_2' -> 'int'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test
new file mode 100644
index 00000000000000..81b78bac032151
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test
@@ -0,0 +1,158 @@
+; REQUIRES: webassembly-registered-target
+
+; Test case 6 - Full logical view
+
+; test.cpp
+; 1 using INTPTR = const int *;
+; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+; 3 if (ParamBool) {
+; 4 typedef int INTEGER;
+; 5 const INTEGER CONSTANT = 7;
+; 6 return CONSTANT;
+; 7 }
+; 8 return ParamUnsigned;
+; 9 }
+
+; Print low level details.
+; The following command prints low level information that includes
+; offsets within the debug information section, debug location
+; operands, linkage names, etc.
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj \
+; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o
+
+; RUN: llvm-debuginfo-analyzer --attribute=all \
+; RUN: --print=all \
+; RUN: %t.test-clang.o 2>&1 | \
+; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT: [0x0000000000][000] {File} '{{.*}}test-clang.o' -> WASM
+; ONE-EMPTY:
+; ONE-NEXT: [0x000000000b][001] {CompileUnit} 'test.cpp'
+; ONE-NEXT: [0x000000000b][002] {Producer} 'clang version 19{{.*}}'
+; ONE-NEXT: {Directory} '{{.*}}/general'
+; ONE-NEXT: {File} 'test.cpp'
+; ONE-NEXT: {Public} 'foo' [0x0000000002:0x000000007f]
+; ONE-NEXT: [0x000000000b][002] {Range} Lines 2:9 [0x0000000002:0x000000007f]
+; ONE-NEXT: [0x00000000b3][002] {BaseType} 'bool'
+; ONE-NEXT: [0x0000000090][002] {BaseType} 'int'
+; ONE-NEXT: [0x00000000ac][002] {BaseType} 'unsigned int'
+; ONE-EMPTY:
+; ONE-NEXT: [0x0000000097][002] {Source} '{{.*}}general/test.cpp'
+; ONE-NEXT: [0x0000000097][002] 1 {TypeAlias} 'INTPTR' -> [0x00000000a2]'* const int'
+; ONE-NEXT: [0x0000000026][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000090]'int'
+; ONE-NEXT: [0x0000000026][003] {Range} Lines 2:9 [0x0000000002:0x000000007f]
+; ONE-NEXT: [0x0000000026][003] {Linkage} 0x3 '_Z3fooPKijb'
+; ONE-NEXT: [0x000000006c][003] {Block}
+; ONE-NEXT: [0x000000006c][004] {Range} Lines 5:0 [0x000000004c:0x0000000064]
+; ONE-NEXT: [0x0000000075][004] 5 {Variable} 'CONSTANT' -> [0x00000000ba]'const INTEGER'
+; ONE-NEXT: [0x0000000075][005] {Coverage} 100.00%
+; ONE-NEXT: [0x0000000076][005] {Location}
+; ONE-NEXT: [0x0000000076][006] {Entry} fbreg 12
+; ONE-NEXT: [0x000000004c][004] 5 {Line} {NewStatement} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x000000004c][004] {Code} 'i32.const 7'
+; ONE-NEXT: [0x000000004e][004] {Code} 'local.set 10'
+; ONE-NEXT: [0x0000000050][004] {Code} 'local.get 5'
+; ONE-NEXT: [0x0000000052][004] {Code} 'local.get 10'
+; ONE-NEXT: [0x0000000054][004] {Code} 'i32.store 12'
+; ONE-NEXT: [0x0000000057][004] 6 {Line} {NewStatement} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000057][004] {Code} 'i32.const 7'
+; ONE-NEXT: [0x0000000059][004] {Code} 'local.set 11'
+; ONE-NEXT: [0x000000005b][004] {Code} 'local.get 5'
+; ONE-NEXT: [0x000000005d][004] {Code} 'local.get 11'
+; ONE-NEXT: [0x000000005f][004] {Code} 'i32.store 28'
+; ONE-NEXT: [0x0000000062][004] {Code} 'br 1'
+; ONE-NEXT: [0x0000000064][004] 0 {Line} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000064][004] {Code} 'end'
+; ONE-NEXT: [0x000000005e][003] 2 {Parameter} 'ParamBool' -> [0x00000000b3]'bool'
+; ONE-NEXT: [0x000000005e][004] {Coverage} 100.00%
+; ONE-NEXT: [0x000000005f][004] {Location}
+; ONE-NEXT: [0x000000005f][005] {Entry} fbreg 19
+; ONE-NEXT: [0x0000000042][003] 2 {Parameter} 'ParamPtr' -> [0x0000000097]'INTPTR'
+; ONE-NEXT: [0x0000000042][004] {Coverage} 100.00%
+; ONE-NEXT: [0x0000000043][004] {Location}
+; ONE-NEXT: [0x0000000043][005] {Entry} fbreg 24
+; ONE-NEXT: [0x0000000050][003] 2 {Parameter} 'ParamUnsigned' -> [0x00000000ac]'unsigned int'
+; ONE-NEXT: [0x0000000050][004] {Coverage} 100.00%
+; ONE-NEXT: [0x0000000051][004] {Location}
+; ONE-NEXT: [0x0000000051][005] {Entry} fbreg 20
+; ONE-NEXT: [0x0000000084][003] 4 {TypeAlias} 'INTEGER' -> [0x0000000090]'int'
+; ONE-NEXT: [0x0000000002][003] 2 {Line} {NewStatement} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000002][003] {Code} 'nop'
+; ONE-NEXT: [0x0000000003][003] {Code} 'end'
+; ONE-NEXT: [0x0000000004][003] {Code} 'i64.div_s'
+; ONE-NEXT: [0x0000000005][003] {Code} 'global.get 0'
+; ONE-NEXT: [0x000000000b][003] {Code} 'local.set 3'
+; ONE-NEXT: [0x000000000d][003] {Code} 'i32.const 32'
+; ONE-NEXT: [0x000000000f][003] {Code} 'local.set 4'
+; ONE-NEXT: [0x0000000011][003] {Code} 'local.get 3'
+; ONE-NEXT: [0x0000000013][003] {Code} 'local.get 4'
+; ONE-NEXT: [0x0000000015][003] {Code} 'i32.sub'
+; ONE-NEXT: [0x0000000016][003] {Code} 'local.set 5'
+; ONE-NEXT: [0x0000000018][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x000000001a][003] {Code} 'local.get 0'
+; ONE-NEXT: [0x000000001c][003] {Code} 'i32.store 24'
+; ONE-NEXT: [0x000000001f][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x0000000021][003] {Code} 'local.get 1'
+; ONE-NEXT: [0x0000000023][003] {Code} 'i32.store 20'
+; ONE-NEXT: [0x0000000026][003] {Code} 'local.get 2'
+; ONE-NEXT: [0x0000000028][003] {Code} 'local.set 6'
+; ONE-NEXT: [0x000000002a][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x000000002c][003] {Code} 'local.get 6'
+; ONE-NEXT: [0x000000002e][003] {Code} 'i32.store8 19'
+; ONE-NEXT: [0x0000000031][003] 3 {Line} {NewStatement} {PrologueEnd} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000031][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x0000000033][003] {Code} 'i32.load8_u 19'
+; ONE-NEXT: [0x0000000036][003] {Code} 'local.set 7'
+; ONE-NEXT: [0x0000000038][003] 3 {Line} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000038][003] {Code} 'i32.const 1'
+; ONE-NEXT: [0x000000003a][003] {Code} 'local.set 8'
+; ONE-NEXT: [0x000000003c][003] {Code} 'local.get 7'
+; ONE-NEXT: [0x000000003e][003] {Code} 'local.get 8'
+; ONE-NEXT: [0x0000000040][003] {Code} 'i32.and'
+; ONE-NEXT: [0x0000000041][003] {Code} 'local.set 9'
+; ONE-NEXT: [0x0000000043][003] {Code} 'block'
+; ONE-NEXT: [0x0000000045][003] {Code} 'block'
+; ONE-NEXT: [0x0000000047][003] {Code} 'local.get 9'
+; ONE-NEXT: [0x0000000049][003] {Code} 'i32.eqz'
+; ONE-NEXT: [0x000000004a][003] {Code} 'br_if 0'
+; ONE-NEXT: [0x0000000065][003] 8 {Line} {NewStatement} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000065][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x0000000067][003] {Code} 'i32.load 20'
+; ONE-NEXT: [0x000000006a][003] {Code} 'local.set 12'
+; ONE-NEXT: [0x000000006c][003] 8 {Line} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x000000006c][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x000000006e][003] {Code} 'local.get 12'
+; ONE-NEXT: [0x0000000070][003] {Code} 'i32.store 28'
+; ONE-NEXT: [0x0000000073][003] 0 {Line} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000073][003] {Code} 'end'
+; ONE-NEXT: [0x0000000074][003] 9 {Line} {NewStatement} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x0000000074][003] {Code} 'local.get 5'
+; ONE-NEXT: [0x0000000076][003] {Code} 'i32.load 28'
+; ONE-NEXT: [0x0000000079][003] {Code} 'local.set 13'
+; ONE-NEXT: [0x000000007b][003] {Code} 'local.get 13'
+; ONE-NEXT: [0x000000007d][003] {Code} 'return'
+; ONE-NEXT: [0x000000007e][003] {Code} 'end'
+; ONE-NEXT: [0x000000007f][003] 9 {Line} {NewStatement} {EndSequence} '{{.*}}/general/test.cpp'
+; ONE-NEXT: [0x000000007f][003] {Code} 'unreachable'
+; ONE-EMPTY:
+; ONE-NEXT: -----------------------------
+; ONE-NEXT: Element Total Printed
+; ONE-NEXT: -----------------------------
+; ONE-NEXT: Scopes 3 3
+; ONE-NEXT: Symbols 4 4
+; ONE-NEXT: Types 5 5
+; ONE-NEXT: Lines 73 73
+; ONE-NEXT: -----------------------------
+; ONE-NEXT: Total 85 85
+; ONE-EMPTY:
+; ONE-NEXT: Scope Sizes:
+; ONE-NEXT: 180 (100.00%) : [0x000000000b][001] {CompileUnit} 'test.cpp'
+; ONE-NEXT: 105 ( 58.33%) : [0x0000000026][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000090]'int'
+; ONE-NEXT: 23 ( 12.78%) : [0x000000006c][003] {Block}
+; ONE-EMPTY:
+; ONE-NEXT: Totals by lexical level:
+; ONE-NEXT: [001]: 180 (100.00%)
+; ONE-NEXT: [002]: 105 ( 58.33%)
+; ONE-NEXT: [003]: 23 ( 12.78%)
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h
new file mode 100644
index 00000000000000..dfbd3db044dd80
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h
@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------------
+// Definitions.
+//-----------------------------------------------------------------------------
+#ifndef SUITE_DEFINITIONS_H
+#define SUITE_DEFINITIONS_H
+
+#ifdef _MSC_VER
+#define forceinline __forceinline
+#define OPTIMIZE_OFF __pragma(optimize("", off))
+#define OPTIMIZE_ON __pragma(optimize("", on))
+#elif defined(__clang__)
+#if __has_attribute(__always_inline__)
+#define forceinline inline __attribute__((__always_inline__))
+#else
+#define forceinline inline
+#endif
+#define OPTIMIZE_OFF _Pragma("clang optimize off")
+#define OPTIMIZE_ON _Pragma("clang optimize on")
+#elif defined(__GNUC__)
+#define forceinline inline __attribute__((__always_inline__))
+#define OPTIMIZE_OFF _Pragma("GCC optimize off")
+#define OPTIMIZE_ON _Pragma("GCC optimize on")
+#else
+#define forceinline inline
+#define OPTIMIZE_OFF
+#define OPTIMIZE_ON
+#error
+#endif
+
+#endif // SUITE_DEFINITIONS_H
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s
new file mode 100644
index 00000000000000..bfba259b626b0f
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s
@@ -0,0 +1,286 @@
+ .text
+ .file "hello-world.cpp"
+ .file 1 "/data/projects/scripts/regression-suite/input/general" "hello-world.cpp"
+ .globaltype __stack_pointer, i32
+ .functype __original_main () -> (i32)
+ .functype _Z6printfPKcz (i32, i32) -> (i32)
+ .functype main (i32, i32) -> (i32)
+ .section .text.__original_main,"",@
+ .hidden __original_main # -- Begin function __original_main
+ .globl __original_main
+ .type __original_main, at function
+__original_main: # @__original_main
+.Lfunc_begin0:
+ .loc 1 4 0 # hello-world.cpp:4:0
+ .functype __original_main () -> (i32)
+ .local i32, i32, i32, i32, i32, i32, i32, i32, i32
+# %bb.0: # %entry
+ global.get __stack_pointer
+ local.set 0
+ i32.const 16
+ local.set 1
+ local.get 0
+ local.get 1
+ i32.sub
+ local.set 2
+ local.get 2
+ global.set __stack_pointer
+ i32.const 0
+ local.set 3
+ local.get 2
+ local.get 3
+ i32.store 12
+.Ltmp0:
+ .loc 1 5 3 prologue_end # hello-world.cpp:5:3
+ i32.const .L.str
+ local.set 4
+ i32.const 0
+ local.set 5
+ local.get 4
+ local.get 5
+ call _Z6printfPKcz
+ drop
+ .loc 1 6 3 # hello-world.cpp:6:3
+ i32.const 0
+ local.set 6
+ i32.const 16
+ local.set 7
+ local.get 2
+ local.get 7
+ i32.add
+ local.set 8
+ local.get 8
+ global.set __stack_pointer
+ local.get 6
+ return
+ end_function
+.Ltmp1:
+.Lfunc_end0:
+ # -- End function
+ .section .text.main,"",@
+ .hidden main # -- Begin function main
+ .globl main
+ .type main, at function
+main: # @main
+.Lfunc_begin1:
+ .functype main (i32, i32) -> (i32)
+ .local i32
+# %bb.0: # %body
+ call __original_main
+ local.set 2
+ local.get 2
+ return
+ end_function
+.Lfunc_end1:
+ # -- End function
+ .type .L.str, at object # @.str
+ .section .rodata..L.str,"S",@
+.L.str:
+ .asciz "Hello, World\n"
+ .size .L.str, 14
+
+ .globl __main_void
+ .type __main_void, at function
+ .hidden __main_void
+.set __main_void, __original_main
+ .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 52 # DW_TAG_variable
+ .int8 0 # DW_CHILDREN_no
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 2 # DW_AT_location
+ .int8 24 # DW_FORM_exprloc
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 3 # Abbreviation Code
+ .int8 1 # DW_TAG_array_type
+ .int8 1 # DW_CHILDREN_yes
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 4 # Abbreviation Code
+ .int8 33 # DW_TAG_subrange_type
+ .int8 0 # DW_CHILDREN_no
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 55 # DW_AT_count
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 5 # 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 6 # 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 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 11 # DW_AT_byte_size
+ .int8 11 # DW_FORM_data1
+ .int8 62 # DW_AT_encoding
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 8 # Abbreviation Code
+ .int8 46 # DW_TAG_subprogram
+ .int8 0 # DW_CHILDREN_no
+ .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 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 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:0x67 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:0xd DW_TAG_variable
+ .int32 51 # DW_AT_type
+ .int8 1 # DW_AT_decl_file
+ .int8 5 # DW_AT_decl_line
+ .int8 5 # DW_AT_location
+ .int8 3
+ .int32 .L.str
+ .int8 3 # Abbrev [3] 0x33:0xc DW_TAG_array_type
+ .int32 63 # DW_AT_type
+ .int8 4 # Abbrev [4] 0x38:0x6 DW_TAG_subrange_type
+ .int32 75 # DW_AT_type
+ .int8 14 # DW_AT_count
+ .int8 0 # End Of Children Mark
+ .int8 5 # Abbrev [5] 0x3f:0x5 DW_TAG_const_type
+ .int32 68 # DW_AT_type
+ .int8 6 # Abbrev [6] 0x44:0x7 DW_TAG_base_type
+ .int32 .Linfo_string3 # DW_AT_name
+ .int8 6 # DW_AT_encoding
+ .int8 1 # DW_AT_byte_size
+ .int8 7 # Abbrev [7] 0x4b:0x7 DW_TAG_base_type
+ .int32 .Linfo_string4 # DW_AT_name
+ .int8 8 # DW_AT_byte_size
+ .int8 7 # DW_AT_encoding
+ .int8 8 # Abbrev [8] 0x52:0x18 DW_TAG_subprogram
+ .int32 .Lfunc_begin0 # DW_AT_low_pc
+ .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .int8 4 # DW_AT_frame_base
+ .int8 237
+ .int8 0
+ .int8 2
+ .int8 159
+ .int32 .Linfo_string5 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 3 # DW_AT_decl_line
+ .int32 106 # DW_AT_type
+ # DW_AT_external
+ .int8 6 # Abbrev [6] 0x6a:0x7 DW_TAG_base_type
+ .int32 .Linfo_string6 # DW_AT_name
+ .int8 5 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str,"S",@
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0
+.Linfo_string1:
+ .asciz "hello-world.cpp" # string offset=111
+.Linfo_string2:
+ .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=127
+.Linfo_string3:
+ .asciz "char" # string offset=181
+.Linfo_string4:
+ .asciz "__ARRAY_SIZE_TYPE__" # string offset=186
+.Linfo_string5:
+ .asciz "main" # string offset=206
+.Linfo_string6:
+ .asciz "int" # string offset=211
+ .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+ .no_dead_strip __indirect_function_table
+ .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/Inputs/hello-world.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world.cpp
new file mode 100644
index 00000000000000..73a8e247e26ec3
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world.cpp
@@ -0,0 +1,7 @@
+extern int printf(const char * format, ... );
+
+int main()
+{
+ printf("Hello, World\n");
+ return 0;
+}
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s
new file mode 100644
index 00000000000000..fb70b36173fd97
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s
@@ -0,0 +1,457 @@
+ .text
+ .file "pr-43860.cpp"
+ .globaltype __stack_pointer, i32
+ .functype _Z4testii (i32, i32) -> (i32)
+ .section .text._Z4testii,"",@
+ .hidden _Z4testii # -- Begin function _Z4testii
+ .globl _Z4testii
+ .type _Z4testii, at function
+_Z4testii: # @_Z4testii
+.Lfunc_begin0:
+ .file 1 "/data/projects/scripts/regression-suite/input/general" "pr-43860.cpp"
+ .loc 1 11 0 # pr-43860.cpp:11:0
+ .functype _Z4testii (i32, i32) -> (i32)
+ .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32
+# %bb.0: # %entry
+ global.get __stack_pointer
+ local.set 2
+ i32.const 32
+ local.set 3
+ local.get 2
+ local.get 3
+ i32.sub
+ local.set 4
+ local.get 4
+ local.get 0
+ i32.store 16
+ local.get 4
+ local.get 1
+ i32.store 12
+.Ltmp0:
+ .loc 1 12 11 prologue_end # pr-43860.cpp:12:11
+ local.get 4
+ i32.load 16
+ local.set 5
+ .loc 1 12 7 is_stmt 0 # pr-43860.cpp:12:7
+ local.get 4
+ local.get 5
+ i32.store 8
+ .loc 1 13 23 is_stmt 1 # pr-43860.cpp:13:23
+ local.get 4
+ i32.load 12
+ local.set 6
+ local.get 4
+ local.get 6
+ i32.store 28
+.Ltmp1:
+ .loc 1 3 15 # pr-43860.cpp:3:15
+ local.get 4
+ i32.load 28
+ local.set 7
+ .loc 1 3 7 is_stmt 0 # pr-43860.cpp:3:7
+ local.get 4
+ local.get 7
+ i32.store 24
+.Ltmp2:
+ .loc 1 5 17 is_stmt 1 # pr-43860.cpp:5:17
+ local.get 4
+ i32.load 28
+ local.set 8
+ .loc 1 5 25 is_stmt 0 # pr-43860.cpp:5:25
+ local.get 4
+ i32.load 24
+ local.set 9
+ .loc 1 5 23 # pr-43860.cpp:5:23
+ local.get 8
+ local.get 9
+ i32.add
+ local.set 10
+ .loc 1 5 9 # pr-43860.cpp:5:9
+ local.get 4
+ local.get 10
+ i32.store 20
+ .loc 1 6 13 is_stmt 1 # pr-43860.cpp:6:13
+ local.get 4
+ i32.load 20
+ local.set 11
+ .loc 1 6 11 is_stmt 0 # pr-43860.cpp:6:11
+ local.get 4
+ local.get 11
+ i32.store 24
+.Ltmp3:
+ .loc 1 8 10 is_stmt 1 # pr-43860.cpp:8:10
+ local.get 4
+ i32.load 24
+ local.set 12
+.Ltmp4:
+ .loc 1 13 5 # pr-43860.cpp:13:5
+ local.get 4
+ i32.load 8
+ local.set 13
+ local.get 13
+ local.get 12
+ i32.add
+ local.set 14
+ local.get 4
+ local.get 14
+ i32.store 8
+ .loc 1 14 10 # pr-43860.cpp:14:10
+ local.get 4
+ i32.load 8
+ local.set 15
+ .loc 1 14 3 is_stmt 0 # pr-43860.cpp:14:3
+ local.get 15
+ return
+ end_function
+.Ltmp5:
+.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 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 32 # DW_AT_inline
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 3 # Abbreviation Code
+ .int8 5 # DW_TAG_formal_parameter
+ .int8 0 # DW_CHILDREN_no
+ .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 52 # DW_TAG_variable
+ .int8 0 # DW_CHILDREN_no
+ .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 5 # Abbreviation Code
+ .int8 11 # DW_TAG_lexical_block
+ .int8 1 # DW_CHILDREN_yes
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 6 # 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 7 # 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 8 # 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 9 # 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 10 # Abbreviation Code
+ .int8 29 # DW_TAG_inlined_subroutine
+ .int8 1 # DW_CHILDREN_yes
+ .int8 49 # DW_AT_abstract_origin
+ .int8 19 # DW_FORM_ref4
+ .int8 17 # DW_AT_low_pc
+ .int8 1 # DW_FORM_addr
+ .int8 18 # DW_AT_high_pc
+ .int8 6 # DW_FORM_data4
+ .int8 88 # DW_AT_call_file
+ .int8 11 # DW_FORM_data1
+ .int8 89 # DW_AT_call_line
+ .int8 11 # DW_FORM_data1
+ .int8 87 # DW_AT_call_column
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 11 # Abbreviation Code
+ .int8 5 # DW_TAG_formal_parameter
+ .int8 0 # DW_CHILDREN_no
+ .int8 2 # DW_AT_location
+ .int8 24 # DW_FORM_exprloc
+ .int8 49 # DW_AT_abstract_origin
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 12 # Abbreviation Code
+ .int8 52 # DW_TAG_variable
+ .int8 0 # DW_CHILDREN_no
+ .int8 2 # DW_AT_location
+ .int8 24 # DW_FORM_exprloc
+ .int8 49 # DW_AT_abstract_origin
+ .int8 19 # DW_FORM_ref4
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 13 # 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 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:0xd1 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:0x34 DW_TAG_subprogram
+ .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 90 # DW_AT_type
+ # DW_AT_external
+ .int8 1 # DW_AT_inline
+ .int8 3 # Abbrev [3] 0x36:0xb DW_TAG_formal_parameter
+ .int32 .Linfo_string6 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 2 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ .int8 4 # Abbrev [4] 0x41:0xb DW_TAG_variable
+ .int32 .Linfo_string7 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 3 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ .int8 5 # Abbrev [5] 0x4c:0xd DW_TAG_lexical_block
+ .int8 4 # Abbrev [4] 0x4d:0xb DW_TAG_variable
+ .int32 .Linfo_string8 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 5 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ .int8 0 # End Of Children Mark
+ .int8 0 # End Of Children Mark
+ .int8 6 # Abbrev [6] 0x5a:0x7 DW_TAG_base_type
+ .int32 .Linfo_string5 # DW_AT_name
+ .int8 5 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 7 # Abbrev [7] 0x61:0x7a DW_TAG_subprogram
+ .int32 .Lfunc_begin0 # DW_AT_low_pc
+ .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .int8 4 # DW_AT_frame_base
+ .int8 237
+ .int8 0
+ .int8 4
+ .int8 159
+ .int32 .Linfo_string9 # DW_AT_linkage_name
+ .int32 .Linfo_string10 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 11 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ # DW_AT_external
+ .int8 8 # Abbrev [8] 0x7d:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 16
+ .int32 .Linfo_string11 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 11 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ .int8 8 # Abbrev [8] 0x8b:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 12
+ .int32 .Linfo_string12 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 11 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ .int8 9 # Abbrev [9] 0x99:0xe DW_TAG_variable
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 8
+ .int32 .Linfo_string13 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 12 # DW_AT_decl_line
+ .int32 90 # DW_AT_type
+ .int8 10 # Abbrev [10] 0xa7:0x33 DW_TAG_inlined_subroutine
+ .int32 38 # DW_AT_abstract_origin
+ .int32 .Ltmp1 # DW_AT_low_pc
+ .int32 .Ltmp4-.Ltmp1 # DW_AT_high_pc
+ .int8 1 # DW_AT_call_file
+ .int8 13 # DW_AT_call_line
+ .int8 8 # DW_AT_call_column
+ .int8 11 # Abbrev [11] 0xb7:0x8 DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 28
+ .int32 54 # DW_AT_abstract_origin
+ .int8 12 # Abbrev [12] 0xbf:0x8 DW_TAG_variable
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 24
+ .int32 65 # DW_AT_abstract_origin
+ .int8 13 # Abbrev [13] 0xc7:0x12 DW_TAG_lexical_block
+ .int32 .Ltmp2 # DW_AT_low_pc
+ .int32 .Ltmp3-.Ltmp2 # DW_AT_high_pc
+ .int8 12 # Abbrev [12] 0xd0:0x8 DW_TAG_variable
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 20
+ .int32 77 # DW_AT_abstract_origin
+ .int8 0 # End Of Children Mark
+ .int8 0 # End Of Children Mark
+ .int8 0 # End Of Children Mark
+ .int8 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str,"S",@
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0
+.Linfo_string1:
+ .asciz "pr-43860.cpp" # string offset=111
+.Linfo_string2:
+ .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=124
+.Linfo_string3:
+ .asciz "_Z14InlineFunctioni" # string offset=178
+.Linfo_string4:
+ .asciz "InlineFunction" # string offset=198
+.Linfo_string5:
+ .asciz "int" # string offset=213
+.Linfo_string6:
+ .asciz "Param" # string offset=217
+.Linfo_string7:
+ .asciz "Var_1" # string offset=223
+.Linfo_string8:
+ .asciz "Var_2" # string offset=229
+.Linfo_string9:
+ .asciz "_Z4testii" # string offset=235
+.Linfo_string10:
+ .asciz "test" # string offset=245
+.Linfo_string11:
+ .asciz "Param_1" # string offset=250
+.Linfo_string12:
+ .asciz "Param_2" # string offset=258
+.Linfo_string13:
+ .asciz "A" # string offset=266
+ .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+ .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/Inputs/pr-43860.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860.cpp
new file mode 100644
index 00000000000000..a3d3b76c59e586
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860.cpp
@@ -0,0 +1,15 @@
+#include "definitions.h"
+forceinline int InlineFunction(int Param) {
+ int Var_1 = Param;
+ {
+ int Var_2 = Param + Var_1;
+ Var_1 = Var_2;
+ }
+ return Var_1;
+}
+
+int test(int Param_1, int Param_2) {
+ int A = Param_1;
+ A += InlineFunction(Param_2);
+ return A;
+}
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s
new file mode 100644
index 00000000000000..af9875b1eee2a6
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s
@@ -0,0 +1,488 @@
+ .text
+ .file "pr-44884.cpp"
+ .globaltype __stack_pointer, i32
+ .functype _Z3barf (f32) -> (i32)
+ .functype _Z3fooc (i32) -> (i32)
+ .section .text._Z3barf,"",@
+ .hidden _Z3barf # -- Begin function _Z3barf
+ .globl _Z3barf
+ .type _Z3barf, at function
+_Z3barf: # @_Z3barf
+.Lfunc_begin0:
+ .file 1 "/data/projects/scripts/regression-suite/input/general" "pr-44884.cpp"
+ .loc 1 1 0 # pr-44884.cpp:1:0
+ .functype _Z3barf (f32) -> (i32)
+ .local i32, i32, i32, f32, f32, f32, i32, i32, i32, i32, i32, i32
+# %bb.0: # %entry
+ global.get __stack_pointer
+ local.set 1
+ i32.const 16
+ local.set 2
+ local.get 1
+ local.get 2
+ i32.sub
+ local.set 3
+ local.get 3
+ local.get 0
+ f32.store 12
+.Ltmp0:
+ .loc 1 1 36 prologue_end # pr-44884.cpp:1:36
+ local.get 3
+ f32.load 12
+ local.set 4
+ local.get 4
+ f32.abs
+ local.set 5
+ f32.const 0x1p31
+ local.set 6
+ local.get 5
+ local.get 6
+ f32.lt
+ local.set 7
+ local.get 7
+ i32.eqz
+ local.set 8
+ block
+ block
+ local.get 8
+ br_if 0 # 0: down to label1
+# %bb.1: # %entry
+ local.get 4
+ i32.trunc_f32_s
+ local.set 9
+ local.get 9
+ local.set 10
+ br 1 # 1: down to label0
+.LBB0_2: # %entry
+ .loc 1 0 36 is_stmt 0 # pr-44884.cpp:0:36
+ end_block # label1:
+ .loc 1 1 36 # pr-44884.cpp:1:36
+ i32.const -2147483648
+ local.set 11
+ local.get 11
+ local.set 10
+.LBB0_3: # %entry
+ .loc 1 0 36 # pr-44884.cpp:0:36
+ end_block # label0:
+ .loc 1 1 36 # pr-44884.cpp:1:36
+ local.get 10
+ local.set 12
+ .loc 1 1 24 # pr-44884.cpp:1:24
+ local.get 12
+ return
+ end_function
+.Ltmp1:
+.Lfunc_end0:
+ # -- End function
+ .section .text._Z3fooc,"",@
+ .hidden _Z3fooc # -- Begin function _Z3fooc
+ .globl _Z3fooc
+ .type _Z3fooc, at function
+_Z3fooc: # @_Z3fooc
+.Lfunc_begin1:
+ .loc 1 3 0 is_stmt 1 # pr-44884.cpp:3:0
+ .functype _Z3fooc (i32) -> (i32)
+ .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, f32, f32, i32, i32, i32, i32, i32, i32, i32, i32, i32
+# %bb.0: # %entry
+ global.get __stack_pointer
+ local.set 1
+ i32.const 16
+ local.set 2
+ local.get 1
+ local.get 2
+ i32.sub
+ local.set 3
+ local.get 3
+ global.set __stack_pointer
+ local.get 3
+ local.get 0
+ i32.store8 15
+.Ltmp2:
+ .loc 1 5 15 prologue_end # pr-44884.cpp:5:15
+ local.get 3
+ i32.load8_u 15
+ local.set 4
+ i32.const 24
+ local.set 5
+ local.get 4
+ local.get 5
+ i32.shl
+ local.set 6
+ local.get 6
+ local.get 5
+ i32.shr_s
+ local.set 7
+ .loc 1 5 7 is_stmt 0 # pr-44884.cpp:5:7
+ local.get 3
+ local.get 7
+ i32.store 8
+.Ltmp3:
+ .loc 1 9 21 is_stmt 1 # pr-44884.cpp:9:21
+ local.get 3
+ i32.load 8
+ local.set 8
+ .loc 1 9 29 is_stmt 0 # pr-44884.cpp:9:29
+ local.get 3
+ i32.load8_u 15
+ local.set 9
+ i32.const 24
+ local.set 10
+ local.get 9
+ local.get 10
+ i32.shl
+ local.set 11
+ local.get 11
+ local.get 10
+ i32.shr_s
+ local.set 12
+ .loc 1 9 27 # pr-44884.cpp:9:27
+ local.get 8
+ local.get 12
+ i32.add
+ local.set 13
+ .loc 1 9 21 # pr-44884.cpp:9:21
+ local.get 13
+ f32.convert_i32_s
+ local.set 14
+ .loc 1 9 13 # pr-44884.cpp:9:13
+ local.get 3
+ local.get 14
+ f32.store 4
+ .loc 1 10 19 is_stmt 1 # pr-44884.cpp:10:19
+ local.get 3
+ f32.load 4
+ local.set 15
+ .loc 1 10 15 is_stmt 0 # pr-44884.cpp:10:15
+ local.get 15
+ call _Z3barf
+ local.set 16
+ .loc 1 10 13 # pr-44884.cpp:10:13
+ local.get 3
+ local.get 16
+ i32.store 8
+.Ltmp4:
+ .loc 1 13 10 is_stmt 1 # pr-44884.cpp:13:10
+ local.get 3
+ i32.load 8
+ local.set 17
+ .loc 1 13 18 is_stmt 0 # pr-44884.cpp:13:18
+ local.get 3
+ i32.load8_u 15
+ local.set 18
+ i32.const 24
+ local.set 19
+ local.get 18
+ local.get 19
+ i32.shl
+ local.set 20
+ local.get 20
+ local.get 19
+ i32.shr_s
+ local.set 21
+ .loc 1 13 16 # pr-44884.cpp:13:16
+ local.get 17
+ local.get 21
+ i32.add
+ local.set 22
+ .loc 1 13 3 # pr-44884.cpp:13:3
+ i32.const 16
+ local.set 23
+ local.get 3
+ local.get 23
+ i32.add
+ local.set 24
+ local.get 24
+ global.set __stack_pointer
+ local.get 22
+ return
+ end_function
+.Ltmp5:
+.Lfunc_end1:
+ # -- 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 85 # DW_AT_ranges
+ .int8 23 # DW_FORM_sec_offset
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 2 # 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 3 # 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 4 # 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 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 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 7 # 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 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:0xca 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 0 # DW_AT_low_pc
+ .int32 .Ldebug_ranges0 # DW_AT_ranges
+ .int8 2 # Abbrev [2] 0x26:0x7 DW_TAG_base_type
+ .int32 .Linfo_string3 # DW_AT_name
+ .int8 5 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 3 # Abbrev [3] 0x2d:0x2b DW_TAG_subprogram
+ .int32 .Lfunc_begin0 # DW_AT_low_pc
+ .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .int8 4 # DW_AT_frame_base
+ .int8 237
+ .int8 0
+ .int8 3
+ .int8 159
+ .int32 .Linfo_string4 # DW_AT_linkage_name
+ .int32 .Linfo_string5 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 1 # DW_AT_decl_line
+ .int32 38 # DW_AT_type
+ # DW_AT_external
+ .int8 4 # Abbrev [4] 0x49:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 12
+ .int32 .Linfo_string9 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 1 # DW_AT_decl_line
+ .int32 198 # DW_AT_type
+ .int8 0 # End Of Children Mark
+ .int8 3 # Abbrev [3] 0x58:0x67 DW_TAG_subprogram
+ .int32 .Lfunc_begin1 # DW_AT_low_pc
+ .int32 .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
+ .int8 4 # DW_AT_frame_base
+ .int8 237
+ .int8 0
+ .int8 3
+ .int8 159
+ .int32 .Linfo_string6 # DW_AT_linkage_name
+ .int32 .Linfo_string7 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 3 # DW_AT_decl_line
+ .int32 191 # DW_AT_type
+ # DW_AT_external
+ .int8 4 # Abbrev [4] 0x74:0xe DW_TAG_formal_parameter
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 15
+ .int32 .Linfo_string11 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 3 # DW_AT_decl_line
+ .int32 205 # DW_AT_type
+ .int8 5 # Abbrev [5] 0x82:0xe DW_TAG_variable
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 8
+ .int32 .Linfo_string13 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 5 # DW_AT_decl_line
+ .int32 168 # DW_AT_type
+ .int8 6 # Abbrev [6] 0x90:0x18 DW_TAG_lexical_block
+ .int32 .Ltmp3 # DW_AT_low_pc
+ .int32 .Ltmp4-.Ltmp3 # DW_AT_high_pc
+ .int8 5 # Abbrev [5] 0x99:0xe DW_TAG_variable
+ .int8 2 # DW_AT_location
+ .int8 145
+ .int8 4
+ .int32 .Linfo_string15 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 9 # DW_AT_decl_line
+ .int32 179 # DW_AT_type
+ .int8 0 # End Of Children Mark
+ .int8 7 # Abbrev [7] 0xa8:0xb DW_TAG_typedef
+ .int32 38 # DW_AT_type
+ .int32 .Linfo_string14 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 4 # DW_AT_decl_line
+ .int8 7 # Abbrev [7] 0xb3:0xb DW_TAG_typedef
+ .int32 198 # DW_AT_type
+ .int32 .Linfo_string16 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 7 # DW_AT_decl_line
+ .int8 0 # End Of Children Mark
+ .int8 2 # Abbrev [2] 0xbf:0x7 DW_TAG_base_type
+ .int32 .Linfo_string8 # DW_AT_name
+ .int8 7 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 2 # Abbrev [2] 0xc6:0x7 DW_TAG_base_type
+ .int32 .Linfo_string10 # DW_AT_name
+ .int8 4 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 2 # Abbrev [2] 0xcd:0x7 DW_TAG_base_type
+ .int32 .Linfo_string12 # DW_AT_name
+ .int8 6 # DW_AT_encoding
+ .int8 1 # DW_AT_byte_size
+ .int8 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_ranges,"",@
+.Ldebug_ranges0:
+ .int32 .Lfunc_begin0
+ .int32 .Lfunc_end0
+ .int32 .Lfunc_begin1
+ .int32 .Lfunc_end1
+ .int32 0
+ .int32 0
+ .section .debug_str,"S",@
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0
+.Linfo_string1:
+ .asciz "pr-44884.cpp" # string offset=111
+.Linfo_string2:
+ .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=124
+.Linfo_string3:
+ .asciz "int" # string offset=178
+.Linfo_string4:
+ .asciz "_Z3barf" # string offset=182
+.Linfo_string5:
+ .asciz "bar" # string offset=190
+.Linfo_string6:
+ .asciz "_Z3fooc" # string offset=194
+.Linfo_string7:
+ .asciz "foo" # string offset=202
+.Linfo_string8:
+ .asciz "unsigned int" # string offset=206
+.Linfo_string9:
+ .asciz "Input" # string offset=219
+.Linfo_string10:
+ .asciz "float" # string offset=225
+.Linfo_string11:
+ .asciz "Param" # string offset=231
+.Linfo_string12:
+ .asciz "char" # string offset=237
+.Linfo_string13:
+ .asciz "Value" # string offset=242
+.Linfo_string14:
+ .asciz "INT" # string offset=248
+.Linfo_string15:
+ .asciz "Added" # string offset=252
+.Linfo_string16:
+ .asciz "FLOAT" # string offset=258
+ .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+ .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/Inputs/pr-44884.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884.cpp
new file mode 100644
index 00000000000000..4b47aae8e0b17b
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884.cpp
@@ -0,0 +1,14 @@
+int bar(float Input) { return (int)Input; }
+
+unsigned foo(char Param) {
+ typedef int INT;
+ INT Value = Param;
+ {
+ typedef float FLOAT;
+ {
+ FLOAT Added = Value + Param;
+ Value = bar(Added);
+ }
+ }
+ return Value + Param;
+}
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s
new file mode 100644
index 00000000000000..1056db0760eae7
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s
@@ -0,0 +1,259 @@
+ .text
+ .file "pr-46466.cpp"
+ .file 1 "/data/projects/scripts/regression-suite/input/general" "pr-46466.cpp"
+ .functype _Z4testv () -> (i32)
+ .section .text._Z4testv,"",@
+ .hidden _Z4testv # -- Begin function _Z4testv
+ .globl _Z4testv
+ .type _Z4testv, at function
+_Z4testv: # @_Z4testv
+.Lfunc_begin0:
+ .functype _Z4testv () -> (i32)
+ .local i32
+# %bb.0: # %entry
+ .loc 1 10 3 prologue_end # pr-46466.cpp:10:3
+ i32.const 1
+ local.set 0
+ local.get 0
+ return
+ end_function
+.Ltmp0:
+.Lfunc_end0:
+ # -- End function
+ .hidden S # @S
+ .type S, at object
+ .section .bss.S,"",@
+ .globl S
+S:
+ .skip 1
+ .size S, 1
+
+ .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 52 # DW_TAG_variable
+ .int8 0 # DW_CHILDREN_no
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 63 # DW_AT_external
+ .int8 25 # DW_FORM_flag_present
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 2 # DW_AT_location
+ .int8 24 # DW_FORM_exprloc
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 3 # Abbreviation Code
+ .int8 19 # DW_TAG_structure_type
+ .int8 1 # DW_CHILDREN_yes
+ .int8 54 # DW_AT_calling_convention
+ .int8 11 # DW_FORM_data1
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 11 # DW_AT_byte_size
+ .int8 11 # DW_FORM_data1
+ .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 4 # Abbreviation Code
+ .int8 13 # DW_TAG_member
+ .int8 0 # DW_CHILDREN_no
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 73 # DW_AT_type
+ .int8 19 # DW_FORM_ref4
+ .int8 58 # DW_AT_decl_file
+ .int8 11 # DW_FORM_data1
+ .int8 59 # DW_AT_decl_line
+ .int8 11 # DW_FORM_data1
+ .int8 56 # DW_AT_data_member_location
+ .int8 11 # DW_FORM_data1
+ .int8 0 # EOM(1)
+ .int8 0 # EOM(2)
+ .int8 5 # Abbreviation Code
+ .int8 23 # DW_TAG_union_type
+ .int8 0 # DW_CHILDREN_no
+ .int8 54 # DW_AT_calling_convention
+ .int8 11 # DW_FORM_data1
+ .int8 3 # DW_AT_name
+ .int8 14 # DW_FORM_strp
+ .int8 11 # DW_AT_byte_size
+ .int8 11 # DW_FORM_data1
+ .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 6 # Abbreviation Code
+ .int8 46 # DW_TAG_subprogram
+ .int8 0 # DW_CHILDREN_no
+ .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 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 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:0x72 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:0x11 DW_TAG_variable
+ .int32 .Linfo_string3 # DW_AT_name
+ .int32 55 # DW_AT_type
+ # DW_AT_external
+ .int8 1 # DW_AT_decl_file
+ .int8 8 # DW_AT_decl_line
+ .int8 5 # DW_AT_location
+ .int8 3
+ .int32 S
+ .int8 3 # Abbrev [3] 0x37:0x1f DW_TAG_structure_type
+ .int8 5 # DW_AT_calling_convention
+ .int32 .Linfo_string6 # DW_AT_name
+ .int8 1 # DW_AT_byte_size
+ .int8 1 # DW_AT_decl_file
+ .int8 1 # DW_AT_decl_line
+ .int8 4 # Abbrev [4] 0x40:0xc DW_TAG_member
+ .int32 .Linfo_string4 # DW_AT_name
+ .int32 76 # DW_AT_type
+ .int8 1 # DW_AT_decl_file
+ .int8 5 # DW_AT_decl_line
+ .int8 0 # DW_AT_data_member_location
+ .int8 5 # Abbrev [5] 0x4c:0x9 DW_TAG_union_type
+ .int8 5 # DW_AT_calling_convention
+ .int32 .Linfo_string5 # DW_AT_name
+ .int8 1 # DW_AT_byte_size
+ .int8 1 # DW_AT_decl_file
+ .int8 2 # DW_AT_decl_line
+ .int8 0 # End Of Children Mark
+ .int8 6 # Abbrev [6] 0x56:0x1f DW_TAG_subprogram
+ .int32 .Lfunc_begin0 # DW_AT_low_pc
+ .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .int8 7 # DW_AT_frame_base
+ .int8 237
+ .int8 3
+ .int32 __stack_pointer
+ .int8 159
+ .int32 .Linfo_string7 # DW_AT_linkage_name
+ .int32 .Linfo_string8 # DW_AT_name
+ .int8 1 # DW_AT_decl_file
+ .int8 9 # DW_AT_decl_line
+ .int32 117 # DW_AT_type
+ # DW_AT_external
+ .int8 7 # Abbrev [7] 0x75:0x7 DW_TAG_base_type
+ .int32 .Linfo_string9 # DW_AT_name
+ .int8 5 # DW_AT_encoding
+ .int8 4 # DW_AT_byte_size
+ .int8 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str,"S",@
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0
+.Linfo_string1:
+ .asciz "pr-46466.cpp" # string offset=111
+.Linfo_string2:
+ .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=124
+.Linfo_string3:
+ .asciz "S" # string offset=178
+.Linfo_string4:
+ .asciz "U" # string offset=180
+.Linfo_string5:
+ .asciz "Union" # string offset=182
+.Linfo_string6:
+ .asciz "Struct" # string offset=188
+.Linfo_string7:
+ .asciz "_Z4testv" # string offset=195
+.Linfo_string8:
+ .asciz "test" # string offset=204
+.Linfo_string9:
+ .asciz "int" # string offset=209
+ .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+ .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/Inputs/pr-46466.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466.cpp
new file mode 100644
index 00000000000000..28be9a5d60ec3b
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466.cpp
@@ -0,0 +1,11 @@
+struct Struct {
+ union Union {
+ enum NestedEnum { RED, BLUE };
+ };
+ Union U;
+};
+
+Struct S;
+int test() {
+ return S.U.BLUE;
+}
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.s
new file mode 100644
index 00000000000000..02afaf70d0ea8e
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.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 .Lfunc_begin0 # 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.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0
+.Linfo_string1:
+ .asciz "test.cpp" # string offset=111
+.Linfo_string2:
+ .asciz "/data/projects/scripts/regression-suite/input/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.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+ .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/Inputs/test.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test.cpp
new file mode 100644
index 00000000000000..5cf39f47735844
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test.cpp
@@ -0,0 +1,9 @@
+using INTPTR = const int *;
+int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) {
+ if (ParamBool) {
+ typedef int INTEGER;
+ const INTEGER CONSTANT = 7;
+ return CONSTANT;
+ }
+ return ParamUnsigned;
+}
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt
new file mode 100644
index 00000000000000..6937bb0f41342d
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt
@@ -0,0 +1,28 @@
+Notes:
+------
+As we should avoid committing binaries (.wasm) to be used in tests,
+instead we provide the '.cpp' source files and the '.s' files.
+
+- For the tests, only the '.s' files are required.
+- We use the target 'wasm32' as the 'wasm64' is not standardized yet.
+
+How to generate .s from .cpp
+----------------------------
+Use clang to generate the '.s'.
+
+ clang --target=wasm32 -S -g Inputs/hello-world.cpp -o Inputs/hello-world-clang.s
+ clang --target=wasm32 -S -g Inputs/pr-43860.cpp -o Inputs/pr-43860-clang.s
+ clang --target=wasm32 -S -g Inputs/pr-44884.cpp -o Inputs/pr-44884-clang.s
+ clang --target=wasm32 -S -g Inputs/pr-46466.cpp -o Inputs/pr-46466-clang.s
+ clang --target=wasm32 -S -g Inputs/test.cpp -o Inputs/test-clang.s
+
+How to generate .o from .s
+--------------------------------
+Each test executes one of the following commands in order to generate
+the binary '.wasm' used by that specific test:
+
+ llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/hello-world-clang.s -o hello-world-clang.o
+ llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/pr-43860-clang.s -o pr-43860-clang.o
+ llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/pr-44884-clang.s -o pr-44884-clang.o
+ llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/pr-46466-clang.s -o pr-46466-clang.o
+ llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/test-clang.s -o test-clang.o
More information about the llvm-commits
mailing list