summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/CodeGen/CodeGenAction.h3
-rw-r--r--clang/include/clang/Frontend/CodeGenOptions.h2
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp31
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp4
-rw-r--r--llvm/include/llvm/Linker/Linker.h14
-rw-r--r--llvm/lib/Linker/LinkModules.cpp46
-rw-r--r--llvm/test/Linker/Inputs/linkage.d.ll5
-rw-r--r--llvm/test/Linker/link-flags.ll6
-rw-r--r--llvm/tools/llvm-link/llvm-link.cpp23
9 files changed, 100 insertions, 34 deletions
diff --git a/clang/include/clang/CodeGen/CodeGenAction.h b/clang/include/clang/CodeGen/CodeGenAction.h
index 65eda5bb98e..5a18a9de030 100644
--- a/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/clang/include/clang/CodeGen/CodeGenAction.h
@@ -36,6 +36,9 @@ private:
/// function ourselves.
bool PropagateAttrs;
+ /// If true, we use LLVM module internalizer.
+ bool Internalize;
+
/// Bitwise combination of llvm::LinkerFlags used when we link the module.
unsigned LinkFlags;
};
diff --git a/clang/include/clang/Frontend/CodeGenOptions.h b/clang/include/clang/Frontend/CodeGenOptions.h
index a21abac24b9..f8f32666c53 100644
--- a/clang/include/clang/Frontend/CodeGenOptions.h
+++ b/clang/include/clang/Frontend/CodeGenOptions.h
@@ -137,6 +137,8 @@ public:
/// our CodeGenOptions, much as we set attrs on functions that we generate
/// ourselves.
bool PropagateAttrs = false;
+ /// If true, we use LLVM module internalizer.
+ bool Internalize = false;
/// Bitwise combination of llvm::Linker::Flags, passed to the LLVM linker.
unsigned LinkFlags = 0;
};
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index c7604145619..20a61f33f94 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -28,6 +28,7 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
@@ -38,6 +39,8 @@
#include "llvm/Support/Timer.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Transforms/IPO/Internalize.h"
+
#include <memory>
using namespace clang;
using namespace llvm;
@@ -168,8 +171,22 @@ namespace clang {
Gen->CGM().AddDefaultFnAttrs(F);
CurLinkModule = LM.Module.get();
- if (Linker::linkModules(*getModule(), std::move(LM.Module),
- LM.LinkFlags))
+
+ bool Err;
+ if (LM.Internalize) {
+ Err = Linker::linkModules(
+ *getModule(), std::move(LM.Module), LM.LinkFlags,
+ [](llvm::Module &M, const llvm::StringSet<> &GVS) {
+ internalizeModule(M, [&M, &GVS](const llvm::GlobalValue &GV) {
+ return !GV.hasName() || (GVS.count(GV.getName()) == 0);
+ });
+ });
+ } else {
+ Err = Linker::linkModules(*getModule(), std::move(LM.Module),
+ LM.LinkFlags);
+ }
+
+ if (Err)
return true;
}
return false; // success
@@ -319,7 +336,7 @@ namespace clang {
void OptimizationFailureHandler(
const llvm::DiagnosticInfoOptimizationFailure &D);
};
-
+
void BackendConsumer::anchor() {}
}
@@ -388,7 +405,7 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
// code.
if (LocCookie.isValid()) {
Diags.Report(LocCookie, DiagID).AddString(Message);
-
+
if (D.getLoc().isValid()) {
DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
// Convert the SMDiagnostic ranges into SourceRange and attach them
@@ -401,7 +418,7 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
}
return;
}
-
+
// Otherwise, report the backend issue as occurring in the generated .s file.
// If Loc is invalid, we still need to report the issue, it just gets no
// location info.
@@ -815,8 +832,8 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
LinkModules.clear();
return nullptr;
}
- LinkModules.push_back(
- {std::move(ModuleOrErr.get()), F.PropagateAttrs, F.LinkFlags});
+ LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
+ F.Internalize, F.LinkFlags});
}
CoverageSourceInfo *CoverageInfo = nullptr;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 598af20864b..23529749099 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -727,11 +727,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
CodeGenOptions::BitcodeFileToLink F;
F.Filename = A->getValue();
if (A->getOption().matches(OPT_mlink_cuda_bitcode)) {
- F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded |
- llvm::Linker::Flags::InternalizeLinkedSymbols;
+ F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
// When linking CUDA bitcode, propagate function attributes so that
// e.g. libdevice gets fast-math attrs if we're building with fast-math.
F.PropagateAttrs = true;
+ F.Internalize = true;
}
Opts.LinkBitcodeFiles.push_back(F);
}
diff --git a/llvm/include/llvm/Linker/Linker.h b/llvm/include/llvm/Linker/Linker.h
index f203d349585..628e0112bd9 100644
--- a/llvm/include/llvm/Linker/Linker.h
+++ b/llvm/include/llvm/Linker/Linker.h
@@ -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
diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp
index f11fd54f4af..c0ce4bf76b9 100644
--- a/llvm/lib/Linker/LinkModules.cpp
+++ b/llvm/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,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(GlobalValue &GV, const IRMover::ValueAdder &Add) {
!shouldLinkOnlyNeeded())
return;
- if (shouldInternalizeLinkedSymbols())
+ if (InternalizeCallback)
Internalize.insert(GV.getName());
Add(GV);
@@ -397,7 +403,7 @@ void ModuleLinker::addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add) {
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_ptr<Module> Src, unsigned Flags) {
/// 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));
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/test/Linker/Inputs/linkage.d.ll b/llvm/test/Linker/Inputs/linkage.d.ll
new file mode 100644
index 00000000000..aaf010d3885
--- /dev/null
+++ b/llvm/test/Linker/Inputs/linkage.d.ll
@@ -0,0 +1,5 @@
+@Y = global i8 42
+
+define i64 @foo() { ret i64 7 }
+
+@llvm.used = appending global [2 x i8*] [i8* @Y, i8* bitcast (i64 ()* @foo to i8*)], section "llvm.metadata"
diff --git a/llvm/test/Linker/link-flags.ll b/llvm/test/Linker/link-flags.ll
index c901b699575..1a57e8aa4d2 100644
--- a/llvm/test/Linker/link-flags.ll
+++ b/llvm/test/Linker/link-flags.ll
@@ -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()
diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp
index e89696e7e7c..6cb647d48eb 100644
--- a/llvm/tools/llvm-link/llvm-link.cpp
+++ b/llvm/tools/llvm-link/llvm-link.cpp
@@ -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, LLVMContext &Context, Linker &L,
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, LLVMContext &Context, Linker &L,
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;
OpenPOWER on IntegriCloud