[llvm] [SPIR-V] Implementation of DebugLine for DI (PR #113541)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 7 06:39:34 PST 2024
================
@@ -90,149 +55,469 @@ enum SourceLanguage {
Zig = 12
};
-bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
- // If this MachineFunction doesn't have any BB repeat procedure
- // for the next
- if (MF.begin() == MF.end()) {
- IsGlobalDIEmitted = false;
- return false;
+enum TypesMapping {
+ PrimitiveIntArray,
+ PrimitiveStringArray,
+ DebugSourceArray,
+ DebugCompilationUnitArray,
+ DebugTypeBasicArray,
+ DebugTypePointerArray,
+ DebugInfoNoneArray,
+ DebugLineArray
+};
+
+struct DebugSource {
+ size_t FileId;
+
+ explicit constexpr DebugSource(const size_t FileId) noexcept
+ : FileId(FileId) {}
+
+ explicit constexpr DebugSource(const ArrayRef<size_t> AR) : FileId(AR[0]) {}
+
+ friend bool operator==(const DebugSource &Lhs, const DebugSource &Rhs) {
+ return Lhs.FileId == Rhs.FileId;
}
+};
- // Required variables to get from metadata search
- LLVMContext *Context;
- SmallVector<SmallString<128>> FilePaths;
- SmallVector<int64_t> LLVMSourceLanguages;
- int64_t DwarfVersion = 0;
- int64_t DebugInfoVersion = 0;
- SmallPtrSet<DIBasicType *, 12> BasicTypes;
- SmallPtrSet<DIDerivedType *, 12> PointerDerivedTypes;
- // Searching through the Module metadata to find nescessary
- // information like DwarfVersion or SourceLanguage
- {
- const MachineModuleInfo &MMI =
- getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
- const Module *M = MMI.getModule();
- Context = &M->getContext();
- const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
- if (!DbgCu)
- return false;
- for (const auto *Op : DbgCu->operands()) {
- if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
- DIFile *File = CompileUnit->getFile();
- FilePaths.emplace_back();
- sys::path::append(FilePaths.back(), File->getDirectory(),
- File->getFilename());
- LLVMSourceLanguages.push_back(CompileUnit->getSourceLanguage());
- }
+struct DebugCompilationUnit {
+ size_t DebugInfoVersionId;
+ size_t DwarfVersionId;
+ size_t DebugSourceId;
+ size_t LanguageId;
+
+ constexpr DebugCompilationUnit(const size_t DebugInfoVersionId,
+ const size_t DwarfVersionId,
+ const size_t DebugSourceId,
+ const size_t LanguageId) noexcept
+ : DebugInfoVersionId(DebugInfoVersionId), DwarfVersionId(DwarfVersionId),
+ DebugSourceId(DebugSourceId), LanguageId(LanguageId) {}
+
+ explicit constexpr DebugCompilationUnit(const ArrayRef<size_t> AR) noexcept
+ : DebugInfoVersionId(AR[0]), DwarfVersionId(AR[1]), DebugSourceId(AR[2]),
+ LanguageId(AR[3]) {}
+
+ friend bool operator==(const DebugCompilationUnit &Lhs,
+ const DebugCompilationUnit &Rhs) {
+ return Lhs.DebugInfoVersionId == Rhs.DebugInfoVersionId &
+ Lhs.DwarfVersionId == Rhs.DwarfVersionId &
+ Lhs.DebugSourceId == Rhs.DebugSourceId &
+ Lhs.LanguageId == Rhs.LanguageId;
+ }
+};
+
+struct DebugTypeBasic {
+ size_t NameId;
+ size_t SizeId;
+ size_t BaseTypeEncodingId;
+ size_t FlagsId;
+
+ explicit constexpr DebugTypeBasic(const ArrayRef<size_t> AR)
+ : NameId(AR[0]), SizeId(AR[1]), BaseTypeEncodingId(AR[2]),
+ FlagsId(AR[3]) {}
+
+ friend bool operator==(const DebugTypeBasic &Lhs, const DebugTypeBasic &Rhs) {
+ return Lhs.NameId == Rhs.NameId && Lhs.SizeId == Rhs.SizeId &&
+ Lhs.BaseTypeEncodingId == Rhs.BaseTypeEncodingId &&
+ Lhs.FlagsId == Rhs.FlagsId;
+ }
+};
+
+struct DebugTypePointer {
+ size_t BaseTypeId;
+ size_t StorageClassId;
+ size_t FlagsId;
+
+ DebugTypePointer(const size_t BaseTypeId, const size_t StorageClassId,
+ const size_t FlagsId) noexcept
+ : BaseTypeId(BaseTypeId), StorageClassId(StorageClassId),
+ FlagsId(FlagsId) {}
+
+ explicit DebugTypePointer(const ArrayRef<size_t> AR) noexcept
+ : BaseTypeId(AR[0]), StorageClassId(AR[1]), FlagsId(AR[2]) {}
+
+ friend bool operator==(const DebugTypePointer &Lhs,
+ const DebugTypePointer &Rhs) {
+ return Lhs.BaseTypeId == Rhs.BaseTypeId &&
+ Lhs.StorageClassId == Rhs.StorageClassId &&
+ Lhs.FlagsId == Rhs.FlagsId;
+ }
+};
+
+struct DebugLine {
+ size_t DebugSourceId;
+ size_t LineStartId;
+ size_t LineEndId;
+ size_t ColumnStartId;
+ size_t ColumnEndId;
+
+ explicit DebugLine(const ArrayRef<size_t> AR)
+ : DebugSourceId(AR[0]), LineStartId(AR[1]), LineEndId(AR[2]),
+ ColumnStartId(AR[3]), ColumnEndId(AR[4]) {}
+
+ friend bool operator==(const DebugLine &Lhs, const DebugLine &Rhs) {
+ return Lhs.DebugSourceId == Rhs.DebugSourceId &&
+ Lhs.LineStartId == Rhs.LineStartId &&
+ Lhs.LineEndId == Rhs.LineEndId &&
+ Lhs.ColumnStartId == Rhs.ColumnStartId &&
+ Lhs.ColumnEndId == Rhs.ColumnEndId;
+ }
+};
+
+struct DebugInfoNone;
+
+template <typename T> struct DebugTypeContainer;
+
+template <> struct DebugTypeContainer<int64_t> {
+ static constexpr TypesMapping TM = PrimitiveIntArray;
+};
+
+template <> struct DebugTypeContainer<StringRef> {
+ static constexpr TypesMapping TM = PrimitiveStringArray;
+};
+
+template <> struct DebugTypeContainer<DebugSource> {
+ static constexpr TypesMapping TM = DebugSourceArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugSource;
+};
+
+template <> struct DebugTypeContainer<DebugCompilationUnit> {
+ static constexpr TypesMapping TM = DebugCompilationUnitArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugCompilationUnit;
+};
+
+template <> struct DebugTypeContainer<DebugTypeBasic> {
+ static constexpr TypesMapping TM = DebugTypeBasicArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugTypeBasic;
+};
+
+template <> struct DebugTypeContainer<DebugTypePointer> {
+ static constexpr TypesMapping TM = DebugTypePointerArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugTypePointer;
+};
+
+template <> struct DebugTypeContainer<DebugInfoNone> {
+ static constexpr TypesMapping TM = DebugInfoNoneArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugInfoNone;
+};
+
+template <> struct DebugTypeContainer<DebugLine> {
+ static constexpr TypesMapping TM = DebugLineArray;
+ static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+ SPIRV::NonSemanticExtInst::DebugLine;
+};
+
+template <typename T> struct DebugLiveContainer {
+ SmallVector<T> Values;
+ SmallVector<size_t> BackIdx;
+};
+/// @class LiveRepository
+/// @brief Container for the connection graph between newly emitted Debug
+/// instructions.
+///
+/// The architecture consists of two tiers:
+/// - The **Main tier**, represented by an array of `Instructions`.
+/// - The **Concrete Type tier**, represented by separate arrays for each
+/// corresponding debug type.
+///
+/// The `Instructions` array contains records that include:
+/// - `Type`: An enum value pointing to the specific debug type array in the
+/// Concrete Type tier.
+/// - `Id`: An index into the corresponding array in the Concrete Type tier.
+///
+/// The class is designed to ensure safe and controlled access to its internal
+/// state. All interactions with the repository are done through the
+/// `getOrCreateIdx` function, which restricts direct manipulation of the
+/// underlying data structures, thus minimizing the risk of memory errors or
+/// logical mistakes.
+///
+/// Users of this class interact exclusively with the indexes of the
+/// `Instructions` array and never directly access the internal concrete type
+/// arrays. This property flattens the instruction access,
+// making it easily retrievable.
+///
+///
+/// getOrCreateIdx() <--+ Iidx
+/// V |
+/// +-------------------------+-+
+/// |[Instructions]--{Cidx,Type}|<----+
+/// +------+--------------+-----+ |
+/// v v |
+/// [PrimitiveType] [ConcreteType_0] |
+/// {Data} {Instruction} |
+/// (i32)(i32) (Iidx) (Iidx) |
+/// | | |
+/// +----+-----+
+///
+/// Class is designed to be easily removable by simply replacing the
+/// `getOrConstructIdx` method with another mechanism.
+class LiveRepository {
+ DebugLiveContainer<int64_t> PrimitiveInts;
+ DebugLiveContainer<StringRef> PrimitiveStrings;
+ DebugLiveContainer<DebugSource> DebugSources;
+ DebugLiveContainer<DebugLine> DebugLines;
+ DebugLiveContainer<DebugCompilationUnit> DebugCompilationUnits;
+ DebugLiveContainer<DebugTypeBasic> DebugTypeBasics;
+ DebugLiveContainer<DebugTypePointer> DebugTypePointers;
+
+ SmallVector<Register> Registers;
+ SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
+
+ template <typename T> constexpr SmallVector<T> &values() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return PrimitiveInts.Values;
+ } else if constexpr (std::is_same_v<T, StringRef>) {
+ return PrimitiveStrings.Values;
+ } else if constexpr (std::is_same_v<T, DebugLine>) {
+ return DebugLines.Values;
+ } else if constexpr (std::is_same_v<T, DebugSource>) {
+ return DebugSources.Values;
+ } else if constexpr (std::is_same_v<T, DebugCompilationUnit>) {
+ return DebugCompilationUnits.Values;
+ } else if constexpr (std::is_same_v<T, DebugTypeBasic>) {
+ return DebugTypeBasics.Values;
+ } else if constexpr (std::is_same_v<T, DebugTypePointer>) {
+ return DebugTypePointers.Values;
}
- const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
- for (const auto *Op : ModuleFlags->operands()) {
- const MDOperand &MaybeStrOp = Op->getOperand(1);
- if (MaybeStrOp.equalsStr("Dwarf Version"))
- DwarfVersion =
- cast<ConstantInt>(
- cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
- ->getSExtValue();
- else if (MaybeStrOp.equalsStr("Debug Info Version"))
- DebugInfoVersion =
- cast<ConstantInt>(
- cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
- ->getSExtValue();
+ llvm_unreachable("unreachable");
+ }
+
+ template <typename T> constexpr SmallVector<size_t> &backIdx() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return PrimitiveInts.BackIdx;
+ } else if constexpr (std::is_same_v<T, StringRef>) {
+ return PrimitiveStrings.BackIdx;
+ } else if constexpr (std::is_same_v<T, DebugLine>) {
+ return DebugLines.BackIdx;
+ } else if constexpr (std::is_same_v<T, DebugSource>) {
+ return DebugSources.BackIdx;
+ } else if constexpr (std::is_same_v<T, DebugCompilationUnit>) {
+ return DebugCompilationUnits.BackIdx;
+ } else if constexpr (std::is_same_v<T, DebugTypeBasic>) {
+ return DebugTypeBasics.BackIdx;
+ } else if constexpr (std::is_same_v<T, DebugTypePointer>) {
+ return DebugTypePointers.BackIdx;
}
+ llvm_unreachable("unreachable");
+ }
- // This traversal is the only supported way to access
- // instruction related DI metadata like DIBasicType
- for (auto &F : *M) {
- for (auto &BB : F) {
- for (auto &I : BB) {
- for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
- DILocalVariable *LocalVariable = DVR.getVariable();
- if (auto *BasicType =
- dyn_cast<DIBasicType>(LocalVariable->getType())) {
- BasicTypes.insert(BasicType);
- } else if (auto *DerivedType =
- dyn_cast<DIDerivedType>(LocalVariable->getType())) {
- if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
- PointerDerivedTypes.insert(DerivedType);
- // DIBasicType can be unreachable from DbgRecord and only
- // pointed on from other DI types
- // DerivedType->getBaseType is null when pointer
- // is representing a void type
- if (DerivedType->getBaseType())
- BasicTypes.insert(
- cast<DIBasicType>(DerivedType->getBaseType()));
- }
- }
- }
- }
+ template <typename T>
+ static std::pair<size_t, bool>
+ emplaceOrReturnDuplicate(T Val, SmallVectorImpl<T> &SV) {
+ for (unsigned Idx = 0; Idx < SV.size(); ++Idx) {
+ if (Val == SV[Idx]) {
+ return {Idx, true};
}
}
+ SV.emplace_back(Val);
+ return {SV.size() - 1, false};
}
- // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
- {
- // Required LLVM variables for emitting logic
+
+ static Register emitOpString(const StringRef SR,
+ MachineIRBuilder &MIRBuilder) {
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+ 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;
+ }
+
+ Register emitDIInstruction(SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
+ const ArrayRef<size_t> Ids,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *const TM) {
const SPIRVInstrInfo *TII = TM->getSubtargetImpl()->getInstrInfo();
const SPIRVRegisterInfo *TRI = TM->getSubtargetImpl()->getRegisterInfo();
const RegisterBankInfo *RBI = TM->getSubtargetImpl()->getRegBankInfo();
SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
- MachineRegisterInfo &MRI = MF.getRegInfo();
- MachineBasicBlock &MBB = *MF.begin();
-
- // To correct placement of a OpLabel instruction during SPIRVAsmPrinter
- // emission all new instructions needs to be placed after OpFunction
- // 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;
- };
-
- const SPIRVType *VoidTy =
- GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder);
-
- 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;
- };
+ MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+ const SPIRVType *VoidTy = GR->getOrCreateSPIRVType(
+ Type::getVoidTy(MIRBuilder.getContext()), MIRBuilder);
+ 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(SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100)
+ .addImm(Inst);
+ for (const auto Idx : Ids) {
+ MIB.addUse(Registers[Idx]);
+ }
+ MIB.constrainAllUses(*TII, *TRI, *RBI);
+ GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MIRBuilder.getMF());
+ return InstReg;
+ }
- const SPIRVType *I32Ty =
- GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
+public:
+ /// @brief Retrieves or creates an index for the int64_t primitive type.
+ ///
+ /// It's backed by OpConstantI instruction.
+ /// It either retrieves an existing index or creates a new one based on the
+ /// provided parameters. The function currently has a linear, cache-friendly
+ /// search time for duplicate entries. It assumes that no single type of
+ /// instruction will become so dominant in the module and every entry of that
+ /// type will be unique.
+ ///
+ /// @param[in] Val A int64_t value to retreive or construct.
+ /// @param[in] MIRBuilder A reference to the `MachineIRBuilder` used for
+ /// constructing IR.
+ /// @param[in] TM A pointer to the target machine (`SPIRVTargetMachine`) used
+ /// for this operation.
+ ///
+ /// @return The index (`size_t`) of the retrieved duplicate or newly created
+ /// entry.
+ ///
+ size_t getOrCreateIdx(const int64_t Val, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ auto &SV = values<int64_t>();
+ const auto [ConcreteIdx, IsDuplicate] = emplaceOrReturnDuplicate(Val, SV);
+ if (IsDuplicate) {
+ return backIdx<int64_t>()[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<int64_t>::TM, ConcreteIdx);
+ SPIRVGlobalRegistry *GR = TM->getSubtargetImpl()->getSPIRVGlobalRegistry();
+ const SPIRVType *I32Ty = GR->getOrCreateSPIRVType(
+ Type::getInt32Ty(MIRBuilder.getContext()), MIRBuilder);
+ Registers.emplace_back(GR->buildConstantInt(Val, MIRBuilder, I32Ty, false));
+ backIdx<int64_t>().emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+ }
- const Register DwarfVersionReg =
- GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
+ /// @brief Retrieves or creates an index for the StringRef primitive type.
+ ///
+ /// It's backed by OpString instruction.
+ /// It either retrieves an existing index or creates a new one based on the
+ /// provided parameters. The function currently has a linear, cache-friendly
+ /// search time for duplicate entries. It assumes that no single type of
+ /// instruction will become so dominant in the module and every entry of that
+ /// type will be unique.
+ ///
+ /// @param[in] Val A StringRef value to retreive or construct.
+ /// @param[in] MIRBuilder A reference to the `MachineIRBuilder` used for
+ /// constructing IR.
+ /// @param[in] TM A pointer to the target machine (`SPIRVTargetMachine`) used
+ /// for this operation.
+ ///
+ /// @return The index (`size_t`) of the retrieved duplicate or newly created
+ /// entry.
+ ///
+ size_t getOrCreateIdx(const StringRef Val, MachineIRBuilder &MIRBuilder) {
+ auto &SV = values<StringRef>();
+ const auto [ConcreteIdx, IsDuplicate] = emplaceOrReturnDuplicate(Val, SV);
+ if (IsDuplicate) {
+ return backIdx<StringRef>()[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<StringRef>::TM, ConcreteIdx);
+ Registers.emplace_back(emitOpString(Val, MIRBuilder));
+ backIdx<StringRef>().emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+ }
- const Register DebugInfoVersionReg =
- GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
+ /// @brief Retrieves or creates an index for the specified type.
+ /// It either retrieves an existing index or creates a new one based on the
+ /// provided parameters. The function currently has a linear, cache-friendly
+ /// search time for duplicate entries. It assumes that no single type of
+ /// instruction will become so dominant in the module and every entry of that
+ /// type will be unique.:w
+ ///
+ /// @tparam T The specific type being used for this instantiation.
+ ///
+ /// @param[in] arrayRef A reference to an array containing indices (of type
+ /// `size_t`).
+ /// @param[in] MIRBuilder A reference to the `MachineIRBuilder` used for
+ /// constructing IR.
+ /// @param[in] TM A pointer to the target machine (`SPIRVTargetMachine`) used
+ /// for this operation.
+ ///
+ /// @return The index (`size_t`) of the retrieved duplicate or newly created
+ /// entry.
+ ///
+ template <typename T>
+ constexpr size_t getOrCreateIdx(ArrayRef<size_t> Args,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ auto &SV = values<T>();
+ const auto [ConcreteIdx, IsDuplicate] =
+ emplaceOrReturnDuplicate(T(Args), SV);
+ if (IsDuplicate) {
+ return backIdx<T>()[ConcreteIdx];
+ }
+ Instructions.emplace_back(DebugTypeContainer<T>::TM, ConcreteIdx);
+ Registers.emplace_back(
+ emitDIInstruction(DebugTypeContainer<T>::Inst, Args, MIRBuilder, TM));
+ backIdx<T>().emplace_back(Instructions.size() - 1);
+ return Instructions.size() - 1;
+ }
+};
- for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {
- const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);
+template <>
+size_t
+LiveRepository::getOrCreateIdx<DebugInfoNone>(ArrayRef<size_t>,
+ MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM) {
+ static std::optional<size_t> DebugInfoNoneIdx = std::nullopt;
+ if (!DebugInfoNoneIdx.has_value()) {
+ Instructions.emplace_back(DebugTypeContainer<DebugInfoNone>::TM, 0);
+ Registers.emplace_back(emitDIInstruction(
+ DebugTypeContainer<DebugInfoNone>::Inst, {}, MIRBuilder, TM));
+ DebugInfoNoneIdx.emplace(Instructions.size() - 1);
+ }
+ return DebugInfoNoneIdx.value();
+}
- const Register DebugSourceResIdReg = EmitDIInstruction(
- SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
+size_t emitDebugSource(const DIFile *File, MachineIRBuilder &MIRBuilder,
+ SPIRVTargetMachine *TM, LiveRepository &LR) {
+ SmallString<128> FilePath;
+ sys::path::append(FilePath, File->getDirectory(), File->getFilename());
+ const size_t FilePathId =
+ LR.getOrCreateIdx(StringRef(FilePath.c_str()), MIRBuilder);
+ return LR.getOrCreateIdx<DebugSource>({FilePathId}, MIRBuilder, TM);
+}
- SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
- switch (LLVMSourceLanguages[Idx]) {
+size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
+ const SPIRVTargetMachine *TM,
+ LiveRepository &LR) {
+ std::optional<size_t> DwarfVersionId = std::nullopt;
+ std::optional<size_t> DebugInfoVersionId = std::nullopt;
+ const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
----------------
bwlodarcz wrote:
In theory yes. The problem is that lack of `llvm.module.flags` means that DI and overall Module metadata is malformed and there is no sensible recover from that. In that case optionals will rise exception or we get segfault - effect is the same.
https://github.com/llvm/llvm-project/pull/113541
More information about the llvm-commits
mailing list