Index: include/llvm/Linker/Linker.h =================================================================== --- include/llvm/Linker/Linker.h +++ include/llvm/Linker/Linker.h @@ -11,6 +11,7 @@ #define LLVM_LINKER_LINKER_H #include "llvm/Linker/IRMover.h" +#include "llvm/ADT/StringSet.h" namespace llvm { class Module; @@ -40,10 +41,15 @@ /// shadow those in the Dest. /// /// Returns true on error. - bool linkInModule(std::unique_ptr Src, unsigned Flags = Flags::None); - - static bool linkModules(Module &Dest, 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, + 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 @@ -104,8 +105,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 = + std::function)>()) + : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags), + InternalizeCallback(std::move(InternalizeCallback)) {} bool run(); }; @@ -547,18 +551,19 @@ if (HasErrors) return true; - for (auto &P : Internalize) { - GlobalValue *GV = DstM.getNamedValue(P.first()); - GV->setLinkage(GlobalValue::InternalLinkage); - } + if (shouldInternalizeLinkedSymbols() && 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 +576,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,15 +34,15 @@ #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 #include using namespace llvm; -static cl::list -InputFilenames(cl::Positional, cl::OneOrMore, - cl::desc("")); +static cl::list InputFilenames(cl::Positional, cl::OneOrMore, + cl::desc("")); static cl::list OverridingInputs( "override", cl::ZeroOrMore, cl::value_desc("filename"), @@ -65,39 +65,38 @@ SummaryIndex("summary-index", cl::desc("Module summary index filename"), cl::init(""), cl::value_desc("filename")); -static cl::opt -OutputFilename("o", cl::desc("Override output filename"), cl::init("-"), - cl::value_desc("filename")); +static cl::opt OutputFilename("o", + cl::desc("Override output filename"), + cl::init("-"), + cl::value_desc("filename")); -static cl::opt -Internalize("internalize", cl::desc("Internalize linked symbols")); +static cl::opt Internalize("internalize", + cl::desc("Internalize linked symbols")); static cl::opt DisableDITypeMap("disable-debug-info-type-map", cl::desc("Don't use a uniquing type map for debug info")); -static cl::opt -OnlyNeeded("only-needed", cl::desc("Link only needed symbols")); +static cl::opt OnlyNeeded("only-needed", + cl::desc("Link only needed symbols")); -static cl::opt -Force("f", cl::desc("Enable binary output on terminals")); +static cl::opt Force("f", cl::desc("Enable binary output on terminals")); -static cl::opt - DisableLazyLoad("disable-lazy-loading", - cl::desc("Disable lazy module loading")); +static cl::opt DisableLazyLoad("disable-lazy-loading", + cl::desc("Disable lazy module loading")); static cl::opt OutputAssembly("S", cl::desc("Write output as LLVM assembly"), cl::Hidden); -static cl::opt -Verbose("v", cl::desc("Print information about actions taken")); +static cl::opt Verbose("v", + cl::desc("Print information about actions taken")); -static cl::opt -DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden); +static cl::opt DumpAsm("d", cl::desc("Print assembly as linked"), + cl::Hidden); -static cl::opt -SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"), - cl::init(false)); +static cl::opt SuppressWarnings("suppress-warnings", + cl::desc("Suppress all linking warnings"), + cl::init(false)); static cl::opt PreserveBitcodeUseListOrder( "preserve-bc-uselistorder", @@ -119,7 +118,8 @@ LLVMContext &Context, bool MaterializeMetadata = true) { SMDiagnostic Err; - if (Verbose) errs() << "Loading '" << FN << "'\n"; + if (Verbose) + errs() << "Loading '" << FN << "'\n"; std::unique_ptr Result; if (DisableLazyLoad) Result = parseIRFile(FN, Err, Context); @@ -268,8 +268,7 @@ } static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L, - const cl::list &Files, - unsigned Flags) { + const cl::list &Files, unsigned Flags) { // Filter out flags that don't apply to the first file we load. unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc; for (const auto &File : Files) { @@ -311,7 +310,13 @@ if (Verbose) errs() << "Linking in '" << File << "'\n"; - if (L.linkInModule(std::move(M), ApplicableFlags)) + if (L.linkInModule( + std::move(M), ApplicableFlags, [](Module &M, StringSet<> GVS) { + InternalizePass IP([&M, &GVS](const GlobalValue &GV) { + return !GV.hasName() || (GVS.count(GV.getName()) == 0); + }); + IP.internalizeModule(M); + })) return false; // All linker flags apply to linking of subsequent files. ApplicableFlags = Flags; @@ -330,7 +335,7 @@ LLVMContext Context; Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); if (!DisableDITypeMap) @@ -358,7 +363,8 @@ if (!importFunctions(argv[0], *Composite)) return 1; - if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite; + if (DumpAsm) + errs() << "Here's the assembly:\n" << *Composite; std::error_code EC; tool_output_file Out(OutputFilename, EC, sys::fs::F_None); @@ -372,7 +378,8 @@ return 1; } - if (Verbose) errs() << "Writing bitcode...\n"; + if (Verbose) + errs() << "Writing bitcode...\n"; if (OutputAssembly) { Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder); } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))