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

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 24 06:49:29 PDT 2024


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

>From 598ea9e697d111fe2690af518376f711f99d2265 Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Thu, 24 Oct 2024 11:56:28 +0200
Subject: [PATCH 1/2] [SPIR-V] Implementation of DebugLine for DI

---
 .../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp   | 677 ++++++++++++------
 .../SPIRV/debug-info/debug-type-pointer.ll    |  32 +-
 2 files changed, 473 insertions(+), 236 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index d3e323efaee91b..b0ae0abe4928fa 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -5,17 +5,15 @@
 #include "SPIRVRegisterInfo.h"
 #include "SPIRVTargetMachine.h"
 #include "SPIRVUtils.h"
-#include "llvm/ADT/SmallPtrSet.h"
+
 #include "llvm/ADT/SmallString.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/Register.h"
 #include "llvm/IR/DebugInfoMetadata.h"
@@ -28,9 +26,9 @@
 #define DEBUG_TYPE "spirv-nonsemantic-debug-info"
 
 namespace llvm {
-struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
+struct SPIRVEmitNonSemanticDI : MachineFunctionPass {
   static char ID;
-  SPIRVTargetMachine *TM;
+  SPIRVTargetMachine *TM = nullptr;
   SPIRVEmitNonSemanticDI(SPIRVTargetMachine *TM);
   SPIRVEmitNonSemanticDI();
 
@@ -38,7 +36,8 @@ struct SPIRVEmitNonSemanticDI : public MachineFunctionPass {
 
 private:
   bool IsGlobalDIEmitted = false;
-  bool emitGlobalDI(MachineFunction &MF);
+  bool emitGlobalDI(MachineFunction &MF, const Module *M) const;
+  //bool emitLineDI(MachineFunction &MF);
 };
 } // namespace llvm
 
@@ -63,6 +62,9 @@ SPIRVEmitNonSemanticDI::SPIRVEmitNonSemanticDI() : MachineFunctionPass(ID) {
   initializeSPIRVEmitNonSemanticDIPass(*PassRegistry::getPassRegistry());
 }
 
+
+namespace {
+
 enum BaseTypeAttributeEncoding {
   Unspecified = 0,
   Address = 1,
@@ -90,149 +92,315 @@ 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 {
+  Null = 0,
+  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());
-      }
-    }
-    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();
-    }
+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;
+  }
+};
 
