[llvm] [SPIRV] Addition of extension SPV_KHR_non_semantic_info and SPV_KHR_relaxed_extended_instruction (PR #165302)
Dmitry Sidorov via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 7 03:22:58 PST 2025
================
@@ -175,185 +422,1398 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
// and before first terminator
MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
- const auto EmitOpString = [&](StringRef SR) {
- const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
- MRI.setType(StrReg, LLT::scalar(32));
- MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
- MIB.addDef(StrReg);
- addStringImm(SR, MIB);
- return StrReg;
- };
+ SmallVector<std::pair<const DIBasicType *const, const Register>, 12>
+ BasicTypeRegPairs;
+ SmallVector<std::pair<const DICompositeType *const, const Register>, 12>
+ CompositeTypeRegPairs;
+ SmallVector<std::pair<const DIFile *const, const Register>, 12>
+ SourceRegPairs;
+ SmallVector<std::pair<const DIScope *const, const Register>, 12>
+ ScopeRegPairs;
+ SmallVector<std::pair<const DISubroutineType *const, const Register>, 12>
+ SubRoutineTypeRegPairs;
const SPIRVType *VoidTy =
GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder,
SPIRV::AccessQualifier::ReadWrite, false);
-
- const auto EmitDIInstruction =
- [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
- std::initializer_list<Register> Registers) {
- const Register InstReg =
- MRI.createVirtualRegister(&SPIRV::IDRegClass);
- MRI.setType(InstReg, LLT::scalar(32));
- MachineInstrBuilder MIB =
- MIRBuilder.buildInstr(SPIRV::OpExtInst)
- .addDef(InstReg)
- .addUse(GR->getSPIRVTypeID(VoidTy))
- .addImm(static_cast<int64_t>(
- SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
- .addImm(Inst);
- for (auto Reg : Registers) {
- MIB.addUse(Reg);
- }
- MIB.constrainAllUses(*TII, *TRI, *RBI);
- GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
- return InstReg;
- };
-
const SPIRVType *I32Ty =
GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder,
SPIRV::AccessQualifier::ReadWrite, false);
+ const Register I32ZeroReg =
+ GR->buildConstantInt(1, MIRBuilder, I32Ty, false);
+
const Register DwarfVersionReg =
GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
const Register DebugInfoVersionReg =
GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
+ SPIRVCodeGenContext Ctx(MIRBuilder, MRI, GR, VoidTy, I32Ty, TII, TRI, RBI,
+ MF, I32ZeroReg, TM, SourceRegPairs, ScopeRegPairs,
+ SubRoutineTypeRegPairs, BasicTypeRegPairs,
+ CompositeTypeRegPairs);
+
for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {
- const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);
-
- const Register DebugSourceResIdReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
-
- SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
- switch (LLVMSourceLanguages[Idx]) {
- case dwarf::DW_LANG_OpenCL:
- SpirvSourceLanguage = SourceLanguage::OpenCL_C;
- break;
- case dwarf::DW_LANG_OpenCL_CPP:
- SpirvSourceLanguage = SourceLanguage::OpenCL_CPP;
- break;
- case dwarf::DW_LANG_CPP_for_OpenCL:
- SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL;
- break;
- case dwarf::DW_LANG_GLSL:
- SpirvSourceLanguage = SourceLanguage::GLSL;
- break;
- case dwarf::DW_LANG_HLSL:
- SpirvSourceLanguage = SourceLanguage::HLSL;
- break;
- case dwarf::DW_LANG_SYCL:
- SpirvSourceLanguage = SourceLanguage::SYCL;
- break;
- case dwarf::DW_LANG_Zig:
- SpirvSourceLanguage = SourceLanguage::Zig;
+ emitSingleCompilationUnit(FilePaths[Idx], LLVMSourceLanguages[Idx], Ctx,
+ DebugInfoVersionReg, DwarfVersionReg,
+ DebugSourceResIdReg, DebugCompUnitResIdReg);
+
+ if (const DISubprogram *SP = Ctx.MF.getFunction().getSubprogram()) {
+ if (const DIFile *File = SP->getFile())
+ Ctx.GR->addDebugValue(File, DebugCompUnitResIdReg);
+ if (const DICompileUnit *Unit = SP->getUnit())
+ Ctx.GR->addDebugValue(Unit, DebugCompUnitResIdReg);
+ }
+ }
+ emitDebugMacroDefs(MF, Ctx);
+ emitDebugBuildIdentifier(BuildIdentifier, Ctx);
+ emitDebugStoragePath(BuildStoragePath, Ctx);
+ emitDebugBasicTypes(Collector.BasicTypes, Ctx);
+
+ emitSubroutineTypes(Collector.SubRoutineTypes, Ctx);
+ emitSubprograms(Collector.SubPrograms, Ctx);
+ emitLexicalScopes(Collector.LexicalScopes, Ctx);
+ emitDebugPointerTypes(Collector.PointerDerivedTypes, Ctx);
+ emitDebugArrayTypes(Collector.ArrayTypes, Ctx);
+ emitAllDebugTypeComposites(Collector.CompositeTypes, Ctx);
+ emitDebugTypeEnum(Collector.EnumTypes, Ctx);
+ emitAllTemplateDebugInstructions(Collector.CompositeTypesWithTemplates,
+ Ctx);
+ emitDebugQualifiedTypes(Collector.QualifiedDerivedTypes, Ctx);
+ emitDebugTypedefs(Collector.TypedefTypes, Ctx);
+ emitDebugTypePtrToMember(Collector.PtrToMemberTypes, Ctx);
+ emitAllDebugGlobalVariables(MF, Ctx);
+ emitDebugImportedEntities(Collector.ImportedEntities, Ctx);
+ }
+ return true;
+}
+
+bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
+ bool Res = false;
+ if (!IsGlobalDIEmitted) {
+ IsGlobalDIEmitted = true;
+ Res = emitGlobalDI(MF);
+ }
+ return Res;
+}
+
+Register SPIRVEmitNonSemanticDI::EmitOpString(StringRef SR,
+ SPIRVCodeGenContext &Ctx) {
+ const Register StrReg = Ctx.MRI.createVirtualRegister(&SPIRV::IDRegClass);
+ Ctx.MRI.setType(StrReg, LLT::scalar(32));
+ MachineInstrBuilder MIB = Ctx.MIRBuilder.buildInstr(SPIRV::OpString);
+ MIB.addDef(StrReg);
+ addStringImm(SR, MIB);
+ return StrReg;
+}
+
+Register SPIRVEmitNonSemanticDI::EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
+ ArrayRef<Register> Operands, SPIRVCodeGenContext &Ctx, bool HasForwardRef,
+ Register DefReg) {
+
+ Register InstReg = DefReg;
+ if (!InstReg.isValid()) {
+ InstReg = Ctx.MRI.createVirtualRegister(&SPIRV::IDRegClass);
+ Ctx.MRI.setType(InstReg, LLT::scalar(32));
+ }
+
+ unsigned Opcode =
+ HasForwardRef ? SPIRV::OpExtInstWithForwardRefsKHR : SPIRV::OpExtInst;
+ MachineInstrBuilder MIB =
+ Ctx.MIRBuilder.buildInstr(Opcode)
+ .addDef(InstReg)
+ .addUse(Ctx.GR->getSPIRVTypeID(Ctx.VoidTy))
+ .addImm(static_cast<int64_t>(
+ SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
+ .addImm(Inst);
+ for (auto Reg : Operands) {
+ MIB.addUse(Reg);
+ }
+ MIB.constrainAllUses(*Ctx.TII, *Ctx.TRI, *Ctx.RBI);
+ Ctx.GR->assignSPIRVTypeToVReg(Ctx.VoidTy, InstReg, Ctx.MF);
+
+ // If we were passed a valid DefReg, it was a placeholder.
+ // Now that we've emitted the instruction that defines it, resolve it.
+ if (DefReg.isValid() && Ctx.GR->isForwardPlaceholder(DefReg))
+ Ctx.GR->resolveForwardPlaceholder(DefReg);
+
+ return InstReg;
+}
+
+uint32_t SPIRVEmitNonSemanticDI::transDebugFlags(const DINode *DN) {
+ uint32_t Flags = 0;
+ if (const DIGlobalVariable *GV = dyn_cast<DIGlobalVariable>(DN)) {
+ if (GV->isLocalToUnit())
+ Flags |= Flag::FlagIsLocal;
+ if (GV->isDefinition())
+ Flags |= Flag::FlagIsDefinition;
+ }
+ if (const DISubprogram *DS = dyn_cast<DISubprogram>(DN)) {
+ if (DS->isLocalToUnit())
+ Flags |= Flag::FlagIsLocal;
+ if (DS->isOptimized())
+ Flags |= Flag::FlagIsOptimized;
+ if (DS->isDefinition())
+ Flags |= Flag::FlagIsDefinition;
+ Flags |= mapDebugFlags(DS->getFlags());
+ }
+ if (DN->getTag() == dwarf::DW_TAG_reference_type)
+ Flags |= Flag::FlagIsLValueReference;
+ if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
+ Flags |= Flag::FlagIsRValueReference;
+ if (const DIType *DT = dyn_cast<DIType>(DN))
+ Flags |= mapDebugFlags(DT->getFlags());
+ if (const DILocalVariable *DLocVar = dyn_cast<DILocalVariable>(DN))
+ Flags |= mapDebugFlags(DLocVar->getFlags());
+
+ return Flags;
+}
+
+uint32_t SPIRVEmitNonSemanticDI::mapDebugFlags(DINode::DIFlags DFlags) {
+ uint32_t Flags = 0;
+ if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
+ Flags |= Flag::FlagIsPublic;
+ if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
+ Flags |= Flag::FlagIsProtected;
+ if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
+ Flags |= Flag::FlagIsPrivate;
+
+ if (DFlags & DINode::FlagFwdDecl)
+ Flags |= Flag::FlagIsFwdDecl;
+ if (DFlags & DINode::FlagArtificial)
+ Flags |= Flag::FlagIsArtificial;
+ if (DFlags & DINode::FlagExplicit)
+ Flags |= Flag::FlagIsExplicit;
+ if (DFlags & DINode::FlagPrototyped)
+ Flags |= Flag::FlagIsPrototyped;
+ if (DFlags & DINode::FlagObjectPointer)
+ Flags |= Flag::FlagIsObjectPointer;
+ if (DFlags & DINode::FlagStaticMember)
+ Flags |= Flag::FlagIsStaticMember;
+ // inderect variable flag ?
+ if (DFlags & DINode::FlagLValueReference)
+ Flags |= Flag::FlagIsLValueReference;
+ if (DFlags & DINode::FlagRValueReference)
+ Flags |= Flag::FlagIsRValueReference;
+ if (DFlags & DINode::FlagTypePassByValue)
+ Flags |= Flag::FlagTypePassByValue;
+ if (DFlags & DINode::FlagTypePassByReference)
+ Flags |= Flag::FlagTypePassByReference;
+ if (DFlags & DINode::FlagEnumClass)
+ Flags |= Flag::FlagIsEnumClass;
+ return Flags;
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugTypeEnum(
+ const SmallPtrSetImpl<const DICompositeType *> &EnumTypes,
+ SPIRVCodeGenContext &Ctx) {
+ for (auto *EnumTy : EnumTypes) {
+ if (!EnumTy || EnumTy->getTag() != dwarf::DW_TAG_enumeration_type)
+ continue;
+ if (Register Existing = Ctx.GR->getDebugValue(EnumTy); Existing.isValid())
+ continue;
+ Register NameStr = EmitOpString(EnumTy->getName(), Ctx);
+ bool UnderlyingTypeIsFwd = false;
+ Register UnderlyingTypeReg = findBaseTypeRegisterRecursive(
+ EnumTy->getBaseType(), Ctx, UnderlyingTypeIsFwd);
+ if (!UnderlyingTypeReg.isValid()) {
+ UnderlyingTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+ UnderlyingTypeIsFwd = false;
+ }
+ Register SourceReg =
+ findRegisterFromMap(EnumTy->getFile(), Ctx.SourceRegPairs);
+ if (!SourceReg.isValid()) {
+ SourceReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ }
+ Register Line = Ctx.GR->buildConstantInt(EnumTy->getLine(), Ctx.MIRBuilder,
+ Ctx.I32Ty, false);
+ Register Column =
+ Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false);
+
+ Register ParentReg = Ctx.GR->getDebugValue(EnumTy->getScope());
+ if (!ParentReg.isValid()) {
+ llvm::errs() << "Warning: Could not find Parent scope register for Enum: "
+ << EnumTy->getName() << "\n";
+ ParentReg = Ctx.GR->getDebugValue(EnumTy->getFile());
+ if (!ParentReg.isValid()) {
+ ParentReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
}
+ }
+ Register Size = Ctx.GR->buildConstantInt(EnumTy->getSizeInBits(),
+ Ctx.MIRBuilder, Ctx.I32Ty, false);
+ uint32_t Flags = transDebugFlags(EnumTy);
+ Register FlagsReg =
+ Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false);
+ SmallVector<Register, 16> EnumOperands;
+ for (Metadata *MD : EnumTy->getElements()) {
+ if (auto *E = dyn_cast<DIEnumerator>(MD)) {
+ Register Val = Ctx.GR->buildConstantInt(
+ E->getValue().getZExtValue(), Ctx.MIRBuilder, Ctx.I32Ty, false);
+ Register Name = EmitOpString(E->getName(), Ctx);
+ EnumOperands.push_back(Val);
+ EnumOperands.push_back(Name);
+ }
+ }
+ SmallVector<Register, 12> Ops = {
+ NameStr, UnderlyingTypeReg, SourceReg, Line,
+ Column, ParentReg, Size, FlagsReg};
+ Ops.append(EnumOperands);
+ bool HasForwardRef = UnderlyingTypeIsFwd;
+ Register DefReg = Ctx.GR->getDebugValue(EnumTy);
+ Register Res = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeEnum,
+ Ops, Ctx, HasForwardRef, DefReg);
+ Ctx.GR->addDebugValue(EnumTy, Res);
+ Ctx.CompositeTypeRegPairs.emplace_back(EnumTy, Res);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitSingleCompilationUnit(
+ StringRef FilePath, int64_t Language, SPIRVCodeGenContext &Ctx,
+ Register DebugInfoVersionReg, Register DwarfVersionReg,
+ Register &DebugSourceResIdReg, Register &DebugCompUnitResIdReg) {
+
+ const Register FilePathStrReg = EmitOpString(FilePath, Ctx);
- const Register SourceLanguageReg =
- GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false);
+ const Function *F = &Ctx.MF.getFunction();
+ const DISubprogram *SP = F ? F->getSubprogram() : nullptr;
+ const DIFile *FileMDNode = nullptr;
+ if (SP)
+ FileMDNode = SP->getFile();
- [[maybe_unused]]
- const Register DebugCompUnitResIdReg =
- EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
- {DebugInfoVersionReg, DwarfVersionReg,
- DebugSourceResIdReg, SourceLanguageReg});
+ std::string FileMDContents;
+ if (FileMDNode && FileMDNode->getRawFile() &&
+ FileMDNode->getSource().has_value())
+ FileMDContents = FileMDNode->getSource().value().str();
+
+ if (FileMDContents.empty()) {
+ DebugSourceResIdReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg}, Ctx, false);
+ } else {
+ constexpr size_t MaxNumWords = UINT16_MAX - 2;
+ constexpr size_t MaxStrSize = MaxNumWords * 4 - 1;
+ std::string RemainingSource = FileMDContents;
+ std::string FirstChunk = RemainingSource.substr(0, MaxStrSize);
+ const Register FirstTextStrReg = EmitOpString(FirstChunk, Ctx);
+ DebugSourceResIdReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugSource,
+ {FilePathStrReg, FirstTextStrReg}, Ctx, false);
+
+ RemainingSource.erase(0, FirstChunk.size());
+
+ while (!RemainingSource.empty()) {
+ std::string NextChunk = RemainingSource.substr(0, MaxStrSize);
+ const Register ContinuedStrReg = EmitOpString(NextChunk, Ctx);
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugSourceContinued,
+ {ContinuedStrReg}, Ctx, false);
+ RemainingSource.erase(0, NextChunk.size());
}
+ }
+ Ctx.SourceRegPairs.emplace_back(FileMDNode, DebugSourceResIdReg);
- // We aren't extracting any DebugInfoFlags now so we
- // emitting zero to use as <id>Flags argument for DebugBasicType
- const Register I32ZeroReg =
- GR->buildConstantInt(0, MIRBuilder, I32Ty, false, false);
+ SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
+ switch (Language) {
+ case dwarf::DW_LANG_OpenCL:
+ SpirvSourceLanguage = SourceLanguage::OpenCL_C;
+ break;
+ case dwarf::DW_LANG_OpenCL_CPP:
+ SpirvSourceLanguage = SourceLanguage::OpenCL_CPP;
+ break;
+ case dwarf::DW_LANG_CPP_for_OpenCL:
+ SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL;
+ break;
+ case dwarf::DW_LANG_GLSL:
+ SpirvSourceLanguage = SourceLanguage::GLSL;
+ break;
+ case dwarf::DW_LANG_HLSL:
+ SpirvSourceLanguage = SourceLanguage::HLSL;
+ break;
+ case dwarf::DW_LANG_SYCL:
+ SpirvSourceLanguage = SourceLanguage::SYCL;
+ break;
+ case dwarf::DW_LANG_Zig:
+ SpirvSourceLanguage = SourceLanguage::Zig;
+ break;
+ case dwarf::DW_LANG_C_plus_plus_14:
+ SpirvSourceLanguage = SourceLanguage::CPP;
+ break;
+ default:
+ SpirvSourceLanguage = SourceLanguage::Unknown;
+ break;
+ }
- // We need to store pairs because further instructions reference
- // the DIBasicTypes and size will be always small so there isn't
- // need for any kind of map
- SmallVector<std::pair<const DIBasicType *const, const Register>, 12>
- BasicTypeRegPairs;
- for (auto *BasicType : BasicTypes) {
- const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
-
- const Register ConstIntBitwidthReg = GR->buildConstantInt(
- BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
-
- uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
- switch (BasicType->getEncoding()) {
- case dwarf::DW_ATE_signed:
- AttributeEncoding = BaseTypeAttributeEncoding::Signed;
- break;
- case dwarf::DW_ATE_unsigned:
- AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
- break;
- case dwarf::DW_ATE_unsigned_char:
- AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
- break;
- case dwarf::DW_ATE_signed_char:
- AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
- break;
- case dwarf::DW_ATE_float:
- AttributeEncoding = BaseTypeAttributeEncoding::Float;
- break;
- case dwarf::DW_ATE_boolean:
- AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
- break;
- case dwarf::DW_ATE_address:
- AttributeEncoding = BaseTypeAttributeEncoding::Address;
+ const Register SourceLanguageReg = Ctx.GR->buildConstantInt(
+ SpirvSourceLanguage, Ctx.MIRBuilder, Ctx.I32Ty, false);
+
+ DebugCompUnitResIdReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
+ {DebugInfoVersionReg, DwarfVersionReg,
+ DebugSourceResIdReg, SourceLanguageReg},
+ Ctx, false);
+}
+
+Register SPIRVEmitNonSemanticDI::findEmittedBasicTypeReg(
+ const DIType *BaseType,
+ const SmallVectorImpl<std::pair<const DIBasicType *const, const Register>>
+ &BasicTypeRegPairs) {
+ const DIType *Ty = BaseType;
+
+ while (Ty && !isa<DIBasicType>(Ty)) {
+ if (auto *Derived = dyn_cast<DIDerivedType>(Ty))
+ if (Derived->getBaseType())
+ Ty = Derived->getBaseType();
+ else
+ return Register();
+ else
+ return Register();
+ }
+
+ if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
+ StringRef Name = BT->getName();
+ uint64_t Size = BT->getSizeInBits();
+
+ for (const auto &[DefinedBT, Reg] : BasicTypeRegPairs) {
+ if (DefinedBT->getName() == Name && DefinedBT->getSizeInBits() == Size)
+ return Reg;
+ }
+ }
+ return Register();
+}
+
+Register SPIRVEmitNonSemanticDI::findEmittedCompositeTypeReg(
+ const DIType *BaseType,
+ const SmallVectorImpl<std::pair<const DICompositeType *const,
+ const Register>> &CompositeTypeRegPairs) {
+
+ StringRef Name = BaseType->getName();
+ uint64_t Size = BaseType->getSizeInBits();
+ unsigned Tag = BaseType->getTag();
+
+ for (const auto &[DefinedCT, Reg] : CompositeTypeRegPairs) {
+ if (DefinedCT->getName() == Name && DefinedCT->getSizeInBits() == Size &&
+ DefinedCT->getTag() == Tag)
+ return Reg;
+ }
+
+ return Register();
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugBuildIdentifier(
+ StringRef BuildIdentifier, SPIRVCodeGenContext &Ctx) {
+ if (BuildIdentifier.empty())
+ return;
+
+ const Register BuildIdStrReg = EmitOpString(BuildIdentifier, Ctx);
+ uint32_t Flags = 0;
+ if (BuildIdentifier.contains("IdentifierPossibleDuplicates"))
+ Flags |= (1 << 0);
+ const Register FlagsReg =
+ Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugBuildIdentifier,
+ {BuildIdStrReg, FlagsReg}, Ctx, false);
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugStoragePath(StringRef BuildStoragePath,
+ SPIRVCodeGenContext &Ctx) {
+ if (!BuildStoragePath.empty()) {
+ const Register PathStrReg = EmitOpString(BuildStoragePath, Ctx);
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugStoragePath, {PathStrReg},
+ Ctx, false);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugBasicTypes(
+ const SmallPtrSetImpl<DIBasicType *> &BasicTypes,
+ SPIRVCodeGenContext &Ctx) {
+ // We need to store pairs because further instructions reference
+ // the DIBasicTypes and size will be always small so there isn't
+ // need for any kind of map
+ for (auto *BasicType : BasicTypes) {
+ if (!BasicType)
+ continue;
+ const Register BasicTypeStrReg = EmitOpString(BasicType->getName(), Ctx);
+
+ const Register ConstIntBitwidthReg = Ctx.GR->buildConstantInt(
+ BasicType->getSizeInBits(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
+ switch (BasicType->getEncoding()) {
+ case dwarf::DW_ATE_signed:
+ AttributeEncoding = BaseTypeAttributeEncoding::Signed;
+ break;
+ case dwarf::DW_ATE_unsigned:
+ AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
+ break;
+ case dwarf::DW_ATE_unsigned_char:
+ AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
+ break;
+ case dwarf::DW_ATE_signed_char:
+ AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
+ break;
+ case dwarf::DW_ATE_float:
+ AttributeEncoding = BaseTypeAttributeEncoding::Float;
+ break;
+ case dwarf::DW_ATE_boolean:
+ AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
+ break;
+ case dwarf::DW_ATE_address:
+ AttributeEncoding = BaseTypeAttributeEncoding::Address;
+ }
+
+ const Register AttributeEncodingReg = Ctx.GR->buildConstantInt(
+ AttributeEncoding, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ const Register FlagsReg = Ctx.GR->buildConstantInt(
+ transDebugFlags(BasicType), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ [[maybe_unused]]
+ const Register BasicTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypeBasic,
+ {BasicTypeStrReg, ConstIntBitwidthReg, AttributeEncodingReg, FlagsReg},
+ Ctx, false);
+ Ctx.GR->addDebugValue(BasicType, BasicTypeReg);
+ Ctx.BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugPointerTypes(
+ const SmallPtrSetImpl<DIDerivedType *> &PointerDerivedTypes,
+ SPIRVCodeGenContext &Ctx) {
+
+ if (PointerDerivedTypes.empty())
+ return;
+
+ for (const auto *PointerDerivedType : PointerDerivedTypes) {
+ uint64_t DWARFAddrSpace = 0;
+ if (PointerDerivedType->getDWARFAddressSpace().has_value())
+ DWARFAddrSpace = PointerDerivedType->getDWARFAddressSpace().value();
+ else {
+ LLVM_DEBUG(dbgs() << "Warning: pointer DI has no DWARF address space; "
+ << "falling back to 0 (generic)\n");
+ }
+ const Register StorageClassReg = Ctx.GR->buildConstantInt(
+ addressSpaceToStorageClass(DWARFAddrSpace, *Ctx.TM->getSubtargetImpl()),
+ Ctx.MIRBuilder, Ctx.I32Ty, false);
+ const uint32_t Flags = transDebugFlags(PointerDerivedType);
+ const Register FlagsReg = Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder,
+ Ctx.I32Ty, false, false);
+
+ const DIType *BaseTy = PointerDerivedType->getBaseType();
+ bool HasForwardRef = false;
+ Register BaseTypeReg =
+ findBaseTypeRegisterRecursive(BaseTy, Ctx, HasForwardRef);
+
+ if (!BaseTypeReg.isValid()) {
+ llvm::errs() << "Warning: Failed to find or create placeholder for base "
+ "type of pointer.\n";
+ BaseTypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ HasForwardRef = false;
+ }
+ const Register DebugPointerTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypePointer,
+ {BaseTypeReg, StorageClassReg, FlagsReg}, Ctx, HasForwardRef);
+
+ Ctx.GR->addDebugValue(PointerDerivedType, DebugPointerTypeReg);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitLexicalScopes(
+ const SmallPtrSetImpl<DIScope *> &LexicalScopes, SPIRVCodeGenContext &Ctx) {
+ for (DIScope *Scope : LexicalScopes) {
+ if (!Scope)
+ continue;
+
+ SmallVector<Register, 4> Operands;
+ Register ScopeSourceReg =
+ findRegisterFromMap(Scope->getFile(), Ctx.SourceRegPairs);
+ Register ScopeParentReg =
+ findRegisterFromMap(Scope->getScope(), Ctx.ScopeRegPairs);
+
+ Operands.push_back(ScopeSourceReg);
+
+ if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope)) {
+ Register Discriminator = Ctx.GR->buildConstantInt(
+ LBF->getDiscriminator(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ Operands.push_back(Discriminator);
+ Operands.push_back(ScopeParentReg);
+
+ EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugLexicalBlockDiscriminator, Operands,
+ Ctx, false);
+
+ } else if (auto *LB = dyn_cast<DILexicalBlock>(Scope)) {
+ Operands.push_back(Ctx.GR->buildConstantInt(LB->getLine(), Ctx.MIRBuilder,
+ Ctx.I32Ty, false, false));
+ Operands.push_back(Ctx.GR->buildConstantInt(
+ LB->getColumn(), Ctx.MIRBuilder, Ctx.I32Ty, false, false));
+ Operands.push_back(ScopeParentReg);
+
+ Register LexicalScopeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugLexicalBlock, Operands, Ctx, false);
+
+ Ctx.ScopeRegPairs.emplace_back(Scope, LexicalScopeReg);
+ }
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitSubroutineTypes(
+ const SmallPtrSet<DISubroutineType *, 12> &SubRoutineTypes,
+ SPIRVCodeGenContext &Ctx) {
+
+ for (const auto *SubroutineType : SubRoutineTypes) {
+ SmallVector<Register, 6> TypeRegs;
+ bool HasForwardRef = false;
+
+ const Register FlagsReg =
+ Ctx.GR->buildConstantInt(transDebugFlags(SubroutineType),
+ Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ DITypeRefArray Types = SubroutineType->getTypeArray();
+ const DIType *RetTy =
+ Types.size() > 0 ? dyn_cast_or_null<DIType>(Types[0]) : nullptr;
+ Register RetTypeReg;
+ bool RetTyIsFwd = false;
+ if (RetTy) {
+ RetTypeReg = findBaseTypeRegisterRecursive(RetTy, Ctx, RetTyIsFwd);
+ }
+ if (!RetTypeReg.isValid()) {
+ const SPIRVType *VoidTy = Ctx.GR->getOrCreateSPIRVType(
+ Type::getVoidTy(Ctx.MF.getFunction().getContext()), Ctx.MIRBuilder,
+ SPIRV::AccessQualifier::ReadWrite, false);
+ RetTypeReg = VoidTy->getOperand(0).getReg();
+ RetTyIsFwd = false;
+ }
+ TypeRegs.push_back(RetTypeReg);
+ if (RetTyIsFwd)
+ HasForwardRef = true;
+ for (unsigned I = 1; I < Types.size(); ++I) {
+ if (const DIType *ParamTy = dyn_cast_or_null<DIType>(Types[I])) {
+ bool ParamTyIsFwd = false;
+ Register ParamTypeReg =
+ findBaseTypeRegisterRecursive(ParamTy, Ctx, ParamTyIsFwd);
+
+ if (!ParamTypeReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find type for function parameter.\n";
+ const SPIRVType *VoidTy = Ctx.GR->getOrCreateSPIRVType(
+ Type::getVoidTy(Ctx.MF.getFunction().getContext()),
+ Ctx.MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false);
+ ParamTypeReg = VoidTy->getOperand(0).getReg();
+ ParamTyIsFwd = false;
+ }
+ TypeRegs.push_back(ParamTypeReg);
+ if (ParamTyIsFwd)
+ HasForwardRef = true;
+ } else {
+ const SPIRVType *VoidTy = Ctx.GR->getOrCreateSPIRVType(
+ Type::getVoidTy(Ctx.MF.getFunction().getContext()), Ctx.MIRBuilder,
+ SPIRV::AccessQualifier::ReadWrite, false);
+ Register TypeReg = VoidTy->getOperand(0).getReg();
+ TypeRegs.push_back(TypeReg);
}
+ }
+ Register DefReg = Ctx.GR->getDebugValue(SubroutineType);
+ SmallVector<Register, 6> Operands;
+ Operands.push_back(FlagsReg);
+ Operands.append(TypeRegs);
+ const Register FuncTypeReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeFunction,
+ Operands, Ctx, HasForwardRef, DefReg);
+ Ctx.GR->addDebugValue(SubroutineType, FuncTypeReg);
+ Ctx.SubRoutineTypeRegPairs.emplace_back(SubroutineType, FuncTypeReg);
+ }
+}
- const Register AttributeEncodingReg =
- GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
-
- const Register BasicTypeReg =
- EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
- {BasicTypeStrReg, ConstIntBitwidthReg,
- AttributeEncodingReg, I32ZeroReg});
- BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);
- }
-
- if (PointerDerivedTypes.size()) {
- for (const auto *PointerDerivedType : PointerDerivedTypes) {
-
- assert(PointerDerivedType->getDWARFAddressSpace().has_value());
- const Register StorageClassReg = GR->buildConstantInt(
- addressSpaceToStorageClass(
- PointerDerivedType->getDWARFAddressSpace().value(),
- *TM->getSubtargetImpl()),
- MIRBuilder, I32Ty, false);
-
- // If the Pointer is representing a void type it's getBaseType
- // is a nullptr
- const auto *MaybeNestedBasicType =
- dyn_cast_or_null<DIBasicType>(PointerDerivedType->getBaseType());
- if (MaybeNestedBasicType) {
- for (const auto &BasicTypeRegPair : BasicTypeRegPairs) {
- const auto &[DefinedBasicType, BasicTypeReg] = BasicTypeRegPair;
- if (DefinedBasicType == MaybeNestedBasicType) {
- [[maybe_unused]]
- const Register DebugPointerTypeReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugTypePointer,
- {BasicTypeReg, StorageClassReg, I32ZeroReg});
- }
- }
+void SPIRVEmitNonSemanticDI::emitSubprograms(
+ const SmallPtrSet<DISubprogram *, 12> &SubPrograms,
+ SPIRVCodeGenContext &Ctx) {
+
+ for (const auto *SubProgram : SubPrograms) {
+ SmallVector<Register, 10> Operands;
+
+ Operands.push_back(EmitOpString(SubProgram->getName(), Ctx));
+ Operands.push_back(
+ findRegisterFromMap(SubProgram->getType(), Ctx.SubRoutineTypeRegPairs));
+ Operands.push_back(
+ findRegisterFromMap(SubProgram->getFile(), Ctx.SourceRegPairs));
+ Operands.push_back(Ctx.GR->buildConstantInt(
+ SubProgram->getLine(), Ctx.MIRBuilder, Ctx.I32Ty, false, false));
+ Operands.push_back(Ctx.I32ZeroReg);
+ Operands.push_back(Ctx.GR->getDebugValue(SubProgram->getFile()));
+ Operands.push_back(EmitOpString(SubProgram->getLinkageName(), Ctx));
+ Operands.push_back(Ctx.GR->buildConstantInt(
+ SubProgram->getFlags(), Ctx.MIRBuilder, Ctx.I32Ty, false, false));
+
+ if (!SubProgram->isDefinition()) {
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugFunctionDeclaration,
+ Operands, Ctx, false);
+ } else {
+ Operands.push_back(Ctx.GR->buildConstantInt(
+ SubProgram->getScopeLine(), Ctx.MIRBuilder, Ctx.I32Ty, false, false));
+ const Register FuncReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugFunction, Operands, Ctx, false);
+
+ Ctx.ScopeRegPairs.emplace_back(dynamic_cast<const DIScope *>(SubProgram),
+ FuncReg);
+ }
+ }
+}
+
+uint32_t SPIRVEmitNonSemanticDI::mapTagToQualifierEncoding(unsigned Tag) {
+ switch (Tag) {
+ case dwarf::DW_TAG_const_type:
+ return QualifierTypeAttributeEncoding::ConstType;
+ case dwarf::DW_TAG_volatile_type:
+ return QualifierTypeAttributeEncoding::VolatileType;
+ case dwarf::DW_TAG_restrict_type:
+ return QualifierTypeAttributeEncoding::RestrictType;
+ case dwarf::DW_TAG_atomic_type:
+ return QualifierTypeAttributeEncoding::AtomicType;
+ default:
+ llvm_unreachable("Unknown DWARF tag for DebugTypeQualifier");
+ }
+}
+
+uint32_t SPIRVEmitNonSemanticDI::mapImportedTagToEncoding(
+ const DIImportedEntity *Imported) {
+ switch (Imported->getTag()) {
+ case dwarf::DW_TAG_imported_module:
+ return ImportedEnityAttributeEncoding::ImportedModule;
+ case dwarf::DW_TAG_imported_declaration:
+ return ImportedEnityAttributeEncoding::ImportedDeclaration;
+ default:
+ llvm_unreachable("Unknown DWARF tag for DebugImportedEntity");
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugQualifiedTypes(
+ const SmallPtrSetImpl<DIDerivedType *> &QualifiedDerivedTypes,
+ SPIRVCodeGenContext &Ctx) {
+ if (!QualifiedDerivedTypes.empty()) {
+ for (const auto *QualifiedDT : QualifiedDerivedTypes) {
+ bool IsForwardRef = false;
+ Register BaseTypeReg = findBaseTypeRegisterRecursive(
+ QualifiedDT->getBaseType(), Ctx, IsForwardRef);
+
+ if (!BaseTypeReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find base type for DebugTypeQualifier.\n";
+ BaseTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+ IsForwardRef = false;
+ }
+
+ const uint32_t QualifierValue =
+ mapTagToQualifierEncoding(QualifiedDT->getTag());
+ const Register QualifierConstReg = Ctx.GR->buildConstantInt(
+ QualifierValue, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ Register DefReg = Ctx.GR->getDebugValue(QualifiedDT);
+
+ const Register DebugQualifiedTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypeQualifier,
+ {BaseTypeReg, QualifierConstReg}, Ctx, IsForwardRef, DefReg);
+
+ Ctx.GR->addDebugValue(QualifiedDT, DebugQualifiedTypeReg);
+ }
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugTypedefs(
+ const SmallPtrSetImpl<DIDerivedType *> &TypedefTypes,
+ SPIRVCodeGenContext &Ctx) {
+ for (const auto *TypedefDT : TypedefTypes) {
+ bool HasForwardRef = false;
+ Register BaseTypeReg = findBaseTypeRegisterRecursive(
+ TypedefDT->getBaseType(), Ctx, HasForwardRef);
+
+ if (!BaseTypeReg.isValid()) {
+ llvm::errs() << "Warning: Could not find base type for Typedef: "
+ << TypedefDT->getName() << "\n";
+ BaseTypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ HasForwardRef = false;
+ }
+
+ Register DefReg = Ctx.GR->getDebugValue(TypedefDT);
+
+ Register DebugSourceReg =
+ findRegisterFromMap(TypedefDT->getFile(), Ctx.SourceRegPairs);
+ const Register TypedefNameReg = EmitOpString(TypedefDT->getName(), Ctx);
+ const Register LineReg = Ctx.GR->buildConstantInt(
+ TypedefDT->getLine(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ const Register ColumnReg =
+ Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register ScopeReg = Ctx.GR->getDebugValue(TypedefDT->getFile());
+ const Register DebugTypedefReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypedef,
+ {TypedefNameReg, BaseTypeReg, DebugSourceReg, LineReg,
+ ColumnReg, ScopeReg},
+ Ctx, HasForwardRef, DefReg);
+ Ctx.GR->addDebugValue(TypedefDT, DebugTypedefReg);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugImportedEntities(
+ const SmallVectorImpl<const DIImportedEntity *> &ImportedEntities,
+ SPIRVCodeGenContext &Ctx) {
+ for (const auto *Imported : ImportedEntities) {
+ if (!Imported->getEntity())
+ continue;
+
+ const Register NameStrReg = EmitOpString(Imported->getName(), Ctx);
+ const Register DebugSourceReg =
+ findRegisterFromMap(Imported->getFile(), Ctx.SourceRegPairs);
+ // TODO: Handle Entity as there are no current instructions for DINamespace,
+ // so replaced by DebugInfoNone
+ const Register EntityReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+ const Register LineReg = Ctx.GR->buildConstantInt(
+ Imported->getLine(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ const Register ColumnReg =
+ Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ const Register ScopeReg = Ctx.GR->getDebugValue(Imported->getScope());
+ uint32_t Tag = mapImportedTagToEncoding(Imported);
+ Register TagReg =
+ Ctx.GR->buildConstantInt(Tag, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ [[maybe_unused]]
+ const Register DebugImportedEntityReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugImportedEntity,
+ {NameStrReg, TagReg, DebugSourceReg, EntityReg,
+ LineReg, ColumnReg, ScopeReg},
+ Ctx, false);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitAllDebugGlobalVariables(
+ MachineFunction &MF, SPIRVCodeGenContext &Ctx) {
+
+ const DISubprogram *SP = MF.getFunction().getSubprogram();
+ if (!SP)
+ return;
+
+ const DICompileUnit *CU = SP->getUnit();
+ if (!CU)
+ return;
+
+ auto GlobalVars = CU->getGlobalVariables();
+
+ for (auto *GVE : GlobalVars) {
+ if (GVE)
+ emitDebugGlobalVariable(GVE, Ctx);
+ }
+}
+
+Register SPIRVEmitNonSemanticDI::emitDebugGlobalVariable(
+ const DIGlobalVariableExpression *GVE, SPIRVCodeGenContext &Ctx) {
+
+ const DIGlobalVariable *DIGV = GVE->getVariable();
+ StringRef Name = DIGV->getName();
+ StringRef LinkageName = DIGV->getLinkageName();
+ unsigned Line = DIGV->getLine();
+ unsigned Column = 1;
+ const DIScope *ParentScope = DIGV->getFile();
+ uint32_t Flags = transDebugFlags(DIGV);
+ Register NameStrReg = EmitOpString(Name, Ctx);
+ Register LinkageStrReg = EmitOpString(LinkageName, Ctx);
+ Register LineReg =
+ Ctx.GR->buildConstantInt(Line, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register ColumnReg =
+ Ctx.GR->buildConstantInt(Column, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register FlagsReg =
+ Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ const DIType *Ty = DIGV->getType();
+ bool HasForwardRef = false;
+ Register TypeReg = findBaseTypeRegisterRecursive(Ty, Ctx, HasForwardRef);
+
+ if (!TypeReg.isValid()) {
+ llvm::errs() << "Warning: Could not find type for Global Variable: " << Name
+ << "\n";
+ TypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {},
+ Ctx, false);
+ HasForwardRef = false;
+ }
+
+ Register DebugSourceReg =
+ findRegisterFromMap(DIGV->getFile(), Ctx.SourceRegPairs);
+ Register ParentReg;
+ if (ParentScope) {
+ ParentReg = Ctx.GR->getDebugValue(ParentScope);
+ if (!ParentReg.isValid()) {
+ llvm::errs() << "Warning: Could not find parent scope register for "
+ "Global Variable.\n";
+ ParentReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ }
+ } else {
+ llvm::errs() << "Warning: DIGlobalVariable has no parent scope\n";
+ ParentReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {},
+ Ctx, false);
+ }
+ // TODO: Handle Variable Location operand
+ Register VariableReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+
+ SmallVector<Register, 9> Ops = {NameStrReg, TypeReg, DebugSourceReg,
+ LineReg, ColumnReg, ParentReg,
+ LinkageStrReg, VariableReg, FlagsReg};
+
+ Register DefReg = Ctx.GR->getDebugValue(DIGV);
+
+ Register GlobalVarReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugGlobalVariable, Ops,
+ Ctx, HasForwardRef, DefReg);
+
+ Ctx.GR->addDebugValue(DIGV, GlobalVarReg);
+ return GlobalVarReg;
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugArrayTypes(
+ const SmallPtrSetImpl<DICompositeType *> &ArrayTypes,
+ SPIRVCodeGenContext &Ctx) {
+ for (auto *ArrayTy : ArrayTypes) {
+ DIType *ElementType = ArrayTy->getBaseType();
+ bool HasForwardRef = false;
+ Register BaseTypeReg =
+ findBaseTypeRegisterRecursive(ElementType, Ctx, HasForwardRef);
+
+ if (!BaseTypeReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find element type for Array/Vector.\n";
+ BaseTypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ HasForwardRef = false;
+ }
+
+ DINodeArray Subranges = ArrayTy->getElements();
+ if (ArrayTy->isVector()) {
+ assert(Subranges.size() == 1 && "Only 1D vectors supported!");
+ emitDebugVectorTypes(ArrayTy, BaseTypeReg, Ctx);
+ continue;
+ }
+
+ SmallVector<Register, 4> ComponentCountRegs;
+ for (Metadata *M : Subranges) {
+ if (auto *SR = dyn_cast<DISubrange>(M)) {
+ auto CountValUnion = SR->getCount();
+ if (auto *CountCI = CountValUnion.dyn_cast<ConstantInt *>()) {
+ uint64_t CountVal = CountCI->getZExtValue();
+ Register ConstCountReg = Ctx.GR->buildConstantInt(
+ CountVal, Ctx.MIRBuilder, Ctx.I32Ty, false);
+ ComponentCountRegs.push_back(ConstCountReg);
} else {
- const Register DebugInfoNoneReg =
- EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});
- [[maybe_unused]]
- const Register DebugPointerTypeReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugTypePointer,
- {DebugInfoNoneReg, StorageClassReg, I32ZeroReg});
+ Register ConstZero = Ctx.GR->buildConstantInt(
+ 0, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ ComponentCountRegs.push_back(ConstZero);
}
}
}
+
+ SmallVector<Register, 6> Ops;
+ Ops.push_back(BaseTypeReg);
+ llvm::append_range(Ops, ComponentCountRegs);
+
+ Register DefReg = Ctx.GR->getDebugValue(ArrayTy);
+ Register DebugArrayTypeReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeArray, Ops, Ctx,
+ HasForwardRef, DefReg);
+
+ Ctx.GR->addDebugValue(ArrayTy, DebugArrayTypeReg);
+ Ctx.CompositeTypeRegPairs.emplace_back(ArrayTy, DebugArrayTypeReg);
}
- return true;
}
-bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
- bool Res = false;
- // emitGlobalDI needs to be executed only once to avoid
- // emitting duplicates
- if (!IsGlobalDIEmitted) {
- IsGlobalDIEmitted = true;
- Res = emitGlobalDI(MF);
+void SPIRVEmitNonSemanticDI::emitDebugVectorTypes(DICompositeType *ArrayTy,
+ Register BaseTypeReg,
+ SPIRVCodeGenContext &Ctx) {
+ DINodeArray Subranges = ArrayTy->getElements();
+ Register ComponentCountReg;
+ if (auto *SR = dyn_cast<DISubrange>(Subranges[0])) {
+ auto CountValUnion = SR->getCount();
+ if (auto *CountCI = CountValUnion.dyn_cast<ConstantInt *>()) {
+ uint64_t CountVal = CountCI->getZExtValue();
+ ComponentCountReg = Ctx.GR->buildConstantInt(CountVal, Ctx.MIRBuilder,
+ Ctx.I32Ty, false, false);
+ } else {
+ ComponentCountReg =
+ Ctx.GR->buildConstantInt(0, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ }
}
- return Res;
+
+ SmallVector<Register, 4> Ops;
+ Ops.push_back(BaseTypeReg);
+ Ops.push_back(ComponentCountReg);
+
+ [[maybe_unused]]
+ Register DebugVectorTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypeVector, Ops, Ctx, false);
+}
+
+void SPIRVEmitNonSemanticDI::emitAllTemplateDebugInstructions(
+ const SmallPtrSetImpl<const DICompositeType *> &TemplatedTypes,
+ SPIRVCodeGenContext &Ctx) {
+ for (const DICompositeType *CompTy : TemplatedTypes) {
+ const DINodeArray TemplateParams = CompTy->getTemplateParams();
+ if (TemplateParams.empty())
+ continue;
+ Register DebugSourceReg =
+ findRegisterFromMap(CompTy->getFile(), Ctx.SourceRegPairs);
+ Register LineReg = Ctx.GR->buildConstantInt(
+ CompTy->getLine(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register ColumnReg =
+ Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ SmallVector<Register, 4> ParamRegs;
+ bool HasForwardRef = false;
+
+ for (const auto *MD : TemplateParams) {
+ Register TypeReg;
+ bool ParamHasForwardRef = false;
+
+ if (auto *TTP = dyn_cast<DITemplateTypeParameter>(MD)) {
+ TypeReg = findBaseTypeRegisterRecursive(TTP->getType(), Ctx,
+ ParamHasForwardRef);
+
+ if (!TypeReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find type for DITemplateTypeParameter: "
+ << TTP->getName() << "\n";
+ TypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ ParamHasForwardRef = false;
+ }
+ if (ParamHasForwardRef)
+ HasForwardRef = true;
+
+ Register NameStr = EmitOpString(TTP->getName(), Ctx);
+ Register NoneReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+
+ ParamRegs.push_back(EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypeTemplateParameter,
+ {NameStr, TypeReg, NoneReg, DebugSourceReg, LineReg, ColumnReg},
+ Ctx, ParamHasForwardRef));
+
+ } else if (auto *TVP = dyn_cast<DITemplateValueParameter>(MD)) {
+ Register NameStr = EmitOpString(TVP->getName(), Ctx);
+ TypeReg =
+ findEmittedBasicTypeReg(TVP->getType(), Ctx.BasicTypeRegPairs);
+ if (!TypeReg.isValid()) {
+ bool TVPTypeForwardRef = false;
+ TypeReg = findBaseTypeRegisterRecursive(TVP->getType(), Ctx,
+ TVPTypeForwardRef);
+ if (TVPTypeForwardRef)
+ HasForwardRef = true;
+ }
+
+ if (!TypeReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find type for DITemplateValueParameter: "
+ << TVP->getName() << "\n";
+ TypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ }
+
+ int64_t ActualValue = 0;
+ if (auto *CAM = dyn_cast_or_null<ConstantAsMetadata>(TVP->getValue())) {
+ if (auto *CI = dyn_cast<ConstantInt>(CAM->getValue())) {
+ ActualValue = CI->getSExtValue();
+ }
+ }
+ Register ValueReg = Ctx.GR->buildConstantInt(
+ ActualValue, Ctx.MIRBuilder, Ctx.I32Ty, false);
+ ParamRegs.push_back(EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypeTemplateParameter,
+ {NameStr, TypeReg, ValueReg, DebugSourceReg, LineReg, ColumnReg},
+ Ctx, false));
+ }
+ }
+
+ Register CompositeReg = Ctx.GR->getDebugValue(CompTy);
+ if (!CompositeReg.isValid()) {
+ llvm::errs() << "Missing DebugTypeComposite for templated type: "
+ << CompTy->getName() << "\n";
+ CompositeReg = Ctx.MRI.createVirtualRegister(&SPIRV::IDRegClass);
+ Ctx.MRI.setType(CompositeReg, LLT::scalar(32));
+ Ctx.GR->markAsForwardPlaceholder(CompositeReg);
+ Ctx.GR->addDebugValue(CompTy, CompositeReg);
+ } else if (Ctx.GR->isForwardPlaceholder(CompositeReg)) {
+ HasForwardRef = true;
+ }
+ ParamRegs.insert(ParamRegs.begin(), CompositeReg);
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeTemplate, ParamRegs,
+ Ctx, HasForwardRef);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitAllDebugTypeComposites(
+ const SmallPtrSetImpl<const DICompositeType *> &CompositeTypes,
+ SPIRVCodeGenContext &Ctx) {
+
+ for (auto *CT : CompositeTypes) {
+ emitDebugTypeComposite(CT, Ctx);
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugTypeComposite(
+ const DICompositeType *CompTy, SPIRVCodeGenContext &Ctx) {
+
+ if (!CompTy)
+ return;
+
+ Register NameStr = EmitOpString(CompTy->getName(), Ctx);
+ Register LinkageNameStr = EmitOpString(CompTy->getIdentifier(), Ctx);
+ uint32_t Tag = mapTagToCompositeEncoding(CompTy);
+ Register Tags =
+ Ctx.GR->buildConstantInt(Tag, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register DebugSourceReg =
+ findRegisterFromMap(CompTy->getFile(), Ctx.SourceRegPairs);
+ Register CURegLocal = Ctx.GR->getDebugValue(CompTy->getFile());
+ Register Line = Ctx.GR->buildConstantInt(CompTy->getLine(), Ctx.MIRBuilder,
+ Ctx.I32Ty, false, false);
+ Register Column =
+ Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register SizeReg = Ctx.GR->buildConstantInt(
+ CompTy->getSizeInBits(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ uint32_t Flags = transDebugFlags(CompTy);
+ Register FlagsReg =
+ Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ Register DefReg = Ctx.GR->getDebugValue(CompTy);
+ SmallVector<Register, 4> MemberRegs;
+ bool HasForwardRef = false;
+
+ for (Metadata *El : CompTy->getElements()) {
+ if (auto *DTM = dyn_cast<DIDerivedType>(El)) {
+ emitDebugTypeMember(DTM, Ctx, DefReg, MemberRegs, DebugSourceReg);
+
+ if (Ctx.GR->isForwardPlaceholder(MemberRegs.back()))
+ HasForwardRef = true;
+ }
+ }
+
+ SmallVector<Register, 12> Ops = {NameStr, Tags, DebugSourceReg,
+ Line, Column, CURegLocal,
+ LinkageNameStr, SizeReg, FlagsReg};
+ Ops.append(MemberRegs);
+ Register Res =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeComposite, Ops, Ctx,
+ HasForwardRef, DefReg);
+ Ctx.GR->addDebugValue(CompTy, Res);
+ Ctx.CompositeTypeRegPairs.emplace_back(CompTy, Res);
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugTypeMember(
+ const DIDerivedType *Member, SPIRVCodeGenContext &Ctx,
+ const Register &CompositeReg, SmallVectorImpl<Register> &MemberRegs,
+ Register DebugSourceReg) {
+
+ if (!Member || Member->getTag() != dwarf::DW_TAG_member)
+ return;
+
+ Register NameStr = EmitOpString(Member->getName(), Ctx);
+ const DIType *Ty = Member->getBaseType();
+ Register TypeReg;
+ if (isa<DICompositeType>(Ty)) {
+ TypeReg = findEmittedCompositeTypeReg(Ty, Ctx.CompositeTypeRegPairs);
+ } else {
+ TypeReg = findEmittedBasicTypeReg(Ty, Ctx.BasicTypeRegPairs);
+ }
+
+ Register LineReg = Ctx.GR->buildConstantInt(Member->getLine(), Ctx.MIRBuilder,
+ Ctx.I32Ty, false, false);
+ Register ColumnReg =
+ Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register OffsetReg =
+ Ctx.GR->buildConstantInt(1
+ /*Member->getOffsetInBits()*/,
+ Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ Register SizeReg = Ctx.GR->buildConstantInt(
+ Member->getSizeInBits(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+ uint32_t Flags = transDebugFlags(Member);
+ Register FlagsReg =
+ Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+ SmallVector<Register, 10> Ops = {NameStr, TypeReg, DebugSourceReg,
+ LineReg, ColumnReg, OffsetReg,
+ SizeReg, FlagsReg};
+
+ Register MemberReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugTypeMember, Ops, Ctx, false);
+
+ MemberRegs.push_back(MemberReg);
+}
+
+uint32_t
+SPIRVEmitNonSemanticDI::mapTagToCompositeEncoding(const DICompositeType *CT) {
+ switch (CT->getTag()) {
+ case dwarf::DW_TAG_structure_type:
+ return CompositeTypeAttributeEncoding::Struct;
+ case dwarf::DW_TAG_class_type:
+ return CompositeTypeAttributeEncoding::Class;
+ case dwarf::DW_TAG_union_type:
+ return CompositeTypeAttributeEncoding::Union;
+ default:
+ llvm_unreachable("Unknown DWARF tag for DebugTypeComposite");
+ }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugMacroDefs(MachineFunction &MF,
+ SPIRVCodeGenContext &Ctx) {
+
+ DenseMap<StringRef, Register> MacroDefRegs;
+ const DISubprogram *SP = MF.getFunction().getSubprogram();
+ if (!SP)
+ return;
+
+ const DICompileUnit *CU = SP->getUnit();
+ if (!CU)
+ return;
+
+ if (!CU || !CU->getMacros())
+ return;
+ const StringRef FileName =
+ CU->getFile() ? CU->getFile()->getFilename() : "<unknown>";
+
+ std::function<void(const MDNode *)> WalkMacroTree;
+ WalkMacroTree = [&](const MDNode *Node) {
+ if (const auto *Macro = dyn_cast<DIMacro>(Node)) {
+ if (Macro->getMacinfoType() == dwarf::DW_MACINFO_define) {
+ if (Macro->getLine() == 0)
+ return;
+
+ const StringRef Name = Macro->getName();
+ const StringRef Value = Macro->getValue();
+ const unsigned Line = Macro->getLine();
+ const Register SourceStrReg = EmitOpString(FileName, Ctx);
+ const Register LineConstReg =
+ Ctx.GR->buildConstantInt(Line, Ctx.MIRBuilder, Ctx.I32Ty, false);
+ const Register NameStrReg = EmitOpString(Name, Ctx);
+ const Register ValueStrReg = EmitOpString(Value, Ctx);
+
+ [[maybe_unused]] const Register DebugMacroDefReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugMacroDef,
+ {SourceStrReg, LineConstReg, NameStrReg, ValueStrReg}, Ctx, false);
+ MacroDefRegs[Macro->getName()] = DebugMacroDefReg;
+ } else if (Macro->getMacinfoType() == dwarf::DW_MACINFO_undef) {
+ emitDebugMacroUndef(Macro, FileName, Ctx, MacroDefRegs);
+ }
+ } else if (const auto *MacroFile = dyn_cast<DIMacroFile>(Node)) {
+ for (const auto &Child : MacroFile->getElements())
+ WalkMacroTree(Child);
+ }
+ };
+
+ for (const auto &MacroNode : CU->getMacros()->operands()) {
+ if (const auto *MD = dyn_cast<MDNode>(MacroNode.get()))
+ WalkMacroTree(MD);
+ }
+}
+void SPIRVEmitNonSemanticDI::emitDebugMacroUndef(
+ const DIMacro *MacroUndef, StringRef FileName, SPIRVCodeGenContext &Ctx,
+ const DenseMap<StringRef, Register> &MacroDefRegs) {
+
+ const StringRef Name = MacroUndef->getName();
+ const unsigned Line = MacroUndef->getLine();
+ auto It = MacroDefRegs.find(Name);
+ if (It == MacroDefRegs.end())
+ return;
+
+ Register MacroDefReg = It->second;
+ Register SourceStrReg = EmitOpString(FileName, Ctx);
+ Register LineConstReg =
+ Ctx.GR->buildConstantInt(Line, Ctx.MIRBuilder, Ctx.I32Ty, false);
+
+ [[maybe_unused]] Register MacroUndefReg =
+ EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugMacroUndef,
+ {SourceStrReg, LineConstReg, MacroDefReg}, Ctx, false);
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugTypePtrToMember(
+ const SmallPtrSetImpl<DIDerivedType *> &PtrToMemberTypes,
+ SPIRVCodeGenContext &Ctx) {
+ if (!PtrToMemberTypes.empty()) {
+ for (const auto *PtrToMemberType : PtrToMemberTypes) {
+ assert(PtrToMemberType->getTag() == dwarf::DW_TAG_ptr_to_member_type &&
+ "emitDebugTypePtrToMember expects DW_TAG_ptr_to_member_type");
+ bool OpHasForwardRef = false;
+ const DIType *BaseTy = PtrToMemberType->getBaseType();
+ bool MemberTypeIsFwd = false;
+ Register MemberTypeReg =
+ findBaseTypeRegisterRecursive(BaseTy, Ctx, MemberTypeIsFwd);
+ if (!MemberTypeReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find Member Type for PtrToMember.\n";
+ MemberTypeReg = EmitDIInstruction(
+ SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+ MemberTypeIsFwd = false;
+ }
+ if (MemberTypeIsFwd)
+ OpHasForwardRef = true;
+ const DIType *ClassTy = PtrToMemberType->getClassType();
+ bool ParentTypeIsFwd = false;
+ Register ParentReg =
+ findBaseTypeRegisterRecursive(ClassTy, Ctx, ParentTypeIsFwd);
+ if (!ParentReg.isValid()) {
+ llvm::errs()
+ << "Warning: Could not find Parent Type for PtrToMember.\n";
+ ParentReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+ {}, Ctx, false);
+ ParentTypeIsFwd = false;
+ }
----------------
MrSidims wrote:
Misuse of DebugInfoNone
https://github.com/llvm/llvm-project/pull/165302
More information about the llvm-commits
mailing list