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"
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+
6076bool 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}
0 commit comments