From 66d28ba437b38fe9d93f643a54b1ffbda3be7117 Mon Sep 17 00:00:00 2001 From: Alexander Peskov Date: Thu, 12 Dec 2024 15:12:13 +0400 Subject: [PATCH 1/4] [NVPTX] Fix DWARF address space for globals There was issue with defining actual addr space for module scope globals. Previously it was always ADDR_global_space. Also, introduce enum with CUDA-specific DWARF address space codes. --- llvm/include/llvm/Support/NVPTXAddrSpace.h | 25 ++++++- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 69 +++++++++++-------- llvm/test/DebugInfo/NVPTX/debug-addr-space.ll | 25 +++++++ 3 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 llvm/test/DebugInfo/NVPTX/debug-addr-space.ll diff --git a/llvm/include/llvm/Support/NVPTXAddrSpace.h b/llvm/include/llvm/Support/NVPTXAddrSpace.h index 93eae39e3d230..fc8ae7c37793b 100644 --- a/llvm/include/llvm/Support/NVPTXAddrSpace.h +++ b/llvm/include/llvm/Support/NVPTXAddrSpace.h @@ -17,6 +17,7 @@ namespace llvm { namespace NVPTXAS { + enum AddressSpace : unsigned { ADDRESS_SPACE_GENERIC = 0, ADDRESS_SPACE_GLOBAL = 1, @@ -26,8 +27,30 @@ enum AddressSpace : unsigned { ADDRESS_SPACE_PARAM = 101, }; -} // end namespace NVPTXAS +// According to official PTX Writer's Guide, DWARF debug information should +// contain DW_AT_address_class attribute for all variables and parameters. +// It's required for cuda-gdb to be able to properly reflect the memory space +// of variable address. Acceptable address class codes are listed in this enum. +// +// More detailed information: +// https://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf-definitions +enum DWARF_AddressSpace : unsigned { + DWARF_ADDR_code_space = 1, + DWARF_ADDR_reg_space = 2, + DWARF_ADDR_sreg_space = 3, + DWARF_ADDR_const_space = 4, + DWARF_ADDR_global_space = 5, + DWARF_ADDR_local_space = 6, + DWARF_ADDR_param_space = 7, + DWARF_ADDR_shared_space = 8, + DWARF_ADDR_surf_space = 9, + DWARF_ADDR_tex_space = 10, + DWARF_ADDR_tex_sampler_space = 11, + DWARF_ADDR_generic_space = 12 +}; + +} // end namespace NVPTXAS } // end namespace llvm #endif // LLVM_SUPPORT_NVPTXADDRSPACE_H diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 2f96366b78e97..f87c43e28003a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -33,6 +33,7 @@ #include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/NVPTXAddrSpace.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -75,6 +76,25 @@ static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) { return dwarf::DW_TAG_compile_unit; } +static unsigned translateToNVVMDWARFAddrSpace(unsigned AddrSpace) { + switch (AddrSpace) { + case NVPTXAS::ADDRESS_SPACE_GENERIC: + return NVPTXAS::DWARF_ADDR_generic_space; + case NVPTXAS::ADDRESS_SPACE_GLOBAL: + return NVPTXAS::DWARF_ADDR_global_space; + case NVPTXAS::ADDRESS_SPACE_SHARED: + return NVPTXAS::DWARF_ADDR_shared_space; + case NVPTXAS::ADDRESS_SPACE_CONST: + return NVPTXAS::DWARF_ADDR_const_space; + case NVPTXAS::ADDRESS_SPACE_LOCAL: + return NVPTXAS::DWARF_ADDR_local_space; + default: + llvm_unreachable( + "Cannot translate unknown address space to DWARF address space"); + return AddrSpace; + } +} + DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, UnitKind Kind) @@ -264,14 +284,11 @@ void DwarfCompileUnit::addLocationAttribute( } if (Expr) { - // According to - // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf - // cuda-gdb requires DW_AT_address_class for all variables to be able to - // correctly interpret address space of the variable address. + // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace // Decode DW_OP_constu DW_OP_swap DW_OP_xderef - // sequence for the NVPTX + gdb target. - unsigned LocalNVPTXAddressSpace; + // sequence to specify corresponding address space. if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { + unsigned LocalNVPTXAddressSpace; const DIExpression *NewExpr = DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace); if (NewExpr != Expr) { @@ -363,6 +380,10 @@ void DwarfCompileUnit::addLocationAttribute( DD->addArangeLabel(SymbolCU(this, Sym)); addOpAddress(*Loc, Sym); } + if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB() && + !NVPTXAddressSpace) + NVPTXAddressSpace = translateToNVVMDWARFAddrSpace( + Global->getType()->getAddressSpace()); } // Global variables attached to symbols are memory locations. // It would be better if this were unconditional, but malformed input that @@ -373,13 +394,9 @@ void DwarfCompileUnit::addLocationAttribute( DwarfExpr->addExpression(Expr); } if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { - // According to - // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf - // cuda-gdb requires DW_AT_address_class for all variables to be able to - // correctly interpret address space of the variable address. - const unsigned NVPTX_ADDR_global_space = 5; + // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace addUInt(*VariableDIE, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1, - NVPTXAddressSpace.value_or(NVPTX_ADDR_global_space)); + NVPTXAddressSpace.value_or(NVPTXAS::DWARF_ADDR_global_space)); } if (Loc) addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize()); @@ -793,10 +810,10 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes( const DbgValueLoc *DVal = &Single.getValueLoc(); if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB() && !Single.getExpr()) { - // Lack of expression means it is a register. Registers for PTX need to - // be marked with DW_AT_address_class = 2. See - // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf - addUInt(VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1, 2); + // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace + // Lack of expression means it is a register. + addUInt(VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1, + NVPTXAS::DWARF_ADDR_reg_space); } if (!DVal->isVariadic()) { const DbgValueLocEntry *Entry = DVal->getLocEntries().begin(); @@ -922,14 +939,11 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(const Loc::MMI &MMI, SmallVector Ops; TRI->getOffsetOpcodes(Offset, Ops); - // According to - // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf - // cuda-gdb requires DW_AT_address_class for all variables to be - // able to correctly interpret address space of the variable - // address. Decode DW_OP_constu DW_OP_swap - // DW_OP_xderef sequence for the NVPTX + gdb target. - unsigned LocalNVPTXAddressSpace; + // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace. + // Decode DW_OP_constu DW_OP_swap + // DW_OP_xderef sequence to specify address space. if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { + unsigned LocalNVPTXAddressSpace; const DIExpression *NewExpr = DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace); if (NewExpr != Expr) { @@ -949,14 +963,9 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(const Loc::MMI &MMI, DwarfExpr.addExpression(std::move(Cursor)); } if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) { - // According to - // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf - // cuda-gdb requires DW_AT_address_class for all variables to be - // able to correctly interpret address space of the variable - // address. - const unsigned NVPTX_ADDR_local_space = 6; + // cuda-gdb special requirement. See NVPTXAS::DWARF_AddressSpace. addUInt(VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1, - NVPTXAddressSpace.value_or(NVPTX_ADDR_local_space)); + NVPTXAddressSpace.value_or(NVPTXAS::DWARF_ADDR_local_space)); } addBlock(VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); if (DwarfExpr.TagOffset) diff --git a/llvm/test/DebugInfo/NVPTX/debug-addr-space.ll b/llvm/test/DebugInfo/NVPTX/debug-addr-space.ll new file mode 100644 index 0000000000000..1bde05c77147e --- /dev/null +++ b/llvm/test/DebugInfo/NVPTX/debug-addr-space.ll @@ -0,0 +1,25 @@ +; RUN: llc < %s -march=nvptx64 | FileCheck %s + +; Test that translateToNVVMDWARFAddrSpace() function translates NVVM IR address space +; value `Shared` (3) to the corresponding DWARF DW_AT_address_class attributeĀ for PTX. + +; CHECK: .section .debug_info +; CHECK: .b8 103 // DW_AT_name +; CHECK-NEXT: .b8 0 +; CHECK-NEXT: .b32 55 // DW_AT_type +; CHECK-NEXT: .b8 1 // DW_AT_decl_file +; CHECK-NEXT: .b8 1 // DW_AT_decl_line +; CHECK-NEXT: .b8 8 // DW_AT_address_class + +@g = internal addrspace(3) global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!6} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", linkageName: "g", scope: !2, file: !3, line: 1, type: !5, isLocal: true, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4) +!3 = !DIFile(filename: "test.cu", directory: "test") +!4 = !{!0} +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!6 = !{i32 1, !"Debug Info Version", i32 3} From 128160ca6808f714a3b1457a7deed34e1149e8d5 Mon Sep 17 00:00:00 2001 From: Alexander Peskov Date: Wed, 22 Jan 2025 05:13:38 -0800 Subject: [PATCH 2/4] Add comment line --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index f87c43e28003a..6c1e80a7d272b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -76,6 +76,7 @@ static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) { return dwarf::DW_TAG_compile_unit; } +// Translate NVVM IR address space code to DWARF correspondent value static unsigned translateToNVVMDWARFAddrSpace(unsigned AddrSpace) { switch (AddrSpace) { case NVPTXAS::ADDRESS_SPACE_GENERIC: From c094320bcc55333192929e19b2b17e44bcd3cd4f Mon Sep 17 00:00:00 2001 From: Alexander Peskov Date: Wed, 22 Jan 2025 10:21:31 -0800 Subject: [PATCH 3/4] minor 1 --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 6c1e80a7d272b..e2669e0283933 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -76,7 +76,7 @@ static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) { return dwarf::DW_TAG_compile_unit; } -// Translate NVVM IR address space code to DWARF correspondent value +/// Translate NVVM IR address space code to DWARF correspondent value static unsigned translateToNVVMDWARFAddrSpace(unsigned AddrSpace) { switch (AddrSpace) { case NVPTXAS::ADDRESS_SPACE_GENERIC: From b58174f2c7ec28854036f5e63338b8862d9a1c31 Mon Sep 17 00:00:00 2001 From: Alexander Peskov Date: Fri, 31 Jan 2025 23:57:20 +0400 Subject: [PATCH 4/4] minor 2 --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index e2669e0283933..6cf05fda544ed 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -383,8 +383,8 @@ void DwarfCompileUnit::addLocationAttribute( } if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB() && !NVPTXAddressSpace) - NVPTXAddressSpace = translateToNVVMDWARFAddrSpace( - Global->getType()->getAddressSpace()); + NVPTXAddressSpace = + translateToNVVMDWARFAddrSpace(Global->getType()->getAddressSpace()); } // Global variables attached to symbols are memory locations. // It would be better if this were unconditional, but malformed input that