Index: include/llvm/Linker/Linker.h =================================================================== --- include/llvm/Linker/Linker.h +++ include/llvm/Linker/Linker.h @@ -68,8 +68,10 @@ void deleteModule(); /// \brief Link \p Src into the composite. The source is destroyed. + /// Passing OverrideSymbols as true will have symbols from Src + /// shadow those in the Dest. /// Returns true on error. - bool linkInModule(Module *Src); + bool linkInModule(Module *Src, bool OverrideSymbols = false); /// \brief Set the composite to the passed-in module. void setModule(Module *Dst); Index: lib/Linker/LinkModules.cpp =================================================================== --- lib/Linker/LinkModules.cpp +++ lib/Linker/LinkModules.cpp @@ -424,12 +424,17 @@ DiagnosticHandlerFunction DiagnosticHandler; + /// For symbol clashes, prefer those from Src. + bool OverrideFromSrc; + public: ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM, - DiagnosticHandlerFunction DiagnosticHandler) + DiagnosticHandlerFunction DiagnosticHandler, + bool Override = false) : DstM(dstM), SrcM(srcM), TypeMap(Set), ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues), - DiagnosticHandler(DiagnosticHandler) {} + DiagnosticHandler(DiagnosticHandler), + OverrideFromSrc(Override) {} bool run(); @@ -794,6 +799,12 @@ assert(!Dest.hasExternalWeakLinkage()); assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() && "Unexpected linkage type!"); + + if (OverrideFromSrc) { + LinkFromSrc = true; + return false; + } + return emitError("Linking globals named '" + Src.getName() + "': symbol multiply defined!"); } @@ -1738,9 +1749,9 @@ Composite = nullptr; } -bool Linker::linkInModule(Module *Src) { +bool Linker::linkInModule(Module *Src, bool OverrideSymbols) { ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, - DiagnosticHandler); + DiagnosticHandler, OverrideSymbols); bool RetCode = TheLinker.run(); Composite->dropTriviallyDeadConstantArrays(); return RetCode; Index: test/tools/llvm-link/Inputs/foo.ll =================================================================== --- /dev/null +++ test/tools/llvm-link/Inputs/foo.ll @@ -0,0 +1,4 @@ +define i32 @foo(i32 %i) { +entry: + ret i32 4 +} Index: test/tools/llvm-link/hello.ll =================================================================== --- /dev/null +++ test/tools/llvm-link/hello.ll @@ -0,0 +1,18 @@ +; RUN: llvm-link %s -override %p/Inputs/foo.ll -S | FileCheck %s + + +; CHECK-LABEL: define i32 @foo +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 4 +define i32 @foo(i32 %i) { +entry: + %add = add nsw i32 %i, %i + ret i32 %add +} + +; Function Attrs: nounwind ssp uwtable +define i32 @main(i32 %argc, i8** %argv) { +entry: + %a = call i32 @foo(i32 2) + ret i32 %a +} Index: test/tools/llvm-link/lit.local.cfg =================================================================== --- /dev/null +++ test/tools/llvm-link/lit.local.cfg @@ -0,0 +1 @@ +config.suffixes = ['.ll'] Index: tools/llvm-link/llvm-link.cpp =================================================================== --- tools/llvm-link/llvm-link.cpp +++ tools/llvm-link/llvm-link.cpp @@ -38,6 +38,11 @@ InputFilenames(cl::Positional, cl::OneOrMore, cl::desc("")); +static cl::list +OverridingInputs("override", cl::ZeroOrMore, cl::value_desc("filename"), + cl::desc("input bitcode file which can " + "override previously defined symbol")); + static cl::opt OutputFilename("o", cl::desc("Override output filename"), cl::init("-"), cl::value_desc("filename")); @@ -119,24 +124,29 @@ auto Composite = make_unique("llvm-link", Context); Linker L(Composite.get(), diagnosticHandler); - for (unsigned i = 0; i < InputFilenames.size(); ++i) { - std::unique_ptr M = loadFile(argv[0], InputFilenames[i], Context); - if (!M.get()) { - errs() << argv[0] << ": error loading file '" <& Files, bool Override) { + for (auto File : Files) { + std::unique_ptr M = loadFile(argv[0], File, Context); + if (!M.get()) { + errs() << argv[0] << ": error loading file '" << File << "'\n"; + exit(1); + } - if (verifyModule(*M, &errs())) { - errs() << argv[0] << ": " << InputFilenames[i] - << ": error: input module is broken!\n"; - return 1; - } + if (verifyModule(*M, &errs())) { + errs() << argv[0] << ": " << File + << ": error: input module is broken!\n"; + exit(1); + } - if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n"; + if (Verbose) errs() << "Linking in '" << File << "'\n"; - if (L.linkInModule(M.get())) - return 1; - } + if (L.linkInModule(M.get(), Override)) + exit(1); + } + }; + + linkFiles(InputFilenames, false); + linkFiles(OverridingInputs, true); if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;