Skip to content

Commit d943ea3

Browse files
committed
[SPIR-V] Emit DebugTypeBasic for NonSemantic DI
The commit introduces support for fundamental DI instruction. Metadata handlers required for this instruction is stored inside debug records (https://llvm.org/docs/SourceLevelDebugging.html) parts of the module which rises the necessity of it's traversal.
1 parent bdfd780 commit d943ea3

File tree

3 files changed

+340
-34
lines changed

3 files changed

+340
-34
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp

Lines changed: 106 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include "SPIRVGlobalRegistry.h"
55
#include "SPIRVRegisterInfo.h"
66
#include "SPIRVTargetMachine.h"
7+
#include "llvm/ADT/SmallSet.h"
78
#include "llvm/ADT/SmallString.h"
9+
#include "llvm/BinaryFormat/Dwarf.h"
810
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
911
#include "llvm/CodeGen/MachineBasicBlock.h"
1012
#include "llvm/CodeGen/MachineFunction.h"
@@ -13,7 +15,10 @@
1315
#include "llvm/CodeGen/MachineInstrBuilder.h"
1416
#include "llvm/CodeGen/MachineModuleInfo.h"
1517
#include "llvm/CodeGen/MachineOperand.h"
18+
#include "llvm/CodeGen/MachineRegisterInfo.h"
19+
#include "llvm/CodeGen/Register.h"
1620
#include "llvm/IR/DebugInfoMetadata.h"
21+
#include "llvm/IR/DebugProgramInstruction.h"
1722
#include "llvm/IR/Metadata.h"
1823
#include "llvm/PassRegistry.h"
1924
#include "llvm/Support/Casting.h"
@@ -71,7 +76,7 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
7176
unsigned SourceLanguage = 0;
7277
int64_t DwarfVersion = 0;
7378
int64_t DebugInfoVersion = 0;
74-
79+
SmallSet<DIBasicType *, 12> BasicTypes;
7580
// Searching through the Module metadata to find nescessary
7681
// information like DwarfVersion or SourceLanguage
7782
{
@@ -104,6 +109,24 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
104109
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
105110
->getSExtValue();
106111
}
112+
113+
// This traversal is the only supported way to access
114+
// instruction related DI metadata like DIBasicType
115+
for (auto &F : *M) {
116+
for (auto &BB : F) {
117+
for (auto &I : BB) {
118+
for (DbgRecord &DR : I.getDbgRecordRange()) {
119+
if (auto *DVR = dyn_cast<DbgVariableRecord>(&DR)) {
120+
DILocalVariable *LocalVariable = DVR->getVariable();
121+
if (auto *BasicType =
122+
dyn_cast<DIBasicType>(LocalVariable->getType())) {
123+
BasicTypes.insert(BasicType);
124+
}
125+
}
126+
}
127+
}
128+
}
129+
}
107130
}
108131
// NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
109132
{
@@ -120,29 +143,45 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
120143
// and before first terminator
121144
MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
122145

146+
const auto EmitOpString = [&](StringRef SR) {
147+
const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
148+
MRI.setType(StrReg, LLT::scalar(32));
149+
MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
150+
MIB.addDef(StrReg);
151+
addStringImm(SR, MIB);
152+
return StrReg;
153+
};
154+
123155
// Emit OpString with FilePath which is required by DebugSource
124-
const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
125-
MRI.setType(StrReg, LLT::scalar(32));
126-
MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
127-
MIB.addDef(StrReg);
128-
addStringImm(FilePath, MIB);
156+
const Register FilePathStrReg = EmitOpString(FilePath);
129157

130158
const SPIRVType *VoidTy =
131159
GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder);
132160