-    // 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()));
-              }
-            }
-          }
-        }
-      }
+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;
+};
+
+struct DebugInfoNone;
+
+template <typename T> struct DebugTypeContainer;
+
+template <> struct DebugTypeContainer<int64_t> {
+  static constexpr TypesMapping TM = PrimitiveIntArray;
+  static SmallVector<int64_t> Value;
+  static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<StringRef> {
+  static constexpr TypesMapping TM = PrimitiveStringArray;
+  static SmallVector<StringRef> Value;
+  static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugSource> {
+  static constexpr TypesMapping TM = DebugSourceArray;
+  static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+      SPIRV::NonSemanticExtInst::DebugSource;
+  static SmallVector<DebugSource> Value;
+  static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugCompilationUnit> {
+  static constexpr TypesMapping TM = DebugCompilationUnitArray;
+  static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+      SPIRV::NonSemanticExtInst::DebugCompilationUnit;
+  static SmallVector<DebugCompilationUnit> Value;
+  static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugTypeBasic> {
+  static constexpr TypesMapping TM = DebugTypeBasicArray;
+  static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+      SPIRV::NonSemanticExtInst::DebugTypeBasic;
+  static SmallVector<DebugTypeBasic> Value;
+  static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugTypePointer> {
+  static constexpr TypesMapping TM = DebugTypePointerArray;
+  static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+      SPIRV::NonSemanticExtInst::DebugTypePointer;
+  static SmallVector<DebugTypePointer> Value;
+  static SmallVector<size_t> Back;
+};
+
+template <> struct DebugTypeContainer<DebugInfoNone> {
+  static constexpr TypesMapping TM = DebugInfoNoneArray;
+  static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+      SPIRV::NonSemanticExtInst::DebugInfoNone;
+};
+
+SmallVector<int64_t> DebugTypeContainer<int64_t>::Value;
+SmallVector<StringRef> DebugTypeContainer<StringRef>::Value;
+SmallVector<DebugSource> DebugTypeContainer<DebugSource>::Value;
+SmallVector<DebugCompilationUnit>
+    DebugTypeContainer<DebugCompilationUnit>::Value;
+SmallVector<DebugTypeBasic> DebugTypeContainer<DebugTypeBasic>::Value;
+SmallVector<DebugTypePointer> DebugTypeContainer<DebugTypePointer>::Value;
+
+SmallVector<size_t> DebugTypeContainer<int64_t>::Back;
+SmallVector<size_t> DebugTypeContainer<StringRef>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugSource>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugCompilationUnit>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugTypeBasic>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugTypePointer>::Back;
+
+SmallVector<Register> Registers;
+SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
+
+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 = 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 (auto Id : Ids) {
+    MIB.addUse(Registers[Id]);
+  }
+  MIB.constrainAllUses(*TII, *TRI, *RBI);
+  GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MIRBuilder.getMF());
+  return InstReg;
+}
+
+template <typename T>
+std::pair<size_t, bool> helper(T Val, SmallVectorImpl<T> &SV) {
+  for (unsigned Idx = 0; Idx < SV.size(); ++Idx) {
+    if (Val == SV[Idx]) {
+      return {Idx, true};
     }
   }
-  // NonSemantic.Shader.DebugInfo.100 global DI instruction emitting
-  {
-    // Required LLVM variables for emitting logic
-    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;
-        };
+  SV.emplace_back(Val);
+  return {SV.size() - 1, false};
+}
+
+size_t push(const int64_t Val, MachineIRBuilder &MIRBuilder,
+            const SPIRVTargetMachine *TM) {
+  auto &SV = DebugTypeContainer<int64_t>::Value;
+  const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+  if (IsDuplicate) {
+    return DebugTypeContainer<int64_t>::Back[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));
+  DebugTypeContainer<int64_t>::Back.emplace_back(Instructions.size() - 1);
+  return Instructions.size() - 1;
+}
+
+size_t push(const StringRef Val, MachineIRBuilder &MIRBuilder) {
+  auto &SV = DebugTypeContainer<StringRef>::Value;
+  const auto [ConcreteIdx, IsDuplicate] = helper(Val, SV);
+  if (IsDuplicate) {
+    return DebugTypeContainer<StringRef>::Back[ConcreteIdx];
+  }
+  Instructions.emplace_back(DebugTypeContainer<StringRef>::TM, ConcreteIdx);
+  Registers.emplace_back(emitOpString(Val, MIRBuilder));
+  DebugTypeContainer<StringRef>::Back.emplace_back(Instructions.size() - 1);
+  return Instructions.size() - 1;
+}
 
-    const SPIRVType *I32Ty =
-        GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder);
+template <typename T>
+constexpr size_t push(ArrayRef<size_t> Args, MachineIRBuilder &MIRBuilder,
+                      const SPIRVTargetMachine *TM) {
+  auto &SV = DebugTypeContainer<T>::Value;
+  const auto [ConcreteIdx, IsDuplicate] = helper(T(Args), SV);
+  if (IsDuplicate) {
+    return DebugTypeContainer<T>::Back[ConcreteIdx];
+  }
+  Instructions.emplace_back(DebugTypeContainer<T>::TM, ConcreteIdx);
+  Registers.emplace_back(
+      emitDIInstruction(DebugTypeContainer<T>::Inst, Args, MIRBuilder, TM));
+  DebugTypeContainer<T>::Back.emplace_back(Instructions.size() - 1);
+  return Instructions.size() - 1;
+}
 
-    const Register DwarfVersionReg =
-        GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
+template <>
+size_t push<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 DebugInfoVersionReg =
-        GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
+size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
+                                 const SPIRVTargetMachine *TM) {
+  // TODO: Initialize assholes
+  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 = push(DwarfVersion, MIRBuilder, TM);
+    } else if (MaybeStrOp.equalsStr("Debug Info Version")) {
+      const int64_t DebugInfoVersion =
+          cast<ConstantInt>(
+              cast<ConstantAsMetadata>(Op->getOperand(2))->getValue())
+              ->getSExtValue();
+      DebugInfoVersionId = push(DebugInfoVersion, MIRBuilder, TM);
+    }
+  }
 
