Skip to content

Commit 8e93b9f

Browse files
willghatchpuja2196
authored andcommitted
[NVPTX] add support for encoding PTX registers for DWARF (#109495)
This patch adds support for encoding PTX registers for DWARF, using the encoding supported by nvcc and cuda-gcc. There are some other features still needed for proper register debugging that this patch does not address, such as DW_AT_address_class. This PR is stacked on: llvm/llvm-project#109494
1 parent 569d0a9 commit 8e93b9f

File tree

8 files changed

+1281
-1143
lines changed

8 files changed

+1281
-1143
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI,
105105
DwarfRegs.push_back(Register::createRegister(-1, nullptr));
106106
return true;
107107
}
108+
// Try getting dwarf register for virtual register anyway, eg. for NVPTX.
109+
int64_t Reg = TRI.getDwarfRegNum(MachineReg, false);
110+
if (Reg > 0) {
111+
DwarfRegs.push_back(Register::createRegister(Reg, nullptr));
112+
return true;
113+
}
108114
return false;
109115
}
110116

llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ void NVPTXAsmPrinter::emitFunctionEntryLabel() {
490490
// Emit open brace for function body.
491491
OutStreamer->emitRawText(StringRef("{\n"));
492492
setAndEmitFunctionVirtualRegisters(*MF);
493+
encodeDebugInfoRegisterNumbers(*MF);
493494
// Emit initial .loc debug directive for correct relocation symbol data.
494495
if (const DISubprogram *SP = MF->getFunction().getSubprogram()) {
495496
assert(SP->getUnit());
@@ -1792,6 +1793,26 @@ void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
17921793
OutStreamer->emitRawText(O.str());
17931794
}
17941795

1796+
/// Translate virtual register numbers in DebugInfo locations to their printed
1797+
/// encodings, as used by CUDA-GDB.
1798+
void NVPTXAsmPrinter::encodeDebugInfoRegisterNumbers(
1799+
const MachineFunction &MF) {
1800+
const NVPTXSubtarget &STI = MF.getSubtarget<NVPTXSubtarget>();
1801+
const NVPTXRegisterInfo *registerInfo = STI.getRegisterInfo();
1802+
1803+
// Clear the old mapping, and add the new one. This mapping is used after the
1804+
// printing of the current function is complete, but before the next function
1805+
// is printed.
1806+
registerInfo->clearDebugRegisterMap();
1807+
1808+
for (auto &classMap : VRegMapping) {
1809+
for (auto &registerMapping : classMap.getSecond()) {
1810+
auto reg = registerMapping.getFirst();
1811+
registerInfo->addToDebugRegisterMap(reg, getVirtualRegisterName(reg));
1812+
}
1813+
}
1814+
}
1815+
17951816
void NVPTXAsmPrinter::printFPConstant(const ConstantFP *Fp, raw_ostream &O) {
17961817
APFloat APF = APFloat(Fp->getValueAPF()); // make a copy
17971818
bool ignored;

llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter {
181181
void emitVirtualRegister(unsigned int vr, raw_ostream &);
182182
void emitFunctionParamList(const Function *, raw_ostream &O);
183183
void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
184+
void encodeDebugInfoRegisterNumbers(const MachineFunction &MF);
184185
void printReturnValStr(const Function *, raw_ostream &O);
185186
void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
186187
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

llvm/lib/Target/NVPTX/NVPTXRegisterInfo.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "NVPTXRegisterInfo.h"
14+
#include "MCTargetDesc/NVPTXInstPrinter.h"
1415
#include "NVPTX.h"
1516
#include "NVPTXSubtarget.h"
1617
#include "NVPTXTargetMachine.h"
@@ -141,3 +142,47 @@ NVPTXRegisterInfo::getFrameLocalRegister(const MachineFunction &MF) const {
141142
static_cast<const NVPTXTargetMachine &>(MF.getTarget());
142143
return TM.is64Bit() ? NVPTX::VRFrameLocal64 : NVPTX::VRFrameLocal32;
143144
}
145+
146+
void NVPTXRegisterInfo::clearDebugRegisterMap() const {
147+
debugRegisterMap.clear();
148+
}
149+
150+
static uint64_t encodeRegisterForDwarf(std::string registerName) {
151+
if (registerName.length() > 8) {
152+
// The name is more than 8 characters long, and so won't fit into 64 bits.
153+
return 0;
154+
}
155+
156+
// Encode the name string into a DWARF register number using cuda-gdb's
157+
// encoding. See cuda_check_dwarf2_reg_ptx_virtual_register in cuda-tdep.c,
158+
// https://github.com/NVIDIA/cuda-gdb/blob/e5cf3bddae520ffb326f95b4d98ce5c7474b828b/gdb/cuda/cuda-tdep.c#L353
159+
// IE the bytes of the string are concatenated in reverse into a single
160+
// number, which is stored in ULEB128, but in practice must be no more than 8
161+
// bytes (excluding null terminator, which is not included).
162+
uint64_t result = 0;
163+
for (int i = 0; i < registerName.length(); ++i) {
164+
result = result << 8;
165+
unsigned char c = registerName[i];
166+
result |= c;
167+
}
168+
return result;
169+
}
170+
171+
void NVPTXRegisterInfo::addToDebugRegisterMap(
172+
uint64_t preEncodedVirtualRegister, std::string registerName) const {
173+
uint64_t mapped = encodeRegisterForDwarf(registerName);
174+
if (mapped == 0)
175+
return;
176+
debugRegisterMap.insert({preEncodedVirtualRegister, mapped});
177+
}
178+
179+
int64_t NVPTXRegisterInfo::getDwarfRegNum(MCRegister RegNum, bool isEH) const {
180+
if (Register::isPhysicalRegister(RegNum)) {
181+
std::string name = NVPTXInstPrinter::getRegisterName(RegNum.id());
182+
return encodeRegisterForDwarf(name);
183+
}
184+
uint64_t lookup = debugRegisterMap.lookup(RegNum.id());
185+
if (lookup)
186+
return lookup;
187+
return -1;
188+
}

llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class NVPTXRegisterInfo : public NVPTXGenRegisterInfo {
2626
// Hold Strings that can be free'd all together with NVPTXRegisterInfo
2727
BumpPtrAllocator StrAlloc;
2828
UniqueStringSaver StrPool;
29+
// State for debug register mapping that can be mutated even through a const
30+
// pointer so that we can get the proper dwarf register encoding during ASM
31+
// emission.
32+
mutable DenseMap<uint64_t, uint64_t> debugRegisterMap;
2933

3034
public:
3135
NVPTXRegisterInfo();
@@ -56,6 +60,18 @@ class NVPTXRegisterInfo : public NVPTXGenRegisterInfo {
5660
return getStrPool().save(O.str()).data();
5761
}
5862

63+
// Manage the debugRegisterMap. PTX virtual registers for DebugInfo are
64+
// encoded using the names used in the emitted text of the PTX assembly. This
65+
// mapping must be managed during assembly emission.
66+
//
67+
// These are marked const because the interfaces used to access this
68+
// RegisterInfo object are all const, but we need to communicate some state
69+
// here, because the proper encoding for debug registers is available only
70+
// temporarily during ASM emission.
71+
void addToDebugRegisterMap(uint64_t preEncodedVirtualRegister,
72+
std::string registerName) const;
73+
void clearDebugRegisterMap() const;
74+
int64_t getDwarfRegNum(MCRegister RegNum, bool isEH) const override;
5975
};
6076

6177
std::string getNVPTXRegClassName(const TargetRegisterClass *RC);

llvm/test/DebugInfo/NVPTX/cu-range-hole.ll

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ entry:
120120
; CHECK-NEXT: .b8 3 // Abbreviation Code
121121
; CHECK-NEXT: .b8 5 // DW_TAG_formal_parameter
122122
; CHECK-NEXT: .b8 0 // DW_CHILDREN_no
123+
; CHECK-NEXT: .b8 2 // DW_AT_location
124+
; CHECK-NEXT: .b8 10 // DW_FORM_block1
123125
; CHECK-NEXT: .b8 3 // DW_AT_name
124126
; CHECK-NEXT: .b8 8 // DW_FORM_string
125127
; CHECK-NEXT: .b8 58 // DW_AT_decl_file
@@ -145,12 +147,12 @@ entry:
145147
; CHECK-NEXT: }
146148
; CHECK-NEXT: .section .debug_info
147149
; CHECK-NEXT: {
148-
; CHECK-NEXT: .b32 183 // Length of Unit
150+
; CHECK-NEXT: .b32 195 // Length of Unit
149151
; CHECK-NEXT: .b8 2 // DWARF version number
150152
; CHECK-NEXT: .b8 0
151153
; CHECK-NEXT: .b32 .debug_abbrev // Offset Into Abbrev. Section
152154
; CHECK-NEXT: .b8 8 // Address Size (in bytes)
153-
; CHECK-NEXT: .b8 1 // Abbrev [1] 0xb:0xb0 DW_TAG_compile_unit
155+
; CHECK-NEXT: .b8 1 // Abbrev [1] 0xb:0xbc DW_TAG_compile_unit
154156
; CHECK-NEXT: .b8 99 // DW_AT_producer
155157
; CHECK-NEXT: .b8 108
156158
; CHECK-NEXT: .b8 97
@@ -223,7 +225,7 @@ entry:
223225
; CHECK-NEXT: .b8 0
224226
; CHECK-NEXT: .b64 $L__func_begin0 // DW_AT_low_pc
225227
; CHECK-NEXT: .b64 $L__func_end2 // DW_AT_high_pc
226-
; CHECK-NEXT: .b8 2 // Abbrev [2] 0x65:0x27 DW_TAG_subprogram
228+
; CHECK-NEXT: .b8 2 // Abbrev [2] 0x65:0x2d DW_TAG_subprogram
227229
; CHECK-NEXT: .b64 $L__func_begin0 // DW_AT_low_pc
228230
; CHECK-NEXT: .b64 $L__func_end0 // DW_AT_high_pc
229231
; CHECK-NEXT: .b8 1 // DW_AT_frame_base
@@ -233,16 +235,22 @@ entry:
233235
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
234236
; CHECK-NEXT: .b8 1 // DW_AT_decl_line
235237
; CHECK-NEXT: .b8 1 // DW_AT_prototyped
236-
; CHECK-NEXT: .b32 179 // DW_AT_type
238+
; CHECK-NEXT: .b32 191 // DW_AT_type
237239
; CHECK-NEXT: .b8 1 // DW_AT_external
238-
; CHECK-NEXT: .b8 3 // Abbrev [3] 0x82:0x9 DW_TAG_formal_parameter
240+
; CHECK-NEXT: .b8 3 // Abbrev [3] 0x82:0xf DW_TAG_formal_parameter
241+
; CHECK-NEXT: .b8 5 // DW_AT_location
242+
; CHECK-NEXT: .b8 144
243+
; CHECK-NEXT: .b8 177
244+
; CHECK-NEXT: .b8 228
245+
; CHECK-NEXT: .b8 149
246+
; CHECK-NEXT: .b8 1
239247
; CHECK-NEXT: .b8 99 // DW_AT_name
240248
; CHECK-NEXT: .b8 0
241249
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
242250
; CHECK-NEXT: .b8 1 // DW_AT_decl_line
243-
; CHECK-NEXT: .b32 179 // DW_AT_type
251+
; CHECK-NEXT: .b32 191 // DW_AT_type
244252
; CHECK-NEXT: .b8 0 // End Of Children Mark
245-
; CHECK-NEXT: .b8 2 // Abbrev [2] 0x8c:0x27 DW_TAG_subprogram
253+
; CHECK-NEXT: .b8 2 // Abbrev [2] 0x92:0x2d DW_TAG_subprogram
246254
; CHECK-NEXT: .b64 $L__func_begin2 // DW_AT_low_pc
247255
; CHECK-NEXT: .b64 $L__func_end2 // DW_AT_high_pc
248256
; CHECK-NEXT: .b8 1 // DW_AT_frame_base
@@ -252,16 +260,22 @@ entry:
252260
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
253261
; CHECK-NEXT: .b8 3 // DW_AT_decl_line
254262
; CHECK-NEXT: .b8 1 // DW_AT_prototyped
255-
; CHECK-NEXT: .b32 179 // DW_AT_type
263+
; CHECK-NEXT: .b32 191 // DW_AT_type
256264
; CHECK-NEXT: .b8 1 // DW_AT_external
257-
; CHECK-NEXT: .b8 3 // Abbrev [3] 0xa9:0x9 DW_TAG_formal_parameter
265+
; CHECK-NEXT: .b8 3 // Abbrev [3] 0xaf:0xf DW_TAG_formal_parameter
266+
; CHECK-NEXT: .b8 5 // DW_AT_location
267+
; CHECK-NEXT: .b8 144
268+
; CHECK-NEXT: .b8 177
269+
; CHECK-NEXT: .b8 228
270+
; CHECK-NEXT: .b8 149
271+
; CHECK-NEXT: .b8 1
258272
; CHECK-NEXT: .b8 101 // DW_AT_name
259273
; CHECK-NEXT: .b8 0
260274
; CHECK-NEXT: .b8 1 // DW_AT_decl_file
261275
; CHECK-NEXT: .b8 3 // DW_AT_decl_line
262-
; CHECK-NEXT: .b32 179 // DW_AT_type
276+
; CHECK-NEXT: .b32 191 // DW_AT_type
263277
; CHECK-NEXT: .b8 0 // End Of Children Mark
264-
; CHECK-NEXT: .b8 4 // Abbrev [4] 0xb3:0x7 DW_TAG_base_type
278+
; CHECK-NEXT: .b8 4 // Abbrev [4] 0xbf:0x7 DW_TAG_base_type
265279
; CHECK-NEXT: .b8 105 // DW_AT_name
266280
; CHECK-NEXT: .b8 110
267281
; CHECK-NEXT: .b8 116

llvm/test/DebugInfo/NVPTX/debug-addr-class.ll

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
160160
; CHECK-NEXT:.b8 5 // Abbreviation Code
161161
; CHECK-NEXT:.b8 5 // DW_TAG_formal_parameter
162162
; CHECK-NEXT:.b8 0 // DW_CHILDREN_no
163+
; CHECK-NEXT:.b8 2 // DW_AT_location
164+
; CHECK-NEXT:.b8 10 // DW_FORM_block1
163165
; CHECK-NEXT:.b8 3 // DW_AT_name
164166
; CHECK-NEXT:.b8 8 // DW_FORM_string
165167
; CHECK-NEXT:.b8 58 // DW_AT_decl_file
@@ -171,6 +173,19 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
171173
; CHECK-NEXT:.b8 0 // EOM(1)
172174
; CHECK-NEXT:.b8 0 // EOM(2)
173175
; CHECK-NEXT:.b8 6 // Abbreviation Code
176+
; CHECK-NEXT:.b8 5 // DW_TAG_formal_parameter
177+
; CHECK-NEXT:.b8 0 // DW_CHILDREN_no
178+
; CHECK-NEXT:.b8 3 // DW_AT_name
179+
; CHECK-NEXT:.b8 8 // DW_FORM_string
180+
; CHECK-NEXT:.b8 58 // DW_AT_decl_file
181+
; CHECK-NEXT:.b8 11 // DW_FORM_data1
182+
; CHECK-NEXT:.b8 59 // DW_AT_decl_line
183+
; CHECK-NEXT:.b8 11 // DW_FORM_data1
184+
; CHECK-NEXT:.b8 73 // DW_AT_type
185+
; CHECK-NEXT:.b8 19 // DW_FORM_ref4
186+
; CHECK-NEXT:.b8 0 // EOM(1)
187+
; CHECK-NEXT:.b8 0 // EOM(2)
188+
; CHECK-NEXT:.b8 7 // Abbreviation Code
174189
; CHECK-NEXT:.b8 15 // DW_TAG_pointer_type
175190
; CHECK-NEXT:.b8 0 // DW_CHILDREN_no
176191
; CHECK-NEXT:.b8 73 // DW_AT_type
@@ -181,12 +196,12 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
181196
; CHECK-NEXT: }
182197
; CHECK-NEXT: .section .debug_info
183198
; CHECK-NEXT: {
184-
; CHECK-NEXT:.b32 240 // Length of Unit
199+
; CHECK-NEXT:.b32 252 // Length of Unit
185200
; CHECK-NEXT:.b8 2 // DWARF version number
186201
; CHECK-NEXT:.b8 0
187202
; CHECK-NEXT:.b32 .debug_abbrev // Offset Into Abbrev. Section
188203
; CHECK-NEXT:.b8 8 // Address Size (in bytes)
189-
; CHECK-NEXT:.b8 1 // Abbrev [1] 0xb:0xe9 DW_TAG_compile_unit
204+
; CHECK-NEXT:.b8 1 // Abbrev [1] 0xb:0xf5 DW_TAG_compile_unit
190205
; CHECK-NEXT:.b8 99 // DW_AT_producer
191206
; CHECK-NEXT:.b8 108
192207
; CHECK-NEXT:.b8 97
@@ -298,7 +313,7 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
298313
; CHECK-NEXT:.b8 9 // DW_AT_location
299314
; CHECK-NEXT:.b8 3
300315
; CHECK-NEXT:.b64 SHARED
301-
; CHECK-NEXT:.b8 4 // Abbrev [4] 0xa0:0x45 DW_TAG_subprogram
316+
; CHECK-NEXT:.b8 4 // Abbrev [4] 0xa0:0x51 DW_TAG_subprogram
302317
; CHECK-NEXT:.b64 $L__func_begin0 // DW_AT_low_pc
303318
; CHECK-NEXT:.b64 $L__func_end0 // DW_AT_high_pc
304319
; CHECK-NEXT:.b8 1 // DW_AT_frame_base
@@ -316,32 +331,44 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
316331
; CHECK-NEXT:.b8 1 // DW_AT_decl_file
317332
; CHECK-NEXT:.b8 6 // DW_AT_decl_line
318333
; CHECK-NEXT:.b8 1 // DW_AT_external
319-
; CHECK-NEXT:.b8 5 // Abbrev [5] 0xc0:0x9 DW_TAG_formal_parameter
334+
; CHECK-NEXT:.b8 5 // Abbrev [5] 0xc0:0xf DW_TAG_formal_parameter
335+
; CHECK-NEXT:.b8 5 // DW_AT_location
336+
; CHECK-NEXT:.b8 144
337+
; CHECK-NEXT:.b8 177
338+
; CHECK-NEXT:.b8 204
339+
; CHECK-NEXT:.b8 149
340+
; CHECK-NEXT:.b8 1
320341
; CHECK-NEXT:.b8 97 // DW_AT_name
321342
; CHECK-NEXT:.b8 0
322343
; CHECK-NEXT:.b8 1 // DW_AT_decl_file
323344
; CHECK-NEXT:.b8 6 // DW_AT_decl_line
324-
; CHECK-NEXT:.b32 229 // DW_AT_type
325-
; CHECK-NEXT:.b8 5 // Abbrev [5] 0xc9:0x9 DW_TAG_formal_parameter
345+
; CHECK-NEXT:.b32 241 // DW_AT_type
346+
; CHECK-NEXT:.b8 6 // Abbrev [6] 0xcf:0x9 DW_TAG_formal_parameter
326347
; CHECK-NEXT:.b8 120 // DW_AT_name
327348
; CHECK-NEXT:.b8 0
328349
; CHECK-NEXT:.b8 1 // DW_AT_decl_file
329350
; CHECK-NEXT:.b8 6 // DW_AT_decl_line
330-
; CHECK-NEXT:.b32 238 // DW_AT_type
331-
; CHECK-NEXT:.b8 5 // Abbrev [5] 0xd2:0x9 DW_TAG_formal_parameter
351+
; CHECK-NEXT:.b32 250 // DW_AT_type
352+
; CHECK-NEXT:.b8 6 // Abbrev [6] 0xd8:0x9 DW_TAG_formal_parameter
332353
; CHECK-NEXT:.b8 121 // DW_AT_name
333354
; CHECK-NEXT:.b8 0
334355
; CHECK-NEXT:.b8 1 // DW_AT_decl_file
335356
; CHECK-NEXT:.b8 6 // DW_AT_decl_line
336-
; CHECK-NEXT:.b32 238 // DW_AT_type
337-
; CHECK-NEXT:.b8 5 // Abbrev [5] 0xdb:0x9 DW_TAG_formal_parameter
357+
; CHECK-NEXT:.b32 250 // DW_AT_type
358+
; CHECK-NEXT:.b8 5 // Abbrev [5] 0xe1:0xf DW_TAG_formal_parameter
359+
; CHECK-NEXT:.b8 5 // DW_AT_location
360+
; CHECK-NEXT:.b8 144
361+
; CHECK-NEXT:.b8 177
362+
; CHECK-NEXT:.b8 228
363+
; CHECK-NEXT:.b8 149
364+
; CHECK-NEXT:.b8 1
338365
; CHECK-NEXT:.b8 105 // DW_AT_name
339366
; CHECK-NEXT:.b8 0
340367
; CHECK-NEXT:.b8 1 // DW_AT_decl_file
341368
; CHECK-NEXT:.b8 6 // DW_AT_decl_line
342369
; CHECK-NEXT:.b32 127 // DW_AT_type
343370
; CHECK-NEXT:.b8 0 // End Of Children Mark
344-
; CHECK-NEXT:.b8 3 // Abbrev [3] 0xe5:0x9 DW_TAG_base_type
371+
; CHECK-NEXT:.b8 3 // Abbrev [3] 0xf1:0x9 DW_TAG_base_type
345372
; CHECK-NEXT:.b8 102 // DW_AT_name
346373
; CHECK-NEXT:.b8 108
347374
; CHECK-NEXT:.b8 111
@@ -350,8 +377,8 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
350377
; CHECK-NEXT:.b8 0
351378
; CHECK-NEXT:.b8 4 // DW_AT_encoding
352379
; CHECK-NEXT:.b8 4 // DW_AT_byte_size
353-
; CHECK-NEXT:.b8 6 // Abbrev [6] 0xee:0x5 DW_TAG_pointer_type
354-
; CHECK-NEXT:.b32 229 // DW_AT_type
380+
; CHECK-NEXT:.b8 7 // Abbrev [7] 0xfa:0x5 DW_TAG_pointer_type
381+
; CHECK-NEXT:.b32 241 // DW_AT_type
355382
; CHECK-NEXT:.b8 0 // End Of Children Mark
356383
; CHECK-NEXT: }
357384
; CHECK-NEXT: .section .debug_loc { }

0 commit comments

Comments
 (0)