Index: include/llvm/Linker/Linker.h =================================================================== --- include/llvm/Linker/Linker.h +++ include/llvm/Linker/Linker.h @@ -10,6 +10,7 @@ #ifndef LLVM_LINKER_LINKER_H #define LLVM_LINKER_LINKER_H +#include "llvm/ADT/StringSet.h" #include "llvm/Linker/IRMover.h" namespace llvm { @@ -29,7 +30,6 @@ None = 0, OverrideFromSrc = (1 << 0), LinkOnlyNeeded = (1 << 1), - InternalizeLinkedSymbols = (1 << 2), }; Linker(Module &M); @@ -40,10 +40,14 @@ /// shadow those in the Dest. /// /// Returns true on error. - bool linkInModule(std::unique_ptr Src, unsigned Flags = Flags::None); + bool linkInModule(std::unique_ptr Src, unsigned Flags = Flags::None, + std::function &)> + InternalizeCallback = {}); static bool linkModules(Module &Dest, std::unique_ptr Src, - unsigned Flags = Flags::None); + unsigned Flags = Flags::None, + std::function &)> + InternalizeCallback = {}); }; } // End llvm namespace Index: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ lib/Linker/LinkModules.cpp @@ -14,7 +14,6 @@ #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" @@ -33,11 +32,13 @@ std::unique_ptr SrcM; SetVector ValuesToLink; - StringSet<> Internalize; /// For symbol clashes, prefer those from Src. unsigned Flags; + StringSet<> Internalize; + std::function &)> InternalizeCallback; + /// Used as the callback for lazy linking. /// The mover has just hit GV and we have to decide if it, and other members /// of the same comdat, should be linked. Every member to be linked is passed @@ -46,9 +47,6 @@ 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); @@ -104,8 +102,11 @@ bool linkIfNeeded(GlobalValue &GV); public: - ModuleLinker(IRMover &Mover, std::unique_ptr SrcM, unsigned Flags) - : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags) {} + ModuleLinker(IRMover &Mover, std::unique_ptr SrcM, unsigned Flags, + std::function &)> + InternalizeCallback = {}) + : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags), + InternalizeCallback(std::move(InternalizeCallback)) {} bool run(); }; @@ -383,7 +384,7 @@ !shouldLinkOnlyNeeded()) return; - if (shouldInternalizeLinkedSymbols()) + if (InternalizeCallback) Internalize.insert(GV.getName()); Add(GV); @@ -397,7 +398,7 @@ return; if (!LinkFromSrc) continue; - if (shouldInternalizeLinkedSymbols()) + if (InternalizeCallback) Internalize.insert(GV2->getName()); Add(*GV2); } @@ -526,7 +527,7 @@ } } - if (shouldInternalizeLinkedSymbols()) { + if (InternalizeCallback) { for (GlobalValue *GV : ValuesToLink) Internalize.insert(GV->getName()); } @@ -547,18 +548,19 @@ 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 Src, unsigned Flags) { - ModuleLinker ModLinker(Mover, std::move(Src), Flags); +bool Linker::linkInModule( + std::unique_ptr Src, unsigned Flags, + std::function &)> InternalizeCallback) { + ModuleLinker ModLinker(Mover, std::move(Src), Flags, + std::move(InternalizeCallback)); return ModLinker.run(); } @@ -571,10 +573,11 @@ /// 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 Src, - unsigned Flags) { +bool Linker::linkModules( + Module &Dest, std::unique_ptr Src, unsigned Flags, + std::function &)> InternalizeCallback) { Linker L(Dest); - return L.linkInModule(std::move(Src), Flags); + return L.linkInModule(std::move(Src), Flags, std::move(InternalizeCallback)); } //===----------------------------------------------------------------------===// Index: tools/llvm-link/llvm-link.cpp =================================================================== --- tools/llvm-link/llvm-link.cpp +++ tools/llvm-link/llvm-link.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/SystemUtils.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Transforms/IPO/FunctionImport.h" +#include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include @@ -272,6 +273,8 @@ unsigned Flags) { // Filter out flags that don't apply to the first file we load. unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc; + // Similar to some falgs, internalization doesn't apply to the first file. + bool InternalizeLinkedSymbols = false; for (const auto &File : Files) { std::unique_ptr M = loadFile(argv0, File, Context); if (!M.get()) { @@ -311,8 +314,24 @@ if (Verbose) errs() << "Linking in '" << File << "'\n"; - if (L.linkInModule(std::move(M), ApplicableFlags)) + bool Err = false; + if (InternalizeLinkedSymbols) { + Err = L.linkInModule( + std::move(M), ApplicableFlags, [](Module &M, const StringSet<> &GVS) { + internalizeModule(M, [&M, &GVS](const GlobalValue &GV) { + return !GV.hasName() || (GVS.count(GV.getName()) == 0); + }); + }); + } else { + Err = L.linkInModule(std::move(M), ApplicableFlags); + } + + if (Err) return false; + + // Internalization applies to linking of subsequent files. + InternalizeLinkedSymbols = Internalize; + // All linker flags apply to linking of subsequent files. ApplicableFlags = Flags; } @@ -340,8 +359,6 @@ Linker L(*Composite); unsigned Flags = Linker::Flags::None; - if (Internalize) - Flags |= Linker::Flags::InternalizeLinkedSymbols; if (OnlyNeeded) Flags |= Linker::Flags::LinkOnlyNeeded;