Skip to content

Commit 12854b3

Browse files
committed
[SPIRV] Emitting DebugSource, DebugCompileUnit
This commit introduces emission of DebugSource, DebugCompileUnit from NonSemantic.Shader.DebugInfo.100 and required OpString with filename. NonSemantic.Shader.DebugInfo.100 is divided, following DWARF into two main concepts – emitting DIE and Line . In DWARF .debug_abbriev and .debug_line sections are responsible for emitting tree with information (DEIs) about e.g. types, compilation unit. Corresponding to that in NonSemantic.Shader.DebugInfo.100 have instructions like DebugSource, DebugCompileUnit etc. which preforms same role in SPIR-V file. The difference is in fact that in SPIR-V there are no sections but logical layout which forces order of the instruction emission. The NonSemantic.Shader.DebugInfo.100 requires for this type of global information to be emitted after OpTypeXXX and OpConstantXXX instructions. One of the goals was to minimize changes and interaction with SPIRVModuleAnalysis as possible which current commit achieves by emitting it’s instructions directly into MachineFunction. The possibility of duplicates are mitigated by guard inside pass which emits the global information only once in one function. By that method duplicates don’t have chance to be emitted. From that point, adding new debug global instructions should be straightforward.
1 parent cd6da10 commit 12854b3

File tree

6 files changed

+132
-20
lines changed

6 files changed

+132
-20
lines changed

llvm/lib/Target/SPIRV/SPIRV.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ FunctionPass *createSPIRVRegularizerPass();
2626
FunctionPass *createSPIRVPreLegalizerPass();
2727
FunctionPass *createSPIRVPostLegalizerPass();
2828
ModulePass *createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM);
29-
MachineFunctionPass *createSPIRVEmitNonSemanticDIPass();
29+
MachineFunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM);
3030
InstructionSelector *
3131
createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
3232
const SPIRVSubtarget &Subtarget,

llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ void SPIRVAsmPrinter::outputDebugSourceAndStrings(const Module &M) {
273273
addStringImm(Str.first(), Inst);
274274
outputMCInst(Inst);
275275
}
276+
// Output OpString.
277+
outputModuleSection(SPIRV::MB_DebugStrings);
276278
// Output OpSource.
277279
MCInst Inst;
278280
Inst.setOpcode(SPIRV::OpSource);
@@ -588,9 +590,11 @@ void SPIRVAsmPrinter::outputModuleSections() {
588590
// the first section to allow use of: OpLine and OpNoLine debug information;
589591
// non-semantic instructions with OpExtInst.
590592
outputModuleSection(SPIRV::MB_TypeConstVars);
591-
// 10. All function declarations (functions without a body).
593+
// 10. All global NonSemantic.Shader.DebugInfo.100 instructions.
594+
outputModuleSection(SPIRV::MB_NonSemanticGlobalDI);
595+
// 11. All function declarations (functions without a body).
592596
outputExtFuncDecls();
593-
// 11. All function definitions (functions with a body).
597+
// 12. All function definitions (functions with a body).
594598
// This is done in regular function output.
595599
}
596600

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1+
#include "MCTargetDesc/SPIRVBaseInfo.h"
2+
#include "SPIRVGlobalRegistry.h"
3+
#include "SPIRVRegisterInfo.h"
4+
#include "SPIRVTargetMachine.h"
5+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
16
#include "llvm/CodeGen/MachineFunction.h"
27
#include "llvm/CodeGen/MachineFunctionPass.h"
8+
#include "llvm/CodeGen/MachineInstr.h"
9+
#include "llvm/CodeGen/MachineInstrBuilder.h"
310
#include "llvm/CodeGen/MachineModuleInfo.h"
11+
#include "llvm/CodeGen/MachineOperand.h"
412
#include "llvm/IR/DebugInfoMetadata.h"
513
#include "llvm/IR/Metadata.h"
614
#include "llvm/PassRegistry.h"
@@ -9,15 +17,21 @@
917
namespace llvm {
1018
struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
1119
static char ID;
20+
SPIRVTargetMachine *TM;
21+
SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM);
1222
SPIRVEmitNonSemanticDI();
1323

1424
bool runOnMachineFunction(MachineFunction &MF) override;
25+
26+
private:
27+
bool IsGlobalDIEmitted = false;
28+
bool emitGlobalDI(MachineFunction &MF);
1529
};
1630

1731
void initializeSPIRVEmitNonSemanticDIPass(PassRegistry &);
1832