161+
const auto EmitDIInstruction =
162+
[&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
163+
std::initializer_list<Register> Registers) {
164+
const Register InstReg =
165+
MRI.createVirtualRegister(&SPIRV::IDRegClass);
166+
MRI.setType(InstReg, LLT::scalar(32));
167+
MachineInstrBuilder MIB =
168+
MIRBuilder.buildInstr(SPIRV::OpExtInst)
169+
.addDef(InstReg)
170+
.addUse(GR->getSPIRVTypeID(VoidTy))
171+
.addImm(static_cast<int64_t>(
172+
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
173+
.addImm(Inst);
174+
for (auto Reg : Registers) {
175+
MIB.addUse(Reg);
176+
}
177+
MIB.constrainAllUses(*TII, *TRI, *RBI);
178+
GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
179+
return InstReg;
180+
};
181+
133182
// Emit DebugSource which is required by DebugCompilationUnit
134-
const Register DebugSourceResIdReg =
135-
MRI.createVirtualRegister(&SPIRV::IDRegClass);
136-
MRI.setType(DebugSourceResIdReg, LLT::scalar(32));
137-
MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst)
138-
.addDef(DebugSourceResIdReg)
139-
.addUse(GR->getSPIRVTypeID(VoidTy))
140-
.addImm(static_cast<int64_t>(
141-
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
142-
.addImm(SPIRV::NonSemanticExtInst::DebugSource)
143-
.addUse(StrReg);
144-
MIB.constrainAllUses(*TII, *TRI, *RBI);
145-
GR->assignSPIRVTypeToVReg(VoidTy, DebugSourceResIdReg, MF);
183+
const Register DebugSourceResIdReg = EmitDIInstruction(
184+
SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
146185

147186
const SPIRVType *I32Ty =
148187
GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
@@ -156,22 +195,56 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
156195
const Register SourceLanguageReg =
157196
GR->buildConstantInt(SourceLanguage, MIRBuilder, I32Ty, false);
158197

159-
// Emit DebugCompilationUnit
198+
[[maybe_unused]]
160199
const Register DebugCompUnitResIdReg =
161-
MRI.createVirtualRegister(&SPIRV::IDRegClass);
162-
MRI.setType(DebugCompUnitResIdReg, LLT::scalar(32));
163-
MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst)
164-
.addDef(DebugCompUnitResIdReg)
165-
.addUse(GR->getSPIRVTypeID(VoidTy))
166-
.addImm(static_cast<int64_t>(
167-
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
168-
.addImm(SPIRV::NonSemanticExtInst::DebugCompilationUnit)
169-
.addUse(DebugInfoVersionReg)
170-
.addUse(DwarfVersionReg)
171-
.addUse(DebugSourceResIdReg)
172-
.addUse(SourceLanguageReg);
173-
MIB.constrainAllUses(*TII, *TRI, *RBI);
174-
GR->assignSPIRVTypeToVReg(VoidTy, DebugCompUnitResIdReg, MF);
200+
EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
201+
{DebugInfoVersionReg, DwarfVersionReg,
202+
DebugSourceResIdReg, SourceLanguageReg});
203+
204+
// Emit DebugInfoNone. This instruction is a wildcard accepted
205+
// by standard to put into instruction arguments as Not Available/Null
206+
const Register DebugInfoNoneReg =
207+
EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});
208+
209+
for (auto *BasicType : BasicTypes) {
210+
const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
211+
212+
const Register ConstIntBitwidthReg = GR->buildConstantInt(
213+
BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
214+
215+
uint64_t AttributeEncoding = 0;
216+
switch (BasicType->getEncoding()) {
217+
case dwarf::DW_ATE_signed:
218+
AttributeEncoding = 4;
219+
break;
220+
case dwarf::DW_ATE_unsigned:
221+
AttributeEncoding = 6;
222+
break;
223+
case dwarf::DW_ATE_unsigned_char:
224+
AttributeEncoding = 7;
225+
break;
226+
case dwarf::DW_ATE_signed_char:
227+
AttributeEncoding = 5;
228+
break;
229+
case dwarf::DW_ATE_float:
230+
AttributeEncoding = 3;
231+
break;
232+
case dwarf::DW_ATE_boolean:
233+
AttributeEncoding = 2;
234+
break;
235+
case dwarf::DW_ATE_address:
236+
AttributeEncoding = 1;
237+
}
238+
239+
const Register AttributeEncodingReg =
240+
GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
241+
242+
[[maybe_unused]]
243+
const Register BasicTypeReg =
244+
EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
245+
{BasicTypeStrReg, ConstIntBitwidthReg,
246+
AttributeEncodingReg, DebugInfoNoneReg});
247+
}
175248
}
176249
return true;
177250
}

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
432432
MachineOperand Ins = MI.getOperand(3);
433433
namespace NS = SPIRV::NonSemanticExtInst;
434434
static constexpr int64_t GlobalNonSemanticDITy[] = {
435-
NS::DebugSource, NS::DebugCompilationUnit};
435+
NS::DebugSource, NS::DebugCompilationUnit, NS::DebugInfoNone,
436+
NS::DebugTypeBasic};
436437
bool IsGlobalDI = false;
437438
for (unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy); ++Idx)
438439
IsGlobalDI |= Ins.getImm() == GlobalNonSemanticDITy[Idx];

0 commit comments

Comments
 (0)