-    for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {
-      const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);
+  const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
+  for (const auto *Op : DbgCu->operands()) {
+    if (const auto *CompileUnit = dyn_cast<DICompileUnit>(Op)) {
+      const DIFile *File = CompileUnit->getFile();
+      SmallString<128> FilePath;
+      sys::path::append(FilePath, File->getDirectory(), File->getFilename());
 
-      const Register DebugSourceResIdReg = EmitDIInstruction(
-          SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
+      const size_t FilePathId = push(StringRef(FilePath.c_str()), MIRBuilder);
+      const size_t DebugSourceId =
+          push<DebugSource>({FilePathId}, MIRBuilder, TM);
 
-      SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
-      switch (LLVMSourceLanguages[Idx]) {
+      SourceLanguage SpirvSourceLanguage;
+      switch (CompileUnit->getSourceLanguage()) {
       case dwarf::DW_LANG_OpenCL:
         SpirvSourceLanguage = SourceLanguage::OpenCL_C;
         break;
@@ -253,99 +421,141 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
         break;
       case dwarf::DW_LANG_Zig:
         SpirvSourceLanguage = SourceLanguage::Zig;
+        break;
+      default:
+        SpirvSourceLanguage = SourceLanguage::Unknown;
       }
 
-      const Register SourceLanguageReg =
-          GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false);
-
-      [[maybe_unused]]
-      const Register DebugCompUnitResIdReg =
-          EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
-                            {DebugInfoVersionReg, DwarfVersionReg,
-                             DebugSourceResIdReg, SourceLanguageReg});
+      size_t SpirvSourceLanguageId = push(SpirvSourceLanguage, MIRBuilder, TM);
+      push<DebugCompilationUnit>({DebugInfoVersionId.value(), DwarfVersionId.value(),
+                                  DebugSourceId, SpirvSourceLanguageId},
+                                 MIRBuilder, TM);
     }
+  }
+  return 0;
+}
 
-    // 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);
-
-    // 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;
-      }
+size_t emitDebugTypeBasic(const DIBasicType *BT, size_t I32ZeroIdx,
+                          MachineIRBuilder &MIRBuilder,
+                          const SPIRVTargetMachine *TM) {
+
+  const size_t BasicTypeStrId = push(BT->getName(), MIRBuilder);
+
+  const size_t ConstIntBitWidthId = push(BT->getSizeInBits(), MIRBuilder, TM);
+
+  uint64_t AttributeEncoding;
+  switch (BT->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;
+    break;
+  default:
+    AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
+  }
 
-      const Register AttributeEncodingReg =
-          GR->buildConstantInt(AttributeEncoding, MIRBuilder, I32Ty, false);
+  const size_t AttributeEncodingId = push(AttributeEncoding, MIRBuilder, TM);
 
-      const Register BasicTypeReg =
-          EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeBasic,
-                            {BasicTypeStrReg, ConstIntBitwidthReg,
-                             AttributeEncodingReg, I32ZeroReg});
-      BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);
-    }
+  return push<DebugTypeBasic>(
+      {BasicTypeStrId, ConstIntBitWidthId, AttributeEncodingId, I32ZeroIdx},
+      MIRBuilder, TM);
+}
+
+size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t BasicTypeIdx,
+                            const size_t I32ZeroIdx,
+                            MachineIRBuilder &MIRBuilder,
+                            const SPIRVTargetMachine *TM) {
+  assert(DT->getDWARFAddressSpace().has_value());
+
+  size_t StorageClassIdx =
+      push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+                                      *TM->getSubtargetImpl()),
+           MIRBuilder, TM);
+
+  return push<DebugTypePointer>({BasicTypeIdx, StorageClassIdx, I32ZeroIdx},
+                                MIRBuilder, TM);
+}
 
