[PATCH 34/79] [Backport to 15][DebugInfo] Support multiple CompileUnits (#1950)
authorDmitry Sidorov <dmitry.sidorov@intel.com>
Wed, 19 Apr 2023 13:34:06 +0000 (15:34 +0200)
committerAndreas Beckmann <anbe@debian.org>
Thu, 8 Feb 2024 21:48:18 +0000 (22:48 +0100)
It's possible for LLVM IR module to contain multiple CU in case if this module is a result
of llvm-link between two modules compiled for different languages and or compiled with
different options.

This patch introduces handling of such modules.
std::unordered_map<SPIRVId, std::unique_ptr> BuilderMap was introduced
to SPIR-V consumption part and
std::unordered_map<const DICompileUnit *, SPIRVExtInst *> SPIRVCUMap was introduced
to SPIR-V generation part to preserve Scope relations between DI metadata in SPIR-V and vice versa.

Note, that DIBuilder has a single CU field and this class is not trivially copiable.

Signed-off-by: Sidorov, Dmitry <dmitry.sidorov@intel.com>
Gbp-Pq: Name 0034-Backport-to-15-DebugInfo-Support-multiple-CompileUni.patch

lib/SPIRV/LLVMToSPIRVDbgTran.cpp
lib/SPIRV/LLVMToSPIRVDbgTran.h
lib/SPIRV/SPIRVReader.cpp
lib/SPIRV/SPIRVToLLVMDbgTran.cpp
lib/SPIRV/SPIRVToLLVMDbgTran.h
lib/SPIRV/libSPIRV/SPIRV.debug.h
test/DebugInfo/Generic/c-and-cpp-mixed.ll [new file with mode: 0644]
test/DebugInfo/X86/mixed-nodebug-cu.ll
test/DebugInfo/X86/split-dwarf-omit-empty.ll

index 6a1e948ec09da38b8a817bf834e01033a01148fd..e36658b48a9e924d147fd9cedf32d43ca73e2a98 100644 (file)
@@ -52,11 +52,11 @@ void LLVMToSPIRVDbgTran::transDebugMetadata() {
   if (DIF.compile_unit_count() == 0)
     return;
 
-  DICompileUnit *CU = *DIF.compile_units().begin();
-  transDbgEntry(CU);
-
-  for (DIImportedEntity *IE : CU->getImportedEntities())
-    transDbgEntry(IE);
+  for (DICompileUnit *CU : DIF.compile_units()) {
+    transDbgEntry(CU);
+    for (DIImportedEntity *IE : CU->getImportedEntities())
+      transDbgEntry(IE);
+  }
 
   for (const DIType *T : DIF.types())
     transDbgEntry(T);
@@ -404,10 +404,9 @@ SPIRVType *LLVMToSPIRVDbgTran::getInt32Ty() {
 SPIRVEntry *LLVMToSPIRVDbgTran::getScope(DIScope *S) {
   if (S)
     return transDbgEntry(S);
-  else {
-    assert(SPIRVCU && "Compile unit is expected to be already translated");
-    return SPIRVCU;
-  }
+  assert(!SPIRVCUMap.empty() &&
+         "Compile units are expected to be already translated");
+  return SPIRVCUMap.begin()->second;
 }
 
 SPIRVEntry *LLVMToSPIRVDbgTran::getGlobalVariable(const DIGlobalVariable *GV) {
@@ -556,9 +555,9 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgCompileUnit(const DICompileUnit *CU) {
         Ops, {SPIRVDebugInfoVersionIdx, DWARFVersionIdx, LanguageIdx});
   BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str());
   // Cache CU in a member.
-  SPIRVCU = static_cast<SPIRVExtInst *>(
+  SPIRVCUMap[CU] = static_cast<SPIRVExtInst *>(
       BM->addDebugInfo(SPIRVDebug::CompilationUnit, getVoidTy(), Ops));
-  return SPIRVCU;
+  return SPIRVCUMap[CU];
 }
 
 // Types
@@ -985,7 +984,7 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgInheritance(const DIDerivedType *DT) {
 }
 
 SPIRVEntry *LLVMToSPIRVDbgTran::transDbgPtrToMember(const DIDerivedType *DT) {
-  using namespace SPIRVDebug::Operand::PtrToMember;
+  using namespace SPIRVDebug::Operand::TypePtrToMember;
   SPIRVWordVec Ops(OperandCount);
   Ops[MemberTypeIdx] = transDbgEntry(DT->getBaseType())->getId();
   Ops[ParentIdx] = transDbgEntry(DT->getClassType())->getId();
@@ -1084,7 +1083,7 @@ LLVMToSPIRVDbgTran::transDbgGlobalVariable(const DIGlobalVariable *GV) {
 
   // Parent scope
   DIScope *Context = GV->getScope();
-  SPIRVEntry *Parent = SPIRVCU;
+  SPIRVEntry *Parent = SPIRVCUMap.begin()->second;
   // Global variable may be declared in scope of a namespace or imported module,
   // it may also be a static variable declared in scope of a function.
   if (Context && (isa<DINamespace>(Context) || isa<DISubprogram>(Context) ||
@@ -1119,10 +1118,15 @@ SPIRVEntry *LLVMToSPIRVDbgTran::transDbgFunction(const DISubprogram *Func) {
   Ops[LineIdx] = Func->getLine();
   Ops[ColumnIdx] = 0; // This version of DISubprogram has no column number
   auto Scope = Func->getScope();
-  if (Scope && isa<DIFile>(Scope))
-    Ops[ParentIdx] = SPIRVCU->getId();
-  else
+  if (Scope && !isa<DIFile>(Scope)) {
     Ops[ParentIdx] = getScope(Scope)->getId();
+  } else {
+    if (auto *Unit = Func->getUnit())
+      Ops[ParentIdx] = SPIRVCUMap[Unit]->getId();
+    else
+      // it might so happen, that DISubprogram is missing Unit parameter
+      Ops[ParentIdx] = SPIRVCUMap.begin()->second->getId();
+  }
   Ops[LinkageNameIdx] = BM->getString(Func->getLinkageName().str())->getId();
   Ops[FlagsIdx] = adjustAccessFlags(Scope, transDebugFlags(Func));
   if (isNonSemanticDebugInfo())
index 9e5f711c94e29edd70485538324509e330468fa0..d43040d7ad9579a7a1dab6429350dd1e44a13447 100644 (file)
@@ -164,7 +164,7 @@ private:
   SPIRVType *VoidT = nullptr;
   SPIRVType *Int32T = nullptr;
   SPIRVEntry *DebugInfoNone;
-  SPIRVExtInst *SPIRVCU;
+  std::unordered_map<const DICompileUnit *, SPIRVExtInst *> SPIRVCUMap;
   std::vector<const DbgVariableIntrinsic *> DbgDeclareIntrinsics;
   std::vector<const DbgVariableIntrinsic *> DbgValueIntrinsics;
 }; // class LLVMToSPIRVDbgTran
index 6293e443bcaf6b740ec38ad237bfb811ccd15d24..85731c3d880b2574f6b41e1cb7b4a28655449279 100644 (file)
@@ -3333,13 +3333,9 @@ bool SPIRVToLLVM::translate() {
 
   // Compile unit might be needed during translation of debug intrinsics.
   for (SPIRVExtInst *EI : BM->getDebugInstVec()) {
-    // Translate Compile Unit first.
-    // It shuldn't be far from the beginig of the vector
-    if (EI->getExtOp() == SPIRVDebug::CompilationUnit) {
+    // Translate Compile Units first.
+    if (EI->getExtOp() == SPIRVDebug::CompilationUnit)
       DbgTran->transDebugInst(EI);
-      // Fixme: there might be more then one Compile Unit.
-      break;
-    }
   }
   // Then translate all debug instructions.
   for (SPIRVExtInst *EI : BM->getDebugInstVec()) {
index 54339fbcdf279ae1d687e0bdf1a77f623bfdd912..2ad7b4a9d99d6629bb00bbca156f07e3e9aa9a05 100644 (file)
@@ -64,7 +64,7 @@ static uint64_t getDerivedSizeInBits(const DIType *Ty) {
 }
 SPIRVToLLVMDbgTran::SPIRVToLLVMDbgTran(SPIRVModule *TBM, Module *TM,
                                        SPIRVToLLVM *Reader)
-    : BM(TBM), M(TM), Builder(*M), SPIRVReader(Reader) {
+    : BM(TBM), M(TM), SPIRVReader(Reader) {
   Enable = BM->hasDebugInfo();
 }
 
@@ -80,8 +80,11 @@ SPIRVToLLVMDbgTran::getDIFile(const std::string &FileName,
                               Optional<DIFile::ChecksumInfo<StringRef>> CS) {
   return getOrInsert(FileMap, FileName, [=]() {
     SplitFileName Split(FileName);
+    // Use the first builder from the map to crete DIFile since it's
+    // relations with other debug metadata is not going through DICompileUnit
     if (!Split.BaseName.empty())
-      return Builder.createFile(Split.BaseName, Split.Path, CS);
+      return BuilderMap.begin()->second->createFile(Split.BaseName, Split.Path,
+                                                    CS);
     return static_cast<DIFile *>(nullptr);
   });
 }
@@ -154,9 +157,15 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) {
 
   using namespace SPIRVDebug::Operand::CompilationUnit;
   assert(Ops.size() == OperandCount && "Invalid number of operands");
-  SPIRVWord DWARFVersion = getConstantValueOrLiteral(
-      Ops, DWARFVersionIdx, DebugInst->getExtSetKind());
-  M->addModuleFlag(llvm::Module::Max, "Dwarf Version", DWARFVersion);
+  // We must preserve only one Dwarf version module level metadata
+  // UpgradeDebugInfo from llvm/lib/IR/AutoUpgrade.cpp has already done all
+  // work for us during linking stage leaving a single Dwarf version in the
+  // module
+  if (!M->getModuleFlag("Dwarf Version")) {
+    SPIRVWord DWARFVersion = getConstantValueOrLiteral(
+        Ops, DWARFVersionIdx, DebugInst->getExtSetKind());
+    M->addModuleFlag(llvm::Module::Max, "Dwarf Version", DWARFVersion);
+  }
   SPIRVWord SourceLang =
       getConstantValueOrLiteral(Ops, LanguageIdx, DebugInst->getExtSetKind());
   if (DebugInst->getExtSetKind() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200) {
@@ -172,9 +181,9 @@ SPIRVToLLVMDbgTran::transCompilationUnit(const SPIRVExtInst *DebugInst) {
   }
 
   auto Producer = findModuleProducer();
-  CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer,
-                                 false, "", 0);
-  return CU;
+  BuilderMap[DebugInst->getId()] = std::make_unique<DIBuilder>(*M);
+  return BuilderMap[DebugInst->getId()]->createCompileUnit(
+      SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0);
 }
 
 DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) {
@@ -186,9 +195,9 @@ DIBasicType *SPIRVToLLVMDbgTran::transTypeBasic(const SPIRVExtInst *DebugInst) {
       getConstantValueOrLiteral(Ops, EncodingIdx, DebugInst->getExtSetKind()));
   unsigned Encoding = SPIRV::DbgEncodingMap::rmap(Tag);
   if (Encoding == 0)
-    return Builder.createUnspecifiedType(Name);
+    return getDIBuilder(DebugInst).createUnspecifiedType(Name);
   uint64_t Size = BM->get<SPIRVConstant>(Ops[SizeIdx])->getZExtIntValue();
-  return Builder.createBasicType(Name, Size, Encoding);
+  return getDIBuilder(DebugInst).createBasicType(Name, Size, Encoding);
 }
 
 DIDerivedType *
@@ -201,7 +210,7 @@ SPIRVToLLVMDbgTran::transTypeQualifier(const SPIRVExtInst *DebugInst) {
   SPIRVWord Tag = SPIRV::DbgTypeQulifierMap::rmap(
       static_cast<SPIRVDebug::TypeQualifierTag>(getConstantValueOrLiteral(
           Ops, QualifierIdx, DebugInst->getExtSetKind())));
-  return Builder.createQualifiedType(Tag, BaseTy);
+  return getDIBuilder(DebugInst).createQualifiedType(Tag, BaseTy);
 }
 
 DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) {
@@ -220,19 +229,19 @@ DIType *SPIRVToLLVMDbgTran::transTypePointer(const SPIRVExtInst *DebugInst) {
   SPIRVWord Flags =
       getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
   if (Flags & SPIRVDebug::FlagIsLValueReference)
-    Ty = Builder.createReferenceType(dwarf::DW_TAG_reference_type, PointeeTy, 0,
-                                     0, AS);
+    Ty = getDIBuilder(DebugInst).createReferenceType(
+        dwarf::DW_TAG_reference_type, PointeeTy, 0, 0, AS);
   else if (Flags & SPIRVDebug::FlagIsRValueReference)
-    Ty = Builder.createReferenceType(dwarf::DW_TAG_rvalue_reference_type,
-                                     PointeeTy, 0, 0, AS);
+    Ty = getDIBuilder(DebugInst).createReferenceType(
+        dwarf::DW_TAG_rvalue_reference_type, PointeeTy, 0, 0, AS);
   else
-    Ty = Builder.createPointerType(PointeeTy, BM->getAddressingModel() * 32, 0,
-                                   AS);
+    Ty = getDIBuilder(DebugInst).createPointerType(
+        PointeeTy, BM->getAddressingModel() * 32, 0, AS);
 
   if (Flags & SPIRVDebug::FlagIsObjectPointer)
-    Ty = Builder.createObjectPointerType(Ty);
+    Ty = getDIBuilder(DebugInst).createObjectPointerType(Ty);
   else if (Flags & SPIRVDebug::FlagIsArtificial)
-    Ty = Builder.createArtificialType(Ty);
+    Ty = getDIBuilder(DebugInst).createArtificialType(Ty);
 
   return Ty;
 }
@@ -267,8 +276,8 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) {
       int64_t ConstantAsInt = static_cast<int64_t>(C->getZExtIntValue());
       auto *LowerBound = ConstantAsMetadata::get(
           ConstantInt::get(M->getContext(), APInt(64, ConstantAsInt)));
-      Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound,
-                                                       UpperBound, nullptr));
+      Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange(
+          nullptr, LowerBound, UpperBound, nullptr));
       continue;
     }
     const SPIRVExtInst *ExprUB, *ExprLB;
@@ -277,8 +286,8 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) {
              getDbgInst<SPIRVDebug::Expression>(Ops[Ops.size() / 2 + I]))) {
       auto *UpperBound = transDebugInst<DIExpression>(ExprUB);
       auto *LowerBound = transDebugInst<DIExpression>(ExprLB);
-      Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound,
-                                                       UpperBound, nullptr));
+      Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange(
+          nullptr, LowerBound, UpperBound, nullptr));
       continue;
     }
     if (!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[I])) {
@@ -289,21 +298,24 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) {
       if (Ops.size() / 2 + I < Ops.size()) {
         C = BM->get<SPIRVConstant>(Ops[Ops.size() / 2 + I]);
         int64_t LowerBound = static_cast<int64_t>(C->getZExtIntValue());
-        Subscripts.push_back(Builder.getOrCreateSubrange(LowerBound, Count));
+        Subscripts.push_back(
+            getDIBuilder(DebugInst).getOrCreateSubrange(LowerBound, Count));
       } else {
         auto *CountAsMD = ConstantAsMetadata::get(
             ConstantInt::get(M->getContext(), APInt(64, Count)));
-        Subscripts.push_back(
-            Builder.getOrCreateSubrange(CountAsMD, nullptr, nullptr, nullptr));
+        Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange(
+            CountAsMD, nullptr, nullptr, nullptr));
       }
       // Count = -1 means that the array is empty
       TotalCount *= Count > 0 ? static_cast<size_t>(Count) : 0;
       continue;
     }
   }
