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

Dmitry Sidorov via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 10 04:05:41 PST 2025


================
@@ -175,185 +422,1398 @@ bool SPIRVEmitNonSemanticDI::emitGlobalDI(MachineFunction &MF) {
     // and before first terminator
     MachineIRBuilder MIRBuilder(MBB, MBB.getFirstTerminator());
 
-    const auto EmitOpString = [&](StringRef SR) {
-      const Register StrReg = MRI.createVirtualRegister(&SPIRV::IDRegClass);
-      MRI.setType(StrReg, LLT::scalar(32));
-      MachineInstrBuilder MIB = MIRBuilder.buildInstr(SPIRV::OpString);
-      MIB.addDef(StrReg);
-      addStringImm(SR, MIB);
-      return StrReg;
-    };
+    SmallVector<std::pair<const DIBasicType *const, const Register>, 12>
+        BasicTypeRegPairs;
+    SmallVector<std::pair<const DICompositeType *const, const Register>, 12>
+        CompositeTypeRegPairs;
+    SmallVector<std::pair<const DIFile *const, const Register>, 12>
+        SourceRegPairs;
+    SmallVector<std::pair<const DIScope *const, const Register>, 12>
+        ScopeRegPairs;
+    SmallVector<std::pair<const DISubroutineType *const, const Register>, 12>
+        SubRoutineTypeRegPairs;
 
     const SPIRVType *VoidTy =
         GR->getOrCreateSPIRVType(Type::getVoidTy(*Context), MIRBuilder,
                                  SPIRV::AccessQualifier::ReadWrite, false);
-
-    const auto EmitDIInstruction =
-        [&](SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
-            std::initializer_list<Register> Registers) {
-          const Register InstReg =
-              MRI.createVirtualRegister(&SPIRV::IDRegClass);
-          MRI.setType(InstReg, LLT::scalar(32));
-          MachineInstrBuilder MIB =
-              MIRBuilder.buildInstr(SPIRV::OpExtInst)
-                  .addDef(InstReg)
-                  .addUse(GR->getSPIRVTypeID(VoidTy))
-                  .addImm(static_cast<int64_t>(
-                      SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
-                  .addImm(Inst);
-          for (auto Reg : Registers) {
-            MIB.addUse(Reg);
-          }
-          MIB.constrainAllUses(*TII, *TRI, *RBI);
-          GR->assignSPIRVTypeToVReg(VoidTy, InstReg, MF);
-          return InstReg;
-        };
-
     const SPIRVType *I32Ty =
         GR->getOrCreateSPIRVType(Type::getInt32Ty(*Context), MIRBuilder,
                                  SPIRV::AccessQualifier::ReadWrite, false);
 
+    const Register I32ZeroReg =
+        GR->buildConstantInt(1, MIRBuilder, I32Ty, false);
+
     const Register DwarfVersionReg =
         GR->buildConstantInt(DwarfVersion, MIRBuilder, I32Ty, false);
 
     const Register DebugInfoVersionReg =
         GR->buildConstantInt(DebugInfoVersion, MIRBuilder, I32Ty, false);
 
+    SPIRVCodeGenContext Ctx(MIRBuilder, MRI, GR, VoidTy, I32Ty, TII, TRI, RBI,
+                            MF, I32ZeroReg, TM, SourceRegPairs, ScopeRegPairs,
+                            SubRoutineTypeRegPairs, BasicTypeRegPairs,
+                            CompositeTypeRegPairs);
+
     for (unsigned Idx = 0; Idx < LLVMSourceLanguages.size(); ++Idx) {
-      const Register FilePathStrReg = EmitOpString(FilePaths[Idx]);
-
-      const Register DebugSourceResIdReg = EmitDIInstruction(
-          SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg});
-
-      SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
-      switch (LLVMSourceLanguages[Idx]) {
-      case dwarf::DW_LANG_OpenCL:
-        SpirvSourceLanguage = SourceLanguage::OpenCL_C;
-        break;
-      case dwarf::DW_LANG_OpenCL_CPP:
-        SpirvSourceLanguage = SourceLanguage::OpenCL_CPP;
-        break;
-      case dwarf::DW_LANG_CPP_for_OpenCL:
-        SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL;
-        break;
-      case dwarf::DW_LANG_GLSL:
-        SpirvSourceLanguage = SourceLanguage::GLSL;
-        break;
-      case dwarf::DW_LANG_HLSL:
-        SpirvSourceLanguage = SourceLanguage::HLSL;
-        break;
-      case dwarf::DW_LANG_SYCL:
-        SpirvSourceLanguage = SourceLanguage::SYCL;
-        break;
-      case dwarf::DW_LANG_Zig:
-        SpirvSourceLanguage = SourceLanguage::Zig;
+      emitSingleCompilationUnit(FilePaths[Idx], LLVMSourceLanguages[Idx], Ctx,
+                                DebugInfoVersionReg, DwarfVersionReg,
+                                DebugSourceResIdReg, DebugCompUnitResIdReg);
+
+      if (const DISubprogram *SP = Ctx.MF.getFunction().getSubprogram()) {
+        if (const DIFile *File = SP->getFile())
+          Ctx.GR->addDebugValue(File, DebugCompUnitResIdReg);
+        if (const DICompileUnit *Unit = SP->getUnit())
+          Ctx.GR->addDebugValue(Unit, DebugCompUnitResIdReg);
+      }
+    }
+    emitDebugMacroDefs(MF, Ctx);
+    emitDebugBuildIdentifier(BuildIdentifier, Ctx);
+    emitDebugStoragePath(BuildStoragePath, Ctx);
+    emitDebugBasicTypes(Collector.BasicTypes, Ctx);
+
+    emitSubroutineTypes(Collector.SubRoutineTypes, Ctx);
+    emitSubprograms(Collector.SubPrograms, Ctx);
+    emitLexicalScopes(Collector.LexicalScopes, Ctx);
+    emitDebugPointerTypes(Collector.PointerDerivedTypes, Ctx);
+    emitDebugArrayTypes(Collector.ArrayTypes, Ctx);
+    emitAllDebugTypeComposites(Collector.CompositeTypes, Ctx);
+    emitDebugTypeEnum(Collector.EnumTypes, Ctx);
+    emitAllTemplateDebugInstructions(Collector.CompositeTypesWithTemplates,
+                                     Ctx);
+    emitDebugQualifiedTypes(Collector.QualifiedDerivedTypes, Ctx);
+    emitDebugTypedefs(Collector.TypedefTypes, Ctx);
+    emitDebugTypePtrToMember(Collector.PtrToMemberTypes, Ctx);
+    emitAllDebugGlobalVariables(MF, Ctx);
+    emitDebugImportedEntities(Collector.ImportedEntities, Ctx);
+  }
+  return true;
+}
+
+bool SPIRVEmitNonSemanticDI::runOnMachineFunction(MachineFunction &MF) {
+  bool Res = false;
+  if (!IsGlobalDIEmitted) {
+    IsGlobalDIEmitted = true;
+    Res = emitGlobalDI(MF);
+  }
+  return Res;
+}
+
+Register SPIRVEmitNonSemanticDI::EmitOpString(StringRef SR,
+                                              SPIRVCodeGenContext &Ctx) {
+  const Register StrReg = Ctx.MRI.createVirtualRegister(&SPIRV::IDRegClass);
+  Ctx.MRI.setType(StrReg, LLT::scalar(32));
+  MachineInstrBuilder MIB = Ctx.MIRBuilder.buildInstr(SPIRV::OpString);
+  MIB.addDef(StrReg);
+  addStringImm(SR, MIB);
+  return StrReg;
+}
+
+Register SPIRVEmitNonSemanticDI::EmitDIInstruction(
+    SPIRV::NonSemanticExtInst::NonSemanticExtInst Inst,
+    ArrayRef<Register> Operands, SPIRVCodeGenContext &Ctx, bool HasForwardRef,
+    Register DefReg) {
+
+  Register InstReg = DefReg;
+  if (!InstReg.isValid()) {
+    InstReg = Ctx.MRI.createVirtualRegister(&SPIRV::IDRegClass);
+    Ctx.MRI.setType(InstReg, LLT::scalar(32));
+  }
+
+  unsigned Opcode =
+      HasForwardRef ? SPIRV::OpExtInstWithForwardRefsKHR : SPIRV::OpExtInst;
+  MachineInstrBuilder MIB =
+      Ctx.MIRBuilder.buildInstr(Opcode)
+          .addDef(InstReg)
+          .addUse(Ctx.GR->getSPIRVTypeID(Ctx.VoidTy))
+          .addImm(static_cast<int64_t>(
+              SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100))
+          .addImm(Inst);
+  for (auto Reg : Operands) {
+    MIB.addUse(Reg);
+  }
+  MIB.constrainAllUses(*Ctx.TII, *Ctx.TRI, *Ctx.RBI);
+  Ctx.GR->assignSPIRVTypeToVReg(Ctx.VoidTy, InstReg, Ctx.MF);
+
+  // If we were passed a valid DefReg, it was a placeholder.
+  // Now that we've emitted the instruction that defines it, resolve it.
+  if (DefReg.isValid() && Ctx.GR->isForwardPlaceholder(DefReg))
+    Ctx.GR->resolveForwardPlaceholder(DefReg);
+
+  return InstReg;
+}
+
+uint32_t SPIRVEmitNonSemanticDI::transDebugFlags(const DINode *DN) {
+  uint32_t Flags = 0;
+  if (const DIGlobalVariable *GV = dyn_cast<DIGlobalVariable>(DN)) {
+    if (GV->isLocalToUnit())
+      Flags |= Flag::FlagIsLocal;
+    if (GV->isDefinition())
+      Flags |= Flag::FlagIsDefinition;
+  }
+  if (const DISubprogram *DS = dyn_cast<DISubprogram>(DN)) {
+    if (DS->isLocalToUnit())
+      Flags |= Flag::FlagIsLocal;
+    if (DS->isOptimized())
+      Flags |= Flag::FlagIsOptimized;
+    if (DS->isDefinition())
+      Flags |= Flag::FlagIsDefinition;
+    Flags |= mapDebugFlags(DS->getFlags());
+  }
+  if (DN->getTag() == dwarf::DW_TAG_reference_type)
+    Flags |= Flag::FlagIsLValueReference;
+  if (DN->getTag() == dwarf::DW_TAG_rvalue_reference_type)
+    Flags |= Flag::FlagIsRValueReference;
+  if (const DIType *DT = dyn_cast<DIType>(DN))
+    Flags |= mapDebugFlags(DT->getFlags());
+  if (const DILocalVariable *DLocVar = dyn_cast<DILocalVariable>(DN))
+    Flags |= mapDebugFlags(DLocVar->getFlags());
+
+  return Flags;
+}
+
+uint32_t SPIRVEmitNonSemanticDI::mapDebugFlags(DINode::DIFlags DFlags) {
+  uint32_t Flags = 0;
+  if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPublic)
+    Flags |= Flag::FlagIsPublic;
+  if ((DFlags & DINode::FlagAccessibility) == DINode::FlagProtected)
+    Flags |= Flag::FlagIsProtected;
+  if ((DFlags & DINode::FlagAccessibility) == DINode::FlagPrivate)
+    Flags |= Flag::FlagIsPrivate;
+
+  if (DFlags & DINode::FlagFwdDecl)
+    Flags |= Flag::FlagIsFwdDecl;
+  if (DFlags & DINode::FlagArtificial)
+    Flags |= Flag::FlagIsArtificial;
+  if (DFlags & DINode::FlagExplicit)
+    Flags |= Flag::FlagIsExplicit;
+  if (DFlags & DINode::FlagPrototyped)
+    Flags |= Flag::FlagIsPrototyped;
+  if (DFlags & DINode::FlagObjectPointer)
+    Flags |= Flag::FlagIsObjectPointer;
+  if (DFlags & DINode::FlagStaticMember)
+    Flags |= Flag::FlagIsStaticMember;
+  // inderect variable flag ?
+  if (DFlags & DINode::FlagLValueReference)
+    Flags |= Flag::FlagIsLValueReference;
+  if (DFlags & DINode::FlagRValueReference)
+    Flags |= Flag::FlagIsRValueReference;
+  if (DFlags & DINode::FlagTypePassByValue)
+    Flags |= Flag::FlagTypePassByValue;
+  if (DFlags & DINode::FlagTypePassByReference)
+    Flags |= Flag::FlagTypePassByReference;
+  if (DFlags & DINode::FlagEnumClass)
+    Flags |= Flag::FlagIsEnumClass;
+  return Flags;
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugTypeEnum(
+    const SmallPtrSetImpl<const DICompositeType *> &EnumTypes,
+    SPIRVCodeGenContext &Ctx) {
+  for (auto *EnumTy : EnumTypes) {
+    if (!EnumTy || EnumTy->getTag() != dwarf::DW_TAG_enumeration_type)
+      continue;
+    if (Register Existing = Ctx.GR->getDebugValue(EnumTy); Existing.isValid())
+      continue;
+    Register NameStr = EmitOpString(EnumTy->getName(), Ctx);
+    bool UnderlyingTypeIsFwd = false;
+    Register UnderlyingTypeReg = findBaseTypeRegisterRecursive(
+        EnumTy->getBaseType(), Ctx, UnderlyingTypeIsFwd);
+    if (!UnderlyingTypeReg.isValid()) {
+      UnderlyingTypeReg = EmitDIInstruction(
+          SPIRV::NonSemanticExtInst::DebugInfoNone, {}, Ctx, false);
+      UnderlyingTypeIsFwd = false;
+    }
+    Register SourceReg =
+        findRegisterFromMap(EnumTy->getFile(), Ctx.SourceRegPairs);
+    if (!SourceReg.isValid()) {
+      SourceReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+                                    {}, Ctx, false);
+    }
+    Register Line = Ctx.GR->buildConstantInt(EnumTy->getLine(), Ctx.MIRBuilder,
+                                             Ctx.I32Ty, false);
+    Register Column =
+        Ctx.GR->buildConstantInt(1, Ctx.MIRBuilder, Ctx.I32Ty, false);
+
+    Register ParentReg = Ctx.GR->getDebugValue(EnumTy->getScope());
+    if (!ParentReg.isValid()) {
+      llvm::errs() << "Warning: Could not find Parent scope register for Enum: "
+                   << EnumTy->getName() << "\n";
+      ParentReg = Ctx.GR->getDebugValue(EnumTy->getFile());
+      if (!ParentReg.isValid()) {
+        ParentReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+                                      {}, Ctx, false);
       }
+    }
+    Register Size = Ctx.GR->buildConstantInt(EnumTy->getSizeInBits(),
+                                             Ctx.MIRBuilder, Ctx.I32Ty, false);
+    uint32_t Flags = transDebugFlags(EnumTy);
+    Register FlagsReg =
+        Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false);
+    SmallVector<Register, 16> EnumOperands;
+    for (Metadata *MD : EnumTy->getElements()) {
+      if (auto *E = dyn_cast<DIEnumerator>(MD)) {
+        Register Val = Ctx.GR->buildConstantInt(
+            E->getValue().getZExtValue(), Ctx.MIRBuilder, Ctx.I32Ty, false);
+        Register Name = EmitOpString(E->getName(), Ctx);
+        EnumOperands.push_back(Val);
+        EnumOperands.push_back(Name);
+      }
+    }
+    SmallVector<Register, 12> Ops = {
+        NameStr, UnderlyingTypeReg, SourceReg, Line,
+        Column,  ParentReg,         Size,      FlagsReg};
+    Ops.append(EnumOperands);
+    bool HasForwardRef = UnderlyingTypeIsFwd;
+    Register DefReg = Ctx.GR->getDebugValue(EnumTy);
+    Register Res = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugTypeEnum,
+                                     Ops, Ctx, HasForwardRef, DefReg);
+    Ctx.GR->addDebugValue(EnumTy, Res);
+    Ctx.CompositeTypeRegPairs.emplace_back(EnumTy, Res);
+  }
+}
+
+void SPIRVEmitNonSemanticDI::emitSingleCompilationUnit(
+    StringRef FilePath, int64_t Language, SPIRVCodeGenContext &Ctx,
+    Register DebugInfoVersionReg, Register DwarfVersionReg,
+    Register &DebugSourceResIdReg, Register &DebugCompUnitResIdReg) {
+
+  const Register FilePathStrReg = EmitOpString(FilePath, Ctx);
 
-      const Register SourceLanguageReg =
-          GR->buildConstantInt(SpirvSourceLanguage, MIRBuilder, I32Ty, false);
+  const Function *F = &Ctx.MF.getFunction();
+  const DISubprogram *SP = F ? F->getSubprogram() : nullptr;
+  const DIFile *FileMDNode = nullptr;
+  if (SP)
+    FileMDNode = SP->getFile();
 
-      [[maybe_unused]]
-      const Register DebugCompUnitResIdReg =
-          EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
-                            {DebugInfoVersionReg, DwarfVersionReg,
-                             DebugSourceResIdReg, SourceLanguageReg});
+  std::string FileMDContents;
+  if (FileMDNode && FileMDNode->getRawFile() &&
+      FileMDNode->getSource().has_value())
+    FileMDContents = FileMDNode->getSource().value().str();
+
+  if (FileMDContents.empty()) {
+    DebugSourceResIdReg = EmitDIInstruction(
+        SPIRV::NonSemanticExtInst::DebugSource, {FilePathStrReg}, Ctx, false);
+  } else {
+    constexpr size_t MaxNumWords = UINT16_MAX - 2;
+    constexpr size_t MaxStrSize = MaxNumWords * 4 - 1;
+    std::string RemainingSource = FileMDContents;
+    std::string FirstChunk = RemainingSource.substr(0, MaxStrSize);
+    const Register FirstTextStrReg = EmitOpString(FirstChunk, Ctx);
+    DebugSourceResIdReg =
+        EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugSource,
+                          {FilePathStrReg, FirstTextStrReg}, Ctx, false);
+
+    RemainingSource.erase(0, FirstChunk.size());
+
+    while (!RemainingSource.empty()) {
+      std::string NextChunk = RemainingSource.substr(0, MaxStrSize);
+      const Register ContinuedStrReg = EmitOpString(NextChunk, Ctx);
+      EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugSourceContinued,
+                        {ContinuedStrReg}, Ctx, false);
+      RemainingSource.erase(0, NextChunk.size());
     }
