diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
commit | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch) | |
tree | 5343938942df402b49ec7300a1c25a2d4ccd5821 /lib/Linker | |
parent | 31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff) |
Diffstat (limited to 'lib/Linker')
-rw-r--r-- | lib/Linker/IRMover.cpp | 24 | ||||
-rw-r--r-- | lib/Linker/LinkModules.cpp | 105 |
2 files changed, 44 insertions, 85 deletions
diff --git a/lib/Linker/IRMover.cpp b/lib/Linker/IRMover.cpp index 9f3cfc0eace4..15a46a2d0420 100644 --- a/lib/Linker/IRMover.cpp +++ b/lib/Linker/IRMover.cpp @@ -395,11 +395,12 @@ class IRLinker { Worklist.push_back(GV); } - /// Flag whether the ModuleInlineAsm string in Src should be linked with - /// (concatenated into) the ModuleInlineAsm string for the destination - /// module. It should be true for full LTO, but not when importing for - /// ThinLTO, otherwise we can have duplicate symbols. - bool LinkModuleInlineAsm; + /// Whether we are importing globals for ThinLTO, as opposed to linking the + /// source module. If this flag is set, it means that we can rely on some + /// other object file to define any non-GlobalValue entities defined by the + /// source module. This currently causes us to not link retained types in + /// debug info metadata and module inline asm. + bool IsPerformingImport; /// Set to true when all global value body linking is complete (including /// lazy linking). Used to prevent metadata linking from creating new @@ -491,10 +492,10 @@ public: IRMover::IdentifiedStructTypeSet &Set, std::unique_ptr<Module> SrcM, ArrayRef<GlobalValue *> ValuesToLink, std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor, - bool LinkModuleInlineAsm, bool IsPerformingImport) + bool IsPerformingImport) : DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(std::move(AddLazyFor)), TypeMap(Set), GValMaterializer(*this), LValMaterializer(*this), - SharedMDs(SharedMDs), LinkModuleInlineAsm(LinkModuleInlineAsm), + SharedMDs(SharedMDs), IsPerformingImport(IsPerformingImport), Mapper(ValueMap, RF_MoveDistinctMDs | RF_IgnoreMissingLocals, &TypeMap, &GValMaterializer), AliasMCID(Mapper.registerAlternateMappingContext(AliasValueMap, @@ -870,9 +871,6 @@ bool IRLinker::shouldLink(GlobalValue *DGV, GlobalValue &SGV) { if (DGV && !DGV->isDeclarationForLinker()) return false; - if (SGV.hasAvailableExternallyLinkage()) - return true; - if (SGV.isDeclaration() || DoneLinkingBodies) return false; @@ -1297,7 +1295,7 @@ Error IRLinker::run() { DstM.setTargetTriple(mergeTriples(SrcTriple, DstTriple)); // Append the module inline asm string. - if (LinkModuleInlineAsm && !SrcM->getModuleInlineAsm().empty()) { + if (!IsPerformingImport && !SrcM->getModuleInlineAsm().empty()) { if (DstM.getModuleInlineAsm().empty()) DstM.setModuleInlineAsm(SrcM->getModuleInlineAsm()); else @@ -1436,10 +1434,10 @@ IRMover::IRMover(Module &M) : Composite(M) { Error IRMover::move( std::unique_ptr<Module> Src, ArrayRef<GlobalValue *> ValuesToLink, std::function<void(GlobalValue &, ValueAdder Add)> AddLazyFor, - bool LinkModuleInlineAsm, bool IsPerformingImport) { + bool IsPerformingImport) { IRLinker TheIRLinker(Composite, SharedMDs, IdentifiedStructTypes, std::move(Src), ValuesToLink, std::move(AddLazyFor), - LinkModuleInlineAsm, IsPerformingImport); + IsPerformingImport); Error E = TheIRLinker.run(); Composite.dropTriviallyDeadConstantArrays(); return E; diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index cf2c4ccf523e..c0ce4bf76b9f 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -14,12 +14,13 @@ #include "LinkDiagnosticInfo.h" #include "llvm-c/Linker.h" #include "llvm/ADT/SetVector.h" -#include "llvm/ADT/StringSet.h" +#include "llvm/IR/Comdat.h" #include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/Error.h" -#include "llvm/Transforms/Utils/FunctionImportUtils.h" using namespace llvm; namespace { @@ -31,14 +32,17 @@ class ModuleLinker { std::unique_ptr<Module> SrcM; SetVector<GlobalValue *> ValuesToLink; - StringSet<> Internalize; /// For symbol clashes, prefer those from Src. unsigned Flags; - /// Functions to import from source module, all other functions are - /// imported as declarations instead of definitions. - DenseSet<const GlobalValue *> *GlobalsToImport; + /// List of global value names that should be internalized. + StringSet<> Internalize; + + /// Function that will perform the actual internalization. The reason for a + /// callback is that the linker cannot call internalizeModule without + /// creating a circular dependency between IPO and the linker. + std::function<void(Module &, const StringSet<> &)> InternalizeCallback; /// Used as the callback for lazy linking. /// The mover has just hit GV and we have to decide if it, and other members @@ -46,14 +50,8 @@ class ModuleLinker { /// to Add. void addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add); - bool shouldLinkReferencedLinkOnce() { - return !(Flags & Linker::DontForceLinkLinkonceODR); - } bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; } bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; } - bool shouldInternalizeLinkedSymbols() { - return Flags & Linker::InternalizeLinkedSymbols; - } bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest, const GlobalValue &Src); @@ -108,31 +106,17 @@ class ModuleLinker { bool linkIfNeeded(GlobalValue &GV); - /// Helper method to check if we are importing from the current source - /// module. - bool isPerformingImport() const { return GlobalsToImport != nullptr; } - - /// If we are importing from the source module, checks if we should - /// import SGV as a definition, otherwise import as a declaration. - bool doImportAsDefinition(const GlobalValue *SGV); - public: ModuleLinker(IRMover &Mover, std::unique_ptr<Module> SrcM, unsigned Flags, - DenseSet<const GlobalValue *> *GlobalsToImport = nullptr) + std::function<void(Module &, const StringSet<> &)> + InternalizeCallback = {}) : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags), - GlobalsToImport(GlobalsToImport) {} + InternalizeCallback(std::move(InternalizeCallback)) {} bool run(); }; } -bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) { - if (!isPerformingImport()) - return false; - return FunctionImportGlobalProcessing::doImportAsDefinition(SGV, - GlobalsToImport); -} - static GlobalValue::VisibilityTypes getMinVisibility(GlobalValue::VisibilityTypes A, GlobalValue::VisibilityTypes B) { @@ -266,18 +250,10 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc, // We always have to add Src if it has appending linkage. if (Src.hasAppendingLinkage()) { - // Should have prevented importing for appending linkage in linkIfNeeded. - assert(!isPerformingImport()); LinkFromSrc = true; return false; } - if (isPerformingImport()) { - // LinkFromSrc iff this is a global requested for importing. - LinkFromSrc = GlobalsToImport->count(&Src); - return false; - } - bool SrcIsDeclaration = Src.isDeclarationForLinker(); bool DestIsDeclaration = Dest.isDeclarationForLinker(); @@ -383,19 +359,9 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) { GV.setUnnamedAddr(UnnamedAddr); } - // Don't want to append to global_ctors list, for example, when we - // are importing for ThinLTO, otherwise the global ctors and dtors - // get executed multiple times for local variables (the latter causing - // double frees). - if (GV.hasAppendingLinkage() && isPerformingImport()) - return false; - - if (isPerformingImport()) { - if (!doImportAsDefinition(&GV)) - return false; - } else if (!DGV && !shouldOverrideFromSrc() && - (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() || - GV.hasAvailableExternallyLinkage())) + if (!DGV && !shouldOverrideFromSrc() && + (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() || + GV.hasAvailableExternallyLinkage())) return false; if (GV.isDeclaration()) @@ -418,17 +384,12 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) { } void ModuleLinker::addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add) { - if (!shouldLinkReferencedLinkOnce()) - // For ThinLTO we don't import more than what was required. - // The client has to guarantee that the linkonce will be availabe at link - // time (by promoting it to weak for instance). - return; - // Add these to the internalize list - if (!GV.hasLinkOnceLinkage() && !shouldLinkOnlyNeeded()) + if (!GV.hasLinkOnceLinkage() && !GV.hasAvailableExternallyLinkage() && + !shouldLinkOnlyNeeded()) return; - if (shouldInternalizeLinkedSymbols()) + if (InternalizeCallback) Internalize.insert(GV.getName()); Add(GV); @@ -442,7 +403,7 @@ void ModuleLinker::addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add) { return; if (!LinkFromSrc) continue; - if (shouldInternalizeLinkedSymbols()) + if (InternalizeCallback) Internalize.insert(GV2->getName()); Add(*GV2); } @@ -571,7 +532,7 @@ bool ModuleLinker::run() { } } - if (shouldInternalizeLinkedSymbols()) { + if (InternalizeCallback) { for (GlobalValue *GV : ValuesToLink) Internalize.insert(GV->getName()); } @@ -583,8 +544,7 @@ bool ModuleLinker::run() { [this](GlobalValue &GV, IRMover::ValueAdder Add) { addLazyFor(GV, Add); }, - /* LinkModuleInlineAsm */ !isPerformingImport(), - /* IsPerformingImport */ isPerformingImport())) { + /* IsPerformingImport */ false)) { handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { DstM.getContext().diagnose(LinkDiagnosticInfo(DS_Error, EIB.message())); HasErrors = true; @@ -593,19 +553,19 @@ bool ModuleLinker::run() { if (HasErrors) return true; - for (auto &P : Internalize) { - GlobalValue *GV = DstM.getNamedValue(P.first()); - GV->setLinkage(GlobalValue::InternalLinkage); - } + if (InternalizeCallback) + InternalizeCallback(DstM, Internalize); return false; } Linker::Linker(Module &M) : Mover(M) {} -bool Linker::linkInModule(std::unique_ptr<Module> Src, unsigned Flags, - DenseSet<const GlobalValue *> *GlobalsToImport) { - ModuleLinker ModLinker(Mover, std::move(Src), Flags, GlobalsToImport); +bool Linker::linkInModule( + std::unique_ptr<Module> Src, unsigned Flags, + std::function<void(Module &, const StringSet<> &)> InternalizeCallback) { + ModuleLinker ModLinker(Mover, std::move(Src), Flags, + std::move(InternalizeCallback)); return ModLinker.run(); } @@ -618,10 +578,11 @@ bool Linker::linkInModule(std::unique_ptr<Module> Src, unsigned Flags, /// true is returned and ErrorMsg (if not null) is set to indicate the problem. /// Upon failure, the Dest module could be in a modified state, and shouldn't be /// relied on to be consistent. -bool Linker::linkModules(Module &Dest, std::unique_ptr<Module> Src, - unsigned Flags) { +bool Linker::linkModules( + Module &Dest, std::unique_ptr<Module> Src, unsigned Flags, + std::function<void(Module &, const StringSet<> &)> InternalizeCallback) { Linker L(Dest); - return L.linkInModule(std::move(Src), Flags); + return L.linkInModule(std::move(Src), Flags, std::move(InternalizeCallback)); } //===----------------------------------------------------------------------===// |