LLVM 22.0.0git
SPIRVEmitNonSemanticDI.cpp
Go to the documentation of this file.
3#include "SPIRV.h"
5#include "SPIRVRegisterInfo.h"
7#include "SPIRVUtils.h"
23#include "llvm/IR/Metadata.h"
25#include "llvm/Support/Path.h"
26
27#define DEBUG_TYPE "spirv-nonsemantic-debug-info"
28
29using namespace llvm;
30
31namespace {
32struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
33 static char ID;
35 SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM = nullptr)
36 : MachineFunctionPass(ID), TM(TM) {}
37
38 bool runOnMachineFunction(MachineFunction &MF) override;
39
40private:
41 bool IsGlobalDIEmitted = false;
42 bool emitGlobalDI(MachineFunction &MF);
43};
44} // anonymous namespace
45
46INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE,
47 "SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false)
48
49char SPIRVEmitNonSemanticDI::ID = 0;
50
53 return new SPIRVEmitNonSemanticDI(TM);
54}
55
60 Float = 3,
61 Signed = 4,
64 UnsignedChar = 7
65};
66
69 ESSL = 1,
70 GLSL = 2,
73 HLSL = 5,
75 SYCL = 7,
76 HERO_C = 8,
77 NZSL = 9,
78 WGSL = 10,
79 Slang = 11,
80 Zig = 12
81};
82
83bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
84 // If this MachineFunction doesn't have any BB repeat procedure
85 // for the next
86 if (MF.begin() == MF.end()) {
87 IsGlobalDIEmitted = false;
88 return false;
89 }
90
91 // Required variables to get from metadata search
94 SmallVector<int64_t> LLVMSourceLanguages;
95 int64_t DwarfVersion = 0;
96 int64_t DebugInfoVersion = 0;
98 SmallPtrSet<DIDerivedType *, 12> PointerDerivedTypes;
99 // Searching through the Module metadata to find nescessary
100 // information like DwarfVersion or SourceLanguage
101 {
102 const MachineModuleInfo &MMI =
103 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
104 const Module *M = MMI.getModule();
105 Context = &M->getContext();
106 const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
107 if (!DbgCu)
108 return false;
109 for (const auto *Op : DbgCu->operands()) {
110 if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
111 DIFile *File = CompileUnit->getFile();
112 FilePaths.emplace_back();
113 sys::path::append(FilePaths.back(), File->getDirectory(),
114 File->getFilename());
115 LLVMSourceLanguages.push_back(CompileUnit->getSourceLanguage());
116 }
117 }
118 const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
119 assert(ModuleFlags && "Expected llvm.module.flags metadata to be present");
120 for (const auto *Op : ModuleFlags->operands()) {
121 const MDOperand &MaybeStrOp = Op->getOperand(1);
122 if (MaybeStrOp.equalsStr("Dwarf Version"))
123 DwarfVersion =
124 cast<ConstantInt>(
125 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
126 ->getSExtValue();
127 else if (MaybeStrOp.equalsStr("Debug Info Version"))
128 DebugInfoVersion =
129 cast<ConstantInt>(
130 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
131 ->getSExtValue();
132 }
133
134 // This traversal is the only supported way to access
135 // instruction related DI metadata like DIBasicType
136 for (auto &F : *M) {
137 for (auto &BB : F) {
138 for (auto &I : BB) {
139 for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
140 DILocalVariable *LocalVariable = DVR.getVariable();
141 if (auto *BasicType =
142 dyn_cast<DIBasicType>(LocalVariable->getType())) {
143 BasicTypes.insert(BasicType);
144 } else if (auto *DerivedType =
145 dyn_cast<DIDerivedType>(LocalVariable->getType())) {
146 if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
147 PointerDerivedTypes.insert(DerivedType);
148 // DIBasicType can be unreachable from DbgRecord and only
149 // pointed on from other DI types
150 // DerivedType->getBaseType is null when pointer
151 // is representing a void type
152 if (auto *BT = dyn_cast_or_null<DIBasicType>(
153 DerivedType->getBaseType()))
154 BasicTypes.insert(BT);
155 }
156 }
157 }
158 }
159 }
160 }
161 }
162 // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
163 {
164 // Required LLVM variables for emitting logic
165 const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
166 const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
167 const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
168 SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
170 MachineBasicBlock &MBB = *MF.begin();
171
172 // To correct placement of a OpLabel instruction during SPIRVAsmPrinter
173 // emission all new instructions needs to be placed after OpFunction
174 // and before first terminator
176
177 const auto EmitOpString = [&](StringRef SR) {
178 const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
179 MRI.setType(StrReg, LLT::scalar(32));
180 MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
181 MIB.addDef(StrReg);
182 addStringImm(SR, MIB);
183 return StrReg;
184 };
185
186 const SPIRVType *VoidTy =
187 GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder,
188 SPIRV::AccessQualifier::ReadWrite, false);
189
190 const auto EmitDIInstruction =
191 [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
192 std::initializer_list<Register> Registers) {
193 const Register InstReg =
194 MRI.createVirtualRegister(&SPIRV::IDRegClass);
195 MRI.setType(InstReg, LLT::scalar(32));
197 MIRBuilder.buildInstr(SPIRV::OpExtInst)
198 .addDef(InstReg)
199 .addUse(GR->getSPIRVTypeID(VoidTy))
200 .addImm(static_cast<int64_t>(
201 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
202 .addImm(Inst);
203 for (auto Reg : Registers) {
204 MIB.addUse(Reg);
205 }
206 MIB.constrainAllUses(*TII, *TRI, *RBI);
207 GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
208 return InstReg;
209 };
210
211 const SPIRVType *I32Ty =
212 GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder,
213 SPIRV::AccessQualifier::ReadWrite, false);
214
215 const Register DwarfVersionReg =
216 GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
217
218 const Register DebugInfoVersionReg =
219 GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
220
221 for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {
222 const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);
223
224 const Register DebugSourceResIdReg = EmitDIInstruction(
225 SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
226
227 SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
228 switch (LLVMSourceLanguages[Idx]) {
229 case dwarf::DW_LANG_OpenCL:
230 SpirvSourceLanguage = SourceLanguage::OpenCL_C;
231 break;
232 case dwarf::DW_LANG_OpenCL_CPP:
233 SpirvSourceLanguage = SourceLanguage::OpenCL_CPP;
234 break;
235 case dwarf::DW_LANG_CPP_for_OpenCL:
236 SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL;
237 break;
238 case dwarf::DW_LANG_GLSL:
239 SpirvSourceLanguage = SourceLanguage::GLSL;
240 break;
241 case dwarf::DW_LANG_HLSL:
242 SpirvSourceLanguage = SourceLanguage::HLSL;
243 break;
244 case dwarf::DW_LANG_SYCL:
245 SpirvSourceLanguage = SourceLanguage::SYCL;
246 break;
247 case dwarf::DW_LANG_Zig:
248 SpirvSourceLanguage = SourceLanguage::Zig;
249 }
250
251 const Register SourceLanguageReg =
252 GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false);
253
254 [[maybe_unused]]
255 const Register DebugCompUnitResIdReg =
256 EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
257 {DebugInfoVersionReg, DwarfVersionReg,
258 DebugSourceResIdReg, SourceLanguageReg});
259 }
260
261 // We aren't extracting any DebugInfoFlags now so we
262 // emitting zero to use as <id>Flags argument for DebugBasicType
263 const Register I32ZeroReg =
264 GR->buildConstantInt(0, MIRBuilder, I32Ty, false, false);
265
266 // We need to store pairs because further instructions reference
267 // the DIBasicTypes and size will be always small so there isn't
268 // need for any kind of map
270 BasicTypeRegPairs;
271 for (auto *BasicType : BasicTypes) {
272 const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
273
274 const Register ConstIntBitwidthReg = GR->buildConstantInt(
275 BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
276
278 switch (BasicType->getEncoding()) {
279 case dwarf::DW_ATE_signed:
280 AttributeEncoding = BaseTypeAttributeEncoding::Signed;
281 break;
282 case dwarf::DW_ATE_unsigned:
283 AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
284 break;
285 case dwarf::DW_ATE_unsigned_char:
286 AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
287 break;
288 case dwarf::DW_ATE_signed_char:
289 AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
290 break;
291 case dwarf::DW_ATE_float:
292 AttributeEncoding = BaseTypeAttributeEncoding::Float;
293 break;
294 case dwarf::DW_ATE_boolean:
295 AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
296 break;
297 case dwarf::DW_ATE_address:
298 AttributeEncoding = BaseTypeAttributeEncoding::Address;
299 }
300
301 const Register AttributeEncodingReg =
302 GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
303
304 const Register BasicTypeReg =
305 EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
306 {BasicTypeStrReg, ConstIntBitwidthReg,
307 AttributeEncodingReg, I32ZeroReg});
308 BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);
309 }
310
311 if (PointerDerivedTypes.size()) {
312 for (const auto *PointerDerivedType : PointerDerivedTypes) {
313
314 assert(PointerDerivedType->getDWARFAddressSpace().has_value());
315 const Register StorageClassReg = GR->buildConstantInt(
317 PointerDerivedType->getDWARFAddressSpace().value(),
318 *TM->getSubtargetImpl()),
319 MIRBuilder, I32Ty, false);
320
321 // If the Pointer is representing a void type it's getBaseType
322 // is a nullptr
323 const auto *MaybeNestedBasicType =
324 dyn_cast_or_null<DIBasicType>(PointerDerivedType->getBaseType());
325 if (MaybeNestedBasicType) {
326 for (const auto &BasicTypeRegPair : BasicTypeRegPairs) {
327 const auto &[DefinedBasicType, BasicTypeReg] = BasicTypeRegPair;
328 if (DefinedBasicType == MaybeNestedBasicType) {
329 [[maybe_unused]]
330 const Register DebugPointerTypeReg = EmitDIInstruction(
331 SPIRV::NonSemanticExtInst::DebugTypePointer,
332 {BasicTypeReg, StorageClassReg, I32ZeroReg});
333 }
334 }
335 } else {
336 const Register DebugInfoNoneReg =
337 EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});
338 [[maybe_unused]]
339 const Register DebugPointerTypeReg = EmitDIInstruction(
340 SPIRV::NonSemanticExtInst::DebugTypePointer,
341 {DebugInfoNoneReg, StorageClassReg, I32ZeroReg});
342 }
343 }
344 }
345 }
346 return true;
347}
348
349bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
350 bool Res = false;
351 // emitGlobalDI needs to be executed only once to avoid
352 // emitting duplicates
353 if (!IsGlobalDIEmitted) {
354 IsGlobalDIEmitted = true;
355 Res = emitGlobalDI(MF);
356 }
357 return Res;
358}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file contains constants used for implementing Dwarf debug support.
const HexagonInstrInfo * TII
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
This file contains the declarations for metadata subclasses.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
SI Pre allocate WWM Registers
BaseTypeAttributeEncoding
#define DEBUG_TYPE
This file defines the SmallPtrSet class.
This file defines the SmallString class.
DIType * getType() const
This class represents an Operation in the Expression.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:43
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
Tracking metadata reference owned by Metadata.
Definition: Metadata.h:899
bool equalsStr(StringRef Str) const
Definition: Metadata.h:921
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:72
This class contains meta information specific to a module.
const Module * getModule() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
A tuple of MDNodes.
Definition: Metadata.h:1753
iterator_range< op_iterator > operands()
Definition: Metadata.h:1849
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR, bool ZeroAsNull=true)
size_type size() const
Definition: SmallPtrSet.h:99
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:401
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:541
size_t size() const
Definition: SmallVector.h:79
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Stores all information relating to a compile unit, be it in its original instance in the object file ...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineFunctionPass * createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM)
unsigned char Boolean
Definition: ConvertUTF.h:132
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:245
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:54
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.