-    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 =
-            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});
+size_t emitDebugTypePointer(const DIDerivedType *DT, const size_t I32ZeroIdx,
+                            MachineIRBuilder &MIRBuilder,
+                            const SPIRVTargetMachine *TM) {
+  assert(DT->getDWARFAddressSpace().has_value());
+
+  size_t StorageClassIdx =
+      push(addressSpaceToStorageClass(DT->getDWARFAddressSpace().value(),
+                                      *TM->getSubtargetImpl()),
+           MIRBuilder, TM);
+
+  // If the Pointer is representing a void type it's getBaseType
+  // is a nullptr
+  size_t DebugInfoNoneIdx = push<DebugInfoNone>({}, MIRBuilder, TM);
+  return push<DebugTypePointer>({DebugInfoNoneIdx, StorageClassIdx, I32ZeroIdx},
+                                MIRBuilder, TM);
+}
+} // namespace
+
+bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
+                                          const Module *M) const {
+  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());
+
+  emitDebugCompilationUnits(M, MIRBuilder, TM);
+
+  for (auto &F : *M) {
+    for (auto &BB : F) {
+      for (auto &I : BB) {
+        for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) {
+          const DILocalVariable *LocalVariable = DVR.getVariable();
+          if (const auto *BasicType =
+                  dyn_cast<DIBasicType>(LocalVariable->getType())) {
+            // We aren't extracting any DebugInfoFlags now so we're
+            // emitting zero to use as <id>Flags argument for DebugBasicType
+            const size_t I32ZeroIdx = push(0, MIRBuilder, TM);
+            emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM);
+            continue;
+          }
+          // Beware else if here. Types from previous scopes are
+          // counterintuitively still visible for the next ifs scopes.
+          if (const auto *DerivedType =
+                  dyn_cast<DIDerivedType>(LocalVariable->getType())) {
+            if (DerivedType->getTag() == dwarf::DW_TAG_pointer_type) {
+              const size_t I32ZeroIdx = push(0, MIRBuilder, TM);
+              // 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()) {
+                const auto *BasicType =
+                    cast<DIBasicType>(DerivedType->getBaseType());
+                const size_t BTIdx =
+                    emitDebugTypeBasic(BasicType, I32ZeroIdx, MIRBuilder, TM);
+                emitDebugTypePointer(DerivedType, BTIdx, I32ZeroIdx, MIRBuilder,
+                                     TM);
+              } else {
+                emitDebugTypePointer(DerivedType, I32ZeroIdx, MIRBuilder, TM);
+              }
             }
           }
-        } else {
-          const Register DebugInfoNoneReg =
-              EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone, {});
-          [[maybe_unused]]
-          const Register DebugPointerTypeReg = EmitDIInstruction(
-              SPIRV::NonSemanticExtInst::DebugTypePointer,
-              {DebugInfoNoneReg, StorageClassReg, I32ZeroReg});
         }
       }
     }
@@ -353,13 +563,34 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
   return true;
 }
 
+// bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
+//   for (auto &MBB : MF) {
+//     for (auto &MI : MBB) {
+//       if (MI.isDebugValue()) {
+//         DebugLoc DL = MI.getDebugLoc();
+//       }
+//     }
+//   }
+//   return false;
+// }
+
 bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
   bool Res = false;
   // emitGlobalDI needs to be executed only once to avoid
   // emitting duplicates
   if (!IsGlobalDIEmitted) {
+    if (MF.begin() == MF.end()) {
+      return false;
+    }
     IsGlobalDIEmitted = true;
-    Res = emitGlobalDI(MF);
+    const MachineModuleInfo &MMI =
+        getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+    const Module *M = MMI.getModule();
+    const NamedMDNode *DbgCu = M->getNamedMetadata("llvm.dbg.cu");
+    if (!DbgCu)
+      return false;
+    Res = emitGlobalDI(MF, M);
   }
+  // Res |= emitLineDI(MF);
   return Res;
 }