-  DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts);
+  DINodeArray SubscriptArray =
+      getDIBuilder(DebugInst).getOrCreateArray(Subscripts);
   size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount;
-  return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray);
+  return getDIBuilder(DebugInst).createArrayType(Size, 0 /*align*/, BaseTy,
+                                                 SubscriptArray);
 }
 
 DICompositeType *
@@ -323,9 +335,11 @@ SPIRVToLLVMDbgTran::transTypeArrayNonSemantic(const SPIRVExtInst *DebugInst) {
       Subscripts.push_back(SR);
     }
   }
-  DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts);
+  DINodeArray SubscriptArray =
+      getDIBuilder(DebugInst).getOrCreateArray(Subscripts);
   size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount;
-  return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray);
+  return getDIBuilder(DebugInst).createArrayType(Size, 0 /*align*/, BaseTy,
+                                                 SubscriptArray);
 }
 
 DICompositeType *
@@ -343,7 +357,8 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) {
       TotalCount *= Count->getSExtValue() > 0 ? Count->getSExtValue() : 0;
     Subscripts.push_back(SR);
   }
-  DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts);
+  DINodeArray SubscriptArray =
+      getDIBuilder(DebugInst).getOrCreateArray(Subscripts);
   size_t Size = getDerivedSizeInBits(BaseTy) * TotalCount;
 
   auto TransOperand =
