[llvm] [SPIRV] Addition of extension SPV_KHR_non_semantic_info and SPV_KHR_relaxed_extended_instruction (PR #165302)

Dmitry Sidorov via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 7 03:22:58 PST 2025


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

Misuse of DebugInfoNone

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


More information about the llvm-commits mailing list