[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
Mon Nov 10 04:05:41 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;
+ }
----------------
MrSidims wrote:
We can leave it as `DebugInfoNone`.
https://github.com/llvm/llvm-project/pull/165302
More information about the llvm-commits
mailing list