+  }
+  Ctx.SourceRegPairs.emplace_back(FileMDNode, DebugSourceResIdReg);
 
-    // We aren't extracting any DebugInfoFlags now so we
-    // emitting zero to use as <id>Flags argument for DebugBasicType
-    const Register I32ZeroReg =
-        GR->buildConstantInt(0, MIRBuilder, I32Ty, false, false);
+  SourceLanguage SpirvSourceLanguage = SourceLanguage::Unknown;
+  switch (Language) {
+  case dwarf::DW_LANG_OpenCL:
+    SpirvSourceLanguage = SourceLanguage::OpenCL_C;
+    break;
+  case dwarf::DW_LANG_OpenCL_CPP:
+    SpirvSourceLanguage = SourceLanguage::OpenCL_CPP;
+    break;
+  case dwarf::DW_LANG_CPP_for_OpenCL:
+    SpirvSourceLanguage = SourceLanguage::CPP_for_OpenCL;
+    break;
+  case dwarf::DW_LANG_GLSL:
+    SpirvSourceLanguage = SourceLanguage::GLSL;
+    break;
+  case dwarf::DW_LANG_HLSL:
+    SpirvSourceLanguage = SourceLanguage::HLSL;
+    break;
+  case dwarf::DW_LANG_SYCL:
+    SpirvSourceLanguage = SourceLanguage::SYCL;
+    break;
+  case dwarf::DW_LANG_Zig:
+    SpirvSourceLanguage = SourceLanguage::Zig;
+    break;
+  case dwarf::DW_LANG_C_plus_plus_14:
+    SpirvSourceLanguage = SourceLanguage::CPP;
+    break;
+  default:
+    SpirvSourceLanguage = SourceLanguage::Unknown;
+    break;
+  }
 
