[llvm] r297649 - [Linker] Provide callback for internalization

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 13 11:08:12 PDT 2017


Author: jdevlieghere
Date: Mon Mar 13 13:08:11 2017
New Revision: 297649

URL: http://llvm.org/viewvc/llvm-project?rev=297649&view=rev
Log:
[Linker] Provide callback for internalization

Differential Revision: https://reviews.llvm.org/D30738

Added:
    llvm/trunk/test/Linker/Inputs/linkage.d.ll
Modified:
    llvm/trunk/include/llvm/Linker/Linker.h
    llvm/trunk/lib/Linker/LinkModules.cpp
    llvm/trunk/test/Linker/link-flags.ll
    llvm/trunk/tools/llvm-link/llvm-link.cpp

Modified: llvm/trunk/include/llvm/Linker/Linker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Linker/Linker.h?rev=297649&r1=297648&r2=297649&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Linker/Linker.h (original)
+++ llvm/trunk/include/llvm/Linker/Linker.h Mon Mar 13 13:08:11 2017
@@ -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 @@ public:
     None = 0,
     OverrideFromSrc = (1 << 0),
     LinkOnlyNeeded = (1 << 1),
-    InternalizeLinkedSymbols = (1 << 2),
   };
 
   Linker(Module &M);
@@ -39,11 +39,19 @@ public:
   /// Passing OverrideSymbols as true will have symbols from Src
   /// shadow those in the Dest.
   ///
+  /// Passing InternalizeCallback will have the linker call the function with
+  /// the new module and a list of global value names to be internalized by the
+  /// callback.
+  ///
   /// Returns true on error.
-  bool linkInModule(std::unique_ptr<Module> Src, unsigned Flags = Flags::None);
+  bool linkInModule(std::unique_ptr<Module> Src, unsigned Flags = Flags::None,
+                    std::function<void(Module &, const StringSet<> &)>
+                        InternalizeCallback = {});
 
   static bool linkModules(Module &Dest, std::unique_ptr<Module> Src,
-                          unsigned Flags = Flags::None);
+                          unsigned Flags = Flags::None,
+                          std::function<void(Module &, const StringSet<> &)>
+                              InternalizeCallback = {});
 };
 
 } // End llvm namespace

Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=297649&r1=297648&r2=297649&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Mar 13 13:08:11 2017
@@ -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,18 @@ class ModuleLinker {
   std::unique_ptr<Module> SrcM;
 
   SetVector<GlobalValue *> ValuesToLink;
-  StringSet<> Internalize;
 
   /// For symbol clashes, prefer those from Src.
   unsigned Flags;
 
+  /// List of global value names that should be internalized.
+  StringSet<> Internalize;
+
+  /// Function that will perform the actual internalization. The reason for a
+  /// callback is that the linker cannot call internalizeModule without
+  /// creating a circular dependency between IPO and the linker.
+  std::function<void(Module &, const StringSet<> &)> 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 +52,6 @@ class ModuleLinker {
 
   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 +107,11 @@ class ModuleLinker {
   bool linkIfNeeded(GlobalValue &GV);
 
 public:
-  ModuleLinker(IRMover &Mover, std::unique_ptr<Module> SrcM, unsigned Flags)
-      : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags) {}
+  ModuleLinker(IRMover &Mover, std::unique_ptr<Module> SrcM, unsigned Flags,
+               std::function<void(Module &, const StringSet<> &)>
+                   InternalizeCallback = {})
+      : Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags),
+        InternalizeCallback(std::move(InternalizeCallback)) {}
 
   bool run();
 };
@@ -383,7 +389,7 @@ void ModuleLinker::addLazyFor(GlobalValu
       !shouldLinkOnlyNeeded())
     return;
 
-  if (shouldInternalizeLinkedSymbols())
+  if (InternalizeCallback)
     Internalize.insert(GV.getName());
   Add(GV);
 
@@ -397,7 +403,7 @@ void ModuleLinker::addLazyFor(GlobalValu
       return;
     if (!LinkFromSrc)
       continue;
-    if (shouldInternalizeLinkedSymbols())
+    if (InternalizeCallback)
       Internalize.insert(GV2->getName());
     Add(*GV2);
   }
@@ -526,7 +532,7 @@ bool ModuleLinker::run() {
     }
   }
 
