Skip to content

Commit f99bb02

Browse files
authored
[SPIR-V] Emit DebugTypeBasic for NonSemantic DI (#106980)
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 48498ec commit f99bb02

File tree

4 files changed

+350
-35
lines changed

4 files changed

+350
-35
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp

Lines changed: 114 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/SmallPtrSet.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"
@@ -57,6 +62,17 @@ SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
5762
initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
5863
}
5964

65+
enum BaseTypeAttributeEncoding {
66+
Unspecified = 0,
67+
Address = 1,
68+
Boolean = 2,
69+
Float = 3,
70+
Signed = 4,
71+
SignedChar = 5,
72+
Unsigned = 6,
73+
UnsignedChar = 7
74+
};
75+
6076
bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
6177
// If this MachineFunction doesn't have any BB repeat procedure
6278
// for the next
@@ -71,7 +87,7 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
7187
unsigned SourceLanguage = 0;
7288
int64_t DwarfVersion = 0;
7389
int64_t DebugInfoVersion = 0;
74-
90+
SmallPtrSet<DIBasicType *, 12> BasicTypes;
7591
// Searching through the Module metadata to find nescessary
7692
// information like DwarfVersion or SourceLanguage
7793
{
@@ -104,6 +120,21 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
104120
cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
105121
->getSExtValue();
106122
}
123+
124+
// This traversal is the only supported way to access
125+
// instruction related DI metadata like DIBasicType
126+
for (auto &F : *M) {
127+
for (auto &BB : F) {
128+
for (auto &I : BB) {
129+
for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
130+
DILocalVariable *LocalVariable = DVR.getVariable();
131+
if (auto *BasicType =
132+
dyn_cast<DIBasicType>(LocalVariable->getType()))
133+
BasicTypes.insert(BasicType);
134+
}
135+
}
136+
}
137+
}
107138
}
108139
// NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
109140
{
@@ -120,29 +151,45 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
120151
// and before first terminator
121152
MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
122153

154+
const auto EmitOpString = [&](StringRef SR) {
155+
const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
156+
MRI.setType(StrReg, LLT::scalar(32));
157+
MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
158+
MIB.addDef(StrReg);
159+
addStringImm(SR, MIB);
160+
return StrReg;
161+
};
162+
123163
// 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);
164+
const Register FilePathStrReg = EmitOpString(FilePath);
129165

130166
const SPIRVType *VoidTy =
131167
GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder);
132168

169+
const auto EmitDIInstruction =
170+
[&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
171+
std::initializer_list<Register> Registers) {
172+
const Register InstReg =
173+
MRI.createVirtualRegister(&SPIRV::IDRegClass);
174+
MRI.setType(InstReg, LLT::scalar(32));
175+
MachineInstrBuilder MIB =
176+
MIRBuilder.buildInstr(SPIRV::OpExtInst)
177+
.addDef(InstReg)
178+
.addUse(GR->getSPIRVTypeID(VoidTy))
179+
.addImm(static_cast<int64_t>(
180+
SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
181+
.addImm(Inst);
182+
for (auto Reg : Registers) {
183+
MIB.addUse(Reg);
184+
}
185+
MIB.constrainAllUses(*TII, *TRI, *RBI);
186+
GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
187+
return InstReg;
188+
};
189+
133190
// 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);
191+
const Register DebugSourceResIdReg = EmitDIInstruction(
192+
SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
146193

147194
const SPIRVType *I32Ty =
148195
GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
@@ -156,22 +203,56 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
156203
const Register SourceLanguageReg =
157204
GR->buildConstantInt(SourceLanguage, MIRBuilder, I32Ty, false);
158205

159-
// Emit DebugCompilationUnit
206+
[[maybe_unused]]
160207
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);
208+
EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
209+
{DebugInfoVersionReg, DwarfVersionReg,
210+
DebugSourceResIdReg, SourceLanguageReg});
211+
212+
// We aren't extracting any DebugInfoFlags now so we
213+
// emitting zero to use as <id>Flags argument for DebugBasicType
214+
const Register I32ZeroReg =
215+
GR->buildConstantInt(0, MIRBuilder, I32Ty, false);
216+
217+
for (auto *BasicType : BasicTypes) {
218+
const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
219+
220+
const Register ConstIntBitwidthReg = GR->buildConstantInt(
221+
BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
222+
223+
uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
224+
switch (BasicType->getEncoding()) {
225+
case dwarf::DW_ATE_signed:
226+
AttributeEncoding = BaseTypeAttributeEncoding::Signed;
227+
break;
228+
case dwarf::DW_ATE_unsigned:
229+
AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
230+
break;
231+
case dwarf::DW_ATE_unsigned_char:
232+
AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
233+
break;
234+
case dwarf::DW_ATE_signed_char:
235+
AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
236+
break;
237+
case dwarf::DW_ATE_float:
238+
AttributeEncoding = BaseTypeAttributeEncoding::Float;
239+
break;
240+
case dwarf::DW_ATE_boolean:
241+
AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
242+
break;
243+
case dwarf::DW_ATE_address:
244+
AttributeEncoding = BaseTypeAttributeEncoding::Address;
245+
}
246+
247+
const Register AttributeEncodingReg =
248+
GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
249+
250+
[[maybe_unused]]
251+
const Register BasicTypeReg =
252+
EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
253+
{BasicTypeStrReg, ConstIntBitwidthReg,
254+
AttributeEncodingReg, I32ZeroReg});
255+
}
175256
}
176257
return true;
177258
}

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

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

llvm/test/CodeGen/SPIRV/debug-info/basic-global-di.ll renamed to llvm/test/CodeGen/SPIRV/debug-info/debug-compilation-unit.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info --print-after=spirv-nonsemantic-debug-info -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-MIR
22
; RUN: llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
33
; RUN: llc --verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_non_semantic_info %s -o - | FileCheck %s --check-prefix=CHECK-OPTION
4-
; RUN: %if spirv-tools %{ llc --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
4+
; RUN: %if spirv-tools %{ llc --verify-machineinstrs --spv-emit-nonsemantic-debug-info --spirv-ext=+SPV_KHR_non_semantic_info -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
55

66
; CHECK-MIR-DAG: [[type_void:%[0-9]+\:type]] = OpTypeVoid
77
; CHECK-MIR-DAG: [[type_i64:%[0-9]+\:type\(s64\)]] = OpTypeInt 32, 0

0 commit comments

Comments
 (0)