1 #include "MCTargetDesc/SPIRVBaseInfo.h" 2 #include "MCTargetDesc/SPIRVMCTargetDesc.h" 3 #include "SPIRV.h" 4 #include "SPIRVGlobalRegistry.h" 5 #include "SPIRVRegisterInfo.h" 6 #include "SPIRVTargetMachine.h" 7 #include "SPIRVUtils.h" 8 #include "llvm/ADT/SmallPtrSet.h" 9 #include "llvm/ADT/SmallString.h" 10 #include "llvm/BinaryFormat/Dwarf.h" 11 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 12 #include "llvm/CodeGen/MachineBasicBlock.h" 13 #include "llvm/CodeGen/MachineFunction.h" 14 #include "llvm/CodeGen/MachineFunctionPass.h" 15 #include "llvm/CodeGen/MachineInstr.h" 16 #include "llvm/CodeGen/MachineInstrBuilder.h" 17 #include "llvm/CodeGen/MachineModuleInfo.h" 18 #include "llvm/CodeGen/MachineOperand.h" 19 #include "llvm/CodeGen/MachineRegisterInfo.h" 20 #include "llvm/CodeGen/Register.h" 21 #include "llvm/IR/DebugInfoMetadata.h" 22 #include "llvm/IR/DebugProgramInstruction.h" 23 #include "llvm/IR/Metadata.h" 24 #include "llvm/PassRegistry.h" 25 #include "llvm/Support/Casting.h" 26 #include "llvm/Support/Path.h" 27 28 #define DEBUG_TYPE "spirv-nonsemantic-debug-info" 29 30 namespace llvm { 31 struct SPIRVEmitNonSemanticDI : public MachineFunctionPass { 32 static char ID; 33 SPIRVTargetMachine *TM; 34 SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM); 35 SPIRVEmitNonSemanticDI(); 36 37 bool runOnMachineFunction(MachineFunction &MF) override; 38 39 private: 40 bool IsGlobalDIEmitted = false; 41 bool emitGlobalDI(MachineFunction &MF); 42 }; 43 } // namespace llvm 44 45 using namespace llvm; 46 47 INITIALIZE_PASS(SPIRVEmitNonSemanticDI, DEBUG_TYPE, 48 "SPIRV NonSemantic.Shader.DebugInfo.100 emitter", false, false) 49 50 char SPIRVEmitNonSemanticDI::ID = 0; 51 52 MachineFunctionPass * 53 llvm::createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM) { 54 return new SPIRVEmitNonSemanticDI(TM); 55 } 56 57 SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM) 58 : MachineFunctionPass(ID), TM(TM) { 59 initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry()); 60 } 61 62 SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) { 63 initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry()); 64 } 65 66 enum BaseTypeAttributeEncoding { 67 Unspecified = 0, 68 Address = 1, 69 Boolean = 2, 70 Float = 3, 71 Signed = 4, 72 SignedChar = 5, 73 Unsigned = 6, 74 UnsignedChar = 7 75 }; 76 77 enum SourceLanguage { 78 Unknown = 0, 79 ESSL = 1, 80 GLSL = 2, 81 OpenCL_C = 3, 82 OpenCL_CPP = 4, 83 HLSL = 5, 84 CPP_for_OpenCL = 6, 85 SYCL = 7, 86 HERO_C = 8, 87 NZSL = 9, 88 WGSL = 10, 89 Slang = 11, 90 Zig = 12 91 }; 92 93 bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) { 94 // If this MachineFunction doesn't have any BB repeat procedure 95 // for the next 96 if (MF.begin() == MF.end()) { 97 IsGlobalDIEmitted = false; 98 return false; 99 } 100 101 // Required variables to get from metadata search 102 LLVMContext *Context; 103 SmallVector<SmallString<128>> FilePaths; 104 SmallVector<int64_t> LLVMSourceLanguages; 105 int64_t DwarfVersion = 0; 106 int64_t DebugInfoVersion = 0; 107 SmallPtrSet<DIBasicType *, 12> BasicTypes; 108 SmallPtrSet<DIDerivedType *, 12> PointerDerivedTypes; 109 // Searching through the Module metadata to find nescessary 110 // information like DwarfVersion or SourceLanguage 111 { 112 const MachineModuleInfo &MMI = 113 getAnalysis<MachineModuleInfoWrapperPass>().getMMI(); 114 const Module *M = MMI.getModule(); 115 Context = &M->getContext(); 116 const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu"); 117 if (!DbgCu) 118 return false; 119 for (const auto *Op : DbgCu->operands()) { 120 if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) { 121 DIFile *File = CompileUnit->getFile(); 122 FilePaths.emplace_back(); 123 sys::path::append(FilePaths.back(), File->getDirectory(), 124 File->getFilename()); 125 LLVMSourceLanguages.push_back(CompileUnit->getSourceLanguage()); 126 } 127 } 128 const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags"); 129 for (const auto *Op : ModuleFlags->operands()) { 130 const MDOperand &MaybeStrOp = Op->getOperand(1); 131 if (MaybeStrOp.equalsStr("Dwarf Version")) 132 DwarfVersion = 133 cast<ConstantInt>( 134 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue()) 135 ->getSExtValue(); 136 else if (MaybeStrOp.equalsStr("Debug Info Version")) 137 DebugInfoVersion = 138 cast<ConstantInt>( 139 cast<ConstantAsMetadata>(Op->getOperand(2))->getValue()) 140 ->getSExtValue(); 141 } 142 143 // This traversal is the only supported way to access 144 // instruction related DI metadata like DIBasicType 145 for (auto &F : *M) { 146 for (auto &BB : F) { 147 for (auto &I : BB) { 148 for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { 149 DILocalVariable *LocalVariable = DVR.getVariable(); 150 if (auto *BasicType = 151 dyn_cast<DIBasicType>(LocalVariable->getType())) { 152 BasicTypes.insert(BasicType); 153 } else if (auto *DerivedType = 154 dyn_cast<DIDerivedType>(LocalVariable->getType())) { 155 if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) { 156 PointerDerivedTypes.insert(DerivedType); 157 // DIBasicType can be unreachable from DbgRecord and only 158 // pointed on from other DI types 159 // DerivedType->getBaseType is null when pointer 160 // is representing a void type 161 if (DerivedType->getBaseType()) 162 BasicTypes.insert( 163 cast<DIBasicType>(DerivedType->getBaseType())); 164 } 165 } 166 } 167 } 168 } 169 } 170 } 171 // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting 172 { 173 // Required LLVM variables for emitting logic 174 const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo(); 175 const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo(); 176 const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo(); 177 SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry(); 178 MachineRegisterInfo &MRI = MF.getRegInfo(); 179 MachineBasicBlock &MBB = *MF.begin(); 180 181 // To correct placement of a OpLabel instruction during SPIRVAsmPrinter 182 // emission all new instructions needs to be placed after OpFunction 183 // and before first terminator 184 MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator()); 185 186 const auto EmitOpString = [&](StringRef SR) { 187 const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass); 188 MRI.setType(StrReg, LLT::scalar(32)); 189 MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString); 190 MIB.addDef(StrReg); 191 addStringImm(SR, MIB); 192 return StrReg; 193 }; 194 195 const SPIRVType *VoidTy = 196 GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder); 197 198 const auto EmitDIInstruction = 199 [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst, 200 std::initializer_list<Register> Registers) { 201 const Register InstReg = 202 MRI.createVirtualRegister(&SPIRV::IDRegClass); 203 MRI.setType(InstReg, LLT::scalar(32)); 204 MachineInstrBuilder MIB = 205 MIRBuilder.buildInstr(SPIRV::OpExtInst) 206 .addDef(InstReg) 207 .addUse(GR->getSPIRVTypeID(VoidTy)) 208 .addImm(static_cast<int64_t>( 209 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)) 210 .addImm(Inst); 211 for (auto Reg : Registers) { 212 MIB.addUse(Reg); 213 } 214 MIB.constrainAllUses(*TII, *TRI, *RBI); 215 GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF); 216 return InstReg; 217 }; 218 219 const SPIRVType *I32Ty = 220 GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder); 221 222 const Register DwarfVersionReg = 223 GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false); 224 225 const Register DebugInfoVersionReg = 226 GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false); 227 228 for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) { 229 const Register FilePathStrReg = EmitOpString(FilePaths[Idx]); 230 231 const Register DebugSourceResIdReg = EmitDIInstruction( 232 SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg}); 233 234 SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown; 235 switch (LLVMSourceLanguages[Idx]) { 236 case dwarf::DW_LANG_OpenCL: 237 SpirvSourceLanguage = SourceLanguage::OpenCL_C; 238 break; 239 case dwarf::DW_LANG_OpenCL_CPP: 240 SpirvSourceLanguage = SourceLanguage::OpenCL_CPP; 241 break; 242 case dwarf::DW_LANG_CPP_for_OpenCL: 243 SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL; 244 break; 245 case dwarf::DW_LANG_GLSL: 246 SpirvSourceLanguage = SourceLanguage::GLSL; 247 break; 248 case dwarf::DW_LANG_HLSL: 249 SpirvSourceLanguage = SourceLanguage::HLSL; 250 break; 251 case dwarf::DW_LANG_SYCL: 252 SpirvSourceLanguage = SourceLanguage::SYCL; 253 break; 254 case dwarf::DW_LANG_Zig: 255 SpirvSourceLanguage = SourceLanguage::Zig; 256 } 257 258 const Register SourceLanguageReg = 259 GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false); 260 261 [[maybe_unused]] 262 const Register DebugCompUnitResIdReg = 263 EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit, 264 {DebugInfoVersionReg, DwarfVersionReg, 265 DebugSourceResIdReg, SourceLanguageReg}); 266 } 267 268 // We aren't extracting any DebugInfoFlags now so we 269 // emitting zero to use as <id>Flags argument for DebugBasicType 270 const Register I32ZeroReg = 271 GR->buildConstantInt(0, MIRBuilder, I32Ty, false, false); 272 273 // We need to store pairs because further instructions reference 274 // the DIBasicTypes and size will be always small so there isn't 275 // need for any kind of map 276 SmallVector<std::pair<const DIBasicType *const, const Register>, 12> 277 BasicTypeRegPairs; 278 for (auto *BasicType : BasicTypes) { 279 const Register BasicTypeStrReg = EmitOpString(BasicType->getName()); 280 281 const Register ConstIntBitwidthReg = GR->buildConstantInt( 282 BasicType->getSizeInBits(), MIRBuilder, I32Ty, false); 283 284 uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified; 285 switch (BasicType->getEncoding()) { 286 case dwarf::DW_ATE_signed: 287 AttributeEncoding = BaseTypeAttributeEncoding::Signed; 288 break; 289 case dwarf::DW_ATE_unsigned: 290 AttributeEncoding = BaseTypeAttributeEncoding::Unsigned; 291 break; 292 case dwarf::DW_ATE_unsigned_char: 293 AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar; 294 break; 295 case dwarf::DW_ATE_signed_char: 296 AttributeEncoding = BaseTypeAttributeEncoding::SignedChar; 297 break; 298 case dwarf::DW_ATE_float: 299 AttributeEncoding = BaseTypeAttributeEncoding::Float; 300 break; 301 case dwarf::DW_ATE_boolean: 302 AttributeEncoding = BaseTypeAttributeEncoding::Boolean; 303 break; 304 case dwarf::DW_ATE_address: 305 AttributeEncoding = BaseTypeAttributeEncoding::Address; 306 } 307 308 const Register AttributeEncodingReg = 309 GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false); 310 311 const Register BasicTypeReg = 312 EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic, 313 {BasicTypeStrReg, ConstIntBitwidthReg, 314 AttributeEncodingReg, I32ZeroReg}); 315 BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg); 316 } 317 318 if (PointerDerivedTypes.size()) { 319 for (const auto *PointerDerivedType : PointerDerivedTypes) { 320 321 assert(PointerDerivedType->getDWARFAddressSpace().has_value()); 322 const Register StorageClassReg = GR->buildConstantInt( 323 addressSpaceToStorageClass( 324 PointerDerivedType->getDWARFAddressSpace().value(), 325 *TM->getSubtargetImpl()), 326 MIRBuilder, I32Ty, false); 327 328 // If the Pointer is representing a void type it's getBaseType 329 // is a nullptr 330 const auto *MaybeNestedBasicType = 331 cast_or_null<DIBasicType>(PointerDerivedType->getBaseType()); 332 if (MaybeNestedBasicType) { 333 for (const auto &BasicTypeRegPair : BasicTypeRegPairs) { 334 const auto &[DefinedBasicType, BasicTypeReg] = BasicTypeRegPair; 335 if (DefinedBasicType == MaybeNestedBasicType) { 336 [[maybe_unused]] 337 const Register DebugPointerTypeReg = EmitDIInstruction( 338 SPIRV::NonSemanticExtInst::DebugTypePointer, 339 {BasicTypeReg, StorageClassReg, I32ZeroReg}); 340 } 341 } 342 } else { 343 const Register DebugInfoNoneReg = 344 EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {}); 345 [[maybe_unused]] 346 const Register DebugPointerTypeReg = EmitDIInstruction( 347 SPIRV::NonSemanticExtInst::DebugTypePointer, 348 {DebugInfoNoneReg, StorageClassReg, I32ZeroReg}); 349 } 350 } 351 } 352 } 353 return true; 354 } 355 356 bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) { 357 bool Res = false; 358 // emitGlobalDI needs to be executed only once to avoid 359 // emitting duplicates 360 if (!IsGlobalDIEmitted) { 361 IsGlobalDIEmitted = true; 362 Res = emitGlobalDI(MF); 363 } 364 return Res; 365 } 366