From 3254815539b36049fb074bf3cb18ee8bbb2ffdb6 Mon Sep 17 00:00:00 2001 From: Adam Yang <31109344+adam-yang@users.noreply.github.com> Date: Fri, 20 Jun 2025 16:52:37 -0700 Subject: [PATCH 01/11] Made llvm-debuginfo-analyzer work for AMDGPU. A few changes to generate DWARF correctly in AMDGPU --- .../LogicalView/Readers/LVBinaryReader.h | 3 +- .../LogicalView/Readers/LVBinaryReader.cpp | 4 +- .../LogicalView/Readers/LVCodeViewReader.cpp | 10 +- .../LogicalView/Readers/LVDWARFReader.cpp | 12 +- .../AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp | 3 +- .../Target/AMDGPU/SIPreAllocateWWMRegs.cpp | 3 + .../llvm-debuginfo-analyzer/DWARF/amdgpu.ll | 103 ++++++++++++++++++ 7 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h index 1847fa8323480..1f8b884bc1b5d 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h @@ -159,7 +159,8 @@ class LVBinaryReader : public LVReader { LVAddress WasmCodeSectionOffset = 0; // Loads all info for the architecture of the provided object file. - Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures); + Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures, + StringRef CPU); virtual void mapRangeAddress(const object::ObjectFile &Obj) {} virtual void mapRangeAddress(const object::ObjectFile &Obj, diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp index 80b4185b7c600..414f0f3efc82d 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp @@ -275,7 +275,8 @@ void LVBinaryReader::mapVirtualAddress(const object::COFFObjectFile &COFFObj) { } Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, - StringRef TheFeatures) { + StringRef TheFeatures, + StringRef CPU) { std::string TargetLookupError; const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, TargetLookupError); @@ -298,7 +299,6 @@ Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, MAI.reset(AsmInfo); // Target subtargets. - StringRef CPU; MCSubtargetInfo *SubtargetInfo( TheTarget->createMCSubtargetInfo(TheTriple, CPU, TheFeatures)); if (!SubtargetInfo) diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp index e5895516b5e77..2ff70816b4bf1 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp @@ -1190,7 +1190,12 @@ Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) { FeaturesValue = SubtargetFeatures(); } FeaturesValue = *Features; - return loadGenericTargetInfo(TT.str(), FeaturesValue.getString()); + + StringRef CPU; + if (auto OptCPU = Obj.tryGetCPUName()) + CPU = *OptCPU; + + return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU); } Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) { @@ -1200,8 +1205,9 @@ Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) { TT.setOS(Triple::Win32); StringRef TheFeature = ""; + StringRef TheCPU = ""; - return loadGenericTargetInfo(TT.str(), TheFeature); + return loadGenericTargetInfo(TT.str(), TheFeature, TheCPU); } std::string LVCodeViewReader::getRegisterName(LVSmall Opcode, diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 696e2bc948a2e..62134dfdadf46 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -956,10 +956,7 @@ LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset, Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) { // Detect the architecture from the object file. We usually don't need OS // info to lookup a target and create register info. - Triple TT; - TT.setArch(Triple::ArchType(Obj.getArch())); - TT.setVendor(Triple::UnknownVendor); - TT.setOS(Triple::UnknownOS); + Triple TT = Obj.makeTriple(); // Features to be passed to target/subtarget Expected Features = Obj.getFeatures(); @@ -969,7 +966,12 @@ Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) { FeaturesValue = SubtargetFeatures(); } FeaturesValue = *Features; - return loadGenericTargetInfo(TT.str(), FeaturesValue.getString()); + + StringRef CPU; + if (auto OptCPU = Obj.tryGetCPUName()) + CPU = *OptCPU; + + return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU); } void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) { diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp index 8f89168754180..bf390e836078e 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp @@ -226,7 +226,8 @@ class ELFAMDGPUAsmBackend : public AMDGPUAsmBackend { public: ELFAMDGPUAsmBackend(const Target &T, const Triple &TT) : AMDGPUAsmBackend(T), Is64Bit(TT.isAMDGCN()), - HasRelocationAddend(TT.getOS() == Triple::AMDHSA) { + HasRelocationAddend(TT.getOS() == Triple::AMDHSA || + TT.getOS() == Triple::AMDPAL) { switch (TT.getOS()) { case Triple::AMDHSA: OSABI = ELF::ELFOSABI_AMDGPU_HSA; diff --git a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp index 205a45a045a42..469a6525b4ac0 100644 --- a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp +++ b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp @@ -130,6 +130,9 @@ void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) { if (VirtReg.isPhysical()) continue; + if (MI.isDebugInstr() && VirtReg == AMDGPU::NoRegister) + continue; + if (!VRM->hasPhys(VirtReg)) continue; diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll new file mode 100644 index 0000000000000..1d031979309a6 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll @@ -0,0 +1,103 @@ +; RUN: llc %s -o %t.o -mcpu=gfx1030 -filetype=obj -O0 +; RUN: llvm-debuginfo-analyzer %t.o --print=all --attribute=all | FileCheck %s + +; This test compiles this module with AMDGPU backend under -O0, +; and makes sure llvm-debuginfo-analzyer works for it. + +; Simple checks to make sure llvm-debuginfo-analzyer didn't fail early. +; CHECK: Logical View: +; CHECK: {CompileUnit} +; CHECK: {Code} 's_endpgm' + +source_filename = "module" +target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-p10:32:32-p11:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9-p32:32:32-v8:8-v16:16-v32:32-v48:32-v64:32-v80:32-v96:32-v112:32-v128:32-v144:32-v160:32-v176:32-v192:32-v208:32-v224:32-v240:32-v256:32-i1:32-i8:8-i16:16-i32:32-i64:32-f16:16-f32:32-f64:32" +target triple = "amdgcn-amd-amdpal" + +%dx.types.ResRet.f32 = type { float, float, float, float, i32 } + +; Function Attrs: memory(readwrite) +define dllexport amdgpu_cs void @_amdgpu_cs_main(i32 inreg noundef %globalTable, i32 inreg noundef %userdata4, <3 x i32> inreg noundef %WorkgroupId, i32 inreg noundef %MultiDispatchInfo, <3 x i32> noundef %LocalInvocationId) #0 !dbg !14 { + %LocalInvocationId.i0 = extractelement <3 x i32> %LocalInvocationId, i64 0, !dbg !28 + %WorkgroupId.i0 = extractelement <3 x i32> %WorkgroupId, i64 0, !dbg !28 + %1 = call i64 @llvm.amdgcn.s.getpc(), !dbg !28 + %2 = shl i32 %WorkgroupId.i0, 6, !dbg !28 + %3 = add i32 %LocalInvocationId.i0, %2, !dbg !28 + #dbg_value(i32 %3, !29, !DIExpression(DW_OP_LLVM_fragment, 0, 32), !28) + %4 = and i64 %1, -4294967296, !dbg !30 + %5 = zext i32 %userdata4 to i64, !dbg !30 + %6 = or disjoint i64 %4, %5, !dbg !30 + %7 = inttoptr i64 %6 to ptr addrspace(4), !dbg !30 + call void @llvm.assume(i1 true) [ "align"(ptr addrspace(4) %7, i32 4), "dereferenceable"(ptr addrspace(4) %7, i32 -1) ], !dbg !30 + %8 = load <4 x i32>, ptr addrspace(4) %7, align 4, !dbg !30, !invariant.load !2 + %9 = call float @llvm.amdgcn.struct.buffer.load.format.f32(<4 x i32> %8, i32 %3, i32 0, i32 0, i32 0), !dbg !30 + #dbg_value(%dx.types.ResRet.f32 poison, !31, !DIExpression(), !32) + %10 = fmul reassoc arcp contract afn float %9, 2.000000e+00, !dbg !33 + #dbg_value(float %10, !34, !DIExpression(), !35) + call void @llvm.assume(i1 true) [ "align"(ptr addrspace(4) %7, i32 4), "dereferenceable"(ptr addrspace(4) %7, i32 -1) ], !dbg !36 + %11 = getelementptr i8, ptr addrspace(4) %7, i64 32, !dbg !36 + %.upto01 = insertelement <4 x float> poison, float %10, i64 0, !dbg !36 + %12 = shufflevector <4 x float> %.upto01, <4 x float> poison, <4 x i32> zeroinitializer, !dbg !36 + %13 = load <4 x i32>, ptr addrspace(4) %11, align 4, !dbg !36, !invariant.load !2 + call void @llvm.amdgcn.struct.buffer.store.format.v4f32(<4 x float> %12, <4 x i32> %13, i32 %3, i32 0, i32 0, i32 0), !dbg !36 + ret void, !dbg !37 +} + +; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) +declare noundef i64 @llvm.amdgcn.s.getpc() #1 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) +declare void @llvm.assume(i1 noundef) #2 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(write) +declare void @llvm.amdgcn.struct.buffer.store.format.v4f32(<4 x float>, <4 x i32>, i32, i32, i32, i32 immarg) #3 + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(read) +declare float @llvm.amdgcn.struct.buffer.load.format.f32(<4 x i32>, i32, i32, i32, i32 immarg) #4 + +attributes #0 = { memory(readwrite) "amdgpu-flat-work-group-size"="64,64" "amdgpu-memory-bound"="false" "amdgpu-num-sgpr"="4294967295" "amdgpu-num-vgpr"="4294967295" "amdgpu-prealloc-sgpr-spill-vgprs" "amdgpu-unroll-threshold"="1200" "amdgpu-wave-limiter"="false" "amdgpu-work-group-info-arg-no"="3" "denormal-fp-math"="ieee" "denormal-fp-math-f32"="preserve-sign" "target-features"=",+wavefrontsize64,+cumode,+enable-flat-scratch" } +attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } +attributes #2 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } +attributes #3 = { nocallback nofree nosync nounwind willreturn memory(write) } +attributes #4 = { nocallback nofree nosync nounwind willreturn memory(read) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!12, !13} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "dxcoob 1.7.2308.16 (52da17e29)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3) +!1 = !DIFile(filename: "tests\\basic_var.hlsl", directory: "") +!2 = !{} +!3 = !{!4, !10} +!4 = distinct !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) +!5 = !DIGlobalVariable(name: "u0", linkageName: "\01?u0@@3V?$RWBuffer@M@@A", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true) +!6 = !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer", file: !1, line: 2, size: 32, align: 32, elements: !2, templateParams: !7) +!7 = !{!8} +!8 = !DITemplateTypeParameter(name: "element", type: !9) +!9 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) +!10 = distinct !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) +!11 = !DIGlobalVariable(name: "u1", linkageName: "\01?u1@@3V?$RWBuffer@M@@A", scope: !0, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true) +!12 = !{i32 2, !"Dwarf Version", i32 5} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !15, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) +!15 = !DISubroutineType(types: !16) +!16 = !{null, !17} +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint3", file: !1, baseType: !18) +!18 = !DICompositeType(tag: DW_TAG_class_type, name: "vector", file: !1, size: 96, align: 32, elements: !19, templateParams: !24) +!19 = !{!20, !22, !23} +!20 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !18, file: !1, baseType: !21, size: 32, align: 32, flags: DIFlagPublic) +!21 = !DIBasicType(name: "unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned) +!22 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !18, file: !1, baseType: !21, size: 32, align: 32, offset: 32, flags: DIFlagPublic) +!23 = !DIDerivedType(tag: DW_TAG_member, name: "z", scope: !18, file: !1, baseType: !21, size: 32, align: 32, offset: 64, flags: DIFlagPublic) +!24 = !{!25, !26} +!25 = !DITemplateTypeParameter(name: "element", type: !21) +!26 = !DITemplateValueParameter(name: "element_count", type: !27, value: i32 3) +!27 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!28 = !DILocation(line: 7, column: 17, scope: !14) +!29 = !DILocalVariable(name: "dtid", arg: 1, scope: !14, file: !1, line: 7, type: !17) +!30 = !DILocation(line: 11, column: 18, scope: !14) +!31 = !DILocalVariable(name: "my_var", scope: !14, file: !1, line: 11, type: !9) +!32 = !DILocation(line: 11, column: 9, scope: !14) +!33 = !DILocation(line: 14, column: 26, scope: !14) +!34 = !DILocalVariable(name: "my_var2", scope: !14, file: !1, line: 14, type: !9) +!35 = !DILocation(line: 14, column: 9, scope: !14) +!36 = !DILocation(line: 17, column: 14, scope: !14) +!37 = !DILocation(line: 19, column: 1, scope: !14) \ No newline at end of file From c6bacae4803be21e4204a202d4c2b1c4a5559bb6 Mon Sep 17 00:00:00 2001 From: Adam Yang <31109344+adam-yang@users.noreply.github.com> Date: Fri, 20 Jun 2025 18:21:29 -0700 Subject: [PATCH 02/11] Moved the test to amdgpu target tests --- .../AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename llvm/test/{tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll => CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll} (100%) diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll similarity index 100% rename from llvm/test/tools/llvm-debuginfo-analyzer/DWARF/amdgpu.ll rename to llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll From dd3c72b32b8a23ba8a8a332433b704f86de2142a Mon Sep 17 00:00:00 2001 From: Adam Yang <31109344+adam-yang@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:17:30 -0700 Subject: [PATCH 03/11] Added new tool, and test code --- .../llvm/DebugInfo/DWARF/DWARFFormValue.h | 1 + .../DebugInfo/LogicalView/Core/LVLocation.h | 2 + llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 2 + .../DebugInfo/LogicalView/Core/LVLocation.cpp | 19 +- .../DebugInfo/LogicalView/Core/LVScope.cpp | 3 + .../LogicalView/Readers/LVBinaryReader.cpp | 3 + .../LogicalView/Readers/LVDWARFReader.cpp | 11 +- .../tools/llvm-debuginfo-check/CMakeLists.txt | 17 + .../llvm-debuginfo-check.cpp | 457 ++++++++++++++++++ 9 files changed, 511 insertions(+), 4 deletions(-) create mode 100644 llvm/tools/llvm-debuginfo-check/CMakeLists.txt create mode 100644 llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 3818a90b909c6..bfbc7d5cc087d 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -83,6 +83,7 @@ class DWARFFormValue { LLVM_ABI bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } + LLVM_DUMP_METHOD void dump() const; LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; LLVM_ABI void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h index 0718e33f5645b..c16a52300c546 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h @@ -159,6 +159,7 @@ class LLVM_ABI LVLocation : public LVObject { void print(raw_ostream &OS, bool Full = true) const override; void printExtra(raw_ostream &OS, bool Full = true) const override; + virtual void printLocations(raw_ostream &OS) const {} }; class LLVM_ABI LVLocationSymbol final : public LVLocation { @@ -179,6 +180,7 @@ class LLVM_ABI LVLocationSymbol final : public LVLocation { void printRawExtra(raw_ostream &OS, bool Full = true) const override; void printExtra(raw_ostream &OS, bool Full = true) const override; + void printLocations(raw_ostream &OS) const override; }; } // end namespace logicalview diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index bc4badc771380..01cc184fc8ea8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -379,6 +379,8 @@ void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, OS << format(" [%" PRIu64 "]", SectionIndex); } +LLVM_DUMP_METHOD void DWARFFormValue::dump() const { dump(dbgs()); } + void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { uint64_t UValue = Value.uval; bool CURelativeOffset = false; diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp index 3c078d8ee74b8..5d068e2871899 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp @@ -648,6 +648,19 @@ void LVLocation::print(LVLocations *Locations, raw_ostream &OS, bool Full) { Location->print(OS, Full); } +void LVLocationSymbol::printLocations(raw_ostream &OS) const { + if (Entries) { + bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation(); + std::string Leading; + for (LVOperation *Operation : *Entries) { + OS << Leading + << (CodeViewLocation ? Operation->getOperandsCodeViewInfo() + : Operation->getOperandsDWARFInfo()); + Leading = ", "; + } + } +} + void LVLocationSymbol::printExtra(raw_ostream &OS, bool Full) const { OS << "{Location}"; if (getIsCallSite()) @@ -657,8 +670,11 @@ void LVLocationSymbol::printExtra(raw_ostream &OS, bool Full) const { // Print location entries. if (Full && Entries) { + std::string Str; + raw_string_ostream Stream(Str); + printLocations(Stream); + #if 0 bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation(); - std::stringstream Stream; std::string Leading; for (LVOperation *Operation : *Entries) { Stream << Leading @@ -666,6 +682,7 @@ void LVLocationSymbol::printExtra(raw_ostream &OS, bool Full) const { : Operation->getOperandsDWARFInfo()); Leading = ", "; } + #endif printAttributes(OS, Full, "{Entry} ", const_cast(this), StringRef(Stream.str()), /*UseQuotes=*/false, diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp index 93a567e89f774..714b269e477c1 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp @@ -134,6 +134,9 @@ void LVScope::addElement(LVLine *Line) { if (!Lines) Lines = std::make_unique(); + if (Line->getAddress() == 0x2fc) + outs() << "Set Parent for line at addr: " << Line->getAddress() + << "\n "; // Add it to parent. Lines->push_back(Line); Line->setParent(this); diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp index 414f0f3efc82d..42d71e13fa512 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp @@ -733,6 +733,9 @@ void LVBinaryReader::processLines(LVLines *DebugLines, for (LVLine *Line : *DebugLines) { // Using the current line address, get its associated lexical scope and // add the line information to it. + + if (Line->getAddress() == 0x2fc) + outs() << ""; Scope = ScopesWithRanges->getEntry(Line->getAddress()); if (!Scope) { // If missing scope, use the compile unit. diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 62134dfdadf46..267a4ea40661a 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -252,6 +252,8 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die, case dwarf::DW_AT_ranges: if (RangesDataAvailable && options().getGeneralCollectRanges()) { + if (CurrentScope->getID() == 2237) + outs() << ""; auto GetRanges = [](const DWARFFormValue &FormValue, DWARFUnit *U) -> Expected { if (FormValue.getForm() == dwarf::DW_FORM_rnglistx) @@ -274,7 +276,7 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die, for (DWARFAddressRange &Range : Ranges) { // This seems to be a tombstone for empty ranges. if ((Range.LowPC == Range.HighPC) || - (Range.LowPC = getTombstoneAddress())) + (Range.LowPC == getTombstoneAddress())) continue; // Store the real upper limit for the address range. if (UpdateHighAddress && Range.HighPC > 0) @@ -461,13 +463,16 @@ LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, if (!CurrentRanges.empty()) { for (LVAddressRange &Range : CurrentRanges) addSectionRange(SectionIndex, CurrentScope, Range.first, - Range.second); + Range.second > Range.first ? Range.second - 1 + : Range.second); CurrentRanges.clear(); } // If the scope is the CU, do not update the ranges set. if (FoundLowPC && FoundHighPC && !IsCompileUnit) { addSectionRange(SectionIndex, CurrentScope, CurrentLowPC, - CurrentHighPC); + CurrentHighPC > CurrentLowPC + ? CurrentHighPC - 1 + : CurrentHighPC); // Make hi-pc exclusive } } } diff --git a/llvm/tools/llvm-debuginfo-check/CMakeLists.txt b/llvm/tools/llvm-debuginfo-check/CMakeLists.txt new file mode 100644 index 0000000000000..4ca37ac8ae856 --- /dev/null +++ b/llvm/tools/llvm-debuginfo-check/CMakeLists.txt @@ -0,0 +1,17 @@ +set(LLVM_LINK_COMPONENTS + AllTargetsDescs + AllTargetsDisassemblers + AllTargetsInfos + BinaryFormat + DebugInfoCodeView + DebugInfoLogicalView + DebugInfoPDB + MC + MCDisassembler + Object + Support + ) + +add_llvm_tool(llvm-debuginfo-check + llvm-debuginfo-check.cpp + ) diff --git a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp new file mode 100644 index 0000000000000..3fbbdb5f79cd4 --- /dev/null +++ b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp @@ -0,0 +1,457 @@ +//===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This tool prints out the logical view of debug info in a way that is easy +// to verify correctness. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" +#include "llvm/ADT/SetVector.h" + +#include +#include +#include + +using namespace llvm; +using namespace logicalview; + +static cl::opt + InputFilename(cl::Positional, "", + cl::desc("Input file, an object file with DWARF."), + cl::Required); + +static cl::opt IncludeCode("code", cl::desc("Include asm")); +static cl::opt IncludeRanges("ranges", cl::desc("Include variable ranges")); +static cl::opt IncludeVars("vars", cl::desc("Include live variables")); + +template T Take(Expected ExpectedResult, const Twine &Msg) { + if (!ExpectedResult) { + auto Err = ExpectedResult.takeError(); + errs() << Msg << " " << toStringWithoutConsuming(Err) << '\n'; + exit(2); + } + T ret = std::move(*ExpectedResult); + return ret; +} + +struct ScopePrinterMk2 { + + std::vector Lines; + std::unordered_map> LivetimeBegins; + std::unordered_map> + LivetimeEndsExclusive; + raw_ostream &OS; + + void Walk(raw_ostream &OS, const LVScope* Scope) { + if (Scope->scopeCount()) { + for (const LVScope *ChildScope : *Scope->getScopes()) + Walk(OS, ChildScope); + } + if (Scope->lineCount()) { + for (const LVLine *Line : *Scope->getLines()) { + Lines.push_back(Line); + if (Line->getParentScope() != Scope) + OS << ""; + } + } + if (Scope->symbolCount()) { + for (const LVSymbol *Symbol : *Scope->getSymbols()) { + LVLocations SymbolLocations; + Symbol->getLocations(SymbolLocations); + if (SymbolLocations.empty()) + continue; + + if (IncludeRanges) { + OS << "RANGES: " << Symbol->getName() << " (line " << Symbol->getLineNumber() << ")" << ": "; + } + + for (const LVLocation *Loc : SymbolLocations) { + if (Loc->getIsGapEntry()) + continue; + + LVAddress Begin = Loc->getLowerAddress(); + LVAddress End = Loc->getUpperAddress(); + LivetimeBegins[Begin].push_back(Loc); + LivetimeEndsExclusive[End].push_back(Loc); + if (IncludeRanges) { + OS << "[" << hexValue(Begin) << ":" << hexValue(End) << "] "; + } + } + + if (IncludeRanges) + OS << "\n"; + } + } + } + + ScopePrinterMk2(raw_ostream &OS, const LVScopeFunction *Fn) : OS(OS) { + Walk(OS, Fn); + std::sort(Lines.begin(), Lines.end(), + [](const LVLine *a, const LVLine *b) -> bool { + if (a->getAddress() != b->getAddress()) + return a->getAddress() < b->getAddress(); + if (a->getIsLineDebug() != b->getIsLineDebug()) + return a->getIsLineDebug(); + return a->getID() < b->getID(); + }); + + //DumpAllInlineFunctionLevels(Fn); + } + + + static void PrintIndent(int Indent) { + for (int i = 0; i < Indent; i++) + outs() << " "; + } + + static void PrintCallstack(raw_ostream& OS, const LVScope* Scope) { + bool First = true; + const LVScope *PrevScope = nullptr; + while (Scope) { + if (Scope->getIsFunction() || Scope->getIsInlinedFunction()) { + OS << "[" << Scope->getName(); + if (PrevScope && PrevScope->getIsInlinedFunction()) { + OS << ":" << cast(PrevScope)->getCallLineNumber(); + } + OS << "]"; + First = false; + PrevScope = Scope; + } + Scope = Scope->getParentScope(); + } + } + + void DumpAllInlineFunctionLevels(const LVScope *Scope) { + if (Scope->getIsInlinedFunction()) { + outs() << Scope->getName() << " ID:" << Scope->getID(); + if (Scope->rangeCount()) { + for (auto R : *Scope->getRanges()) { + auto Lo = Scope->getRanges()->front()->getLowerAddress(); + auto Hi = Scope->getRanges()->front()->getUpperAddress(); + outs() << " [" << hexValue(Lo) << ":" + << hexValue(Hi) << "]"; + } + } + + outs() << ", level: " << Scope->getLevel() << "\n"; + } + if (Scope->scopeCount()) + for (auto S : *Scope->getScopes()) + DumpAllInlineFunctionLevels(S); + } + + static bool IsChildScopeOf(const LVScope *A, const LVScope *B) { + while (A) { + A = A->getParentScope(); + if (A == B) + return true; + } + return false; + } + + void Print() { + SetVector LiveSymbols; // This needs to be ordered since we're iterating over it. + int LastLine = -1; + StringRef LastFilename; + for (const LVLine *Line : Lines) { + + const LVScope *Scope = Line->getParentScope(); + + // Update live list: Add lives + for (auto Loc : LivetimeBegins[Line->getAddress()]) + LiveSymbols.insert(Loc); + // Update live list: remove dead + for (auto Loc : LivetimeEndsExclusive[Line->getAddress()]) + LiveSymbols.remove(Loc); + + if (Line->getIsLineDebug() && Line->getLineNumber() != 0) { + auto LineDebug = cast(Line); + + if (LastLine != LineDebug->getLineNumber() || + LineDebug->getPathname() != LastFilename) { + OS << "LINE: " << " [" << hexValue(LineDebug->getAddress()) << "] " + << LineDebug->getPathname() << ":" << LineDebug->getLineNumber() + << " "; + PrintCallstack(OS, Scope); + OS << "\n"; + if (IncludeVars) { + for (auto SymLoc : LiveSymbols) { + const LVSymbol *Sym = SymLoc->getParentSymbol(); + if (Sym->getName() == "InMRT1") + outs() << ""; + auto SymScope = Sym->getParentScope(); + auto LineScope = LineDebug->getParentScope(); + if (SymScope != LineScope && !IsChildScopeOf(LineScope, SymScope)) + continue; + PrintIndent(1); + OS << "VAR: " << Sym->getName() << ": " + << Sym->getType()->getName() + << " : "; + SymLoc->printLocations(OS); + OS << " (line " << Sym->getLineNumber() << ")"; + OS << "\n"; + } + } + } + + LastLine = Line->getLineNumber(); + LastFilename = Line->getPathname(); + } else if (IncludeCode && Line->getIsLineAssembler()) { + OS << " CODE: " << " [" << hexValue(Line->getAddress()) << "] " + << Line->getName() << "\n"; + } + } + } +}; + +struct ScopePrinter { + unsigned NumScopesPrinted = 0; + std::unordered_map> LivetimeBegins; + std::unordered_map> + LivetimeEndsInclusive; + SetVector LiveSymbols; // This needs to be ordered since we're iterating over it. + std::unordered_set SeenScopes; + + static void PrintIndent(int Indent) { + for (int i = 0; i < Indent; i++) + outs() << " "; + }; + + void PrintScope(const LVScope *Scope, int Indent) { + NumScopesPrinted++; + SeenScopes.insert(Scope); + + bool IsInlined = false; + if (Scope->getIsInlinedFunction()) { + Indent++; + auto InlinedFn = cast(Scope); + IsInlined = true; + PrintIndent(Indent); + outs() << "INLINED_FUNCTION: " << InlinedFn->getName() << "\n"; + } + + if (const LVSymbols *Symbols = Scope->getSymbols()) { + for (const LVSymbol *Symbol : *Symbols) { + LVLocations SymbolLocations; + Symbol->getLocations(SymbolLocations); + for (const LVLocation *Loc : SymbolLocations) { + if (Loc->getIsGapEntry()) + continue; + + LVAddress Begin = Loc->getLowerAddress(); + LVAddress End = Loc->getUpperAddress(); + LivetimeBegins[Begin].push_back(Loc); + LivetimeEndsInclusive[End].push_back(Loc); + if (IncludeRanges) { + outs() << "RANGE: " << Symbol->getName() << ": [" + << hexValue(Begin) << ":" << hexValue(End) << "]\n"; + } + } + } + } + + auto Lines = Scope->getLines(); + if (Lines) { + int LastLine = -1; + StringRef LastFilename; + for (const LVLine *Line : *Lines) { + + if (auto Scopes = Scope->getScopes()) { + for (const LVScope *SubScope : *Scopes) { + if (SeenScopes.count(SubScope)) + continue; +#if 0 + if (SubScope->getBaseAddress() < Line->getAddress()) { + PrintScope(SubScope, Indent); + } +#else + + + struct Local { + static LVAddress GetBaseAddress(const LVScope *S) { + if (S->rangeCount()) { + return S->getRanges()->front()->getLowerAddress(); + } + if (S->lineCount()) { + return S->getLines()->front()->getAddress(); + } + if (S->scopeCount()) { + for (LVScope *SubS : *S->getScopes()) { + LVAddress A = GetBaseAddress(SubS); + if (A != -1) + return A; + } + } + return -1; + }; + }; +#if 0 + auto ScopeLines = SubScope->getLines(); + if (ScopeLines && ScopeLines->size() && + ScopeLines->front()->getAddress() < Line->getAddress()) { + PrintScope(SubScope, Indent); + } else { + outs() << ""; + } +#else + unsigned BaseAdress = Local::GetBaseAddress(SubScope); + if (BaseAdress < Line->getAddress()) { + PrintScope(SubScope, Indent); + } +#endif +#endif + } + } + + // Update live list: Add lives + for (auto Loc : LivetimeBegins[Line->getAddress()]) + LiveSymbols.insert(Loc); + + if (Line->getIsLineDebug() && Line->getLineNumber() != 0) { + auto LineDebug = cast(Line); + if (LineDebug->getLineNumber() == 605) + outs() << ""; + if (LastLine != LineDebug->getLineNumber() || + LineDebug->getPathname() != LastFilename) { + PrintIndent(Indent+1); + outs() << "LINE: " << " [" + << hexValue(LineDebug->getAddress()) << "] " + << LineDebug->getPathname() << ":" + << LineDebug->getLineNumber() << "\n"; + + if (IncludeVars) { + for (auto SymLoc : LiveSymbols) { + PrintIndent(Indent+2); + const LVSymbol *Sym = SymLoc->getParentSymbol(); + outs() << "VAR: " << Sym->getName() << ": " + << Sym->getType()->getName() + << " : "; + SymLoc->printLocations(outs()); + outs() << "\n"; + } + } + } + LastLine = LineDebug->getLineNumber(); + LastFilename = LineDebug->getPathname(); + } else if (Line->getIsLineAssembler()) { + if (IncludeCode) + outs() << " CODE: " << " [" << hexValue(Line->getAddress()) + << "] " << Line->getName() << "\n"; + } + + // Update live list: remove dead + for (auto Loc : LivetimeEndsInclusive[Line->getAddress()]) + LiveSymbols.remove(Loc); + } + } else if (Scope->scopeCount()) { + for (auto SubS : *Scope->getScopes()) { + PrintScope(SubS, Indent); + } + } + + if (IsInlined) { + PrintIndent(Indent); + outs() << "END_INLINED_FUNCTION\n"; + Indent--; + } + } + + static unsigned CountScopes(const LVScope *Scope) { + unsigned Count = 0; + auto Scopes = Scope->getScopes(); + if (Scopes) { + for (auto S : *Scopes) + Count += CountScopes(S); + } + return Count + 1; + } + + std::vector UnseenScopes; + void CollectUnsceenScopes(const LVScope *Scope) { + if (!SeenScopes.count(Scope)) { + UnseenScopes.push_back(Scope); + Scope->dump(); + } + if (Scope->scopeCount()) { + for (auto S : *Scope->getScopes()) + CollectUnsceenScopes(S); + } + } + +}; + +int main(int argc, char *argv[]) { + InitLLVM X(argc, argv); + + // Initialize targets and assembly printers/parsers. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + InitializeAllDisassemblers(); + + cl::ParseCommandLineOptions(argc, argv, + "Check debug info correctness via annotations.\n"); + + ScopedPrinter W(llvm::outs()); + LVOptions Options; + Options.setAttributeAll(); + Options.setAttributeAnyLocation(); + Options.setPrintAll(); + Options.setPrintAnyLine(); + Options.resolveDependencies(); + std::vector Objects; + LVReaderHandler Handler(Objects, W, Options); + auto Readers = Take(Handler.createReader(InputFilename), + Twine("Failed to create LV reader from '") + Twine(InputFilename) + + Twine("'")); + + auto *CU = Readers->getCompileUnit(); + if (!CU) + return 2; + + for (LVElement *Child : *CU->getChildren()) { + auto *Fn = dyn_cast(Child); + if (Fn) { + const LVLines *Lines = Fn->getLines(); + // If there's no lines, this function has no body. + if (!Lines) + continue; + outs() << "FUNCTION: " << Child->getName() << "\n"; + +#if 0 + ScopePrinter P; + P.PrintScope(Fn, 0); + + P.CollectUnsceenScopes(Fn); + + for (auto S : P.UnseenScopes) { + if (S->symbolCount()) { + for (auto Sym : *S->getSymbols()) + outs() << Sym->getName() << ": " << Sym->getTypeName() << " (line" + << Sym->getLineNumber() << ")" << "\n"; + } + } + + //unsigned NumScopes = ScopePrinter::CountScopes(Fn); + + outs() << ""; +#else + ScopePrinterMk2 P(outs(), Fn); + P.Print(); +#endif + + } + } + + return EXIT_SUCCESS; +} From 5465020274d753e285c60bfd2379f16dd6982efe Mon Sep 17 00:00:00 2001 From: Adam Yang <31109344+adam-yang@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:21:00 -0700 Subject: [PATCH 04/11] Deleted old code. Small cleanup --- .../llvm-debuginfo-check.cpp | 231 +----------------- 1 file changed, 6 insertions(+), 225 deletions(-) diff --git a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp index 3fbbdb5f79cd4..c0072b16505b8 100644 --- a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp +++ b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp @@ -45,8 +45,7 @@ template T Take(Expected ExpectedResult, const Twine &Msg) { return ret; } -struct ScopePrinterMk2 { - +struct ScopePrinter { std::vector Lines; std::unordered_map> LivetimeBegins; std::unordered_map> @@ -95,7 +94,7 @@ struct ScopePrinterMk2 { } } - ScopePrinterMk2(raw_ostream &OS, const LVScopeFunction *Fn) : OS(OS) { + ScopePrinter(raw_ostream &OS, const LVScopeFunction *Fn) : OS(OS) { Walk(OS, Fn); std::sort(Lines.begin(), Lines.end(), [](const LVLine *a, const LVLine *b) -> bool { @@ -105,14 +104,11 @@ struct ScopePrinterMk2 { return a->getIsLineDebug(); return a->getID() < b->getID(); }); - - //DumpAllInlineFunctionLevels(Fn); } - - static void PrintIndent(int Indent) { + static void PrintIndent(raw_ostream &OS, int Indent) { for (int i = 0; i < Indent; i++) - outs() << " "; + OS << " "; } static void PrintCallstack(raw_ostream& OS, const LVScope* Scope) { @@ -132,25 +128,6 @@ struct ScopePrinterMk2 { } } - void DumpAllInlineFunctionLevels(const LVScope *Scope) { - if (Scope->getIsInlinedFunction()) { - outs() << Scope->getName() << " ID:" << Scope->getID(); - if (Scope->rangeCount()) { - for (auto R : *Scope->getRanges()) { - auto Lo = Scope->getRanges()->front()->getLowerAddress(); - auto Hi = Scope->getRanges()->front()->getUpperAddress(); - outs() << " [" << hexValue(Lo) << ":" - << hexValue(Hi) << "]"; - } - } - - outs() << ", level: " << Scope->getLevel() << "\n"; - } - if (Scope->scopeCount()) - for (auto S : *Scope->getScopes()) - DumpAllInlineFunctionLevels(S); - } - static bool IsChildScopeOf(const LVScope *A, const LVScope *B) { while (A) { A = A->getParentScope(); @@ -194,7 +171,7 @@ struct ScopePrinterMk2 { auto LineScope = LineDebug->getParentScope(); if (SymScope != LineScope && !IsChildScopeOf(LineScope, SymScope)) continue; - PrintIndent(1); + PrintIndent(OS, 1); OS << "VAR: " << Sym->getName() << ": " << Sym->getType()->getName() << " : "; @@ -215,182 +192,6 @@ struct ScopePrinterMk2 { } }; -struct ScopePrinter { - unsigned NumScopesPrinted = 0; - std::unordered_map> LivetimeBegins; - std::unordered_map> - LivetimeEndsInclusive; - SetVector LiveSymbols; // This needs to be ordered since we're iterating over it. - std::unordered_set SeenScopes; - - static void PrintIndent(int Indent) { - for (int i = 0; i < Indent; i++) - outs() << " "; - }; - - void PrintScope(const LVScope *Scope, int Indent) { - NumScopesPrinted++; - SeenScopes.insert(Scope); - - bool IsInlined = false; - if (Scope->getIsInlinedFunction()) { - Indent++; - auto InlinedFn = cast(Scope); - IsInlined = true; - PrintIndent(Indent); - outs() << "INLINED_FUNCTION: " << InlinedFn->getName() << "\n"; - } - - if (const LVSymbols *Symbols = Scope->getSymbols()) { - for (const LVSymbol *Symbol : *Symbols) { - LVLocations SymbolLocations; - Symbol->getLocations(SymbolLocations); - for (const LVLocation *Loc : SymbolLocations) { - if (Loc->getIsGapEntry()) - continue; - - LVAddress Begin = Loc->getLowerAddress(); - LVAddress End = Loc->getUpperAddress(); - LivetimeBegins[Begin].push_back(Loc); - LivetimeEndsInclusive[End].push_back(Loc); - if (IncludeRanges) { - outs() << "RANGE: " << Symbol->getName() << ": [" - << hexValue(Begin) << ":" << hexValue(End) << "]\n"; - } - } - } - } - - auto Lines = Scope->getLines(); - if (Lines) { - int LastLine = -1; - StringRef LastFilename; - for (const LVLine *Line : *Lines) { - - if (auto Scopes = Scope->getScopes()) { - for (const LVScope *SubScope : *Scopes) { - if (SeenScopes.count(SubScope)) - continue; -#if 0 - if (SubScope->getBaseAddress() < Line->getAddress()) { - PrintScope(SubScope, Indent); - } -#else - - - struct Local { - static LVAddress GetBaseAddress(const LVScope *S) { - if (S->rangeCount()) { - return S->getRanges()->front()->getLowerAddress(); - } - if (S->lineCount()) { - return S->getLines()->front()->getAddress(); - } - if (S->scopeCount()) { - for (LVScope *SubS : *S->getScopes()) { - LVAddress A = GetBaseAddress(SubS); - if (A != -1) - return A; - } - } - return -1; - }; - }; -#if 0 - auto ScopeLines = SubScope->getLines(); - if (ScopeLines && ScopeLines->size() && - ScopeLines->front()->getAddress() < Line->getAddress()) { - PrintScope(SubScope, Indent); - } else { - outs() << ""; - } -#else - unsigned BaseAdress = Local::GetBaseAddress(SubScope); - if (BaseAdress < Line->getAddress()) { - PrintScope(SubScope, Indent); - } -#endif -#endif - } - } - - // Update live list: Add lives - for (auto Loc : LivetimeBegins[Line->getAddress()]) - LiveSymbols.insert(Loc); - - if (Line->getIsLineDebug() && Line->getLineNumber() != 0) { - auto LineDebug = cast(Line); - if (LineDebug->getLineNumber() == 605) - outs() << ""; - if (LastLine != LineDebug->getLineNumber() || - LineDebug->getPathname() != LastFilename) { - PrintIndent(Indent+1); - outs() << "LINE: " << " [" - << hexValue(LineDebug->getAddress()) << "] " - << LineDebug->getPathname() << ":" - << LineDebug->getLineNumber() << "\n"; - - if (IncludeVars) { - for (auto SymLoc : LiveSymbols) { - PrintIndent(Indent+2); - const LVSymbol *Sym = SymLoc->getParentSymbol(); - outs() << "VAR: " << Sym->getName() << ": " - << Sym->getType()->getName() - << " : "; - SymLoc->printLocations(outs()); - outs() << "\n"; - } - } - } - LastLine = LineDebug->getLineNumber(); - LastFilename = LineDebug->getPathname(); - } else if (Line->getIsLineAssembler()) { - if (IncludeCode) - outs() << " CODE: " << " [" << hexValue(Line->getAddress()) - << "] " << Line->getName() << "\n"; - } - - // Update live list: remove dead - for (auto Loc : LivetimeEndsInclusive[Line->getAddress()]) - LiveSymbols.remove(Loc); - } - } else if (Scope->scopeCount()) { - for (auto SubS : *Scope->getScopes()) { - PrintScope(SubS, Indent); - } - } - - if (IsInlined) { - PrintIndent(Indent); - outs() << "END_INLINED_FUNCTION\n"; - Indent--; - } - } - - static unsigned CountScopes(const LVScope *Scope) { - unsigned Count = 0; - auto Scopes = Scope->getScopes(); - if (Scopes) { - for (auto S : *Scopes) - Count += CountScopes(S); - } - return Count + 1; - } - - std::vector UnseenScopes; - void CollectUnsceenScopes(const LVScope *Scope) { - if (!SeenScopes.count(Scope)) { - UnseenScopes.push_back(Scope); - Scope->dump(); - } - if (Scope->scopeCount()) { - for (auto S : *Scope->getScopes()) - CollectUnsceenScopes(S); - } - } - -}; - int main(int argc, char *argv[]) { InitLLVM X(argc, argv); @@ -428,28 +229,8 @@ int main(int argc, char *argv[]) { continue; outs() << "FUNCTION: " << Child->getName() << "\n"; -#if 0 - ScopePrinter P; - P.PrintScope(Fn, 0); - - P.CollectUnsceenScopes(Fn); - - for (auto S : P.UnseenScopes) { - if (S->symbolCount()) { - for (auto Sym : *S->getSymbols()) - outs() << Sym->getName() << ": " << Sym->getTypeName() << " (line" - << Sym->getLineNumber() << ")" << "\n"; - } - } - - //unsigned NumScopes = ScopePrinter::CountScopes(Fn); - - outs() << ""; -#else - ScopePrinterMk2 P(outs(), Fn); + ScopePrinter P(outs(), Fn); P.Print(); -#endif - } } From 33a5977b98a9dbd6c16c7cfafdf622f0706fde30 Mon Sep 17 00:00:00 2001 From: Adam Yang <31109344+adam-yang@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:27:50 -0700 Subject: [PATCH 05/11] Deleted test code. Formatting. --- .../llvm/DebugInfo/DWARF/DWARFFormValue.h | 1 - llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 2 - .../DebugInfo/LogicalView/Core/LVLocation.cpp | 10 ----- .../DebugInfo/LogicalView/Core/LVScope.cpp | 3 -- .../LogicalView/Readers/LVBinaryReader.cpp | 3 -- .../LogicalView/Readers/LVDWARFReader.cpp | 11 +++-- .../llvm-debuginfo-check.cpp | 43 +++++++++---------- 7 files changed, 26 insertions(+), 47 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index bfbc7d5cc087d..3818a90b909c6 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -83,7 +83,6 @@ class DWARFFormValue { LLVM_ABI bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } - LLVM_DUMP_METHOD void dump() const; LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; LLVM_ABI void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 01cc184fc8ea8..bc4badc771380 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -379,8 +379,6 @@ void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, OS << format(" [%" PRIu64 "]", SectionIndex); } -LLVM_DUMP_METHOD void DWARFFormValue::dump() const { dump(dbgs()); } - void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { uint64_t UValue = Value.uval; bool CURelativeOffset = false; diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp index 5d068e2871899..4724f4f007163 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp @@ -673,16 +673,6 @@ void LVLocationSymbol::printExtra(raw_ostream &OS, bool Full) const { std::string Str; raw_string_ostream Stream(Str); printLocations(Stream); - #if 0 - bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation(); - std::string Leading; - for (LVOperation *Operation : *Entries) { - Stream << Leading - << (CodeViewLocation ? Operation->getOperandsCodeViewInfo() - : Operation->getOperandsDWARFInfo()); - Leading = ", "; - } - #endif printAttributes(OS, Full, "{Entry} ", const_cast(this), StringRef(Stream.str()), /*UseQuotes=*/false, diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp index 714b269e477c1..93a567e89f774 100644 --- a/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp @@ -134,9 +134,6 @@ void LVScope::addElement(LVLine *Line) { if (!Lines) Lines = std::make_unique(); - if (Line->getAddress() == 0x2fc) - outs() << "Set Parent for line at addr: " << Line->getAddress() - << "\n "; // Add it to parent. Lines->push_back(Line); Line->setParent(this); diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp index 42d71e13fa512..414f0f3efc82d 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp @@ -733,9 +733,6 @@ void LVBinaryReader::processLines(LVLines *DebugLines, for (LVLine *Line : *DebugLines) { // Using the current line address, get its associated lexical scope and // add the line information to it. - - if (Line->getAddress() == 0x2fc) - outs() << ""; Scope = ScopesWithRanges->getEntry(Line->getAddress()); if (!Scope) { // If missing scope, use the compile unit. diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 267a4ea40661a..3ba5061718144 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -252,8 +252,6 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die, case dwarf::DW_AT_ranges: if (RangesDataAvailable && options().getGeneralCollectRanges()) { - if (CurrentScope->getID() == 2237) - outs() << ""; auto GetRanges = [](const DWARFFormValue &FormValue, DWARFUnit *U) -> Expected { if (FormValue.getForm() == dwarf::DW_FORM_rnglistx) @@ -463,16 +461,17 @@ LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, if (!CurrentRanges.empty()) { for (LVAddressRange &Range : CurrentRanges) addSectionRange(SectionIndex, CurrentScope, Range.first, - Range.second > Range.first ? Range.second - 1 - : Range.second); + Range.second > Range.first + ? Range.second - 1 // Make hi-pc exclusive + : Range.second); CurrentRanges.clear(); } // If the scope is the CU, do not update the ranges set. if (FoundLowPC && FoundHighPC && !IsCompileUnit) { addSectionRange(SectionIndex, CurrentScope, CurrentLowPC, CurrentHighPC > CurrentLowPC - ? CurrentHighPC - 1 - : CurrentHighPC); // Make hi-pc exclusive + ? CurrentHighPC - 1 // Make hi-pc exclusive + : CurrentHighPC); } } } diff --git a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp index c0072b16505b8..0a3986229f532 100644 --- a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp +++ b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp @@ -11,17 +11,17 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/InitLLVM.h" -#include "llvm/Support/TargetSelect.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/InitLLVM.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/ScopedPrinter.h" -#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h" -#include "llvm/ADT/SetVector.h" +#include "llvm/Support/TargetSelect.h" #include -#include #include +#include using namespace llvm; using namespace logicalview; @@ -32,7 +32,8 @@ static cl::opt cl::Required); static cl::opt IncludeCode("code", cl::desc("Include asm")); -static cl::opt IncludeRanges("ranges", cl::desc("Include variable ranges")); +static cl::opt IncludeRanges("ranges", + cl::desc("Include variable ranges")); static cl::opt IncludeVars("vars", cl::desc("Include live variables")); template T Take(Expected ExpectedResult, const Twine &Msg) { @@ -52,7 +53,7 @@ struct ScopePrinter { LivetimeEndsExclusive; raw_ostream &OS; - void Walk(raw_ostream &OS, const LVScope* Scope) { + void Walk(raw_ostream &OS, const LVScope *Scope) { if (Scope->scopeCount()) { for (const LVScope *ChildScope : *Scope->getScopes()) Walk(OS, ChildScope); @@ -60,8 +61,6 @@ struct ScopePrinter { if (Scope->lineCount()) { for (const LVLine *Line : *Scope->getLines()) { Lines.push_back(Line); - if (Line->getParentScope() != Scope) - OS << ""; } } if (Scope->symbolCount()) { @@ -72,7 +71,8 @@ struct ScopePrinter { continue; if (IncludeRanges) { - OS << "RANGES: " << Symbol->getName() << " (line " << Symbol->getLineNumber() << ")" << ": "; + OS << "RANGES: " << Symbol->getName() << " (line " + << Symbol->getLineNumber() << ")" << ": "; } for (const LVLocation *Loc : SymbolLocations) { @@ -111,14 +111,15 @@ struct ScopePrinter { OS << " "; } - static void PrintCallstack(raw_ostream& OS, const LVScope* Scope) { + static void PrintCallstack(raw_ostream &OS, const LVScope *Scope) { bool First = true; const LVScope *PrevScope = nullptr; while (Scope) { if (Scope->getIsFunction() || Scope->getIsInlinedFunction()) { OS << "[" << Scope->getName(); if (PrevScope && PrevScope->getIsInlinedFunction()) { - OS << ":" << cast(PrevScope)->getCallLineNumber(); + OS << ":" + << cast(PrevScope)->getCallLineNumber(); } OS << "]"; First = false; @@ -138,7 +139,8 @@ struct ScopePrinter { } void Print() { - SetVector LiveSymbols; // This needs to be ordered since we're iterating over it. + SetVector + LiveSymbols; // This needs to be ordered since we're iterating over it. int LastLine = -1; StringRef LastFilename; for (const LVLine *Line : Lines) { @@ -165,16 +167,13 @@ struct ScopePrinter { if (IncludeVars) { for (auto SymLoc : LiveSymbols) { const LVSymbol *Sym = SymLoc->getParentSymbol(); - if (Sym->getName() == "InMRT1") - outs() << ""; auto SymScope = Sym->getParentScope(); auto LineScope = LineDebug->getParentScope(); if (SymScope != LineScope && !IsChildScopeOf(LineScope, SymScope)) continue; PrintIndent(OS, 1); OS << "VAR: " << Sym->getName() << ": " - << Sym->getType()->getName() - << " : "; + << Sym->getType()->getName() << " : "; SymLoc->printLocations(OS); OS << " (line " << Sym->getLineNumber() << ")"; OS << "\n"; @@ -200,8 +199,8 @@ int main(int argc, char *argv[]) { llvm::InitializeAllTargetMCs(); InitializeAllDisassemblers(); - cl::ParseCommandLineOptions(argc, argv, - "Check debug info correctness via annotations.\n"); + cl::ParseCommandLineOptions( + argc, argv, "Check debug info correctness via annotations.\n"); ScopedPrinter W(llvm::outs()); LVOptions Options; @@ -213,8 +212,8 @@ int main(int argc, char *argv[]) { std::vector Objects; LVReaderHandler Handler(Objects, W, Options); auto Readers = Take(Handler.createReader(InputFilename), - Twine("Failed to create LV reader from '") + Twine(InputFilename) + - Twine("'")); + Twine("Failed to create LV reader from '") + + Twine(InputFilename) + Twine("'")); auto *CU = Readers->getCompileUnit(); if (!CU) @@ -228,7 +227,7 @@ int main(int argc, char *argv[]) { if (!Lines) continue; outs() << "FUNCTION: " << Child->getName() << "\n"; - + ScopePrinter P(outs(), Fn); P.Print(); } From c13d01501827da08525b647090440897604a56ca Mon Sep 17 00:00:00 2001 From: Adam Yang Date: Mon, 21 Jul 2025 16:07:42 -0700 Subject: [PATCH 06/11] Fixed old test fails from the logical view changes --- .../DWARF/01-dwarf-print-basic-details.test | 6 +++--- .../DWARF/01-dwarf-select-logical-elements.test | 2 +- .../DWARF/02-dwarf-logical-lines.test | 4 ++-- .../03-dwarf-incorrect-lexical-scope-typedef.test | 6 +++--- .../DWARF/06-dwarf-full-logical-view.test | 6 +++--- .../DWARF/pr-incorrect-logical-instructions.test | 11 +++++------ 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-print-basic-details.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-print-basic-details.test index 54dbd7466e4f6..6d767eb9e883a 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-print-basic-details.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-print-basic-details.test @@ -45,8 +45,6 @@ ; ONE-NEXT: [004] 6 {Line} ; ONE-NEXT: [004] {Code} 'movl $0x7, -0x4(%rbp)' ; ONE-NEXT: [004] {Code} 'jmp 0x6' -; ONE-NEXT: [004] 8 {Line} -; ONE-NEXT: [004] {Code} 'movl -0x14(%rbp), %eax' ; ONE-NEXT: [003] 4 {TypeAlias} 'INTEGER' -> 'int' ; ONE-NEXT: [003] 2 {Line} ; ONE-NEXT: [003] {Code} 'pushq %rbp' @@ -60,10 +58,12 @@ ; ONE-NEXT: [003] {Code} 'testb $0x1, -0x15(%rbp)' ; ONE-NEXT: [003] {Code} 'je 0x13' ; ONE-NEXT: [003] 8 {Line} +; ONE-NEXT: [003] {Code} 'movl -0x14(%rbp), %eax' +; ONE-NEXT: [003] 8 {Line} ; ONE-NEXT: [003] {Code} 'movl %eax, -0x4(%rbp)' ; ONE-NEXT: [003] 9 {Line} ; ONE-NEXT: [003] {Code} 'movl -0x4(%rbp), %eax' ; ONE-NEXT: [003] {Code} 'popq %rbp' ; ONE-NEXT: [003] {Code} 'retq' -; ONE-NEXT: [003] 9 {Line} ; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int' +; ONE-NEXT: [002] 9 {Line} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-select-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-select-logical-elements.test index f84e9201d3044..5690cf585c379 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-select-logical-elements.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-select-logical-elements.test @@ -34,7 +34,7 @@ ; ONE-NEXT: [004] {Code} 'movl $0x7, -0x4(%rbp)' ; ONE-NEXT: [003] {Code} 'movl %eax, -0x4(%rbp)' ; ONE-NEXT: [003] {Code} 'movl %esi, -0x14(%rbp)' -; ONE-NEXT: [004] {Code} 'movl -0x14(%rbp), %eax' +; ONE-NEXT: [003] {Code} 'movl -0x14(%rbp), %eax' ; ONE-NEXT: [003] {Code} 'movl -0x4(%rbp), %eax' ; ONE-NEXT: [003] 4 {TypeAlias} 'INTEGER' -> 'int' ; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/02-dwarf-logical-lines.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/02-dwarf-logical-lines.test index 533914f002827..bff7c945b6eac 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/02-dwarf-logical-lines.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/02-dwarf-logical-lines.test @@ -42,7 +42,7 @@ ; ONE-NEXT: [003] {Code} 'addq $0x10, %rsp' ; ONE-NEXT: [003] {Code} 'popq %rbp' ; ONE-NEXT: [003] {Code} 'retq' -; ONE-NEXT: [003] 6 {Line} +; ONE-NEXT: [002] 6 {Line} ; ONE-EMPTY: ; ONE-NEXT: Logical View: ; ONE-NEXT: [000] {File} 'hello-world-dwarf-gcc.o' -> elf64-x86-64 @@ -64,4 +64,4 @@ ; ONE-NEXT: [003] 7 {Line} ; ONE-NEXT: [003] {Code} 'popq %rbp' ; ONE-NEXT: [003] {Code} 'retq' -; ONE-NEXT: [003] 7 {Line} +; ONE-NEXT: [002] 7 {Line} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/03-dwarf-incorrect-lexical-scope-typedef.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/03-dwarf-incorrect-lexical-scope-typedef.test index dc57d01f3b8bb..69b65148361d7 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/03-dwarf-incorrect-lexical-scope-typedef.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/03-dwarf-incorrect-lexical-scope-typedef.test @@ -59,7 +59,6 @@ ; 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' @@ -71,6 +70,7 @@ ; ONE-NEXT: [003] 13 {Line} ; ONE-NEXT: [003] 13 {Line} ; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [002] 13 {Line} ; ONE-EMPTY: ; ONE-NEXT: Logical View: ; ONE-NEXT: [000] {File} 'pr-44884-dwarf-gcc.o' -> elf64-x86-64 @@ -91,7 +91,6 @@ ; 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' @@ -99,8 +98,9 @@ ; ONE-NEXT: [003] 3 {Line} ; ONE-NEXT: [003] 5 {Line} ; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [003] 13 {Line} ; ONE-NEXT: [003] 14 {Line} -; ONE-NEXT: [003] 14 {Line} +; ONE-NEXT: [002] 14 {Line} ; Using the selection facilities, we can produce a simple tabular ; output showing just the logical types that are 'Typedef'. diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test index 6616710a10045..a2f05ddb3e6ec 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/06-dwarf-full-logical-view.test @@ -53,8 +53,6 @@ ; ONE-NEXT: [0x0000000023][004] 6 {Line} {NewStatement} '/data/projects/tests/input/general/test.cpp' ; ONE-NEXT: [0x0000000023][004] {Code} 'movl $0x7, -0x4(%rbp)' ; ONE-NEXT: [0x000000002a][004] {Code} 'jmp 0x6' -; ONE-NEXT: [0x000000002f][004] 8 {Line} {NewStatement} '/data/projects/tests/input/general/test.cpp' -; ONE-NEXT: [0x000000002f][004] {Code} 'movl -0x14(%rbp), %eax' ; ONE-NEXT: [0x0000000063][003] 2 {Parameter} 'ParamBool' -> [0x00000000bc]'bool' ; ONE-NEXT: [0x0000000063][004] {Coverage} 100.00% ; ONE-NEXT: [0x0000000064][004] {Location} @@ -79,13 +77,15 @@ ; ONE-NEXT: [0x0000000012][003] 3 {Line} {NewStatement} {PrologueEnd} '/data/projects/tests/input/general/test.cpp' ; ONE-NEXT: [0x0000000012][003] {Code} 'testb $0x1, -0x15(%rbp)' ; ONE-NEXT: [0x0000000016][003] {Code} 'je 0x13' +; ONE-NEXT: [0x000000002f][003] 8 {Line} {NewStatement} '/data/projects/tests/input/general/test.cpp' +; ONE-NEXT: [0x000000002f][003] {Code} 'movl -0x14(%rbp), %eax' ; ONE-NEXT: [0x0000000032][003] 8 {Line} '/data/projects/tests/input/general/test.cpp' ; ONE-NEXT: [0x0000000032][003] {Code} 'movl %eax, -0x4(%rbp)' ; ONE-NEXT: [0x0000000035][003] 9 {Line} {NewStatement} '/data/projects/tests/input/general/test.cpp' ; ONE-NEXT: [0x0000000035][003] {Code} 'movl -0x4(%rbp), %eax' ; ONE-NEXT: [0x0000000038][003] {Code} 'popq %rbp' ; ONE-NEXT: [0x0000000039][003] {Code} 'retq' -; ONE-NEXT: [0x000000003a][003] 9 {Line} {NewStatement} {EndSequence} '/data/projects/tests/input/general/test.cpp' +; ONE-NEXT: [0x000000003a][002] 9 {Line} {NewStatement} {EndSequence} '/data/projects/tests/input/general/test.cpp' ; ONE-EMPTY: ; ONE-NEXT: ----------------------------- ; ONE-NEXT: Element Total Printed diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-incorrect-logical-instructions.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-incorrect-logical-instructions.test index a99eae2aa2933..b38db28085b3e 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-incorrect-logical-instructions.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-incorrect-logical-instructions.test @@ -84,7 +84,6 @@ ; ONE-NEXT: [003] {Code} 'addq $0x10, %rsp' ; ONE-NEXT: [003] {Code} 'popq %rbp' ; ONE-NEXT: [003] {Code} 'retq' -; ONE-NEXT: [003] {Code} 'data16' ; ONE-NEXT: [002] 10 {Function} extern not_inlined 'test' -> 'int' ; ONE-NEXT: [003] {Block} ; ONE-NEXT: [004] 13 {Line} @@ -106,8 +105,6 @@ ; ONE-NEXT: [004] {Code} 'movl -0x8(%rbp), %eax' ; ONE-NEXT: [004] {Code} 'addl $0x1, %eax' ; ONE-NEXT: [004] {Code} 'movl %eax, -0x8(%rbp)' -; ONE-NEXT: [004] 17 {Line} -; ONE-NEXT: [004] {Code} 'movl -0x8(%rbp), %eax' ; ONE-NEXT: [003] 10 {Line} ; ONE-NEXT: [003] {Code} 'pushq %rbp' ; ONE-NEXT: [003] {Code} 'movq %rsp, %rbp' @@ -120,6 +117,8 @@ ; ONE-NEXT: [003] 11 {Line} ; ONE-NEXT: [003] {Code} 'movl %eax, -0x8(%rbp)' ; ONE-NEXT: [003] 17 {Line} +; ONE-NEXT: [003] {Code} 'movl -0x8(%rbp), %eax' +; ONE-NEXT: [003] 17 {Line} ; ONE-NEXT: [003] {Code} 'addq $0x10, %rsp' ; ONE-NEXT: [003] {Code} 'popq %rbp' ; ONE-NEXT: [003] {Code} 'retq' @@ -132,7 +131,8 @@ ; ONE-NEXT: [003] {Code} 'xorl %eax, %eax' ; ONE-NEXT: [003] {Code} 'popq %rbp' ; ONE-NEXT: [003] {Code} 'retq' -; ONE-NEXT: [003] 21 {Line} +; ONE-NEXT: [002] {Code} 'data16' +; ONE-NEXT: [002] 21 {Line} ; RUN: llvm-debuginfo-analyzer --attribute=level \ ; RUN: --print=instructions \ @@ -172,7 +172,6 @@ ; TWO-NEXT: [003] {Code} 'addq $0x10, %rsp' ; TWO-NEXT: [003] {Code} 'popq %rbp' ; TWO-NEXT: [003] {Code} 'retq' -; TWO-NEXT: [003] {Code} 'data16' ; TWO-NEXT: [002] 10 {Function} extern not_inlined 'test' -> 'int' ; TWO-NEXT: [003] {Block} ; TWO-NEXT: [004] {Code} 'movl $0x0, -0xc(%rbp)' @@ -187,7 +186,6 @@ ; TWO-NEXT: [004] {Code} 'movl -0x8(%rbp), %eax' ; TWO-NEXT: [004] {Code} 'addl $0x1, %eax' ; TWO-NEXT: [004] {Code} 'movl %eax, -0x8(%rbp)' -; TWO-NEXT: [004] {Code} 'movl -0x8(%rbp), %eax' ; TWO-NEXT: [003] {Code} 'pushq %rbp' ; TWO-NEXT: [003] {Code} 'movq %rsp, %rbp' ; TWO-NEXT: [003] {Code} 'subq $0x10, %rsp' @@ -195,6 +193,7 @@ ; TWO-NEXT: [003] {Code} 'movl -0x4(%rbp), %eax' ; TWO-NEXT: [003] {Code} 'subl (%rip), %eax' ; TWO-NEXT: [003] {Code} 'movl %eax, -0x8(%rbp)' +; TWO-NEXT: [003] {Code} 'movl -0x8(%rbp), %eax' ; TWO-NEXT: [003] {Code} 'addq $0x10, %rsp' ; TWO-NEXT: [003] {Code} 'popq %rbp' ; TWO-NEXT: [003] {Code} 'retq' From 405c70e4529b759ba16ae5f5ec9ca1d149eba042 Mon Sep 17 00:00:00 2001 From: Adam Yang Date: Mon, 21 Jul 2025 16:08:19 -0700 Subject: [PATCH 07/11] Made the new test a real test --- .../AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll index 1d031979309a6..569c975409c37 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll @@ -1,13 +1,25 @@ ; RUN: llc %s -o %t.o -mcpu=gfx1030 -filetype=obj -O0 -; RUN: llvm-debuginfo-analyzer %t.o --print=all --attribute=all | FileCheck %s +; RUN: llvm-debuginfo-check %t.o --vars | FileCheck %s ; This test compiles this module with AMDGPU backend under -O0, -; and makes sure llvm-debuginfo-analzyer works for it. +; and makes sure llvm-debuginfo-check works for it. -; Simple checks to make sure llvm-debuginfo-analzyer didn't fail early. -; CHECK: Logical View: -; CHECK: {CompileUnit} -; CHECK: {Code} 's_endpgm' +; CHECK: FUNCTION: main +; CHECK: LINE: {{.+}}basic_var.hlsl:7 +; CHECK: LINE: {{.+}}basic_var.hlsl:11 +; CHECK: VAR: dtid: uint3 : reg{{.+}}, piece 4 +; CHECK: LINE: {{.+}}basic_var.hlsl:17 +; CHECK: VAR: dtid: uint3 : reg{{.+}}, piece 4 +; CHECK: LINE: {{.+}}basic_var.hlsl:11 +; CHECK: VAR: dtid: uint3 : reg{{.+}}, piece 4 +; CHECK: LINE: {{.+}}basic_var.hlsl:14 +; CHECK-DAG: VAR: dtid: uint3 : reg{{.+}}, piece 4 +; CHECK: LINE: {{.+}}basic_var.hlsl:17 +; CHECK-DAG: VAR: dtid: uint3 : reg{{.+}}, piece 4 +; CHECK-DAG: VAR: my_var2: float : reg{{.+}} +; CHECK: LINE: {{.+}}basic_var.hlsl:19 +; CHECK-DAG: VAR: dtid: uint3 : reg{{.+}}, piece 4 +; CHECK-DAG: VAR: my_var2: float : reg{{.+}} source_filename = "module" target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-p10:32:32-p11:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9-p32:32:32-v8:8-v16:16-v32:32-v48:32-v64:32-v80:32-v96:32-v112:32-v128:32-v144:32-v160:32-v176:32-v192:32-v208:32-v224:32-v240:32-v256:32-i1:32-i8:8-i16:16-i32:32-i64:32-f16:16-f32:32-f64:32" @@ -100,4 +112,4 @@ attributes #4 = { nocallback nofree nosync nounwind willreturn memory(read) } !34 = !DILocalVariable(name: "my_var2", scope: !14, file: !1, line: 14, type: !9) !35 = !DILocation(line: 14, column: 9, scope: !14) !36 = !DILocation(line: 17, column: 14, scope: !14) -!37 = !DILocation(line: 19, column: 1, scope: !14) \ No newline at end of file +!37 = !DILocation(line: 19, column: 1, scope: !14) From 5a649ba86ced560e971b818418eab807b436fd14 Mon Sep 17 00:00:00 2001 From: Adam Yang Date: Tue, 22 Jul 2025 13:48:01 -0700 Subject: [PATCH 08/11] Fixed the rest of the tests --- .../test/CodeGen/AMDGPU/amdgpu-reloc-const.ll | 4 ++-- .../01-wasm-print-basic-details.test | 8 ++++---- .../WebAssembly/02-wasm-logical-lines.test | 4 ++-- ...-wasm-incorrect-lexical-scope-typedef.test | 8 ++++---- .../06-wasm-full-logical-view.test | 8 ++++---- .../DebugInfo/LogicalView/DWARFReaderTest.cpp | 20 +++++-------------- 6 files changed, 21 insertions(+), 31 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll index 1af5938a5d48f..7f9587567a371 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll @@ -11,8 +11,8 @@ ; GCN-NEXT: .Lfunc_end ; ELF: Relocations [ -; ELF-NEXT: Section (3) .rel.text { -; ELF-NEXT: 0x{{[0-9]+}} R_AMDGPU_ABS32_LO doff_0_0_b{{$}} +; ELF-NEXT: Section (3) .rela.text { +; ELF-NEXT: 0x{{[0-9]+}} R_AMDGPU_ABS32_LO doff_0_0_b 0x0 define amdgpu_ps void @ps_main(i32 %arg, i32 inreg %arg1, i32 inreg %arg2) local_unnamed_addr #0 { %rc = call i32 @llvm.amdgcn.reloc.constant(metadata !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 index 4927086563330..183e3ddc75ca1 100644 --- 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 @@ -56,8 +56,6 @@ ; 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' @@ -98,6 +96,8 @@ ; ONE-NEXT: [003] {Code} 'local.get 9' ; ONE-NEXT: [003] {Code} 'i32.eqz' ; ONE-NEXT: [003] {Code} 'br_if 0' +; ONE-NEXT: [003] - {Line} +; ONE-NEXT: [003] {Code} 'end' ; ONE-NEXT: [003] 8 {Line} ; ONE-NEXT: [003] {Code} 'local.get 5' ; ONE-NEXT: [003] {Code} 'i32.load 20' @@ -115,6 +115,6 @@ ; 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' +; ONE-NEXT: [002] 9 {Line} +; ONE-NEXT: [002] {Code} 'unreachable' 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 index 50a531ad7d823..8d764648bdd5a 100644 --- 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 @@ -71,5 +71,5 @@ ; 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' +; ONE-NEXT: [002] 6 {Line} +; ONE-NEXT: [002] {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 index 1192a0cb7ca5a..a89d49abd6280 100644 --- 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 @@ -55,7 +55,6 @@ ; 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' @@ -67,7 +66,6 @@ ; 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' @@ -79,6 +77,8 @@ ; ONE-NEXT: [003] 13 {Line} ; ONE-NEXT: [003] 13 {Line} ; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [002] 1 {Line} +; ONE-NEXT: [002] 13 {Line} ; ONE-EMPTY: ; ONE-NEXT: Logical View: ; ONE-NEXT: [000] {File} 'pr-44884-dwarf-gcc.o' -> elf64-x86-64 @@ -99,7 +99,6 @@ ; 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' @@ -107,8 +106,9 @@ ; ONE-NEXT: [003] 3 {Line} ; ONE-NEXT: [003] 5 {Line} ; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [003] 13 {Line} ; ONE-NEXT: [003] 14 {Line} -; ONE-NEXT: [003] 14 {Line} +; ONE-NEXT: [002] 14 {Line} ; Using the selection facilities, we can produce a simple tabular ; output showing just the logical types that are 'Typedef'. 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 index ac4873f0a4d34..e152f40d99213 100644 --- 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 @@ -64,8 +64,6 @@ ; 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} @@ -118,6 +116,8 @@ ; 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: [0x0000000064][003] 0 {Line} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000064][003] {Code} 'end' ; 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' @@ -135,8 +135,8 @@ ; 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-NEXT: [0x000000007f][002] 9 {Line} {NewStatement} {EndSequence} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x000000007f][002] {Code} 'unreachable' ; ONE-EMPTY: ; ONE-NEXT: ----------------------------- ; ONE-NEXT: Element Total Printed diff --git a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp index 544c39a3c7b2e..78dc8502e9676 100644 --- a/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp +++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp @@ -81,7 +81,7 @@ void checkElementProperties(LVReader *Reader) { EXPECT_EQ(Language, LVSourceLanguage::DW_LANG_C_plus_plus_14); EXPECT_EQ(Language.getName(), "DW_LANG_C_plus_plus_14"); - EXPECT_EQ(CompileUnit->lineCount(), 0u); + EXPECT_EQ(CompileUnit->lineCount(), 1u); EXPECT_EQ(CompileUnit->scopeCount(), 1u); EXPECT_EQ(CompileUnit->symbolCount(), 0u); EXPECT_EQ(CompileUnit->typeCount(), 7u); @@ -129,7 +129,7 @@ void checkElementProperties(LVReader *Reader) { // Lines (debug and assembler) for 'foo'. const LVLines *Lines = Function->getLines(); ASSERT_NE(Lines, nullptr); - ASSERT_EQ(Lines->size(), 0x12u); + ASSERT_EQ(Lines->size(), 19u); // Check size of types in CompileUnit. const LVTypes *Types = CompileUnit->getTypes(); @@ -252,7 +252,7 @@ void checkElementComparison(LVReader *Reference, LVReader *Target) { // Get comparison table. LVPassTable PassTable = Compare.getPassTable(); - ASSERT_EQ(PassTable.size(), 5u); + ASSERT_EQ(PassTable.size(), 4u); LVReader *Reader; LVElement *Element; @@ -278,18 +278,8 @@ void checkElementComparison(LVReader *Reference, LVReader *Target) { EXPECT_EQ(Element->getName(), "INTEGER"); EXPECT_EQ(Pass, LVComparePass::Missing); - // Reference: Missing DebugLine - std::tie(Reader, Element, Pass) = PassTable[2]; - ASSERT_NE(Reader, nullptr); - ASSERT_NE(Element, nullptr); - EXPECT_EQ(Reader, Reference); - EXPECT_EQ(Element->getLevel(), 3u); - EXPECT_EQ(Element->getLineNumber(), 8u); - EXPECT_EQ(Element->getName(), ""); - EXPECT_EQ(Pass, LVComparePass::Missing); - // Target: Added Variable 'CONSTANT' - std::tie(Reader, Element, Pass) = PassTable[3]; + std::tie(Reader, Element, Pass) = PassTable[2]; ASSERT_NE(Reader, nullptr); ASSERT_NE(Element, nullptr); EXPECT_EQ(Reader, Target); @@ -299,7 +289,7 @@ void checkElementComparison(LVReader *Reference, LVReader *Target) { EXPECT_EQ(Pass, LVComparePass::Added); // Target: Added TypeDefinition 'INTEGER' - std::tie(Reader, Element, Pass) = PassTable[4]; + std::tie(Reader, Element, Pass) = PassTable[3]; ASSERT_NE(Reader, nullptr); ASSERT_NE(Element, nullptr); EXPECT_EQ(Reader, Target); From d831d4208b5cc1a3763989a9e2e789ae58eb74fc Mon Sep 17 00:00:00 2001 From: Adam Yang Date: Tue, 22 Jul 2025 14:43:58 -0700 Subject: [PATCH 09/11] Tests to depend on llvm-debuginfo-check --- llvm/test/CMakeLists.txt | 1 + llvm/test/lit.cfg.py | 1 + 2 files changed, 2 insertions(+) diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt index 2a6135da9a61e..7e0185e5ad9cc 100644 --- a/llvm/test/CMakeLists.txt +++ b/llvm/test/CMakeLists.txt @@ -86,6 +86,7 @@ set(LLVM_TEST_DEPENDS llvm-cxxfilt llvm-cxxmap llvm-debuginfo-analyzer + llvm-debuginfo-check llvm-debuginfod-find llvm-diff llvm-dis diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index bd6e37c848d8c..4e51a52cbded6 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -189,6 +189,7 @@ def get_asan_rtlib(): "llvm-cvtres", "llvm-debuginfod-find", "llvm-debuginfo-analyzer", + "llvm-debuginfo-check", "llvm-diff", "llvm-dis", "llvm-dwarfdump", From 998f845331a4fed0af020fbdcf7c61d0124ee37f Mon Sep 17 00:00:00 2001 From: Adam Yang Date: Wed, 23 Jul 2025 14:07:09 -0700 Subject: [PATCH 10/11] Last bit of cleanup. Help text --- ...yzer.ll => amdgpu-llvm-debuginfo-check.ll} | 0 .../llvm-debuginfo-check.cpp | 74 +++++++++++-------- 2 files changed, 43 insertions(+), 31 deletions(-) rename llvm/test/CodeGen/AMDGPU/{amdgpu-llvm-debuginfo-analyzer.ll => amdgpu-llvm-debuginfo-check.ll} (100%) diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-check.ll similarity index 100% rename from llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-analyzer.ll rename to llvm/test/CodeGen/AMDGPU/amdgpu-llvm-debuginfo-check.ll diff --git a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp index 0a3986229f532..20fa21813660c 100644 --- a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp +++ b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp @@ -1,4 +1,4 @@ -//===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===// +//===-- llvm-debuginfo-check.cpp - LLVM Debug info analysis utility -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -23,6 +23,22 @@ #include #include +constexpr const char *HelpText = + R"(Prints debug info in a way that is easy to verify correctness of debug info. + +FUNCTION: main + LINE: my_source_file.c:1 [main] <---- New statement lines, inlined callstack + VAR: argc : int : {expression} <---- Variables live at this point + VAR: argv : char ** : {expression} + LINE: my_source_file.c:2 [main] + VAR: argc : int + VAR: argv : char ** + LINE: my_source_file.c:3 [main] + VAR: argc : int + VAR: argv : char ** + LINE: my_source_file.c:4 [main] +)"; + using namespace llvm; using namespace logicalview; @@ -32,8 +48,8 @@ static cl::opt cl::Required); static cl::opt IncludeCode("code", cl::desc("Include asm")); -static cl::opt IncludeRanges("ranges", - cl::desc("Include variable ranges")); +static cl::opt + IncludeRanges("ranges", cl::desc("Include variable ranges"), cl::Hidden); static cl::opt IncludeVars("vars", cl::desc("Include live variables")); template T Take(Expected ExpectedResult, const Twine &Msg) { @@ -141,8 +157,6 @@ struct ScopePrinter { void Print() { SetVector LiveSymbols; // This needs to be ordered since we're iterating over it. - int LastLine = -1; - StringRef LastFilename; for (const LVLine *Line : Lines) { const LVScope *Scope = Line->getParentScope(); @@ -154,35 +168,31 @@ struct ScopePrinter { for (auto Loc : LivetimeEndsExclusive[Line->getAddress()]) LiveSymbols.remove(Loc); - if (Line->getIsLineDebug() && Line->getLineNumber() != 0) { + if (Line->getIsNewStatement() && Line->getIsLineDebug() && + Line->getLineNumber() != 0) { auto LineDebug = cast(Line); - if (LastLine != LineDebug->getLineNumber() || - LineDebug->getPathname() != LastFilename) { - OS << "LINE: " << " [" << hexValue(LineDebug->getAddress()) << "] " - << LineDebug->getPathname() << ":" << LineDebug->getLineNumber() - << " "; - PrintCallstack(OS, Scope); - OS << "\n"; - if (IncludeVars) { - for (auto SymLoc : LiveSymbols) { - const LVSymbol *Sym = SymLoc->getParentSymbol(); - auto SymScope = Sym->getParentScope(); - auto LineScope = LineDebug->getParentScope(); - if (SymScope != LineScope && !IsChildScopeOf(LineScope, SymScope)) - continue; - PrintIndent(OS, 1); - OS << "VAR: " << Sym->getName() << ": " - << Sym->getType()->getName() << " : "; - SymLoc->printLocations(OS); - OS << " (line " << Sym->getLineNumber() << ")"; - OS << "\n"; - } + OS << "LINE: " << " [" << hexValue(LineDebug->getAddress()) << "] " + << LineDebug->getPathname() << ":" << LineDebug->getLineNumber() + << " "; + PrintCallstack(OS, Scope); + OS << "\n"; + if (IncludeVars) { + for (auto SymLoc : LiveSymbols) { + const LVSymbol *Sym = SymLoc->getParentSymbol(); + auto SymScope = Sym->getParentScope(); + auto LineScope = LineDebug->getParentScope(); + if (SymScope != LineScope && !IsChildScopeOf(LineScope, SymScope)) + continue; + PrintIndent(OS, 1); + OS << "VAR: " << Sym->getName() << ": " << Sym->getType()->getName() + << " : "; + SymLoc->printLocations(OS); + OS << " (line " << Sym->getLineNumber() << ")"; + OS << "\n"; } } - LastLine = Line->getLineNumber(); - LastFilename = Line->getPathname(); } else if (IncludeCode && Line->getIsLineAssembler()) { OS << " CODE: " << " [" << hexValue(Line->getAddress()) << "] " << Line->getName() << "\n"; @@ -200,7 +210,7 @@ int main(int argc, char *argv[]) { InitializeAllDisassemblers(); cl::ParseCommandLineOptions( - argc, argv, "Check debug info correctness via annotations.\n"); + argc, argv, HelpText); ScopedPrinter W(llvm::outs()); LVOptions Options; @@ -216,8 +226,10 @@ int main(int argc, char *argv[]) { Twine(InputFilename) + Twine("'")); auto *CU = Readers->getCompileUnit(); - if (!CU) + if (!CU) { + errs() << "No compute unit found.\n"; return 2; + } for (LVElement *Child : *CU->getChildren()) { auto *Fn = dyn_cast(Child); From 95a336aaf852229ad3231f34a1eefee2892a5d2f Mon Sep 17 00:00:00 2001 From: Adam Yang Date: Wed, 23 Jul 2025 14:26:51 -0700 Subject: [PATCH 11/11] Stray format change --- llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp index 20fa21813660c..d6ca9f0ee06c9 100644 --- a/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp +++ b/llvm/tools/llvm-debuginfo-check/llvm-debuginfo-check.cpp @@ -209,8 +209,7 @@ int main(int argc, char *argv[]) { llvm::InitializeAllTargetMCs(); InitializeAllDisassemblers(); - cl::ParseCommandLineOptions( - argc, argv, HelpText); + cl::ParseCommandLineOptions(argc, argv, HelpText); ScopedPrinter W(llvm::outs()); LVOptions Options;