[llvm] [SPIR-V] Implementation of DebugLine for DI (PR #113541)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 7 06:36:24 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");
+  for (const auto *Op : ModuleFlags->operands()) {
+    const MDOperand &MaybeStrOp = Op->getOperand(1);
+    if (MaybeStrOp.equalsStr("Dwarf Version")) {
+      const int64_t DwarfVersion =
+          cast<ConstantInt>(
+              cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+              ->getSExtValue();
+      DwarfVersionId = LR.getOrCreateIdx(DwarfVersion, MIRBuilder, TM);
+    } else if (MaybeStrOp.equalsStr("Debug Info Version")) {
+      const int64_t DebugInfoVersion =
+          cast<ConstantInt>(
+              cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+              ->getSExtValue();
+      DebugInfoVersionId = LR.getOrCreateIdx(DebugInfoVersion, MIRBuilder, TM);
+    }
+  }
+  assert(DwarfVersionId.has_value() && DebugInfoVersionId.has_value());
+  const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
----------------
bwlodarcz wrote:

Presence of DbgCu is checked in `runOnMachineFunction` to evaluate if DI is present so here it should always succeed.

https://github.com/llvm/llvm-project/pull/113541


More information about the llvm-commits mailing list