diff --git a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
index b7e6e95f366cf7..d9ef3f59da3577 100644
--- a/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
+++ b/llvm/test/CodeGen/SPIRV/debug-info/debug-type-pointer.ll
@@ -28,19 +28,22 @@
 ; CHECK-MIR-DAG:   [[float:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_float]], [[i32_0]]
 ; CHECK-MIR-DAG:   [[double:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_64]], [[enc_float]], [[i32_0]]
 ; CHECK-MIR-DAG:   [[int:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 2, {{%[0-9]+\:[a-z0-9\(\)]+}}, [[i32_32]], [[enc_signed]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[bool]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[short]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[char]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[long]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[unsigned_int]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[unsigned_short]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[unsigned_char]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[unsigned_long]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[float]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[double]], [[i32_8]], [[i32_0]]
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[int]], [[i32_5]], [[i32_0]]
-; CHECK-MIR:   [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 0
-; CHECK-MIR:   OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[bool]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[short]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[char]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[long]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[unsigned_int]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[unsigned_short]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[unsigned_char]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[unsigned_long]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[float]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[double]], [[i32_8]], [[i32_0]]
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[int]], [[i32_5]], [[i32_0]]
+; CHECK-MIR-DAG:   [[debug_info_none:%[0-9]+\:id\(s32\)]] = OpExtInst [[void_type]], 3, 0
+; CHECK-MIR-DAG:   OpExtInst [[void_type]], 3, 3, [[debug_info_none]], [[i32_5]], [[i32_0]]
+
+; Duplicates check
+; CHECK-MIR-NOT:   OpExtInst [[void_type]], 3, 3
 
 ; CHECK-SPIRV:	[[i32type:%[0-9]+]] = OpTypeInt 32 0
 ; CHECK-SPIRV-DAG:	[[i32_8:%[0-9]+]] = OpConstant [[i32type]] 8
@@ -79,6 +82,9 @@
 ; CHECK-SPIRV-DAG:	[[debug_info_none:%[0-9]+]] = OpExtInst {{%[0-9]+ %[0-9]+}} DebugInfoNone
 ; CHECK-SPIRV-DAG:	OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypePointer [[debug_info_none]] [[i32_5]] [[i32_0]]
 
+; Duplicates check
+; CHECK-SPIRV-NOT:  OpExtInst {{%[0-9]+ %[0-9]+}} DebugTypePointer
+
 ; CHECK-OPTION-NOT: DebugTypePointer
 
 @gi0 = dso_local addrspace(1) global ptr addrspace(4) null, align 4, !dbg !0

>From 31b5f48d1dd47a510a895d7bac07b99d904c25e4 Mon Sep 17 00:00:00 2001
From: "Wlodarczyk, Bertrand" <bertrand.wlodarczyk at intel.com>
Date: Thu, 24 Oct 2024 15:48:52 +0200
Subject: [PATCH 2/2] Support for DebugLine

---
 .../Target/SPIRV/SPIRVEmitNonSemanticDI.cpp   | 80 ++++++++++++++++---
 1 file changed, 67 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
index b0ae0abe4928fa..0fa698592f57d1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitNonSemanticDI.cpp
@@ -37,7 +37,7 @@ struct SPIRVEmitNonSemanticDI : MachineFunctionPass {
 private:
   bool IsGlobalDIEmitted = false;
   bool emitGlobalDI(MachineFunction &MF, const Module *M) const;
-  //bool emitLineDI(MachineFunction &MF);
+  bool emitLineDI(MachineFunction &MF);
 };
 } // namespace llvm
 