-    // We need to store pairs because further instructions reference
-    // the DIBasicTypes and size will be always small so there isn't
-    // need for any kind of map
-    SmallVector<std::pair<const DIBasicType *const, const Register>, 12>
-        BasicTypeRegPairs;
-    for (auto *BasicType : BasicTypes) {
-      const Register BasicTypeStrReg = EmitOpString(BasicType->getName());
-
-      const Register ConstIntBitwidthReg = GR->buildConstantInt(
-          BasicType->getSizeInBits(), MIRBuilder, I32Ty, false);
-
-      uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
-      switch (BasicType->getEncoding()) {
-      case dwarf::DW_ATE_signed:
-        AttributeEncoding = BaseTypeAttributeEncoding::Signed;
-        break;
-      case dwarf::DW_ATE_unsigned:
-        AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
-        break;
-      case dwarf::DW_ATE_unsigned_char:
-        AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
-        break;
-      case dwarf::DW_ATE_signed_char:
-        AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
-        break;
-      case dwarf::DW_ATE_float:
-        AttributeEncoding = BaseTypeAttributeEncoding::Float;
-        break;
-      case dwarf::DW_ATE_boolean:
-        AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
-        break;
-      case dwarf::DW_ATE_address:
-        AttributeEncoding = BaseTypeAttributeEncoding::Address;
+  const Register SourceLanguageReg = Ctx.GR->buildConstantInt(
+      SpirvSourceLanguage, Ctx.MIRBuilder, Ctx.I32Ty, false);
+
+  DebugCompUnitResIdReg =
+      EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugCompilationUnit,
+                        {DebugInfoVersionReg, DwarfVersionReg,
+                         DebugSourceResIdReg, SourceLanguageReg},
+                        Ctx, false);
+}
+
+Register SPIRVEmitNonSemanticDI::findEmittedBasicTypeReg(
+    const DIType *BaseType,
+    const SmallVectorImpl<std::pair<const DIBasicType *const, const Register>>
+        &BasicTypeRegPairs) {
+  const DIType *Ty = BaseType;
+
+  while (Ty && !isa<DIBasicType>(Ty)) {
+    if (auto *Derived = dyn_cast<DIDerivedType>(Ty))
+      if (Derived->getBaseType())
+        Ty = Derived->getBaseType();
+      else
+        return Register();
+    else
+      return Register();
+  }
+
+  if (const auto *BT = dyn_cast<DIBasicType>(Ty)) {
+    StringRef Name = BT->getName();
+    uint64_t Size = BT->getSizeInBits();
+
+    for (const auto &[DefinedBT, Reg] : BasicTypeRegPairs) {
+      if (DefinedBT->getName() == Name && DefinedBT->getSizeInBits() == Size)
+        return Reg;
+    }
+  }
+  return Register();
+}
+
+Register SPIRVEmitNonSemanticDI::findEmittedCompositeTypeReg(
+    const DIType *BaseType,
+    const SmallVectorImpl<std::pair<const DICompositeType *const,
+                                    const Register>> &CompositeTypeRegPairs) {
+
+  StringRef Name = BaseType->getName();
+  uint64_t Size = BaseType->getSizeInBits();
+  unsigned Tag = BaseType->getTag();
+
+  for (const auto &[DefinedCT, Reg] : CompositeTypeRegPairs) {
+    if (DefinedCT->getName() == Name && DefinedCT->getSizeInBits() == Size &&
+        DefinedCT->getTag() == Tag)
+      return Reg;
+  }
+
+  return Register();
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugBuildIdentifier(
+    StringRef BuildIdentifier, SPIRVCodeGenContext &Ctx) {
+  if (BuildIdentifier.empty())
+    return;
+
+  const Register BuildIdStrReg = EmitOpString(BuildIdentifier, Ctx);
+  uint32_t Flags = 0;
+  if (BuildIdentifier.contains("IdentifierPossibleDuplicates"))
+    Flags |= (1 << 0);
+  const Register FlagsReg =
+      Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+  EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugBuildIdentifier,
+                    {BuildIdStrReg, FlagsReg}, Ctx, false);
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugStoragePath(StringRef BuildStoragePath,
+                                                  SPIRVCodeGenContext &Ctx) {
+  if (!BuildStoragePath.empty()) {
+    const Register PathStrReg = EmitOpString(BuildStoragePath, Ctx);
+    EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugStoragePath, {PathStrReg},
+                      Ctx, false);
+  }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugBasicTypes(
+    const SmallPtrSetImpl<DIBasicType *> &BasicTypes,
+    SPIRVCodeGenContext &Ctx) {
+  // We need to store pairs because further instructions reference
+  // the DIBasicTypes and size will be always small so there isn't
+  // need for any kind of map
+  for (auto *BasicType : BasicTypes) {
+    if (!BasicType)
+      continue;
+    const Register BasicTypeStrReg = EmitOpString(BasicType->getName(), Ctx);
+
+    const Register ConstIntBitwidthReg = Ctx.GR->buildConstantInt(
+        BasicType->getSizeInBits(), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+    uint64_t AttributeEncoding = BaseTypeAttributeEncoding::Unspecified;
+    switch (BasicType->getEncoding()) {
+    case dwarf::DW_ATE_signed:
+      AttributeEncoding = BaseTypeAttributeEncoding::Signed;
+      break;
+    case dwarf::DW_ATE_unsigned:
+      AttributeEncoding = BaseTypeAttributeEncoding::Unsigned;
+      break;
+    case dwarf::DW_ATE_unsigned_char:
+      AttributeEncoding = BaseTypeAttributeEncoding::UnsignedChar;
+      break;
+    case dwarf::DW_ATE_signed_char:
+      AttributeEncoding = BaseTypeAttributeEncoding::SignedChar;
+      break;
+    case dwarf::DW_ATE_float:
+      AttributeEncoding = BaseTypeAttributeEncoding::Float;
+      break;
+    case dwarf::DW_ATE_boolean:
+      AttributeEncoding = BaseTypeAttributeEncoding::Boolean;
+      break;
+    case dwarf::DW_ATE_address:
+      AttributeEncoding = BaseTypeAttributeEncoding::Address;
+    }
+
+    const Register AttributeEncodingReg = Ctx.GR->buildConstantInt(
+        AttributeEncoding, Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+    const Register FlagsReg = Ctx.GR->buildConstantInt(
+        transDebugFlags(BasicType), Ctx.MIRBuilder, Ctx.I32Ty, false, false);
+
+    [[maybe_unused]]
+    const Register BasicTypeReg = EmitDIInstruction(
+        SPIRV::NonSemanticExtInst::DebugTypeBasic,
+        {BasicTypeStrReg, ConstIntBitwidthReg, AttributeEncodingReg, FlagsReg},
+        Ctx, false);
+    Ctx.GR->addDebugValue(BasicType, BasicTypeReg);
+    Ctx.BasicTypeRegPairs.emplace_back(BasicType, BasicTypeReg);
+  }
+}
+
+void SPIRVEmitNonSemanticDI::emitDebugPointerTypes(
+    const SmallPtrSetImpl<DIDerivedType *> &PointerDerivedTypes,
+    SPIRVCodeGenContext &Ctx) {
+
+  if (PointerDerivedTypes.empty())
+    return;
+
+  for (const auto *PointerDerivedType : PointerDerivedTypes) {
+    uint64_t DWARFAddrSpace = 0;
+    if (PointerDerivedType->getDWARFAddressSpace().has_value())
+      DWARFAddrSpace = PointerDerivedType->getDWARFAddressSpace().value();
+    else {
+      LLVM_DEBUG(dbgs() << "Warning: pointer DI has no DWARF address space; "
+                        << "falling back to 0 (generic)\n");
+    }
+    const Register StorageClassReg = Ctx.GR->buildConstantInt(
+        addressSpaceToStorageClass(DWARFAddrSpace, *Ctx.TM->getSubtargetImpl()),
+        Ctx.MIRBuilder, Ctx.I32Ty, false);
+    const uint32_t Flags = transDebugFlags(PointerDerivedType);
+    const Register FlagsReg = Ctx.GR->buildConstantInt(Flags, Ctx.MIRBuilder,
+                                                       Ctx.I32Ty, false, false);
+
+    const DIType *BaseTy = PointerDerivedType->getBaseType();
+    bool HasForwardRef = false;
+    Register BaseTypeReg =
+        findBaseTypeRegisterRecursive(BaseTy, Ctx, HasForwardRef);
+
+    if (!BaseTypeReg.isValid()) {
+      llvm::errs() << "Warning: Failed to find or create placeholder for base "
+                      "type of pointer.\n";
+      BaseTypeReg = EmitDIInstruction(SPIRV::NonSemanticExtInst::DebugInfoNone,
+                                      {}, Ctx, false);
+      HasForwardRef = false;
+    }
----------------
MrSidims wrote:

We can leave it as `DebugInfoNone`.

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


More information about the llvm-commits mailing list