mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
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 llvm-svn: 246561
This commit is contained in:
parent
666311aee4
commit
08b5e74877
@ -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);
|
||||
|
@ -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<Function>(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<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);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
4
test/Linker/Inputs/linkage.c.ll
Normal file
4
test/Linker/Inputs/linkage.c.ll
Normal file
@ -0,0 +1,4 @@
|
||||
@X = global i32 5
|
||||
@U = global i32 6
|
||||
define i32 @foo() { ret i32 7 }
|
||||
define i32 @unused() { ret i32 8 }
|
21
test/Linker/link-flags.ll
Normal file
21
test/Linker/link-flags.ll
Normal file
@ -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()
|
@ -47,6 +47,12 @@ static cl::opt<std::string>
|
||||
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
|
||||
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"));
|
||||
|
||||
@ -114,7 +120,9 @@ static void diagnosticHandler(const DiagnosticInfo &DI) {
|
||||
|
||||
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, 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<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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user