[PATCH] llvm-link: Add -override flag to prefer duplicate symbols from one module.

Luqman Aden me+llvm at luqman.ca
Mon Apr 20 13:28:22 PDT 2015


>From df1b11c561dc826d8e4836b9e910ac75185bcf05 Mon Sep 17 00:00:00 2001
From: Luqman Aden <luqman at apple.com>
Date: Wed, 15 Apr 2015 12:22:32 -0700
Subject: [PATCH] llvm-link: Add -override flag to prefer one of a duplicate
 symbol.

---
 include/llvm/Linker/Linker.h       |  4 +++-
 lib/Linker/LinkModules.cpp         | 20 +++++++++++++++----
 test/tools/llvm-link/Inputs/foo.ll |  4 ++++
 test/tools/llvm-link/hello.ll      | 20 +++++++++++++++++++
 test/tools/llvm-link/lit.local.cfg |  1 +
 tools/llvm-link/llvm-link.cpp      | 40
++++++++++++++++++++++++--------------
 6 files changed, 69 insertions(+), 20 deletions(-)
 create mode 100644 test/tools/llvm-link/Inputs/foo.ll
 create mode 100644 test/tools/llvm-link/hello.ll
 create mode 100644 test/tools/llvm-link/lit.local.cfg

diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h
index 5ca815c..c43b90e 100644
--- a/include/llvm/Linker/Linker.h
+++ b/include/llvm/Linker/Linker.h
@@ -68,8 +68,10 @@ public:
   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);
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index 21edc50..3a46a33 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -424,12 +424,17 @@ class ModuleLinker {

   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();

@@ -725,6 +730,12 @@ bool ModuleLinker::getComdatResult(const Comdat *SrcC,
 bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
                                         const GlobalValue &Dest,
                                         const GlobalValue &Src) {
+  // Should we unconditionally use the Src?
+  if (OverrideFromSrc) {
+    LinkFromSrc = true;
+    return false;
+  }
+
   // We always have to add Src if it has appending linkage.
   if (Src.hasAppendingLinkage()) {
     LinkFromSrc = true;
@@ -794,6 +805,7 @@ bool ModuleLinker::shouldLinkFromSource(bool
&LinkFromSrc,
   assert(!Dest.hasExternalWeakLinkage());
   assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() &&
          "Unexpected linkage type!");
+
   return emitError("Linking globals named '" + Src.getName() +
                    "': symbol multiply defined!");
 }
@@ -1742,9 +1754,9 @@ void Linker::deleteModule() {
   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;
diff --git a/test/tools/llvm-link/Inputs/foo.ll
b/test/tools/llvm-link/Inputs/foo.ll
new file mode 100644
index 0000000..6e06fa5
--- /dev/null
+++ b/test/tools/llvm-link/Inputs/foo.ll
@@ -0,0 +1,4 @@
+define i32 @foo(i32 %i) {
+entry:
+  ret i32 4
+}
diff --git a/test/tools/llvm-link/hello.ll b/test/tools/llvm-link/hello.ll
new file mode 100644
index 0000000..c124864
--- /dev/null
+++ b/test/tools/llvm-link/hello.ll
@@ -0,0 +1,20 @@
+; RUN: llvm-as %s -o %t-hello.bc
+; RUN: llvm-as %p/Inputs/foo.ll -o %t-foo.bc
+; RUN: llvm-link %t-hello.bc -override %t-foo.bc -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
+}
diff --git a/test/tools/llvm-link/lit.local.cfg
b/test/tools/llvm-link/lit.local.cfg
new file mode 100644
index 0000000..c6106e4
--- /dev/null
+++ b/test/tools/llvm-link/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.ll']
diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp
index 6924aa5..54d49f5 100644
--- a/tools/llvm-link/llvm-link.cpp
+++ b/tools/llvm-link/llvm-link.cpp
@@ -38,6 +38,11 @@ static cl::list<std::string>
 InputFilenames(cl::Positional, cl::OneOrMore,
                cl::desc("<input bitcode files>"));

+static cl::list<std::string>
+OverridingInputs("override", cl::ZeroOrMore, cl::value_desc("filename"),
+                 cl::desc("input bitcode file which can "
+                          "override previously defined symbol"));
+
 static cl::opt<std::string>
 OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
                cl::value_desc("filename"));
@@ -109,24 +114,29 @@ int main(int argc, char **argv) {
   auto Composite = make_unique<Module>("llvm-link", Context);
   Linker L(Composite.get(), diagnosticHandler);

-  for (unsigned i = 0; i < InputFilenames.size(); ++i) {
-    std::unique_ptr<Module> M = loadFile(argv[0], InputFilenames[i],
Context);
-    if (!M.get()) {
-      errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<<
"'\n";
-      return 1;
-    }
+  auto linkFiles = [&](const cl::list<std::string>& Files, bool Override) {
+    for (auto File : Files) {
+      std::unique_ptr<Module> 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;

-- 
2.3.0 (Apple Git-54)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150420/9b1a7ed9/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-llvm-link-Add-override-flag-to-prefer-one-of-a-dupli.patch
Type: application/octet-stream
Size: 6926 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150420/9b1a7ed9/attachment.obj>


More information about the llvm-commits mailing list