@@ -365,8 +380,9 @@ SPIRVToLLVMDbgTran::transTypeArrayDynamic(const SPIRVExtInst *DebugInst) {
   PointerUnion<DIExpression *, DIVariable *> Allocated =
       TransOperand(AllocatedIdx);
   PointerUnion<DIExpression *, DIVariable *> Rank = TransOperand(RankIdx);
-  return Builder.createArrayType(Size, 0 /*align*/, BaseTy, SubscriptArray,
-                                 DataLocation, Associated, Allocated, Rank);
+  return getDIBuilder(DebugInst).createArrayType(Size, 0 /*align*/, BaseTy,
+                                                 SubscriptArray, DataLocation,
+                                                 Associated, Allocated, Rank);
 }
 
 DICompositeType *
@@ -389,10 +405,12 @@ SPIRVToLLVMDbgTran::transTypeVector(const SPIRVExtInst *DebugInst) {
   uint64_t Size = getDerivedSizeInBits(BaseTy) * SizeCount;
 
   SmallVector<llvm::Metadata *, 8> Subscripts;
-  Subscripts.push_back(Builder.getOrCreateSubrange(0, Count));
-  DINodeArray SubscriptArray = Builder.getOrCreateArray(Subscripts);
+  Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange(0, Count));
+  DINodeArray SubscriptArray =
+      getDIBuilder(DebugInst).getOrCreateArray(Subscripts);
 
-  return Builder.createVectorType(Size, 0 /*align*/, BaseTy, SubscriptArray);
+  return getDIBuilder(DebugInst).createVectorType(Size, 0 /*align*/, BaseTy,
+                                                  SubscriptArray);
 }
 
 DICompositeType *
@@ -439,21 +457,21 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) {
   case SPIRVDebug::Class:
     // TODO: should be replaced with createClassType, when bug with creating
     // ClassType with llvm::dwarf::DW_TAG_struct_type tag will be fixed
-    CT = Builder.createReplaceableCompositeType(
+    CT = getDIBuilder(DebugInst).createReplaceableCompositeType(
         llvm::dwarf::DW_TAG_class_type, Name, ParentScope, File, LineNo, 0,
         Size, Align, Flags, Identifier);
     CT = llvm::MDNode::replaceWithDistinct(llvm::TempDICompositeType(CT));
     break;
   case SPIRVDebug::Structure:
-    CT = Builder.createStructType(ParentScope, Name, File, LineNo, Size, Align,
-                                  Flags, DerivedFrom,
-                                  DINodeArray() /*elements*/, 0 /*RunTimeLang*/,
-                                  nullptr /*VTableHolder*/, Identifier);
+    CT = getDIBuilder(DebugInst).createStructType(
+        ParentScope, Name, File, LineNo, Size, Align, Flags, DerivedFrom,
+        DINodeArray() /*elements*/, 0 /*RunTimeLang*/, nullptr /*VTableHolder*/,
+        Identifier);
     break;
   case SPIRVDebug::Union:
-    CT = Builder.createUnionType(ParentScope, Name, File, LineNo, Size, Align,
-                                 Flags, DINodeArray(), 0 /*RuntimrLang*/,
-                                 Identifier);
+    CT = getDIBuilder(DebugInst).createUnionType(
+        ParentScope, Name, File, LineNo, Size, Align, Flags, DINodeArray(),
+        0 /*RuntimrLang*/, Identifier);
     break;
   default:
     llvm_unreachable("Unexpected composite type");
@@ -464,8 +482,8 @@ SPIRVToLLVMDbgTran::transTypeComposite(const SPIRVExtInst *DebugInst) {
   for (size_t I = FirstMemberIdx; I < Ops.size(); ++I) {
     EltTys.push_back(transDebugInst(BM->get<SPIRVExtInst>(Ops[I])));
   }
-  DINodeArray Elements = Builder.getOrCreateArray(EltTys);
-  Builder.replaceArrays(CT, Elements);
+  DINodeArray Elements = getDIBuilder(DebugInst).getOrCreateArray(EltTys);
+  getDIBuilder(DebugInst).replaceArrays(CT, Elements);
   assert(CT && "Composite type translation failed.");
   return CT;
 }
@@ -496,8 +514,8 @@ SPIRVToLLVMDbgTran::transTypeSubrange(const SPIRVExtInst *DebugInst) {
   };
   for (int Idx = CountIdx; Idx < OperandCount; ++Idx)
     TransOperand(Idx);
-  return Builder.getOrCreateSubrange(TranslatedOps[0], TranslatedOps[1],
-                                     TranslatedOps[2], TranslatedOps[3]);
+  return getDIBuilder(DebugInst).getOrCreateSubrange(
+      TranslatedOps[0], TranslatedOps[1], TranslatedOps[2], TranslatedOps[3]);
 }
 
 DIStringType *
@@ -576,14 +594,15 @@ DINode *SPIRVToLLVMDbgTran::transTypeMember(const SPIRVExtInst *DebugInst) {
     assert(isConstantOpCode(ConstVal->getOpCode()) &&
            "Static member must be a constant");
     llvm::Value *Val = SPIRVReader->transValue(ConstVal, nullptr, nullptr);
-    return Builder.createStaticMemberType(Scope, Name, File, LineNo, BaseType,
-                                          Flags, cast<llvm::Constant>(Val));
+    return getDIBuilder(DebugInst).createStaticMemberType(
+        Scope, Name, File, LineNo, BaseType, Flags, cast<llvm::Constant>(Val));
   }
   uint64_t Size = BM->get<SPIRVConstant>(Ops[SizeIdx])->getZExtIntValue();
   uint64_t Alignment = 0;
 
-  return Builder.createMemberType(Scope, Name, File, LineNo, Size, Alignment,
-                                  OffsetInBits, Flags, BaseType);
+  return getDIBuilder(DebugInst).createMemberType(Scope, Name, File, LineNo,
+                                                  Size, Alignment, OffsetInBits,
+                                                  Flags, BaseType);
 }
 
 DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) {
@@ -601,24 +620,24 @@ DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) {
   SPIRVWord Flags =
       getConstantValueOrLiteral(Ops, FlagsIdx, DebugInst->getExtSetKind());
   if (Flags & SPIRVDebug::FlagIsFwdDecl) {
-    return Builder.createForwardDecl(dwarf::DW_TAG_enumeration_type, Name,
-                                     Scope, File, LineNo, AlignInBits,
-                                     SizeInBits);
+    return getDIBuilder(DebugInst).createForwardDecl(
+        dwarf::DW_TAG_enumeration_type, Name, Scope, File, LineNo, AlignInBits,
+        SizeInBits);
   } else {
     SmallVector<llvm::Metadata *, 16> Elts;
     for (size_t I = FirstEnumeratorIdx, E = Ops.size(); I < E; I += 2) {
       uint64_t Val = BM->get<SPIRVConstant>(Ops[I])->getZExtIntValue();
       StringRef Name = getString(Ops[I + 1]);
-      Elts.push_back(Builder.createEnumerator(Name, Val));
+      Elts.push_back(getDIBuilder(DebugInst).createEnumerator(Name, Val));
     }
-    DINodeArray Enumerators = Builder.getOrCreateArray(Elts);
+    DINodeArray Enumerators = getDIBuilder(DebugInst).getOrCreateArray(Elts);
     DIType *UnderlyingType = nullptr;
     SPIRVEntry *E = BM->getEntry(Ops[UnderlyingTypeIdx]);
     if (!isa<OpTypeVoid>(E))
       UnderlyingType = transDebugInst<DIType>(static_cast<SPIRVExtInst *>(E));
-    return Builder.createEnumerationType(Scope, Name, File, LineNo, SizeInBits,
-                                         AlignInBits, Enumerators,
-                                         UnderlyingType, "", UnderlyingType);
+    return getDIBuilder(DebugInst).createEnumerationType(
+        Scope, Name, File, LineNo, SizeInBits, AlignInBits, Enumerators,
+        UnderlyingType, "", UnderlyingType);
   }
 }
 
