Skip to content

Commit

Permalink
[DEBUG_INFO][NVPTX] Generate DW_AT_address_class to get the values in…
Browse files Browse the repository at this point in the history
… debugger.

Summary:
According to
https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf,
the compiler should emit the DW_AT_address_class attribute for all
variable and parameter. It means, that DW_AT_address_class attribute
should be used in the non-standard way to support compatibility with the
cuda-gdb debugger.
Clang is able to generate the information about the variable address
class. This information is emitted as the expression sequence
`DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef`. The patch
tries to find all such expressions and transform them into
`DW_AT_address_class <DWARF Address Space>` if target is NVPTX and the debugger is gdb.
If the expression is not found, then default values are used. For the
local variables <DWARF Address Space> is set to ADDR_local_space(6), for
the globals <DWARF Address Space> is set to ADDR_global_space(5). The
values are taken from the table in the same section 5.2. CUDA-Specific
DWARF Definitions.

Reviewers: echristo, probinson

Subscribers: jholewinski, aprantl, llvm-commits

Differential Revision: https://reviews.llvm.org/D57157

llvm-svn: 353203
  • Loading branch information
alexey-bataev committed Feb 5, 2019
1 parent a3f9b71 commit f3a9150
Show file tree
Hide file tree
Showing 5 changed files with 345 additions and 11 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Expand Up @@ -2510,6 +2510,12 @@ class DIExpression : public MDNode {
/// return true with an offset of zero.
bool extractIfOffset(int64_t &Offset) const;

/// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF
/// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address
/// Space>.
static const DIExpression *extractAddressClass(const DIExpression *Expr,
unsigned &AddrClass);

/// Constants for DIExpression::prepend.
enum { NoDeref = false, WithDeref = true, WithStackValue = true };

Expand Down
56 changes: 54 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Expand Up @@ -167,6 +167,7 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
// Add location.
bool addToAccelTable = false;
DIELoc *Loc = nullptr;
Optional<unsigned> NVPTXAddressSpace;
std::unique_ptr<DIEDwarfExpression> DwarfExpr;
for (const auto &GE : GlobalExprs) {
const GlobalVariable *Global = GE.Var;
Expand Down Expand Up @@ -200,8 +201,24 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
}

if (Expr)
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.
// Decode DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef
// sequence for the NVPTX + gdb target.
unsigned LocalNVPTXAddressSpace;
if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
const DIExpression *NewExpr =
DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
if (NewExpr != Expr) {
Expr = NewExpr;
NVPTXAddressSpace = LocalNVPTXAddressSpace;
}
}
DwarfExpr->addFragmentOffset(Expr);
}

if (Global) {
const MCSymbol *Sym = Asm->getSymbol(Global);
Expand Down Expand Up @@ -246,6 +263,15 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr->setMemoryLocationKind();
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;
addUInt(*VariableDIE, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
NVPTXAddressSpace ? *NVPTXAddressSpace : NVPTX_ADDR_global_space);
}
if (Loc)
addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());

Expand Down Expand Up @@ -591,6 +617,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
if (!DV.hasFrameIndexExprs())
return VariableDie;

Optional<unsigned> NVPTXAddressSpace;
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
for (auto &Fragment : DV.getFrameIndexExprs()) {
Expand All @@ -602,7 +629,23 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
SmallVector<uint64_t, 8> Ops;
Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Offset);
Ops.append(Expr->elements_begin(), Expr->elements_end());
// 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 <DWARF Address Space> DW_OP_swap DW_OP_xderef
// sequence for the NVPTX + gdb target.
unsigned LocalNVPTXAddressSpace;
if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
const DIExpression *NewExpr =
DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
if (NewExpr != Expr) {
Expr = NewExpr;
NVPTXAddressSpace = LocalNVPTXAddressSpace;
}
}
if (Expr)
Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
DwarfExpr.setMemoryLocationKind();
if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
Expand All @@ -612,6 +655,15 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
*Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
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;
addUInt(*VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
NVPTXAddressSpace ? *NVPTXAddressSpace : NVPTX_ADDR_local_space);
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());

return VariableDie;
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/IR/DebugInfoMetadata.cpp
Expand Up @@ -928,6 +928,24 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {
return false;
}

const DIExpression *DIExpression::extractAddressClass(const DIExpression *Expr,
unsigned &AddrClass) {
const unsigned PatternSize = 4;
if (Expr->Elements.size() >= PatternSize &&
Expr->Elements[PatternSize - 4] == dwarf::DW_OP_constu &&
Expr->Elements[PatternSize - 2] == dwarf::DW_OP_swap &&
Expr->Elements[PatternSize - 1] == dwarf::DW_OP_xderef) {
AddrClass = Expr->Elements[PatternSize - 3];

if (Expr->Elements.size() == PatternSize)
return nullptr;
return DIExpression::get(Expr->getContext(),
makeArrayRef(&*Expr->Elements.begin(),
Expr->Elements.size() - PatternSize));
}
return Expr;
}