@@ -187,6 +187,19 @@ struct DebugLine {
   size_t LineEndId;
   size_t ColumnStartId;
   size_t ColumnEndId;
+
+  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;
@@ -243,6 +256,14 @@ template <> struct DebugTypeContainer<DebugInfoNone> {
       SPIRV::NonSemanticExtInst::DebugInfoNone;
 };
 
+template <> struct DebugTypeContainer<DebugLine> {
+  static constexpr TypesMapping TM = DebugLineArray;
+  static constexpr SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst =
+      SPIRV::NonSemanticExtInst::DebugLine;
+  static SmallVector<DebugLine> Value;
+  static SmallVector<size_t> Back;
+};
+
 SmallVector<int64_t> DebugTypeContainer<int64_t>::Value;
 SmallVector<StringRef> DebugTypeContainer<StringRef>::Value;
 SmallVector<DebugSource> DebugTypeContainer<DebugSource>::Value;
@@ -250,6 +271,7 @@ SmallVector<DebugCompilationUnit>
     DebugTypeContainer<DebugCompilationUnit>::Value;
 SmallVector<DebugTypeBasic> DebugTypeContainer<DebugTypeBasic>::Value;
 SmallVector<DebugTypePointer> DebugTypeContainer<DebugTypePointer>::Value;
+SmallVector<DebugLine> DebugTypeContainer<DebugLine>::Value;
 
 SmallVector<size_t> DebugTypeContainer<int64_t>::Back;
 SmallVector<size_t> DebugTypeContainer<StringRef>::Back;
@@ -257,6 +279,7 @@ SmallVector<size_t> DebugTypeContainer<DebugSource>::Back;
 SmallVector<size_t> DebugTypeContainer<DebugCompilationUnit>::Back;
 SmallVector<size_t> DebugTypeContainer<DebugTypeBasic>::Back;
 SmallVector<size_t> DebugTypeContainer<DebugTypePointer>::Back;
+SmallVector<size_t> DebugTypeContainer<DebugLine>::Back;
 
 SmallVector<Register> Registers;
 SmallVector<std::pair<TypesMapping, unsigned>> Instructions;
@@ -365,9 +388,33 @@ size_t push<DebugInfoNone>(ArrayRef<size_t>, MachineIRBuilder &MIRBuilder,
   return DebugInfoNoneIdx.value();
 }
 
+void cleanup() {
+  DebugTypeContainer<int64_t>::Value.clear();
+  DebugTypeContainer<StringRef>::Value.clear();
+  DebugTypeContainer<DebugSource>::Value.clear();
+  DebugTypeContainer<DebugCompilationUnit>::Value.clear();
+  DebugTypeContainer<DebugTypeBasic>::Value.clear();
+  DebugTypeContainer<DebugTypePointer>::Value.clear();
+  DebugTypeContainer<DebugLine>::Value.clear();
+
+  DebugTypeContainer<int64_t>::Back.clear();
+  DebugTypeContainer<StringRef>::Back.clear();
+  DebugTypeContainer<DebugSource>::Back.clear();
+  DebugTypeContainer<DebugCompilationUnit>::Back.clear();
+  DebugTypeContainer<DebugTypeBasic>::Back.clear();
+  DebugTypeContainer<DebugTypePointer>::Back.clear();
+  DebugTypeContainer<DebugLine>::Back.clear();
+}
+
+size_t emitDebugSource(const DIFile *File, MachineIRBuilder &MIRBuilder, SPIRVTargetMachine *TM) {
+  SmallString<128> FilePath;
+  sys::path::append(FilePath, File->getDirectory(), File->getFilename());
+  const size_t FilePathId = push(StringRef(FilePath.c_str()), MIRBuilder);
+  return push<DebugSource>({FilePathId}, MIRBuilder, TM);
+}
+
 size_t emitDebugCompilationUnits(const Module *M, MachineIRBuilder &MIRBuilder,
                                  const SPIRVTargetMachine *TM) {
-  // TODO: Initialize assholes
   std::optional<size_t> DwarfVersionId = std::nullopt;
   std::optional<size_t> DebugInfoVersionId = std::nullopt;
   const NamedMDNode *ModuleFlags = M->getNamedMetadata("llvm.module.flags");
@@ -563,16 +610,22 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF,
   return true;
 }
 
-// bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
-//   for (auto &MBB : MF) {
-//     for (auto &MI : MBB) {
-//       if (MI.isDebugValue()) {
-//         DebugLoc DL = MI.getDebugLoc();
-//       }
-//     }
-//   }
-//   return false;
-// }
+bool SPIRVEmitNonSemanticDI::emitLineDI(MachineFunction &MF) {
+  for (auto &MBB : MF) {
+    for (auto &MI : MBB) {
+      if (MI.isDebugValue()) {
+        MachineIRBuilder MIRBuilder(MBB, MI);
+        DebugLoc DL = MI.getDebugLoc();
+        const auto *File = cast<DISubprogram>(DL.getScope())->getFile();
+        const size_t ScopeIdx = emitDebugSource(File, MIRBuilder, TM);
+        const size_t LineIdx = push(DL.getLine(), MIRBuilder, TM);
+        const size_t ColIdx = push(DL.getLine(), MIRBuilder, TM);
+        push<DebugLine>({ScopeIdx, LineIdx, LineIdx, ColIdx, ColIdx}, MIRBuilder, TM);
+      }
+    }
+  }
+  return false;
+}
 
 bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
   bool Res = false;
@@ -591,6 +644,7 @@ bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
       return false;
     Res = emitGlobalDI(MF, M);
   }
-  // Res |= emitLineDI(MF);
+  Res |= emitLineDI(MF);
+  cleanup();
   return Res;
 }



More information about the llvm-commits mailing list