[llvm] r254559 - Switch the linker to having a whitelist of GVs.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 2 14:59:04 PST 2015
Author: rafael
Date: Wed Dec 2 16:59:04 2015
New Revision: 254559
URL: http://llvm.org/viewvc/llvm-project?rev=254559&view=rev
Log:
Switch the linker to having a whitelist of GVs.
This replaces DoNotLinkFromSource with ValuesToLink. It also moves the
computation of ValuesToLink earlier.
It is a bit simpler and an important step in slitting the linker into an
ir mover and a linker proper.
The test change is because we now avoid creating dead declarations.
Modified:
llvm/trunk/lib/Linker/LinkModules.cpp
llvm/trunk/test/Linker/funcimport.ll
Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=254559&r1=254558&r2=254559&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Wed Dec 2 16:59:04 2015
@@ -392,8 +392,7 @@ class ModuleLinker {
/// but this allows us to reuse the ValueMapper code.
ValueToValueMapTy ValueMap;
- // Set of items not to link in from source.
- SmallPtrSet<const GlobalValue *, 16> DoNotLinkFromSource;
+ SetVector<GlobalValue *> ValuesToLink;
DiagnosticHandlerFunction DiagnosticHandler;
@@ -862,18 +861,8 @@ Value *ModuleLinker::materializeDeclFor(
if (!SGV)
return nullptr;
- // If we are done linking global value bodies (i.e. we are performing
- // metadata linking), don't link in the global value due to this
- // reference, simply map it to null.
- if (DoneLinkingBodies)
- return nullptr;
-
linkGlobalValueProto(SGV);
- if (HasError)
- return nullptr;
- Value *Ret = ValueMap[SGV];
- assert(Ret);
- return Ret;
+ return ValueMap[SGV];
}
void ValueMaterializerTy::materializeInitFor(GlobalValue *New,
@@ -881,6 +870,11 @@ void ValueMaterializerTy::materializeIni
return ModLinker->materializeInitFor(New, Old);
}
+static bool shouldLazyLink(const GlobalValue &GV) {
+ return GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
+ GV.hasAvailableExternallyLinkage();
+}
+
void ModuleLinker::materializeInitFor(GlobalValue *New, GlobalValue *Old) {
if (auto *F = dyn_cast<Function>(New)) {
if (!F->isDeclaration())
@@ -900,7 +894,7 @@ void ModuleLinker::materializeInitFor(Gl
if (isPerformingImport() && !doImportAsDefinition(Old))
return;
- if (!New->hasLocalLinkage() && DoNotLinkFromSource.count(Old))
+ if (!ValuesToLink.count(Old) && !shouldLazyLink(*Old))
return;
linkGlobalValueBody(*New, *Old);
@@ -1342,7 +1336,8 @@ bool ModuleLinker::linkAppendingVarProto
[this](Constant *E) {
auto *Key = dyn_cast<GlobalValue>(
E->getAggregateElement(2)->stripPointerCasts());
- return DoNotLinkFromSource.count(Key);
+ return Key && !ValuesToLink.count(Key) &&
+ !shouldLazyLink(*Key);
}),
SrcElements.end());
uint64_t NewSize = DstElements.size() + SrcElements.size();
@@ -1381,14 +1376,6 @@ bool ModuleLinker::linkGlobalValueProto(
// Handle the ultra special appending linkage case first.
assert(!DGV || SGV->hasAppendingLinkage() == DGV->hasAppendingLinkage());
- if (SGV->hasAppendingLinkage() && isPerformingImport()) {
- // 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).
- DoNotLinkFromSource.insert(SGV);
- return false;
- }
if (SGV->hasAppendingLinkage())
return linkAppendingVarProto(cast_or_null<GlobalVariable>(DGV),
cast<GlobalVariable>(SGV));
@@ -1411,15 +1398,9 @@ bool ModuleLinker::linkGlobalValueProto(
return true;
}
- if (!LinkFromSrc) {
- // Track the source global so that we don't attempt to copy it over when
- // processing global initializers.
- DoNotLinkFromSource.insert(SGV);
-
- if (DGV)
- // Make sure to remember this mapping.
- ValueMap[SGV] =
- ConstantExpr::getBitCast(DGV, TypeMap.get(SGV->getType()));
+ if (!LinkFromSrc && DGV) {
+ // Make sure to remember this mapping.
+ ValueMap[SGV] = ConstantExpr::getBitCast(DGV, TypeMap.get(SGV->getType()));
}
if (DGV)
@@ -1431,6 +1412,12 @@ bool ModuleLinker::linkGlobalValueProto(
// When linking from source we setVisibility from copyGlobalValueProto.
setVisibility(NewGV, SGV, DGV);
} else {
+ // If we are done linking global value bodies (i.e. we are performing
+ // metadata linking), don't link in the global value due to this
+ // reference, simply map it to null.
+ if (DoneLinkingBodies)
+ return false;
+
NewGV = copyGlobalValueProto(TypeMap, SGV, DGV, LinkFromSrc);
}
@@ -1774,30 +1761,62 @@ bool ModuleLinker::linkIfNeeded(GlobalVa
if (shouldLinkOnlyNeeded() && !(DGV && DGV->isDeclaration()))
return false;
- if (DGV && !GV.hasLocalLinkage()) {
+ if (DGV && !GV.hasLocalLinkage() && !GV.hasAppendingLinkage()) {
+ auto *DGVar = dyn_cast<GlobalVariable>(DGV);
+ auto *SGVar = dyn_cast<GlobalVariable>(&GV);
+ if (DGVar && SGVar) {
+ if (DGVar->isDeclaration() && SGVar->isDeclaration() &&
+ (!DGVar->isConstant() || !SGVar->isConstant())) {
+ DGVar->setConstant(false);
+ SGVar->setConstant(false);
+ }
+ if (DGVar->hasCommonLinkage() && SGVar->hasCommonLinkage()) {
+ unsigned Align = std::max(DGVar->getAlignment(), SGVar->getAlignment());
+ SGVar->setAlignment(Align);
+ DGVar->setAlignment(Align);
+ }
+ }
+
GlobalValue::VisibilityTypes Visibility =
getMinVisibility(DGV->getVisibility(), GV.getVisibility());
DGV->setVisibility(Visibility);
GV.setVisibility(Visibility);
+
+ bool HasUnnamedAddr = GV.hasUnnamedAddr() && DGV->hasUnnamedAddr();
+ DGV->setUnnamedAddr(HasUnnamedAddr);
+ GV.setUnnamedAddr(HasUnnamedAddr);
}
+ // 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() && !doImportAsDefinition(&GV))
+ return false;
+
+ if (!DGV && !shouldOverrideFromSrc() &&
+ (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
+ GV.hasAvailableExternallyLinkage()))
+ return false;
+
if (const Comdat *SC = GV.getComdat()) {
bool LinkFromSrc;
Comdat::SelectionKind SK;
std::tie(SK, LinkFromSrc) = ComdatsChosen[SC];
- if (!LinkFromSrc) {
- DoNotLinkFromSource.insert(&GV);
- return false;
- }
- }
-
- if (!DGV && !shouldOverrideFromSrc() &&
- (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() ||
- GV.hasAvailableExternallyLinkage())) {
+ if (LinkFromSrc)
+ ValuesToLink.insert(&GV);
return false;
}
- MapValue(&GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
- return HasError;
+
+ bool LinkFromSrc = true;
+ if (DGV && shouldLinkFromSource(LinkFromSrc, *DGV, GV))
+ return true;
+ if (LinkFromSrc)
+ ValuesToLink.insert(&GV);
+ return false;
}
bool ModuleLinker::run() {
@@ -1881,13 +1900,10 @@ bool ModuleLinker::run() {
if (linkIfNeeded(GA))
return true;
- for (const auto &Entry : DstM.getComdatSymbolTable()) {
- const Comdat &C = Entry.getValue();
- if (C.getSelectionKind() == Comdat::Any)
- continue;
- const GlobalValue *GV = SrcM.getNamedValue(C.getName());
- if (GV)
- MapValue(GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
+ for (GlobalValue *GV : ValuesToLink) {
+ MapValue(GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
+ if (HasError)
+ return true;
}
// Note that we are done linking global value bodies. This prevents
Modified: llvm/trunk/test/Linker/funcimport.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/funcimport.ll?rev=254559&r1=254558&r2=254559&view=diff
==============================================================================
--- llvm/trunk/test/Linker/funcimport.ll (original)
+++ llvm/trunk/test/Linker/funcimport.ll Wed Dec 2 16:59:04 2015
@@ -26,20 +26,20 @@
; lazily linked and never referenced/materialized.
; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB1
; IMPORTGLOB1-DAG: define available_externally void @globalfunc1
-; IMPORTGLOB1-DAG: declare void @globalfunc2
; IMPORTGLOB1-DAG: declare void @weakalias
; IMPORTGLOB1-DAG: declare void @analias
-; IMPORTGLOB1-DAG: @linkoncealias = external global
+; IMPORTGLOB1-NOT: @linkoncealias
; IMPORTGLOB1-NOT: @linkoncefunc
+; IMPORTGLOB1-NOT: declare void @globalfunc2
; Ensure that weak alias to a non-imported function is correctly
; turned into a declaration, but that strong alias to an imported function
; is imported as alias.
; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB2
; IMPORTGLOB2-DAG: declare void @analias
-; IMPORTGLOB2-DAG: declare void @globalfunc1
; IMPORTGLOB2-DAG: define available_externally void @globalfunc2
; IMPORTGLOB2-DAG: declare void @weakalias
+; IMPORTGLOB2-NOT: declare void @globalfunc1
; Ensure that strong alias imported in second pass of importing ends up
; as an alias.
@@ -98,9 +98,9 @@
; reference should turned into an external_weak declaration.
; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=callweakfunc:%t.bc -import=weakfunc:%t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORTWEAKFUNC
; IMPORTWEAKFUNC-DAG: Ignoring import request for weak-any function weakfunc
-; IMPORTWEAKFUNC-DAG: @weakvar = extern_weak global i32, align 4
; IMPORTWEAKFUNC-DAG: declare extern_weak void @weakfunc
; IMPORTWEAKFUNC-DAG: define available_externally void @callweakfunc
+; IMPORTWEAKFUNC-NOT: @weakvar = extern_weak global i32, align 4
@globalvar = global i32 1, align 4
@staticvar = internal global i32 1, align 4
More information about the llvm-commits
mailing list