aboutsummaryrefslogtreecommitdiff
path: root/lib/Linker
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /lib/Linker
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Diffstat (limited to 'lib/Linker')
-rw-r--r--lib/Linker/IRMover.cpp24
-rw-r--r--lib/Linker/LinkModules.cpp105
2 files changed, 44 insertions, 85 deletions
diff --git a/lib/Linker/IRMover.cpp b/lib/Linker/IRMover.cpp
index 9f3cfc0eace4..15a46a2d0420 100644
--- a/lib/Linker/IRMover.cpp
+++ b/lib/Linker/IRMover.cpp
@@ -395,11 +395,12 @@ class IRLinker {
Worklist.push_back(GV);
}
- /// Flag whether the ModuleInlineAsm string in Src should be linked with
- /// (concatenated into) the ModuleInlineAsm string for the destination
- /// module. It should be true for full LTO, but not when importing for
- /// ThinLTO, otherwise we can have duplicate symbols.
- bool LinkModuleInlineAsm;
+ /// Whether we are importing globals for ThinLTO, as opposed to linking the
+ /// source module. If this flag is set, it means that we can rely on some
+ /// other object file to define any non-GlobalValue entities defined by the
+ /// source module. This currently causes us to not link retained types in
+ /// debug info metadata and module inline asm.
+ bool IsPerformingImport;
/// Set to true when all global value body linking is complete (including
/// lazy linking). Used to prevent metadata linking from creating new
@@ -491,10 +492,10 @@ public:
IRMover::IdentifiedStructTypeSet &Set, std::unique_ptr<Module> SrcM,
ArrayRef<GlobalValue *> ValuesToLink,
std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor,
- bool LinkModuleInlineAsm, bool IsPerformingImport)
+ bool IsPerformingImport)
: DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(std::move(AddLazyFor)),
TypeMap(Set), GValMaterializer(*this), LValMaterializer(*this),
- SharedMDs(SharedMDs), LinkModuleInlineAsm(LinkModuleInlineAsm),
+ SharedMDs(SharedMDs), IsPerformingImport(IsPerformingImport),
Mapper(ValueMap, RF_MoveDistinctMDs | RF_IgnoreMissingLocals, &TypeMap,
&GValMaterializer),
AliasMCID(Mapper.registerAlternateMappingContext(AliasValueMap,
@@ -870,9 +871,6 @@ bool IRLinker::shouldLink(GlobalValue *DGV, GlobalValue &SGV) {
if (DGV && !DGV->isDeclarationForLinker())
return false;
- if (SGV.hasAvailableExternallyLinkage())
- return true;
-
if (SGV.isDeclaration() || DoneLinkingBodies)
return false;
@@ -1297,7 +1295,7 @@ Error IRLinker::run() {
DstM.setTargetTriple(mergeTriples(SrcTriple, DstTriple));
// Append the module inline asm string.
- if (LinkModuleInlineAsm && !SrcM->getModuleInlineAsm().empty()) {
+ if (!IsPerformingImport && !SrcM->getModuleInlineAsm().empty()) {
if (DstM.getModuleInlineAsm().empty())
DstM.setModuleInlineAsm(SrcM->getModuleInlineAsm());
else
@@ -1436,10 +1434,10 @@ IRMover::IRMover(Module &M) : Composite(M) {
Error IRMover::move(
std::unique_ptr<Module> Src, ArrayRef<GlobalValue *> ValuesToLink,
std::function<void(GlobalValue &, ValueAdder Add)> AddLazyFor,
- bool LinkModuleInlineAsm, bool IsPerformingImport) {
+ bool IsPerformingImport) {
IRLinker TheIRLinker(Composite, SharedMDs, IdentifiedStructTypes,
std::move(Src), ValuesToLink, std::move(AddLazyFor),
- LinkModuleInlineAsm, IsPerformingImport);
+ IsPerformingImport);
Error E = TheIRLinker.run();
Composite.dropTriviallyDeadConstantArrays();
return E;
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index cf2c4ccf523e..c0ce4bf76b9f 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -14,12 +14,13 @@
#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"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/Error.h"
-#include "llvm/Transforms/Utils/FunctionImportUtils.h"
using namespace llvm;
namespace {
@@ -31,14 +32,17 @@ class ModuleLinker {
std::unique_ptr<Module> SrcM;
SetVector<GlobalValue *> ValuesToLink;
- StringSet<> Internalize;
/// For symbol clashes, prefer those from Src.
unsigned Flags;
- /// Functions to import from source module, all other functions are
- /// imported as declarations instead of definitions.
- DenseSet<const GlobalValue *> *GlobalsToImport;
+ /// 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
@@ -46,14 +50,8 @@ class ModuleLinker {
/// to Add.
void addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add);
- bool shouldLinkReferencedLinkOnce() {
- return !(Flags & Linker::DontForceLinkLinkonceODR);
- }
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);
@@ -108,31 +106,17 @@ class ModuleLinker {
bool linkIfNeeded(GlobalValue &GV);
- /// Helper method to check if we are importing from the current source
- /// module.
- bool isPerformingImport() const { return GlobalsToImport != nullptr; }
-
- /// If we are importing from the source module, checks if we should
- /// import SGV as a definition, otherwise import as a declaration.
- bool doImportAsDefinition(const GlobalValue *SGV);
-
public:
ModuleLinker(IRMover &Mover, std::unique_ptr<Module> SrcM, unsigned Flags,
- DenseSet<const GlobalValue *> *GlobalsToImport = nullptr)
+ std::function<void(Module &, const StringSet<> &)>
+ InternalizeCallback = {})
: Mover(Mover), SrcM(std::move(SrcM)), Flags(Flags),
- GlobalsToImport(GlobalsToImport) {}
+ InternalizeCallback(std::move(InternalizeCallback)) {}
bool run();
};
}
-bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
- if (!isPerformingImport())
- return false;
- return FunctionImportGlobalProcessing::doImportAsDefinition(SGV,
- GlobalsToImport);
-}
-
static GlobalValue::VisibilityTypes
getMinVisibility(GlobalValue::VisibilityTypes A,
GlobalValue::VisibilityTypes B) {
@@ -266,18 +250,10 @@ bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc,
// We always have to add Src if it has appending linkage.
if (Src.hasAppendingLinkage()) {
- // Should have prevented importing for appending linkage in linkIfNeeded.
- assert(!isPerformingImport());
LinkFromSrc = true;
return false;
}
- if (isPerformingImport()) {
- // LinkFromSrc iff this is a global requested for importing.
- LinkFromSrc = GlobalsToImport->count(&Src);
- return false;
- }
-
bool SrcIsDeclaration = Src.isDeclarationForLinker();
bool DestIsDeclaration = Dest.isDeclarationForLinker();
@@ -383,19 +359,9 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
GV.setUnnamedAddr(UnnamedAddr);
}
- // Don't want to append to global_ctors list, for example, when we
- // are importing for ThinLTO, otherwise the global ctors and dtors
- // get executed multiple times for local variables (the latter causing
- // double frees).
- if (GV.hasAppendingLinkage() && isPerformingImport())
- return false;
-
- if (isPerformingImport()) {
- if (!doImportAsDefinition(&GV))
- return false;
- } else if (!DGV && !shouldOverrideFromSrc() &&
- (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
- GV.hasAvailableExternallyLinkage()))
+ if (!DGV && !shouldOverrideFromSrc() &&
+ (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
+ GV.hasAvailableExternallyLinkage()))
return false;
if (GV.isDeclaration())
@@ -418,17 +384,12 @@ bool ModuleLinker::linkIfNeeded(GlobalValue &GV) {
}
void ModuleLinker::addLazyFor(GlobalValue &GV, const IRMover::ValueAdder &Add) {
- if (!shouldLinkReferencedLinkOnce())
- // For ThinLTO we don't import more than what was required.
- // The client has to guarantee that the linkonce will be availabe at link
- // time (by promoting it to weak for instance).
- return;
-
// Add these to the internalize list
- if (!GV.hasLinkOnceLinkage() && !shouldLinkOnlyNeeded())
+ if (!GV.hasLinkOnceLinkage() && !GV.hasAvailableExternallyLinkage() &&
+ !shouldLinkOnlyNeeded())
return;
- if (shouldInternalizeLinkedSymbols())
+ if (InternalizeCallback)
Internalize.insert(GV.getName());
Add(GV);
@@ -442,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);
}
@@ -571,7 +532,7 @@ bool ModuleLinker::run() {
}
}
- if (shouldInternalizeLinkedSymbols()) {
+ if (InternalizeCallback) {
for (GlobalValue *GV : ValuesToLink)
Internalize.insert(GV->getName());
}
@@ -583,8 +544,7 @@ bool ModuleLinker::run() {
[this](GlobalValue &GV, IRMover::ValueAdder Add) {
addLazyFor(GV, Add);
},
- /* LinkModuleInlineAsm */ !isPerformingImport(),
- /* IsPerformingImport */ isPerformingImport())) {
+ /* IsPerformingImport */ false)) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
DstM.getContext().diagnose(LinkDiagnosticInfo(DS_Error, EIB.message()));
HasErrors = true;
@@ -593,19 +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,
- DenseSet<const GlobalValue *> *GlobalsToImport) {
- ModuleLinker ModLinker(Mover, std::move(Src), Flags, GlobalsToImport);
+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();
}
@@ -618,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));
}
//===----------------------------------------------------------------------===//