19-
FunctionPass *createSPIRVEmitNonSemanticDIPass() {
20-
return new SPIRVEmitNonSemanticDI();
33+
FunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) {
34+
return new SPIRVEmitNonSemanticDI(TM);
2135
}
2236
} // namespace llvm
2337

@@ -28,28 +42,107 @@ INITIALIZE_PASS(SPIRVEmitNonSemanticDI, "spirv-nonsemantic-debug-info",
2842

2943
char SPIRVEmitNonSemanticDI::ID = 0;
3044

45+
SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM)
46+
: MachineFunctionPass(ID), TM(TM) {
47+
initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
48+
}
49+
3150
SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
3251
initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
3352
}
3453

35-
[[maybe_unused]]
36-
static void findCompileUnitDI(const MachineFunction &MF) {
54+
bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
3755
MachineModuleInfo &MMI = MF.getMMI();
3856
const Module *M = MMI.getModule();
3957
NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
58+
if (!DbgCu) {
59+
return false;
60+
}
4061
std::string FilePath;
41-
if (DbgCu) {
42-
unsigned NumOp = DbgCu->getNumOperands();
43-
if (NumOp) {
44-
if (const auto *CompileUnit =
45-
dyn_cast<DICompileUnit>(DbgCu->getOperand(0))) {
46-
DIFile *File = CompileUnit->getFile();
47-
FilePath = ((File->getDirectory() + "/" + File->getFilename())).str();
48-
}
62+
unsigned SourceLanguage;
63+
unsigned NumOp = DbgCu->getNumOperands();
64+
if (NumOp) {
65+
if (const auto *CompileUnit =
66+
dyn_cast<DICompileUnit>(DbgCu->getOperand(0))) {
67+
DIFile *File = CompileUnit->getFile();
68+
FilePath = ((File->getDirectory() + "/" + File->getFilename())).str();
69+
SourceLanguage = CompileUnit->getSourceLanguage();
70+
}
71+
}
72+
NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
73+
int64_t DwarfVersion = 0;
74+
int64_t DebugInfoVersion = 0;
75+
for (auto *Op : ModuleFlags->operands()) {
76+
const MDOperand &StrOp = Op->getOperand(1);
77+
if (StrOp.equalsStr("Dwarf Version")) {
78+
DwarfVersion =
79+
cast<ConstantInt>(
80+
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
81+
->getSExtValue();
82+
} else if (StrOp.equalsStr("Debug Info Version")) {
83+
DebugInfoVersion =
84+
cast<ConstantInt>(
85+
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
86+
->getSExtValue();
4987
}
5088
}
89+
const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
90+
const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
91+
const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
92+
SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
93+
MachineRegisterInfo &MRI = MF.getRegInfo();
94+
for (MachineBasicBlock &MBB : MF) {
95+
MachineIRBuilder MIRBuilder(MBB, MBB.begin());
96+
97+
MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
98+
Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
99+
MachineOperand StrRegOp = MachineOperand::CreateReg(StrReg, true);
100+
MIB.add(StrRegOp);
101+
addStringImm(FilePath, MIB);
102+
103+
const MachineInstr *VoidTyMI =
104+
GR->getOrCreateSPIRVType(Type::getVoidTy(M->getContext()), MIRBuilder);
105+
106+
MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst);
107+
Register DebugSourceResIdReg =
108+
MRI.createVirtualRegister(&SPIRV::IDRegClass);
109+
MIB.addDef(DebugSourceResIdReg); // Result ID
110+
MIB.addUse(VoidTyMI->getOperand(0).getReg()); // Result Type
111+
MIB.addImm(static_cast<int64_t>(
112+
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)); // Set ID
113+
MIB.addImm(SPIRV::NonSemanticExtInst::DebugSource); //
114+
MIB.addUse(StrReg);
115+
MIB.constrainAllUses(*TII, *TRI, *RBI);
116+
117+
Register DwarfVersionReg = GR->buildConstantInt(DwarfVersion, MIRBuilder);
118+
Register DebugInfoVersionReg =
119+
GR->buildConstantInt(DebugInfoVersion, MIRBuilder);
120+
Register SourceLanguageReg =
121+
GR->buildConstantInt(SourceLanguage, MIRBuilder);
122+
123+
MIB = MIRBuilder.buildInstr(SPIRV::OpExtInst);
124+
Register DebugCompUnitResIdReg =
125+
MRI.createVirtualRegister(&SPIRV::IDRegClass);
126+
MIB.addDef(DebugCompUnitResIdReg); // Result ID
127+
MIB.addUse(VoidTyMI->getOperand(0).getReg()); // Result Type
128+
MIB.addImm(static_cast<int64_t>(
129+
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)); // Set ID
130+
MIB.addImm(SPIRV::NonSemanticExtInst::DebugCompilationUnit);
131+
MIB.addUse(DebugInfoVersionReg);
132+
MIB.addUse(DwarfVersionReg);
133+
MIB.addUse(DebugSourceResIdReg);
134+
MIB.addUse(SourceLanguageReg);
135+
MIB.constrainAllUses(*TII, *TRI, *RBI);
136+
}
137+
138+
return true;
51139
}
52140

53141
bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
54-
return false;
142+
bool Res = false;
143+
if (!IsGlobalDIEmitted) {
144+
Res = emitGlobalDI(MF);
145+
IsGlobalDIEmitted = true;
146+
}
147+
return Res;
55148
}

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "SPIRVSubtarget.h"
2222
#include "SPIRVTargetMachine.h"
2323
#include "SPIRVUtils.h"
24-
#include "TargetInfo/SPIRVTargetInfo.h"
2524
#include "llvm/ADT/STLExtras.h"
2625
#include "llvm/CodeGen/MachineModuleInfo.h"
2726
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -427,7 +426,22 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
427426
if (MAI.getSkipEmission(&MI))
428427
continue;
429428
const unsigned OpCode = MI.getOpcode();
430-
if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
429+
if (OpCode == SPIRV::OpString) {
430+
collectOtherInstr(MI, MAI, SPIRV::MB_DebugStrings, IS);
431+
} else if (OpCode == SPIRV::OpExtInst) {
432+
MachineOperand Ins = MI.getOperand(3);
433+
namespace NS = SPIRV::NonSemanticExtInst;
434+
static constexpr int64_t GlobalNonSemanticDITy[] = {
435+
NS::DebugSource, NS::DebugCompilationUnit};
436+
bool IsGlobalDI = false;
437+
for (unsigned Idx = 0; Idx < std::size(GlobalNonSemanticDITy);
438+
++Idx) {
439+
IsGlobalDI |= Ins.getImm() == GlobalNonSemanticDITy[Idx];
440+
}
441+
if (IsGlobalDI) {
442+
collectOtherInstr(MI, MAI, SPIRV::MB_NonSemanticGlobalDI, IS);
443+
}
444+
} else if (OpCode == SPIRV::OpName || OpCode == SPIRV::OpMemberName) {
431445
collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames, IS);
432446
} else if (OpCode == SPIRV::OpEntryPoint) {
433447
collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints, IS);

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "llvm/ADT/DenseMap.h"
2121
#include "llvm/ADT/SmallSet.h"
2222
#include "llvm/ADT/SmallVector.h"
23-
#include "llvm/ADT/StringMap.h"
2423

2524
namespace llvm {
2625
class SPIRVSubtarget;
@@ -34,9 +33,11 @@ enum ModuleSectionType {
3433
MB_EntryPoints, // All OpEntryPoint instructions (if any).
3534
// MB_ExecutionModes, MB_DebugSourceAndStrings,
3635
MB_DebugNames, // All OpName and OpMemberName intrs.
36+
MB_DebugStrings, // All OpString intrs.
3737
MB_DebugModuleProcessed, // All OpModuleProcessed instructions.
3838
MB_Annotations, // OpDecorate, OpMemberDecorate etc.
3939
MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables.
40+
MB_NonSemanticGlobalDI, // OpExtInst with e.g. DebugSource, DebugTypeBasic.
4041
MB_ExtFuncDecls, // OpFunction etc. to declare for external funcs.
4142
NUM_MODULE_SECTIONS // Total number of sections requiring basic blocks.
4243
};

llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ void SPIRVPassConfig::addPreLegalizeMachineIR() {
199199
bool SPIRVPassConfig::addLegalizeMachineIR() {
200200
addPass(new Legalizer());
201201
addPass(createSPIRVPostLegalizerPass());
202-
addPass(createSPIRVEmitNonSemanticDIPass());
202+
addPass(createSPIRVEmitNonSemanticDIPass(&getTM<SPIRVTargetMachine>()));
203203
return false;
204204
}
205205

0 commit comments

Comments
 (0)