Index: include/llvm/Linker/IRMover.h =================================================================== --- include/llvm/Linker/IRMover.h +++ include/llvm/Linker/IRMover.h @@ -63,7 +63,8 @@ bool move(Module &Src, ArrayRef ValuesToLink, std::function AddLazyFor, DenseMap *ValIDToTempMDMap = nullptr, - bool IsMetadataLinkingPostpass = false); + bool IsMetadataLinkingPostpass = false, + bool IsFunctionImport = false); Module &getModule() { return Composite; } private: Index: lib/Linker/IRMover.cpp =================================================================== --- lib/Linker/IRMover.cpp +++ lib/Linker/IRMover.cpp @@ -408,6 +408,11 @@ /// importing). bool IsMetadataLinkingPostpass; + /// Flag indicating that this is a module with a function being + /// imported for ThinLTO. Used to control the amount of metadata + /// linked in. + bool IsFunctionImport; + /// Flags to pass to value mapper invocations. RemapFlags ValueMapperFlags = RF_MoveDistinctMDs; @@ -510,11 +515,12 @@ ArrayRef ValuesToLink, std::function AddLazyFor, DenseMap *ValIDToTempMDMap = nullptr, - bool IsMetadataLinkingPostpass = false) + bool IsMetadataLinkingPostpass = false, + bool IsFunctionImport = false) : DstM(DstM), SrcM(SrcM), AddLazyFor(AddLazyFor), TypeMap(Set), GValMaterializer(this), LValMaterializer(this), IsMetadataLinkingPostpass(IsMetadataLinkingPostpass), - ValIDToTempMDMap(ValIDToTempMDMap) { + IsFunctionImport(IsFunctionImport), ValIDToTempMDMap(ValIDToTempMDMap) { for (GlobalValue *GV : ValuesToLink) maybeAdd(GV); @@ -1271,11 +1277,45 @@ void IRLinker::linkNamedMDNodes() { findNeededSubprograms(); const NamedMDNode *SrcModFlags = SrcM.getModuleFlagsMetadata(); + NamedMDNode *CompileUnits = SrcM.getNamedMetadata("llvm.dbg.cu"); for (const NamedMDNode &NMD : SrcM.named_metadata()) { // Don't link module flags here. Do them separately. if (&NMD == SrcModFlags) continue; NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName()); + + // Check if we are importing a function from the source module for + // ThinLTO. In that case we only need to map in metadata for imported + // functions, and don't need to link in the enums, types and other + // metadata hanging off the DICompileUnit. Create a simple DICompileUnit + // with just the needed DISubprograms linked, as well as the DIFile which + // is required. + if (&NMD == CompileUnits && IsFunctionImport) { + for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) { + auto *CU = cast(CompileUnits->getOperand(I)); + assert(CU && "Expected valid compile unit"); + // Map just the DIFile and DISubprogram operands. + auto *NewFile = + MapMetadata(CU->getFile(), ValueMap, + ValueMapperFlags | RF_NullMapMissingGlobalValues, + &TypeMap, &GValMaterializer); + auto *NewSubprograms = + MapMetadata(CU->getSubprograms().get(), ValueMap, + ValueMapperFlags | RF_NullMapMissingGlobalValues, + &TypeMap, &GValMaterializer); + // Create the simple DICompileUnit to hold the necessary + // mapped operands (DISubprogram and DIFile) and other simple + // non-metadata operands. + auto *NewCU = DICompileUnit::getDistinct( + CU->getContext(), CU->getSourceLanguage(), NewFile, nullptr, + CU->isOptimized(), nullptr, CU->getRuntimeVersion(), nullptr, + CU->getEmissionKind(), nullptr, nullptr, NewSubprograms, nullptr, + nullptr, nullptr, CU->getDWOId()); + DestNMD->addOperand(NewCU); + } + continue; + } + // Add Src elements into Dest node. for (const MDNode *op : NMD.operands()) DestNMD->addOperand(MapMetadata( @@ -1671,9 +1711,10 @@ Module &Src, ArrayRef ValuesToLink, std::function AddLazyFor, DenseMap *ValIDToTempMDMap, - bool IsMetadataLinkingPostpass) { + bool IsMetadataLinkingPostpass, bool IsFunctionImport) { IRLinker TheIRLinker(Composite, IdentifiedStructTypes, Src, ValuesToLink, - AddLazyFor, ValIDToTempMDMap, IsMetadataLinkingPostpass); + AddLazyFor, ValIDToTempMDMap, IsMetadataLinkingPostpass, + IsFunctionImport); bool RetCode = TheIRLinker.run(); Composite.dropTriviallyDeadConstantArrays(); return RetCode; Index: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ lib/Linker/LinkModules.cpp @@ -806,7 +806,7 @@ [this](GlobalValue &GV, IRMover::ValueAdder Add) { addLazyFor(GV, Add); }, - ValIDToTempMDMap, false)) + ValIDToTempMDMap, false, isPerformingImport())) return true; Module &DstM = Mover.getModule(); for (auto &P : Internalize) { @@ -839,7 +839,7 @@ if (Mover.move( Src, ValuesToLink.getArrayRef(), [this](GlobalValue &GV, IRMover::ValueAdder Add) { assert(false); }, - ValIDToTempMDMap, true)) + ValIDToTempMDMap, true, true)) return true; return false; } Index: test/Linker/thinlto_funcimport_debug.ll =================================================================== --- test/Linker/thinlto_funcimport_debug.ll +++ test/Linker/thinlto_funcimport_debug.ll @@ -13,6 +13,7 @@ ; that neither contains null. ; CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}} subprograms: ![[SPs1:[0-9]+]] ; CHECK-NOT: ![[SPs1]] = !{{{.*}}null{{.*}}} +; CHECK-NOT: distinct !DICompileUnit({{.*}} enums: ; CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}} subprograms: ![[SPs2:[0-9]+]] ; CHECK-NOT: ![[SPs2]] = !{{{.*}}null{{.*}}} Index: test/Transforms/FunctionImport/funcimport_debug.ll =================================================================== --- test/Transforms/FunctionImport/funcimport_debug.ll +++ test/Transforms/FunctionImport/funcimport_debug.ll @@ -14,6 +14,7 @@ ; CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}} subprograms: ![[SPs1:[0-9]+]] ; CHECK: ![[SPs1]] = !{![[MAINSP:[0-9]+]]} ; CHECK: ![[MAINSP]] = distinct !DISubprogram(name: "main" +; CHECK-NOT: distinct !DICompileUnit({{.*}} enums: ; CHECK: !{{[0-9]+}} = distinct !DICompileUnit({{.*}} subprograms: ![[SPs2:[0-9]+]] ; CHECK-NOT: ![[SPs2]] = !{{{.*}}null{{.*}}} ; CHECK: ![[SPs2]] = !{![[FUNCSP:[0-9]+]]}