From: Artem Belevich Date: Tue, 1 Sep 2015 17:55:55 +0000 (+0000) Subject: New bitcode linker flags: X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=20264d6c67012f8097b7602c267859ed88c697ff 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246561 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 2a46d755b8e..3a6df80aa38 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -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); diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 3b84454455e..9d5e0b475d8 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -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(bool &LinkFromSrc, 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(GlobalValue *SGV) { } 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(DGV)) @@ -1249,6 +1260,9 @@ void ModuleLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) { bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) { Value *Dst = ValueMap[&Src]; assert(Dst); + if (shouldInternalizeLinkedSymbols()) + if (auto *DGV = dyn_cast(Dst)) + DGV->setLinkage(GlobalValue::InternalLinkage); if (auto *F = dyn_cast(&Src)) return linkFunctionBody(cast(*Dst), *F); if (auto *GVar = dyn_cast(&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); } //===----------------------------------------------------------------------===// diff --git a/test/Linker/Inputs/linkage.c.ll b/test/Linker/Inputs/linkage.c.ll new file mode 100644 index 00000000000..6aedf5ab111 --- /dev/null +++ b/test/Linker/Inputs/linkage.c.ll @@ -0,0 +1,4 @@ +@X = global i32 5 +@U = global i32 6 +define i32 @foo() { ret i32 7 } +define i32 @unused() { ret i32 8 } diff --git a/test/Linker/link-flags.ll b/test/Linker/link-flags.ll new file mode 100644 index 00000000000..4c56aedcbbd --- /dev/null +++ b/test/Linker/link-flags.ll @@ -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() diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 369f3477fe5..7f294f3e719 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -47,6 +47,12 @@ static cl::opt OutputFilename("o", cl::desc("Override output filename"), cl::init("-"), cl::value_desc("filename")); +static cl::opt +Internalize("internalize", cl::desc("Internalize linked symbols")); + +static cl::opt +OnlyNeeded("only-needed", cl::desc("Link only needed symbols")); + static cl::opt Force("f", cl::desc("Enable binary output on terminals")); @@ -114,7 +120,9 @@ static void diagnosticHandler(const DiagnosticInfo &DI) { static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L, const cl::list &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 M = loadFile(argv0, File, Context); if (!M.get()) { @@ -130,8 +138,10 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L, 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("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;