From: Dmitry Sidorov Date: Wed, 19 Apr 2023 13:34:06 +0000 (+0200) Subject: [PATCH 34/79] [Backport to 15][DebugInfo] Support multiple CompileUnits (#1950) X-Git-Tag: archive/raspbian/15.0.0-6+rpi1^2~47 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=54a89f302727b8660954d4e07da1955b9d42c6e3;p=spirv-llvm-translator-15.git [PATCH 34/79] [Backport to 15][DebugInfo] Support multiple CompileUnits (#1950) 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 BuilderMap was introduced to SPIR-V consumption part and std::unordered_map 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 Gbp-Pq: Name 0034-Backport-to-15-DebugInfo-Support-multiple-CompileUni.patch --- diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp index 6a1e948..e36658b 100644 --- a/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +++ b/lib/SPIRV/LLVMToSPIRVDbgTran.cpp @@ -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( + SPIRVCUMap[CU] = static_cast( 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(Context) || isa(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(Scope)) - Ops[ParentIdx] = SPIRVCU->getId(); - else + if (Scope && !isa(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()) diff --git a/lib/SPIRV/LLVMToSPIRVDbgTran.h b/lib/SPIRV/LLVMToSPIRVDbgTran.h index 9e5f711..d43040d 100644 --- a/lib/SPIRV/LLVMToSPIRVDbgTran.h +++ b/lib/SPIRV/LLVMToSPIRVDbgTran.h @@ -164,7 +164,7 @@ private: SPIRVType *VoidT = nullptr; SPIRVType *Int32T = nullptr; SPIRVEntry *DebugInfoNone; - SPIRVExtInst *SPIRVCU; + std::unordered_map SPIRVCUMap; std::vector DbgDeclareIntrinsics; std::vector DbgValueIntrinsics; }; // class LLVMToSPIRVDbgTran diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 6293e44..85731c3 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -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()) { diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp index 54339fb..2ad7b4a 100644 --- a/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +++ b/lib/SPIRV/SPIRVToLLVMDbgTran.cpp @@ -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> 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(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(*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(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(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(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(Ops[Ops.size() / 2 + I]))) { auto *UpperBound = transDebugInst(ExprUB); auto *LowerBound = transDebugInst(ExprLB); - Subscripts.push_back(Builder.getOrCreateSubrange(nullptr, LowerBound, - UpperBound, nullptr)); + Subscripts.push_back(getDIBuilder(DebugInst).getOrCreateSubrange( + nullptr, LowerBound, UpperBound, nullptr)); continue; } if (!getDbgInst(Ops[I])) { @@ -289,21 +298,24 @@ SPIRVToLLVMDbgTran::transTypeArrayOpenCL(const SPIRVExtInst *DebugInst) { if (Ops.size() / 2 + I < Ops.size()) { C = BM->get(Ops[Ops.size() / 2 + I]); int64_t LowerBound = static_cast(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(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 Allocated = TransOperand(AllocatedIdx); PointerUnion 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 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(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(Val)); + return getDIBuilder(DebugInst).createStaticMemberType( + Scope, Name, File, LineNo, BaseType, Flags, cast(Val)); } uint64_t Size = BM->get(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 Elts; for (size_t I = FirstEnumeratorIdx, E = Ops.size(); I < E; I += 2) { uint64_t Val = BM->get(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(E)) UnderlyingType = transDebugInst(static_cast(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(Ops[MemberTypeIdx]); DIType *PointeeTy = transDebugInst(Member); SPIRVExtInst *ContainingTy = BM->get(Ops[ParentIdx]); DIType *BaseTy = transDebugInst(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 Elts; - DINodeArray TParams = Builder.getOrCreateArray(Elts); + DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts); llvm::DITemplateParameterArray TParamsArray = TParams.get(); DISubprogram *DIS = nullptr; if (Scope && (isa(Scope) || isa(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 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(Scope) || isa(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(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(static_cast(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(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(Ops[ValueIdx])) { SPIRVValue *Val = BM->get(Ops[ValueIdx]); Value *V = SPIRVReader->transValue(Val, nullptr, nullptr); - return Builder.createTemplateValueParameter(Context, Name, Ty, false, - cast(V)); + return getDIBuilder(DebugInst).createTemplateValueParameter( + Context, Name, Ty, false, cast(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(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(Ops[I]))); } - DINodeArray TParams = Builder.getOrCreateArray(Elts); + DINodeArray TParams = getDIBuilder(DebugInst).getOrCreateArray(Elts); if (DICompositeType *Comp = dyn_cast(D)) { - Builder.replaceArrays(Comp, Comp->getElements(), TParams); + getDIBuilder(DebugInst).replaceArrays(Comp, Comp->getElements(), TParams); return Comp; } if (isa(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(nullptr), File, Line); if (DIModule *DM = dyn_cast(Entity)) - return Builder.createImportedModule(Scope, DM, File, Line); + return getDIBuilder(DebugInst).createImportedModule(Scope, DM, File, + Line); if (DIImportedEntity *IE = dyn_cast(Entity)) - return Builder.createImportedModule(Scope, IE, File, Line); + return getDIBuilder(DebugInst).createImportedModule(Scope, IE, File, + Line); if (DINamespace *NS = dyn_cast(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(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 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 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(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) { diff --git a/lib/SPIRV/SPIRVToLLVMDbgTran.h b/lib/SPIRV/SPIRVToLLVMDbgTran.h index 2102f21..f6b3168 100644 --- a/lib/SPIRV/SPIRVToLLVMDbgTran.h +++ b/lib/SPIRV/SPIRVToLLVMDbgTran.h @@ -160,7 +160,7 @@ private: SPIRVModule *BM; Module *M; - DIBuilder Builder; + std::unordered_map> 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 SPIRVExtInst *getDbgInst(const SPIRVId Id) { if (SPIRVExtInst *DI = getDbgInst(Id)) { if (DI->getExtOp() == OpCode) { diff --git a/lib/SPIRV/libSPIRV/SPIRV.debug.h b/lib/SPIRV/libSPIRV/SPIRV.debug.h index f1e6aba..19170e1 100644 --- a/lib/SPIRV/libSPIRV/SPIRV.debug.h +++ b/lib/SPIRV/libSPIRV/SPIRV.debug.h @@ -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 index 0000000..b1427b0 --- /dev/null +++ b/test/DebugInfo/Generic/c-and-cpp-mixed.ll @@ -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} diff --git a/test/DebugInfo/X86/mixed-nodebug-cu.ll b/test/DebugInfo/X86/mixed-nodebug-cu.ll index 0ec0f2f..27d80af 100644 --- a/test/DebugInfo/X86/mixed-nodebug-cu.ll +++ b/test/DebugInfo/X86/mixed-nodebug-cu.ll @@ -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 diff --git a/test/DebugInfo/X86/split-dwarf-omit-empty.ll b/test/DebugInfo/X86/split-dwarf-omit-empty.ll index b4afeed..03e57cb 100644 --- a/test/DebugInfo/X86/split-dwarf-omit-empty.ll +++ b/test/DebugInfo/X86/split-dwarf-omit-empty.ll @@ -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: