[llvm] r246561 - New bitcode linker flags:
Artem Belevich via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 1 10:55:56 PDT 2015
Author: tra
Date: Tue Sep 1 12:55:55 2015
New Revision: 246561
URL: http://llvm.org/viewvc/llvm-project?rev=246561&view=rev
Log:
New bitcode linker flags:
-only-needed -- link in only symbols needed by destination module
-internalize -- internalize linked symbols
Differential Revision: http://reviews.llvm.org/D12459
Added:
llvm/trunk/test/Linker/Inputs/linkage.c.ll
llvm/trunk/test/Linker/link-flags.ll
Modified:
llvm/trunk/include/llvm/Linker/Linker.h
llvm/trunk/lib/Linker/LinkModules.cpp
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=246561&r1=246560&r2=246561&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Linker/Linker.h (original)
+++ llvm/trunk/include/llvm/Linker/Linker.h Tue Sep 1 12:55:55 2015
@@ -60,6 +60,13 @@ public:
bool hasType(StructType *Ty);
};
+ enum Flags {
+ None = 0,
+ OverrideFromSrc = (1 << 0),
+ LinkOnlyNeeded = (1 << 1),
+ InternalizeLinkedSymbols = (1 << 2)
+ };
+
Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler);
Linker(Module *M);
@@ -70,15 +77,17 @@ public:
/// Passing OverrideSymbols as true will have symbols from Src
/// shadow those in the Dest.
/// Returns true on error.
- bool linkInModule(Module *Src, bool OverrideSymbols = false);
+ bool linkInModule(Module *Src, unsigned Flags = Flags::None);
/// \brief Set the composite to the passed-in module.
void setModule(Module *Dst);
static bool LinkModules(Module *Dest, Module *Src,
- DiagnosticHandlerFunction DiagnosticHandler);
+ DiagnosticHandlerFunction DiagnosticHandler,
+ unsigned Flags = Flags::None);
- static bool LinkModules(Module *Dest, Module *Src);
+ static bool LinkModules(Module *Dest, Module *Src,
+ unsigned Flags = Flags::None);
private:
void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler);
Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=246561&r1=246560&r2=246561&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Tue Sep 1 12:55:55 2015
@@ -425,19 +425,23 @@ class ModuleLinker {
DiagnosticHandlerFunction DiagnosticHandler;
/// For symbol clashes, prefer those from Src.
- bool OverrideFromSrc;
+ unsigned Flags;
public:
ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM,
- DiagnosticHandlerFunction DiagnosticHandler,
- bool OverrideFromSrc)
+ DiagnosticHandlerFunction DiagnosticHandler, unsigned Flags)
: DstM(dstM), SrcM(srcM), TypeMap(Set),
ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues),
- DiagnosticHandler(DiagnosticHandler), OverrideFromSrc(OverrideFromSrc) {
- }
+ DiagnosticHandler(DiagnosticHandler), Flags(Flags) {}
bool run();
+ bool shouldOverrideFromSrc() { return Flags & Linker::OverrideFromSrc; }
+ bool shouldLinkOnlyNeeded() { return Flags & Linker::LinkOnlyNeeded; }
+ bool shouldInternalizeLinkedSymbols() {
+ return Flags & Linker::InternalizeLinkedSymbols;
+ }
+
private:
bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest,
const GlobalValue &Src);
@@ -730,7 +734,7 @@ bool ModuleLinker::shouldLinkFromSource(
const GlobalValue &Dest,
const GlobalValue &Src) {
// Should we unconditionally use the Src?
- if (OverrideFromSrc) {
+ if (shouldOverrideFromSrc()) {
LinkFromSrc = true;
return false;
}
@@ -1081,13 +1085,20 @@ bool ModuleLinker::linkGlobalValueProto(
} else {
// If the GV is to be lazily linked, don't create it just yet.
// The ValueMaterializerTy will deal with creating it if it's used.
- if (!DGV && !OverrideFromSrc &&
+ if (!DGV && !shouldOverrideFromSrc() &&
(SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() ||
SGV->hasAvailableExternallyLinkage())) {
DoNotLinkFromSource.insert(SGV);
return false;
}
+ // When we only want to link in unresolved dependencies, blacklist
+ // the symbol unless unless DestM has a matching declaration (DGV).
+ if (shouldLinkOnlyNeeded() && !(DGV && DGV->isDeclaration())) {
+ DoNotLinkFromSource.insert(SGV);
+ return false;
+ }
+
NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV);
if (DGV && isa<Function>(DGV))
@@ -1249,6 +1260,9 @@ void ModuleLinker::linkAliasBody(GlobalA
bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) {
Value *Dst = ValueMap[&Src];
assert(Dst);
+ if (shouldInternalizeLinkedSymbols())
+ if (auto *DGV = dyn_cast<GlobalValue>(Dst))
+ DGV->setLinkage(GlobalValue::InternalLinkage);
if (auto *F = dyn_cast<Function>(&Src))
return linkFunctionBody(cast<Function>(*Dst), *F);
if (auto *GVar = dyn_cast<GlobalVariable>(&Src)) {
@@ -1632,6 +1646,11 @@ bool ModuleLinker::run() {
GlobalValue *SGV = LazilyLinkGlobalValues.back();
LazilyLinkGlobalValues.pop_back();
+ // Skip declarations that ValueMaterializer may have created in
+ // case we link in only some of SrcM.
+ if (shouldLinkOnlyNeeded() && SGV->isDeclaration())
+ continue;
+
assert(!SGV->isDeclaration() && "users should not pass down decls");
if (linkGlobalValueBody(*SGV))
return true;
@@ -1759,9 +1778,9 @@ void Linker::deleteModule() {
Composite = nullptr;
}
-bool Linker::linkInModule(Module *Src, bool OverrideSymbols) {
+bool Linker::linkInModule(Module *Src, unsigned Flags) {
ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src,
- DiagnosticHandler, OverrideSymbols);
+ DiagnosticHandler, Flags);
bool RetCode = TheLinker.run();
Composite->dropTriviallyDeadConstantArrays();
return RetCode;
@@ -1781,14 +1800,15 @@ void Linker::setModule(Module *Dst) {
/// 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, Module *Src,
- DiagnosticHandlerFunction DiagnosticHandler) {
+ DiagnosticHandlerFunction DiagnosticHandler,
+ unsigned Flags) {
Linker L(Dest, DiagnosticHandler);
- return L.linkInModule(Src);
+ return L.linkInModule(Src, Flags);
}
-bool Linker::LinkModules(Module *Dest, Module *Src) {
+bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Flags) {
Linker L(Dest);
- return L.linkInModule(Src);
+ return L.linkInModule(Src, Flags);
}
//===----------------------------------------------------------------------===//
Added: llvm/trunk/test/Linker/Inputs/linkage.c.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/linkage.c.ll?rev=246561&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/linkage.c.ll (added)
+++ llvm/trunk/test/Linker/Inputs/linkage.c.ll Tue Sep 1 12:55:55 2015
@@ -0,0 +1,4 @@
+ at X = global i32 5
+ at U = global i32 6
+define i32 @foo() { ret i32 7 }
+define i32 @unused() { ret i32 8 }
Added: llvm/trunk/test/Linker/link-flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/link-flags.ll?rev=246561&view=auto
==============================================================================
--- llvm/trunk/test/Linker/link-flags.ll (added)
+++ llvm/trunk/test/Linker/link-flags.ll Tue Sep 1 12:55:55 2015
@@ -0,0 +1,21 @@
+; RUN: llvm-as %S/Inputs/linkage.b.ll -o %t.b.bc
+; RUN: llvm-as %S/Inputs/linkage.c.ll -o %t.c.bc
+; RUN: llvm-link -S %t.b.bc %t.c.bc | FileCheck %s -check-prefix=B -check-prefix=C -check-prefix=CU
+; RUN: llvm-link -S -only-needed %t.b.bc %t.c.bc | FileCheck %s -check-prefix=B -check-prefix=C -check-prefix=CN
+; RUN: llvm-link -S -internalize %t.b.bc %t.c.bc | FileCheck %s -check-prefix=B -check-prefix=CI
+; RUN: llvm-link -S -internalize -only-needed %t.b.bc %t.c.bc | FileCheck %s -check-prefix=B -check-prefix=CN
+
+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-LABEL-NOT:@U
+
+B-LABEL: define void @bar() {
+
+C-LABEL: define i32 @foo()
+CI-LABEL: define internal i32 @foo()
+
+CU-LABEL:define i32 @unused() {
+CI-LABEL:define internal i32 @unused() {
+CN-LABEL-NOT:@unused()
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=246561&r1=246560&r2=246561&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-link/llvm-link.cpp (original)
+++ llvm/trunk/tools/llvm-link/llvm-link.cpp Tue Sep 1 12:55:55 2015
@@ -48,6 +48,12 @@ OutputFilename("o", cl::desc("Override o
cl::value_desc("filename"));
static cl::opt<bool>
+Internalize("internalize", cl::desc("Internalize linked symbols"));
+
+static cl::opt<bool>
+OnlyNeeded("only-needed", cl::desc("Link only needed symbols"));
+
+static cl::opt<bool>
Force("f", cl::desc("Enable binary output on terminals"));
static cl::opt<bool>
@@ -114,7 +120,9 @@ static void diagnosticHandler(const Diag
static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
const cl::list<std::string> &Files,
- bool OverrideDuplicateSymbols) {
+ unsigned Flags) {
+ // Filter out flags that don't apply to the first file we load.
+ unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
for (const auto &File : Files) {
std::unique_ptr<Module> M = loadFile(argv0, File, Context);
if (!M.get()) {
@@ -130,8 +138,10 @@ static bool linkFiles(const char *argv0,
if (Verbose)
errs() << "Linking in '" << File << "'\n";
- if (L.linkInModule(M.get(), OverrideDuplicateSymbols))
+ if (L.linkInModule(M.get(), ApplicableFlags))
return false;
+ // All linker flags apply to linking of subsequent files.
+ ApplicableFlags = Flags;
}
return true;
@@ -149,12 +159,19 @@ int main(int argc, char **argv) {
auto Composite = make_unique<Module>("llvm-link", Context);
Linker L(Composite.get(), diagnosticHandler);
+ unsigned Flags = Linker::Flags::None;
+ if (Internalize)
+ Flags |= Linker::Flags::InternalizeLinkedSymbols;
+ if (OnlyNeeded)
+ Flags |= Linker::Flags::LinkOnlyNeeded;
+
// First add all the regular input files
- if (!linkFiles(argv[0], Context, L, InputFilenames, false))
+ if (!linkFiles(argv[0], Context, L, InputFilenames, Flags))
return 1;
// Next the -override ones.
- if (!linkFiles(argv[0], Context, L, OverridingInputs, true))
+ if (!linkFiles(argv[0], Context, L, OverridingInputs,
+ Flags | Linker::Flags::OverrideFromSrc))
return 1;
if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
More information about the llvm-commits
mailing list