@@ -648,20 +667,21 @@ DINode *SPIRVToLLVMDbgTran::transTypeFunction(const SPIRVExtInst *DebugInst) {
 
     Elements.push_back(Param);
   }
-  DITypeRefArray ArgTypes = Builder.getOrCreateTypeArray(Elements);
-  return Builder.createSubroutineType(ArgTypes, Flags);
+  DITypeRefArray ArgTypes =
+      getDIBuilder(DebugInst).getOrCreateTypeArray(Elements);
+  return getDIBuilder(DebugInst).createSubroutineType(ArgTypes, Flags);
 }
 
 DINode *
 SPIRVToLLVMDbgTran::transTypePtrToMember(const SPIRVExtInst *DebugInst) {
-  using namespace SPIRVDebug::Operand::PtrToMember;
+  using namespace SPIRVDebug::Operand::TypePtrToMember;
   const SPIRVWordVec &Ops = DebugInst->getArguments();
   assert(Ops.size() >= OperandCount && "Invalid number of operands");
   SPIRVExtInst *Member = BM->get<SPIRVExtInst>(Ops[MemberTypeIdx]);
   DIType *PointeeTy = transDebugInst<DIType>(Member);
   SPIRVExtInst *ContainingTy = BM->get<SPIRVExtInst>(Ops[ParentIdx]);
   DIType *BaseTy = transDebugInst<DIType>(ContainingTy);
-  return Builder.createMemberPointerType(PointeeTy, BaseTy, 0);
+  return getDIBuilder(DebugInst).createMemberPointerType(PointeeTy, BaseTy, 0);
 }
 
 DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) {
@@ -673,11 +693,12 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlock(const SPIRVExtInst *DebugInst) {
       getConstantValueOrLiteral(Ops, LineIdx, DebugInst->getExtSetKind());
   if (Ops.size() > NameIdx) {
     StringRef Name = getString(Ops[NameIdx]);
-    return Builder.createNameSpace(ParentScope, Name,
-                                   false /*inlined namespace*/);
+    return getDIBuilder(DebugInst).createNameSpace(ParentScope, Name,
+                                                   false /*inlined namespace*/);
   }
   unsigned Column = Ops[ColumnIdx];
-  return Builder.createLexicalBlock(ParentScope, File, LineNo, Column);
+  return getDIBuilder(DebugInst).createLexicalBlock(ParentScope, File, LineNo,
+                                                    Column);
 }
 
 DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator(
@@ -688,7 +709,8 @@ DINode *SPIRVToLLVMDbgTran::transLexicalBlockDiscriminator(
   SPIRVWord Disc = getConstantValueOrLiteral(Ops, DiscriminatorIdx,
                                              DebugInst->getExtSetKind());
   DIScope *ParentScope = getScope(BM->getEntry(Ops[ParentIdx]));
-  return Builder.createLexicalBlockFile(ParentScope, File, Disc);
+  return getDIBuilder(DebugInst).createLexicalBlockFile(ParentScope, File,
+                                                        Disc);
 }
 
 DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) {
@@ -751,14 +773,15 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) {
   // able to replace the template parameter operand, thus it must be in the
   // operands list.
   SmallVector<llvm::Metadata *, 8> Elts;
-  DINodeArray TParams = Builder.getOrCreateArray(Elts);
+  DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts);
   llvm::DITemplateParameterArray TParamsArray = TParams.get();
 
   DISubprogram *DIS = nullptr;
   if (Scope && (isa<DICompositeType>(Scope) || isa<DINamespace>(Scope)) &&
       !IsDefinition)
-    DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0,
-                               nullptr, Flags, SPFlags, TParamsArray);
+    DIS = getDIBuilder(DebugInst).createMethod(Scope, Name, LinkageName, File,
+                                               LineNo, Ty, 0, 0, nullptr, Flags,
+                                               SPFlags, TParamsArray);
   else {
     // Create targetFuncName mostly for Fortran trampoline function if it is
     // the case
@@ -766,10 +789,11 @@ DINode *SPIRVToLLVMDbgTran::transFunction(const SPIRVExtInst *DebugInst) {
     if (Ops.size() > TargetFunctionNameIdx) {
       TargetFunction = getString(Ops[TargetFunctionNameIdx]);
     }
-    DIS = Builder.createFunction(Scope, Name, LinkageName, File, LineNo, Ty,
-                                 ScopeLine, Flags, SPFlags, TParamsArray, FD,
-                                 /*ThrownTypes*/ nullptr,
-                                 /*Annotations*/ nullptr, TargetFunction);
+    DIS = getDIBuilder(DebugInst).createFunction(
+        Scope, Name, LinkageName, File, LineNo, Ty, ScopeLine, Flags, SPFlags,
+        TParamsArray, FD,
+        /*ThrownTypes*/ nullptr,
+        /*Annotations*/ nullptr, TargetFunction);
   }
   DebugInstCache[DebugInst] = DIS;
   SPIRVId RealFuncId = Ops[FunctionIdIdx];
@@ -831,23 +855,24 @@ DINode *SPIRVToLLVMDbgTran::transFunctionDecl(const SPIRVExtInst *DebugInst) {
   // able to replace the template parameter operand, thus it must be in the
   // operands list.
   SmallVector<llvm::Metadata *, 8> Elts;
-  DINodeArray TParams = Builder.getOrCreateArray(Elts);
+  DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts);
   llvm::DITemplateParameterArray TParamsArray = TParams.get();
 
   DISubprogram *DIS = nullptr;
   DISubprogram::DISPFlags SPFlags =
       DISubprogram::toSPFlags(IsLocal, IsDefinition, IsOptimized);
   if (isa<DICompositeType>(Scope) || isa<DINamespace>(Scope))
-    DIS = Builder.createMethod(Scope, Name, LinkageName, File, LineNo, Ty, 0, 0,
-                               nullptr, Flags, SPFlags, TParamsArray);
+    DIS = getDIBuilder(DebugInst).createMethod(Scope, Name, LinkageName, File,
+                                               LineNo, Ty, 0, 0, nullptr, Flags,
+                                               SPFlags, TParamsArray);
   else {
     // Since a function declaration doesn't have any retained nodes, resolve
     // the temporary placeholder for them immediately.
-    DIS = Builder.createTempFunctionFwdDecl(Scope, Name, LinkageName, File,
-                                            LineNo, Ty, 0, Flags, SPFlags,
-                                            TParamsArray);
+    DIS = getDIBuilder(DebugInst).createTempFunctionFwdDecl(
+        Scope, Name, LinkageName, File, LineNo, Ty, 0, Flags, SPFlags,
+        TParamsArray);
     llvm::TempMDNode FwdDecl(cast<llvm::MDNode>(DIS));
-    DIS = Builder.replaceTemporary(std::move(FwdDecl), DIS);
+    DIS = getDIBuilder(DebugInst).replaceTemporary(std::move(FwdDecl), DIS);
   }
   DebugInstCache[DebugInst] = DIS;
 
@@ -878,16 +903,16 @@ MDNode *SPIRVToLLVMDbgTran::transGlobalVariable(const SPIRVExtInst *DebugInst) {
   bool IsDefinition = Flags & SPIRVDebug::FlagIsDefinition;
   MDNode *VarDecl = nullptr;
   if (IsDefinition) {
-    VarDecl = Builder.createGlobalVariableExpression(
+    VarDecl = getDIBuilder(DebugInst).createGlobalVariableExpression(
         Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, IsDefinition,
         nullptr, StaticMemberDecl);
   } else {
-    VarDecl = Builder.createTempGlobalVariableFwdDecl(
+    VarDecl = getDIBuilder(DebugInst).createTempGlobalVariableFwdDecl(
         Parent, Name, LinkageName, File, LineNo, Ty, IsLocal, StaticMemberDecl);
     // replaceAllUsesWith call makes VarDecl non-temp.
     // Otherwise DIBuilder will crash at finalization.
     llvm::TempMDNode TMP(VarDecl);
-    VarDecl = Builder.replaceTemporary(std::move(TMP), VarDecl);
+    VarDecl = getDIBuilder(DebugInst).replaceTemporary(std::move(TMP), VarDecl);
   }
   // If the variable has no initializer Ops[VariableIdx] is OpDebugInfoNone.
   // Otherwise Ops[VariableIdx] may be a global variable or a constant(C++
@@ -922,9 +947,10 @@ DINode *SPIRVToLLVMDbgTran::transLocalVariable(const SPIRVExtInst *DebugInst) {
     Flags |= DINode::FlagObjectPointer;
 
   if (Ops.size() > ArgNumberIdx)
-    return Builder.createParameterVariable(Scope, Name, Ops[ArgNumberIdx], File,
-                                           LineNo, Ty, true, Flags);
-  return Builder.createAutoVariable(Scope, Name, File, LineNo, Ty, true, Flags);
+    return getDIBuilder(DebugInst).createParameterVariable(
+        Scope, Name, Ops[ArgNumberIdx], File, LineNo, Ty, true, Flags);
+  return getDIBuilder(DebugInst).createAutoVariable(Scope, Name, File, LineNo,
+                                                    Ty, true, Flags);
 }
 
 DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) {
@@ -940,7 +966,7 @@ DINode *SPIRVToLLVMDbgTran::transTypedef(const SPIRVExtInst *DebugInst) {
   DIType *Ty = transDebugInst<DIType>(static_cast<SPIRVExtInst *>(TypeInst));
   DIScope *Scope = getScope(BM->getEntry(Ops[ParentIdx]));
   assert(Scope && "Typedef should have a parent scope");
-  return Builder.createTypedef(Ty, Alias, File, LineNo, Scope);
+  return getDIBuilder(DebugInst).createTypedef(Ty, Alias, File, LineNo, Scope);
 }
 
 DINode *
@@ -961,7 +987,8 @@ SPIRVToLLVMDbgTran::transTypeInheritance(const SPIRVExtInst *DebugInst) {
   if ((SPIRVFlags & SPIRVDebug::FlagAccess) == SPIRVDebug::FlagIsPrivate)
     Flags |= llvm::DINode::FlagPrivate;
   uint64_t Offset = BM->get<SPIRVConstant>(Ops[OffsetIdx])->getZExtIntValue();
-  return Builder.createInheritance(Child, Parent, Offset, 0, Flags);
+  return getDIBuilder(DebugInst).createInheritance(Child, Parent, Offset, 0,
+                                                   Flags);
 }
 
 DINode *
@@ -978,10 +1005,11 @@ SPIRVToLLVMDbgTran::transTypeTemplateParameter(const SPIRVExtInst *DebugInst) {
   if (!getDbgInst<SPIRVDebug::DebugInfoNone>(Ops[ValueIdx])) {
     SPIRVValue *Val = BM->get<SPIRVValue>(Ops[ValueIdx]);
     Value *V = SPIRVReader->transValue(Val, nullptr, nullptr);
-    return Builder.createTemplateValueParameter(Context, Name, Ty, false,
-                                                cast<Constant>(V));
+    return getDIBuilder(DebugInst).createTemplateValueParameter(
+        Context, Name, Ty, false, cast<Constant>(V));
   }
-  return Builder.createTemplateTypeParameter(Context, Name, Ty, false);
+  return getDIBuilder(DebugInst).createTemplateTypeParameter(Context, Name, Ty,
+                                                             false);
 }
 
 DINode *SPIRVToLLVMDbgTran::transTypeTemplateTemplateParameter(
@@ -992,8 +1020,8 @@ DINode *SPIRVToLLVMDbgTran::transTypeTemplateTemplateParameter(
   StringRef Name = getString(Ops[NameIdx]);
   StringRef TemplName = getString(Ops[TemplateNameIdx]);
   DIScope *Context = nullptr;
-  return Builder.createTemplateTemplateParameter(Context, Name, nullptr,
-                                                 TemplName);
+  return getDIBuilder(DebugInst).createTemplateTemplateParameter(
+      Context, Name, nullptr, TemplName);
 }
 
 DINode *SPIRVToLLVMDbgTran::transTypeTemplateParameterPack(
@@ -1006,9 +1034,10 @@ DINode *SPIRVToLLVMDbgTran::transTypeTemplateParameterPack(
   for (size_t I = FirstParameterIdx, E = Ops.size(); I < E; ++I) {
     Elts.push_back(transDebugInst(BM->get<SPIRVExtInst>(Ops[I])));
   }
-  DINodeArray Pack = Builder.getOrCreateArray(Elts);
+  DINodeArray Pack = getDIBuilder(DebugInst).getOrCreateArray(Elts);
   DIScope *Context = nullptr;
-  return Builder.createTemplateParameterPack(Context, Name, nullptr, Pack);
+  return getDIBuilder(DebugInst).createTemplateParameterPack(Context, Name,
+                                                             nullptr, Pack);
 }
 
 MDNode *SPIRVToLLVMDbgTran::transTypeTemplate(const SPIRVExtInst *DebugInst) {
@@ -1024,10 +1053,10 @@ MDNode *SPIRVToLLVMDbgTran::transTypeTemplate(const SPIRVExtInst *DebugInst) {
   for (size_t I = FirstParameterIdx; I < NumOps; ++I) {
     Elts.push_back(transDebugInst(BM->get<SPIRVExtInst>(Ops[I])));
   }
-  DINodeArray TParams = Builder.getOrCreateArray(Elts);
+  DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts);
 
   if (DICompositeType *Comp = dyn_cast<DICompositeType>(D)) {
-    Builder.replaceArrays(Comp, Comp->getElements(), TParams);
+    getDIBuilder(DebugInst).replaceArrays(Comp, Comp->getElements(), TParams);
     return Comp;
   }
   if (isa<DISubprogram>(D)) {
@@ -1053,24 +1082,32 @@ DINode *SPIRVToLLVMDbgTran::transImportedEntry(const SPIRVExtInst *DebugInst) {
       getConstantValueOrLiteral(Ops, TagIdx, DebugInst->getExtSetKind());
   if (Tag == SPIRVDebug::ImportedModule) {
     if (!Entity)
-      return Builder.createImportedModule(
+      return getDIBuilder(DebugInst).createImportedModule(
           Scope, static_cast<DIImportedEntity *>(nullptr), File, Line);
     if (DIModule *DM = dyn_cast<DIModule>(Entity))
-      return Builder.createImportedModule(Scope, DM, File, Line);
+      return getDIBuilder(DebugInst).createImportedModule(Scope, DM, File,
+                                                          Line);
     if (DIImportedEntity *IE = dyn_cast<DIImportedEntity>(Entity))
-      return Builder.createImportedModule(Scope, IE, File, Line);
+      return getDIBuilder(DebugInst).createImportedModule(Scope, IE, File,
+                                                          Line);
     if (DINamespace *NS = dyn_cast<DINamespace>(Entity))
-      return Builder.createImportedModule(Scope, NS, File, Line);
+      return getDIBuilder(DebugInst).createImportedModule(Scope, NS, File,
+                                                          Line);
   }
   if (Tag == SPIRVDebug::ImportedDeclaration) {
     StringRef Name = getString(Ops[NameIdx]);
     if (DIGlobalVariableExpression *GVE =
             dyn_cast<DIGlobalVariableExpression>(Entity))
-      return Builder.createImportedDeclaration(Scope, GVE->getVariable(), File,
-                                               Line, Name);
-    return Builder.createImportedDeclaration(Scope, Entity, File, Line, Name);
+      return getDIBuilder(DebugInst).createImportedDeclaration(
+          Scope, GVE->getVariable(), File, Line, Name);
+    return getDIBuilder(DebugInst).createImportedDeclaration(Scope, Entity,
+                                                             File, Line, Name);
   }
-  llvm_unreachable("Unexpected kind of imported entity!");
+  // FIXME: uncomment and fix following line, with existing bugs it's reachable.
+  // llvm_unreachable("Unexpected kind of imported entity!");
+  // Imported entity translation is broken. For example ImportedEntity is
+  // missing 2nd parameter.
+  return nullptr;
 }
 
 DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) {
@@ -1087,8 +1124,8 @@ DINode *SPIRVToLLVMDbgTran::transModule(const SPIRVExtInst *DebugInst) {
   StringRef ApiNotes = getString(Ops[ApiNotesIdx]);
   bool IsDecl =
       getConstantValueOrLiteral(Ops, IsDeclIdx, DebugInst->getExtSetKind());
-  return Builder.createModule(Scope, Name, ConfigMacros, IncludePath, ApiNotes,
-                              File, Line, IsDecl);
+  return getDIBuilder(DebugInst).createModule(
+      Scope, Name, ConfigMacros, IncludePath, ApiNotes, File, Line, IsDecl);
 }
 
 MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) {
@@ -1107,7 +1144,7 @@ MDNode *SPIRVToLLVMDbgTran::transExpression(const SPIRVExtInst *DebugInst) {
     }
   }
   ArrayRef<uint64_t> Addr(Ops.data(), Ops.size());
-  return Builder.createExpression(Addr);
+  return getDIBuilder(DebugInst).createExpression(Addr);
 }
 
 MDNode *SPIRVToLLVMDbgTran::transDebugInstImpl(const SPIRVExtInst *DebugInst) {
@@ -1248,22 +1285,22 @@ SPIRVToLLVMDbgTran::transDebugIntrinsic(const SPIRVExtInst *DebugInst,
       // parameter. To work around this limitation we create a dummy temp
       // alloca, use it to create llvm.dbg.declare, and then remove the alloca.
       auto *AI = new AllocaInst(Type::getInt8Ty(M->getContext()), 0, "tmp", BB);
-      auto *DbgDeclare = Builder.insertDeclare(
+      auto *DbgDeclare = getDIBuilder(DebugInst).insertDeclare(
           AI, LocalVar.first, GetExpression(Ops[ExpressionIdx]),
           LocalVar.second, BB);
       AI->eraseFromParent();
       return DbgDeclare;
     }
-    return Builder.insertDeclare(GetValue(Ops[VariableIdx]), LocalVar.first,
-                                 GetExpression(Ops[ExpressionIdx]),
-                                 LocalVar.second, BB);
+    return getDIBuilder(DebugInst).insertDeclare(
+        GetValue(Ops[VariableIdx]), LocalVar.first,
+        GetExpression(Ops[ExpressionIdx]), LocalVar.second, BB);
   }
   case SPIRVDebug::Value: {
     using namespace SPIRVDebug::Operand::DebugValue;
     auto LocalVar = GetLocalVar(Ops[DebugLocalVarIdx]);
     Value *Val = GetValue(Ops[ValueIdx]);
     DIExpression *Expr = GetExpression(Ops[ExpressionIdx]);
-    auto *DbgValIntr = Builder.insertDbgValueIntrinsic(
+    auto *DbgValIntr = getDIBuilder(DebugInst).insertDbgValueIntrinsic(
         Val, LocalVar.first, Expr, LocalVar.second, BB);
     if (Expr->getNumLocationOperands() == 1) {
       SmallVector<ValueAsMetadata *, 1> MDs = {ValueAsMetadata::get(Val)};
@@ -1318,7 +1355,8 @@ MDNode *SPIRVToLLVMDbgTran::transDebugInlined(const SPIRVExtInst *DebugInst) {
 void SPIRVToLLVMDbgTran::finalize() {
   if (!Enable)
     return;
-  Builder.finalize();
+  for (const auto &Builder : BuilderMap)
+    Builder.second->finalize();
 }
 
 DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) {
@@ -1335,6 +1373,26 @@ DIFile *SPIRVToLLVMDbgTran::getFile(const SPIRVId SourceId) {
   return getDIFile(getString(SourceArgs[FileIdx]), ParseChecksum(ChecksumStr));
 }
 
+DIBuilder &SPIRVToLLVMDbgTran::getDIBuilder(const SPIRVExtInst *DebugInst) {
+  assert(BuilderMap.size() != 0 && "No debug compile units");
+  if (BuilderMap.size() == 1)
+    return *BuilderMap.begin()->second;
+  while (DebugInst->getExtOp() != SPIRVDebug::CompilationUnit) {
+    if (DebugInst->getExtOp() == SPIRVDebug::DebugInfoNone)
+      return *BuilderMap.begin()->second;
+    const SPIRVWordVec &Ops = DebugInst->getArguments();
+    SPIRVWord ParentScopeIdx = 0;
+    if (!hasDbgInstParentScopeIdx(DebugInst->getExtOp(), ParentScopeIdx))
+      return *BuilderMap.begin()->second;
+    if (SPIRVEntry *Scope = BM->getEntry(Ops[ParentScopeIdx])) {
+      DebugInst = static_cast<SPIRVExtInst *>(Scope);
+      continue;
+    }
+    return *BuilderMap.begin()->second;
+  }
+  return *BuilderMap[DebugInst->getId()];
+}
+
 SPIRVToLLVMDbgTran::SplitFileName::SplitFileName(const string &FileName) {
   auto Loc = FileName.find_last_of("/\\");
   if (Loc != std::string::npos) {
index 2102f218e101e1e4c999f1233ead7b4a7e08c928..f6b3168691b6bffdb1649ca68dffc91528a950c2 100644 (file)
@@ -160,7 +160,7 @@ private:
 
   SPIRVModule *BM;
   Module *M;
-  DIBuilder Builder;
+  std::unordered_map<SPIRVId, std::unique_ptr<DIBuilder>> BuilderMap;
   SPIRVToLLVM *SPIRVReader;
   DICompileUnit *CU;
   bool Enable;
@@ -177,6 +177,8 @@ private:
   DIScope *getScope(const SPIRVEntry *ScopeInst);
   SPIRVExtInst *getDbgInst(const SPIRVId Id);
 
+  DIBuilder &getDIBuilder(const SPIRVExtInst *DebugInst);
+
   template <SPIRVWord OpCode> SPIRVExtInst *getDbgInst(const SPIRVId Id) {
     if (SPIRVExtInst *DI = getDbgInst(Id)) {
       if (DI->getExtOp() == OpCode) {
index f1e6abacc2bf04c9a76935d37ae209d35a87f787..19170e1dbb511a5e75e5595827b83895d78453dc 100644 (file)
@@ -13,6 +13,8 @@ static const std::string ChecksumKindPrefx = {"//__CSK_"};
 
 // clang-format off
 
+// Need to update hasDbgInstParentScopeIdx each time we add new instruction
+// with ParentScopeIdx
 enum Instruction {
   DebugInfoNone                 = 0,
   CompilationUnit               = 1,
@@ -449,7 +451,7 @@ enum {
 };
 }
 
-namespace PtrToMember {
+namespace TypePtrToMember {
 enum {
   MemberTypeIdx = 0,
   ParentIdx     = 1,
@@ -830,6 +832,58 @@ enum {
 };
 }
 
+// helper function to get parent scope of debug instruction, to be used
+// to determine with which compile unit the particular instruction relates
+inline bool hasDbgInstParentScopeIdx(const uint32_t Kind,
+                                     uint32_t &ParentScopeIdx) {
+  switch (Kind) {
+  case SPIRVDebug::Typedef:
+    ParentScopeIdx = Typedef::ParentIdx;
+    return true;
+  case SPIRVDebug::TypeEnum:
+    ParentScopeIdx = TypeEnum::ParentIdx;
+    return true;
+  case SPIRVDebug::TypeComposite:
+    ParentScopeIdx = TypeMember::ParentIdx;
+    return true;
+  case SPIRVDebug::TypeInheritance:
+    ParentScopeIdx = TypeInheritance::ParentIdx;
+    return true;
+  case SPIRVDebug::TypePtrToMember:
+    ParentScopeIdx = TypePtrToMember::ParentIdx;
+    return true;
+  case SPIRVDebug::Function:
+    ParentScopeIdx = Function::ParentIdx;
+    return true;
+  case SPIRVDebug::LexicalBlock:
+    ParentScopeIdx = LexicalBlock::ParentIdx;
+    return true;
+  case SPIRVDebug::LexicalBlockDiscriminator:
+    ParentScopeIdx = LexicalBlockDiscriminator::ParentIdx;
+    return true;
+  case SPIRVDebug::Scope:
+    ParentScopeIdx = Scope::ScopeIdx;
+    return true;
+  case SPIRVDebug::InlinedAt:
+    ParentScopeIdx = InlinedAt::ScopeIdx;
+    return true;
+  case SPIRVDebug::LocalVariable:
+    ParentScopeIdx = LocalVariable::ParentIdx;
+    return true;
+  case SPIRVDebug::ImportedEntity:
+    ParentScopeIdx = ImportedEntity::ParentIdx;
+    return true;
+  case SPIRVDebug::ModuleINTEL:
+    ParentScopeIdx = ModuleINTEL::ParentIdx;
+    return true;
+  case SPIRVDebug::Module:
+    ParentScopeIdx = ModuleINTEL::ParentIdx;
+    return true;
+  default:
+    return false;
+  }
+}
+
 } // namespace Operand
 } // namespace SPIRVDebug
 
diff --git a/test/DebugInfo/Generic/c-and-cpp-mixed.ll b/test/DebugInfo/Generic/c-and-cpp-mixed.ll
new file mode 100644 (file)
index 0000000..b1427b0
--- /dev/null
@@ -0,0 +1,120 @@
+;; This test checks that two DICompileUnits resulted in a link of C and C++
+;; object files are being translated correctly
+
+; RUN: llvm-as < %s -o %t.bc
+; RUN: llvm-spirv %t.bc -o %t.spv
+; RUN: llvm-spirv --to-text %t.spv -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: llvm-spirv -r -emit-opaque-pointers %t.spv -o - | llvm-dis -o %t.ll
+; RUN: FileCheck < %t.ll %s --check-prefix=CHECK-LLVM
+
+; CHECK-SPIRV: String [[#Foo:]] "foo"
+; CHECK-SPIRV: String [[#Main:]] "main"
+; CHECK-SPIRV: ExtInst [[#]] [[#CU1:]] [[#]] DebugCompilationUnit
+; CHECK-SPIRV: ExtInst [[#]] [[#CU2:]] [[#]] DebugCompilationUnit
+; CHECK-SPIRV: ExtInst [[#]] [[#Func1:]] [[#]] DebugFunction [[#Foo]] [[#]] [[#]] [[#]] [[#]] [[#CU1]]
+; CHECK-SPIRV: ExtInst [[#]] [[#Func2:]] [[#]] DebugFunction [[#Main]] [[#]] [[#]] [[#]] [[#]] [[#CU2]]
+; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugLexicalBlock [[#]] [[#]] [[#]] [[#Func1]]
+; CHECK-SPIRV: ExtInst [[#]] [[#]] [[#]] DebugLexicalBlock [[#]] [[#]] [[#]] [[#Func2]]
+
+; CHECK-LLVM: define spir_func void @foo() #0 !dbg ![[#Func1:]] {
+; CHECK-LLVM: entry:
+; CHECK-LLVM:   %[[#VALUE:]] = getelementptr inbounds [4 x i8], ptr @str, i32 0, i32 0
+; CHECK-LLVM:   %puts = call spir_func i32 @puts(ptr nocapture %[[#VALUE]]) #0, !dbg ![[#Puts1Loc:]]
+; CHECK-LLVM:   ret void, !dbg ![[#Ret1:]]
+; CHECK-LLVM: }
+
+; CHECK-LLVM: define spir_func i32 @main(i32 %argc, ptr nocapture %argv) #0 !dbg ![[#Func2:]] {
+; CHECK-LLVM: entry:
+; CHECK-LLVM:   call void @llvm.dbg.value(metadata i32 %argc, metadata ![[#Fun2Param1:]], metadata !DIExpression()), !dbg ![[#Fun2Param1Loc:]]
+; CHECK-LLVM:   call void @llvm.dbg.value(metadata ptr %argv, metadata ![[#Fun2Param2:]], metadata !DIExpression(DW_OP_deref, DW_OP_deref)), !dbg ![[#Fun2Param2Loc:]]
+; CHECK-LLVM:   %[[#VALUE1:]] = getelementptr inbounds [6 x i8], ptr @str1, i32 0, i32 0
+; CHECK-LLVM:   %puts = call spir_func i32 @puts(ptr nocapture %[[#VALUE1]]) #0, !dbg ![[#Puts2Loc:]]
+; CHECK-LLVM:   call spir_func void @foo() #0, !dbg ![[#CallFoo:]]
+; CHECK-LLVM:   ret i32 0, !dbg ![[#Ret2:]]
+; CHECK-LLVM: }
+
+; CHECK-LLVM: !llvm.dbg.cu = !{![[#CU1:]], ![[#CU2:]]}
+; CHECK-LLVM: ![[#CU1]] = distinct !DICompileUnit(language: DW_LANG_OpenCL, file: ![[#File:]], producer: "clang version 14", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK-LLVM: ![[#File]] = !DIFile(filename: "foo.c", directory: "/tmp")
+; CHECK-LLVM: ![[#CU2]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: ![[#File]], producer: "clang version 14", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK-LLVM: ![[#Empty:]] = !{}
+; CHECK-LLVM: ![[#Func1]] = distinct !DISubprogram(name: "foo", scope: null, file: ![[#File]], line: 5, type: ![[#Func1T:]], scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[#CU1]], templateParams: ![[#Empty]], retainedNodes: ![[#Empty]])
+; CHECK-LLVM: ![[#Func1T]] = !DISubroutineType(types: ![[#Func1TP:]])
+; CHECK-LLVM: ![[#Func1TP]] = !{null}
+; CHECK-LLVM: ![[#Puts1Loc]] = !DILocation(line: 6, column: 3, scope: ![[#Puts1Scope:]])
+; CHECK-LLVM: ![[#Puts1Scope]] = distinct !DILexicalBlock(scope: ![[#Func1]], file: ![[#File]], line: 5, column: 16)
+; CHECK-LLVM: ![[#Ret1]] = !DILocation(line: 7, column: 1, scope: ![[#Puts1Scope]])
+; CHECK-LLVM: ![[#Func2]] = distinct !DISubprogram(name: "main", scope: null, file: ![[#File]], line: 11, type: ![[#Func2T:]], scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[#CU2]], templateParams: ![[#Empty]], retainedNodes: ![[#Fun2Params:]])
+; CHECK-LLVM: ![[#Func2T]] = !DISubroutineType(types: ![[#Func2TP:]])
+; CHECK-LLVM: ![[#Func2TP]] = !{![[#Func2TP1:]],
+; CHECK-LLVM-SAME: ![[#Func2TP1]], ![[#Func2TP2:]]
+; CHECK-LLVM: ![[#Func2TP1]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK-LLVM: ![[#Func2TP2]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+; CHECK-LLVM: ![[#Fun2Params]] = !{![[#Fun2Param1]], ![[#Fun2Param2]]}
+; CHECK-LLVM: ![[#Fun2Param1]] = !DILocalVariable(name: "argc", arg: 1, scope: ![[#Func2]], file: ![[#File]], line: 11, type: ![[#Func2TP1]])
+; CHECK-LLVM: ![[#Fun2Param2]] = !DILocalVariable(name: "argv", arg: 2, scope: ![[#Func2]], file: ![[#File]], line: 11, type: ![[#Func2TP2]])
+; CHECK-LLVM: ![[#Fun2Param1Loc:]] = !DILocation(line: 11, column: 14, scope: ![[#Func2]])
+; CHECK-LLVM: ![[#Fun2Param2Loc:]] = !DILocation(line: 11, column: 26, scope: ![[#Func2]])
+; CHECK-LLVM: ![[#Puts2Loc]] = !DILocation(line: 12, column: 3, scope: ![[#Puts2Scope:]]
+; CHECK-LLVM: ![[#Puts2Scope]] = distinct !DILexicalBlock(scope: ![[#Func2]], file: ![[#File]], line: 11, column: 34)
+; CHECK-LLVM: ![[#CallFoo]] = !DILocation(line: 13, column: 3, scope: ![[#Puts2Scope]])
+; CHECK-LLVM: ![[#Ret2]] = !DILocation(line: 14, column: 3, scope: ![[#Puts2Scope]])
+
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
+target triple = "spir64-unknown-unknown"
+
+; ModuleID = 'test.bc'
+
+@str = private unnamed_addr constant [4 x i8] c"FOO\00"
+@str1 = private unnamed_addr constant [6 x i8] c"Main!\00"
+
+define void @foo() nounwind !dbg !5 {
+entry:
+  %puts = tail call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @str, i32 0, i32 0)), !dbg !23
+  ret void, !dbg !25
+}
+
+declare i32 @puts(i8* nocapture) nounwind
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind !dbg !12 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 %argc, metadata !21, metadata !DIExpression()), !dbg !26
+  ; Avoid talking about the pointer size in debug info because that's target dependent
+  tail call void @llvm.dbg.value(metadata i8** %argv, metadata !22, metadata !DIExpression(DW_OP_deref, DW_OP_deref)), !dbg !27
+  %puts = tail call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str1, i32 0, i32 0)), !dbg !28
+  tail call void @foo() nounwind, !dbg !30
+  ret i32 0, !dbg !31
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!0, !9}
+!llvm.module.flags = !{!33}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 14", isOptimized: true, emissionKind: FullDebug, file: !32, enums: !1, retainedTypes: !1, globals: !1, imports: !1)
+!1 = !{}
+!5 = distinct !DISubprogram(name: "foo", line: 5, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 5, file: !32, scope: !6, type: !7, retainedNodes: !1)
+!6 = !DIFile(filename: "foo.c", directory: "/tmp")
+!7 = !DISubroutineType(types: !8)
+!8 = !{null}
+!9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, producer: "clang version 14", isOptimized: true, emissionKind: FullDebug, file: !32, enums: !1, retainedTypes: !1, globals: !1, imports: !1)
+!12 = distinct !DISubprogram(name: "main", line: 11, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !9, scopeLine: 11, file: !32, scope: !6, type: !13, retainedNodes: !19)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!15, !15, !18}
+!15 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!18 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
+!19 = !{!21, !22}
+!21 = !DILocalVariable(name: "argc", line: 11, arg: 1, scope: !12, file: !6, type: !15)
+!22 = !DILocalVariable(name: "argv", line: 11, arg: 2, scope: !12, file: !6, type: !18)
+!23 = !DILocation(line: 6, column: 3, scope: !24)
+!24 = distinct !DILexicalBlock(line: 5, column: 16, file: !32, scope: !5)
+!25 = !DILocation(line: 7, column: 1, scope: !24)
+!26 = !DILocation(line: 11, column: 14, scope: !12)
+!27 = !DILocation(line: 11, column: 26, scope: !12)
+!28 = !DILocation(line: 12, column: 3, scope: !29)
+!29 = distinct !DILexicalBlock(line: 11, column: 34, file: !32, scope: !12)
+!30 = !DILocation(line: 13, column: 3, scope: !29)
+!31 = !DILocation(line: 14, column: 3, scope: !29)
+!32 = !DIFile(filename: "foo.c", directory: "/tmp")
+!33 = !{i32 1, !"Debug Info Version", i32 3}
index 0ec0f2f2a4aeb87740433a049e139c2f5e2f0c9a..27d80af1fd2fabcf7cddaa0eac08127f174af7a0 100644 (file)
@@ -7,7 +7,7 @@
 ; CHECK: DW_TAG_compile_unit
 ; CHECK:   DW_TAG_subprogram
 ; CHECK:     DW_AT_name{{.*}}"f"
-; CHECK-NOT: DW_TAG_compile_unit
+; CHECK: DW_TAG_compile_unit
 ;
 ; created from
 ;   void f() {} // compile with -g
index b4afeed32e766155a9cf14380b70fc79b47c314d..03e57cb6788351494ad23d4b3c8fd47fb5c194a5 100644 (file)
@@ -24,7 +24,7 @@ target triple = "spir64-unknown-unknown"
 
 ; CHECK: .debug_info contents:
 ; CHECK: Compile Unit
-; CHECK-NOT: Compile Unit
+; CHECK: Compile Unit
 ; CHECK: .debug_info.dwo contents: