summaryrefslogtreecommitdiff
path: root/lib/Linker/LinkModules.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-01-05 23:02:01 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-01-05 23:02:01 +0000
commit3ed8815541d2118728a91bbd5bee054fbcfba71f (patch)
tree077ae7fccb56f694d51c3c9457d7a492138602e9 /lib/Linker/LinkModules.cpp
parentdd35df15a296ca7a6722dc6eb04702e687652c45 (diff)
downloadllvm-3ed8815541d2118728a91bbd5bee054fbcfba71f.tar.gz
llvm-3ed8815541d2118728a91bbd5bee054fbcfba71f.tar.bz2
llvm-3ed8815541d2118728a91bbd5bee054fbcfba71f.tar.xz
Link symbols with different visibilities according to the rules in the
System V Application Binary Interface. This lets us use -fvisibility-inlines-hidden with LTO. Fixes PR11697. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147624 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Linker/LinkModules.cpp')
-rw-r--r--lib/Linker/LinkModules.cpp78
1 files changed, 54 insertions, 24 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index 75efce0b18..46a76a2599 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -17,6 +17,7 @@
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
#include "llvm/Transforms/Utils/Cloning.h"
@@ -379,7 +380,9 @@ namespace {
/// getLinkageResult - This analyzes the two global values and determines
/// what the result will look like in the destination module.
bool getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
- GlobalValue::LinkageTypes &LT, bool &LinkFromSrc);
+ GlobalValue::LinkageTypes &LT,
+ GlobalValue::VisibilityTypes &Vis,
+ bool &LinkFromSrc);
/// getLinkedToGlobal - Given a global in the source module, return the
/// global in the destination module that is being linked to, if any.
@@ -451,15 +454,27 @@ static void CopyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) {
forceRenaming(DestGV, SrcGV->getName());
}
+static bool isLessConstraining(GlobalValue::VisibilityTypes a,
+ GlobalValue::VisibilityTypes b) {
+ if (a == GlobalValue::HiddenVisibility)
+ return false;
+ if (b == GlobalValue::HiddenVisibility)
+ return true;
+ if (a == GlobalValue::ProtectedVisibility)
+ return false;
+ if (b == GlobalValue::ProtectedVisibility)
+ return true;
+ return false;
+}
+
/// getLinkageResult - This analyzes the two global values and determines what
/// the result will look like in the destination module. In particular, it
-/// computes the resultant linkage type, computes whether the global in the
-/// source should be copied over to the destination (replacing the existing
-/// one), and computes whether this linkage is an error or not. It also performs
-/// visibility checks: we cannot link together two symbols with different
-/// visibilities.
+/// computes the resultant linkage type and visibility, computes whether the
+/// global in the source should be copied over to the destination (replacing
+/// the existing one), and computes whether this linkage is an error or not.
bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
- GlobalValue::LinkageTypes &LT,
+ GlobalValue::LinkageTypes &LT,
+ GlobalValue::VisibilityTypes &Vis,
bool &LinkFromSrc) {
assert(Dest && "Must have two globals being queried");
assert(!Src->hasLocalLinkage() &&
@@ -521,13 +536,10 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
"': symbol multiply defined!");
}
- // Check visibility
- if (Src->getVisibility() != Dest->getVisibility() &&
- !SrcIsDeclaration && !DestIsDeclaration &&
- !Src->hasAvailableExternallyLinkage() &&
- !Dest->hasAvailableExternallyLinkage())
- return emitError("Linking globals named '" + Src->getName() +
- "': symbols have different visibilities!");
+ // Compute the visibility. We follow the rules in the System V Application
+ // Binary Interface.
+ Vis = isLessConstraining(Src->getVisibility(), Dest->getVisibility()) ?
+ Dest->getVisibility() : Src->getVisibility();
return false;
}
@@ -665,6 +677,7 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
/// merge them into the dest module.
bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
GlobalValue *DGV = getLinkedToGlobal(SGV);
+ llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
if (DGV) {
// Concatenation of appending linkage variables is magic and handled later.
@@ -674,9 +687,11 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
// Determine whether linkage of these two globals follows the source
// module's definition or the destination module's definition.
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
+ GlobalValue::VisibilityTypes NV;
bool LinkFromSrc = false;
- if (getLinkageResult(DGV, SGV, NewLinkage, LinkFromSrc))
+ if (getLinkageResult(DGV, SGV, NewLinkage, NV, LinkFromSrc))
return true;
+ NewVisibility = NV;
// If we're not linking from the source, then keep the definition that we
// have.
@@ -686,9 +701,10 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
DGVar->setConstant(true);
- // Set calculated linkage.
+ // Set calculated linkage and visibility.
DGV->setLinkage(NewLinkage);
-
+ DGV->setVisibility(*NewVisibility);
+
// Make sure to remember this mapping.
ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType()));
@@ -711,6 +727,8 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
SGV->getType()->getAddressSpace());
// Propagate alignment, visibility and section info.
CopyGVAttributes(NewDGV, SGV);
+ if (NewVisibility)
+ NewDGV->setVisibility(*NewVisibility);
if (DGV) {
DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, DGV->getType()));
@@ -726,17 +744,21 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
/// destination module if needed, setting up mapping information.
bool ModuleLinker::linkFunctionProto(Function *SF) {
GlobalValue *DGV = getLinkedToGlobal(SF);
+ llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
if (DGV) {
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
bool LinkFromSrc = false;
- if (getLinkageResult(DGV, SF, NewLinkage, LinkFromSrc))
+ GlobalValue::VisibilityTypes NV;
+ if (getLinkageResult(DGV, SF, NewLinkage, NV, LinkFromSrc))
return true;
-
+ NewVisibility = NV;
+
if (!LinkFromSrc) {
// Set calculated linkage
DGV->setLinkage(NewLinkage);
-
+ DGV->setVisibility(*NewVisibility);
+
// Make sure to remember this mapping.
ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType()));
@@ -753,6 +775,8 @@ bool ModuleLinker::linkFunctionProto(Function *SF) {
Function *NewDF = Function::Create(TypeMap.get(SF->getFunctionType()),
SF->getLinkage(), SF->getName(), DstM);
CopyGVAttributes(NewDF, SF);
+ if (NewVisibility)
+ NewDF->setVisibility(*NewVisibility);
if (DGV) {
// Any uses of DF need to change to NewDF, with cast.
@@ -775,17 +799,21 @@ bool ModuleLinker::linkFunctionProto(Function *SF) {
/// source module.
bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
GlobalValue *DGV = getLinkedToGlobal(SGA);
-
+ llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
+
if (DGV) {
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
+ GlobalValue::VisibilityTypes NV;
bool LinkFromSrc = false;
- if (getLinkageResult(DGV, SGA, NewLinkage, LinkFromSrc))
+ if (getLinkageResult(DGV, SGA, NewLinkage, NV, LinkFromSrc))
return true;
-
+ NewVisibility = NV;
+
if (!LinkFromSrc) {
// Set calculated linkage.
DGV->setLinkage(NewLinkage);
-
+ DGV->setVisibility(*NewVisibility);
+
// Make sure to remember this mapping.
ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
@@ -802,6 +830,8 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
SGA->getLinkage(), SGA->getName(),
/*aliasee*/0, DstM);
CopyGVAttributes(NewDA, SGA);
+ if (NewVisibility)
+ NewDA->setVisibility(*NewVisibility);
if (DGV) {
// Any uses of DGV need to change to NewDA, with cast.