DIExpression *DIExpression::prepend(const DIExpression *Expr, bool DerefBefore,
int64_t Offset, bool DerefAfter,
bool StackValue) {
Expand Down
21 changes: 12 additions & 9 deletions llvm/test/DebugInfo/NVPTX/dbg-declare-alloca.ll
Expand Up @@ -68,6 +68,8 @@
; CHECK-NEXT: .b8 3 // Abbreviation Code
; CHECK-NEXT: .b8 52 // DW_TAG_variable
; CHECK-NEXT: .b8 0 // DW_CHILDREN_no
; CHECK-NEXT: .b8 51 // DW_AT_address_class
; CHECK-NEXT: .b8 11 // DW_FORM_data1
; CHECK-NEXT: .b8 2 // DW_AT_location
; CHECK-NEXT: .b8 10 // DW_FORM_block1
; CHECK-NEXT: .b8 3 // DW_AT_name
Expand Down Expand Up @@ -123,12 +125,12 @@
; CHECK-NEXT: }
; CHECK-NEXT: .section .debug_info
; CHECK-NEXT: {
; CHECK-NEXT: .b32 135 // Length of Unit
; CHECK-NEXT: .b32 136 // Length of Unit
; CHECK-NEXT: .b8 2 // DWARF version number
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b32 .debug_abbrev // Offset Into Abbrev. Section
; CHECK-NEXT: .b8 8 // Address Size (in bytes)
; CHECK-NEXT: .b8 1 // Abbrev [1] 0xb:0x80 DW_TAG_compile_unit
; CHECK-NEXT: .b8 1 // Abbrev [1] 0xb:0x81 DW_TAG_compile_unit
; CHECK-NEXT: .b8 99,108,97,110,103 // DW_AT_producer
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b8 12 // DW_AT_language
Expand All @@ -140,7 +142,7 @@
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b64 Lfunc_begin0 // DW_AT_low_pc
; CHECK-NEXT: .b64 Lfunc_end0 // DW_AT_high_pc
; CHECK-NEXT: .b8 2 // Abbrev [2] 0x31:0x3d DW_TAG_subprogram
; CHECK-NEXT: .b8 2 // Abbrev [2] 0x31:0x3e DW_TAG_subprogram
; CHECK-NEXT: .b64 Lfunc_begin0 // DW_AT_low_pc
; CHECK-NEXT: .b64 Lfunc_end0 // DW_AT_high_pc
; CHECK-NEXT: .b8 1 // DW_AT_frame_base
Expand All @@ -151,7 +153,8 @@
; CHECK-NEXT: .b8 3 // DW_AT_decl_line
; CHECK-NEXT: .b8 1 // DW_AT_prototyped
; CHECK-NEXT: .b8 1 // DW_AT_external
; CHECK-NEXT: .b8 3 // Abbrev [3] 0x58:0x15 DW_TAG_variable
; CHECK-NEXT: .b8 3 // Abbrev [3] 0x58:0x16 DW_TAG_variable
; CHECK-NEXT: .b8 6 // DW_AT_address_class
; CHECK-NEXT: .b8 11 // DW_AT_location
; CHECK-NEXT: .b8 3
; CHECK-NEXT: .b64 __local_depot0
Expand All @@ -161,25 +164,25 @@
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
; CHECK-NEXT: .b8 4 // DW_AT_decl_line
; CHECK-NEXT: .b32 110 // DW_AT_type
; CHECK-NEXT: .b32 111 // DW_AT_type
; CHECK-NEXT: .b8 0 // End Of Children Mark
; CHECK-NEXT: .b8 4 // Abbrev [4] 0x6e:0x15 DW_TAG_structure_type
; CHECK-NEXT: .b8 4 // Abbrev [4] 0x6f:0x15 DW_TAG_structure_type
; CHECK-NEXT: .b8 70,111,111 // DW_AT_name
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b8 4 // DW_AT_byte_size
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
; CHECK-NEXT: .b8 1 // DW_AT_decl_line
; CHECK-NEXT: .b8 5 // Abbrev [5] 0x76:0xc DW_TAG_member
; CHECK-NEXT: .b8 5 // Abbrev [5] 0x77:0xc DW_TAG_member
; CHECK-NEXT: .b8 120 // DW_AT_name
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b32 131 // DW_AT_type
; CHECK-NEXT: .b32 132 // DW_AT_type
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
; CHECK-NEXT: .b8 1 // DW_AT_decl_line
; CHECK-NEXT: .b8 2 // DW_AT_data_member_location
; CHECK-NEXT: .b8 35
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b8 0 // End Of Children Mark
; CHECK-NEXT: .b8 6 // Abbrev [6] 0x83:0x7 DW_TAG_base_type
; CHECK-NEXT: .b8 6 // Abbrev [6] 0x84:0x7 DW_TAG_base_type
; CHECK-NEXT: .b8 105,110,116 // DW_AT_name
; CHECK-NEXT: .b8 0
; CHECK-NEXT: .b8 5 // DW_AT_encoding
Expand Down

0 comments on commit f3a9150

Please sign in to comment.