mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[Linker] Provide callback for internalization
Differential Revision: https://reviews.llvm.org/D30738 llvm-svn: 297649
This commit is contained in:
parent
d35723bd11
commit
9840ae61ae
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
5
test/Linker/Inputs/linkage.d.ll
Normal file
5
test/Linker/Inputs/linkage.d.ll
Normal file
@ -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"
|
@ -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()
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user