<div dir="ltr"><div>From df1b11c561dc826d8e4836b9e910ac75185bcf05 Mon Sep 17 00:00:00 2001<br>From: Luqman Aden <<a href="mailto:luqman@apple.com">luqman@apple.com</a>><br>Date: Wed, 15 Apr 2015 12:22:32 -0700<br>Subject: [PATCH] llvm-link: Add -override flag to prefer one of a duplicate<br> symbol.<br><br>---<br> include/llvm/Linker/Linker.h       |  4 +++-<br> lib/Linker/LinkModules.cpp         | 20 +++++++++++++++----<br> test/tools/llvm-link/Inputs/foo.ll |  4 ++++<br> test/tools/llvm-link/hello.ll      | 20 +++++++++++++++++++<br> test/tools/llvm-link/lit.local.cfg |  1 +<br> tools/llvm-link/llvm-link.cpp      | 40 ++++++++++++++++++++++++--------------<br> 6 files changed, 69 insertions(+), 20 deletions(-)<br> create mode 100644 test/tools/llvm-link/Inputs/foo.ll<br> create mode 100644 test/tools/llvm-link/hello.ll<br> create mode 100644 test/tools/llvm-link/lit.local.cfg<br><br>diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h<br>index 5ca815c..c43b90e 100644<br>--- a/include/llvm/Linker/Linker.h<br>+++ b/include/llvm/Linker/Linker.h<br>@@ -68,8 +68,10 @@ public:<br>   void deleteModule();<br> <br>   /// \brief Link \p Src into the composite. The source is destroyed.<br>+  /// Passing OverrideSymbols as true will have symbols from Src<br>+  /// shadow those in the Dest.<br>   /// Returns true on error.<br>-  bool linkInModule(Module *Src);<br>+  bool linkInModule(Module *Src, bool OverrideSymbols = false);<br> <br>   /// \brief Set the composite to the passed-in module.<br>   void setModule(Module *Dst);<br>diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp<br>index 21edc50..3a46a33 100644<br>--- a/lib/Linker/LinkModules.cpp<br>+++ b/lib/Linker/LinkModules.cpp<br>@@ -424,12 +424,17 @@ class ModuleLinker {<br> <br>   DiagnosticHandlerFunction DiagnosticHandler;<br> <br>+  /// For symbol clashes, prefer those from Src.<br>+  bool OverrideFromSrc;<br>+<br> public:<br>   ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,<br>-               DiagnosticHandlerFunction DiagnosticHandler)<br>+               DiagnosticHandlerFunction DiagnosticHandler,<br>+               bool Override = false)<br>       : DstM(dstM), SrcM(srcM), TypeMap(Set),<br>         ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues),<br>-        DiagnosticHandler(DiagnosticHandler) {}<br>+        DiagnosticHandler(DiagnosticHandler),<br>+        OverrideFromSrc(Override) {}<br> <br>   bool run();<br> <br>@@ -725,6 +730,12 @@ bool ModuleLinker::getComdatResult(const Comdat *SrcC,<br> bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,<br>                                         const GlobalValue &Dest,<br>                                         const GlobalValue &Src) {<br>+  // Should we unconditionally use the Src?<br>+  if (OverrideFromSrc) {<br>+    LinkFromSrc = true;<br>+    return false;<br>+  }<br>+<br>   // We always have to add Src if it has appending linkage.<br>   if (Src.hasAppendingLinkage()) {<br>     LinkFromSrc = true;<br>@@ -794,6 +805,7 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,<br>   assert(!Dest.hasExternalWeakLinkage());<br>   assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() &&<br>          "Unexpected linkage type!");<br>+<br>   return emitError("Linking globals named '" + Src.getName() +<br>                    "': symbol multiply defined!");<br> }<br>@@ -1742,9 +1754,9 @@ void Linker::deleteModule() {<br>   Composite = nullptr;<br> }<br> <br>-bool Linker::linkInModule(Module *Src) {<br>+bool Linker::linkInModule(Module *Src, bool OverrideSymbols) {<br>   ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src,<br>-                         DiagnosticHandler);<br>+                         DiagnosticHandler, OverrideSymbols);<br>   bool RetCode = TheLinker.run();<br>   Composite->dropTriviallyDeadConstantArrays();<br>   return RetCode;<br>diff --git a/test/tools/llvm-link/Inputs/foo.ll b/test/tools/llvm-link/Inputs/foo.ll<br>new file mode 100644<br>index 0000000..6e06fa5<br>--- /dev/null<br>+++ b/test/tools/llvm-link/Inputs/foo.ll<br>@@ -0,0 +1,4 @@<br>+define i32 @foo(i32 %i) {<br>+entry:<br>+  ret i32 4<br>+}<br>diff --git a/test/tools/llvm-link/hello.ll b/test/tools/llvm-link/hello.ll<br>new file mode 100644<br>index 0000000..c124864<br>--- /dev/null<br>+++ b/test/tools/llvm-link/hello.ll<br>@@ -0,0 +1,20 @@<br>+; RUN: llvm-as %s -o %t-hello.bc<br>+; RUN: llvm-as %p/Inputs/foo.ll -o %t-foo.bc<br>+; RUN: llvm-link %t-hello.bc -override %t-foo.bc -S | FileCheck %s<br>+<br>+<br>+; CHECK-LABEL: define i32 @foo<br>+; CHECK-NEXT: entry:<br>+; CHECK-NEXT: ret i32 4<br>+define i32 @foo(i32 %i) {<br>+entry:<br>+  %add = add nsw i32 %i, %i<br>+  ret i32 %add<br>+}<br>+<br>+; Function Attrs: nounwind ssp uwtable<br>+define i32 @main(i32 %argc, i8** %argv) {<br>+entry:<br>+  %a = call i32 @foo(i32 2)<br>+  ret i32 %a<br>+}<br>diff --git a/test/tools/llvm-link/lit.local.cfg b/test/tools/llvm-link/lit.local.cfg<br>new file mode 100644<br>index 0000000..c6106e4<br>--- /dev/null<br>+++ b/test/tools/llvm-link/lit.local.cfg<br>@@ -0,0 +1 @@<br>+config.suffixes = ['.ll']<br>diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp<br>index 6924aa5..54d49f5 100644<br>--- a/tools/llvm-link/llvm-link.cpp<br>+++ b/tools/llvm-link/llvm-link.cpp<br>@@ -38,6 +38,11 @@ static cl::list<std::string><br> InputFilenames(cl::Positional, cl::OneOrMore,<br>                cl::desc("<input bitcode files>"));<br> <br>+static cl::list<std::string><br>+OverridingInputs("override", cl::ZeroOrMore, cl::value_desc("filename"),<br>+                 cl::desc("input bitcode file which can "<br>+                          "override previously defined symbol"));<br>+<br> static cl::opt<std::string><br> OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),<br>                cl::value_desc("filename"));<br>@@ -109,24 +114,29 @@ int main(int argc, char **argv) {<br>   auto Composite = make_unique<Module>("llvm-link", Context);<br>   Linker L(Composite.get(), diagnosticHandler);<br> <br>-  for (unsigned i = 0; i < InputFilenames.size(); ++i) {<br>-    std::unique_ptr<Module> M = loadFile(argv[0], InputFilenames[i], Context);<br>-    if (!M.get()) {<br>-      errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n";<br>-      return 1;<br>-    }<br>+  auto linkFiles = [&](const cl::list<std::string>& Files, bool Override) {<br>+    for (auto File : Files) {<br>+      std::unique_ptr<Module> M = loadFile(argv[0], File, Context);<br>+      if (!M.get()) {<br>+        errs() << argv[0] << ": error loading file '" << File << "'\n";<br>+        exit(1);<br>+      }<br> <br>-    if (verifyModule(*M, &errs())) {<br>-      errs() << argv[0] << ": " << InputFilenames[i]<br>-             << ": error: input module is broken!\n";<br>-      return 1;<br>-    }<br>+      if (verifyModule(*M, &errs())) {<br>+        errs() << argv[0] << ": " << File<br>+               << ": error: input module is broken!\n";<br>+        exit(1);<br>+      }<br> <br>-    if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n";<br>+      if (Verbose) errs() << "Linking in '" << File << "'\n";<br> <br>-    if (L.linkInModule(M.get()))<br>-      return 1;<br>-  }<br>+      if (L.linkInModule(M.get(), Override))<br>+        exit(1);<br>+    }<br>+  };<br>+<br>+  linkFiles(InputFilenames, false);<br>+  linkFiles(OverridingInputs, true);<br> <br>   if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;<br> <br>-- <br>2.3.0 (Apple Git-54)<br><br></div></div>