-  if (shouldInternalizeLinkedSymbols()) {
+  if (InternalizeCallback) {
     for (GlobalValue *GV : ValuesToLink)
       Internalize.insert(GV->getName());
   }
@@ -547,18 +553,19 @@ bool ModuleLinker::run() {
   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<Module> Src, unsigned Flags) {
-  ModuleLinker ModLinker(Mover, std::move(Src), Flags);
+bool Linker::linkInModule(
+    std::unique_ptr<Module> Src, unsigned Flags,
+    std::function<void(Module &, const StringSet<> &)> InternalizeCallback) {
+  ModuleLinker ModLinker(Mover, std::move(Src), Flags,
+                         std::move(InternalizeCallback));
   return ModLinker.run();
 }
 
@@ -571,10 +578,11 @@ bool Linker::linkInModule(std::unique_pt
 /// 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<Module> Src,
-                         unsigned Flags) {
+bool Linker::linkModules(
+    Module &Dest, std::unique_ptr<Module> Src, unsigned Flags,
+    std::function<void(Module &, const StringSet<> &)> InternalizeCallback) {
   Linker L(Dest);
-  return L.linkInModule(std::move(Src), Flags);
+  return L.linkInModule(std::move(Src), Flags, std::move(InternalizeCallback));
 }
 
 //===----------------------------------------------------------------------===//

Added: llvm/trunk/test/Linker/Inputs/linkage.d.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/linkage.d.ll?rev=297649&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/linkage.d.ll (added)
+++ llvm/trunk/test/Linker/Inputs/linkage.d.ll Mon Mar 13 13:08:11 2017
@@ -0,0 +1,5 @@
+ at Y = global i8 42
+
+define i64 @foo() { ret i64 7 }
+
+ at llvm.used = appending global [2 x i8*] [i8* @Y, i8* bitcast (i64 ()* @foo to i8*)], section "llvm.metadata"

Modified: llvm/trunk/test/Linker/link-flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/link-flags.ll?rev=297649&r1=297648&r2=297649&view=diff
==============================================================================
--- llvm/trunk/test/Linker/link-flags.ll (original)
+++ llvm/trunk/test/Linker/link-flags.ll Mon Mar 13 13:08:11 2017
@@ -2,12 +2,15 @@
 ; RUN: llvm-link -S -only-needed %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll | FileCheck %s -check-prefix=B -check-prefix=C -check-prefix=CN
 ; RUN: llvm-link -S -internalize %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll | FileCheck %s -check-prefix=B -check-prefix=CI
 ; RUN: llvm-link -S -internalize -only-needed %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll | FileCheck %s -check-prefix=B -check-prefix=CN
+; RUN: llvm-link -S -internalize %S/Inputs/linkage.b.ll %S/Inputs/linkage.c.ll %S/Inputs/linkage.d.ll | FileCheck %s -check-prefix=B -check-prefix=DI
 
 C-LABEL: @X = global i32 5
 CI-LABEL: @X = internal global i32 5
 CU-LABEL:@U = global i32 6
 CI-LABEL:@U = internal global i32 6
 CN-NOT:@U
+DI-LABEL: @Y = global i8 42
+DI-LABEL: @llvm.used = appending global [2 x i8*] [i8* @Y, i8* bitcast (i64 ()* @foo to i8*)], section "llvm.metadata"
 
 B-LABEL: define void @bar() {
 
@@ -17,3 +20,6 @@ CI-LABEL: define internal i32 @foo()
 CU-LABEL:define i32 @unused() {
 CI-LABEL:define internal i32 @unused() {
 CN-NOT:@unused()
+
+DI-LABEL: define internal i32 @foo.6()
+DI-LABEL: define i64 @foo()

Modified: llvm/trunk/tools/llvm-link/llvm-link.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/llvm-link.cpp?rev=297649&r1=297648&r2=297649&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-link/llvm-link.cpp (original)
+++ llvm/trunk/tools/llvm-link/llvm-link.cpp Mon Mar 13 13:08:11 2017
@@ -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 <memory>
@@ -272,6 +273,8 @@ static bool linkFiles(const char *argv0,
                       unsigned Flags) {
   // Filter out flags that don't apply to the first file we load.
   unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
+  // Similar to some flags, internalization doesn't apply to the first file.
+  bool InternalizeLinkedSymbols = false;
   for (const auto &File : Files) {
     std::unique_ptr<Module> M = loadFile(argv0, File, Context);
     if (!M.get()) {
@@ -311,8 +314,24 @@ static bool linkFiles(const char *argv0,
     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 @@ int main(int argc, char **argv) {
   Linker L(*Composite);
 
   unsigned Flags = Linker::Flags::None;
-  if (Internalize)
-    Flags |= Linker::Flags::InternalizeLinkedSymbols;
   if (OnlyNeeded)
     Flags |= Linker::Flags::LinkOnlyNeeded;
 




More information about the llvm-commits mailing list