[llvm-commits] [llvm] r147624 - in /llvm/trunk: lib/Linker/LinkModules.cpp test/Linker/visibility1.ll test/Linker/visibility2.ll
Rafael Espindola
rafael.espindola at gmail.com
Thu Jan 5 15:02:01 PST 2012
Author: rafael
Date: Thu Jan 5 17:02:01 2012
New Revision: 147624
URL: http://llvm.org/viewvc/llvm-project?rev=147624&view=rev
Log:
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.
Added:
llvm/trunk/test/Linker/visibility1.ll
llvm/trunk/test/Linker/visibility2.ll
Modified:
llvm/trunk/lib/Linker/LinkModules.cpp
Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=147624&r1=147623&r2=147624&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Thu Jan 5 17:02:01 2012
@@ -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 @@
/// 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 <, bool &LinkFromSrc);
+ GlobalValue::LinkageTypes <,
+ 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 @@
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 <,
+ GlobalValue::LinkageTypes <,
+ GlobalValue::VisibilityTypes &Vis,
bool &LinkFromSrc) {
assert(Dest && "Must have two globals being queried");
assert(!Src->hasLocalLinkage() &&
@@ -521,13 +536,10 @@
"': 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 @@
/// 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 @@
// 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 @@
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 @@
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 @@
/// 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 @@
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 @@
/// 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 @@
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.
Added: llvm/trunk/test/Linker/visibility1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/visibility1.ll?rev=147624&view=auto
==============================================================================
--- llvm/trunk/test/Linker/visibility1.ll (added)
+++ llvm/trunk/test/Linker/visibility1.ll Thu Jan 5 17:02:01 2012
@@ -0,0 +1,46 @@
+; RUN: llvm-link %s %p/visibility2.ll -S | FileCheck %s
+; RUN: llvm-link %p/visibility2.ll %s -S | FileCheck %s
+
+; The values in this file are strong, the ones in visibility2.ll are weak,
+; but we should still get the visibility from them.
+
+; Variables
+; CHECK: @v1 = hidden global i32 0
+ at v1 = global i32 0
+
+; CHECK: @v2 = protected global i32 0
+ at v2 = global i32 0
+
+; CHECK: @v3 = hidden global i32 0
+ at v3 = protected global i32 0
+
+
+; Aliases
+; CHECK: @a1 = hidden alias i32* @v1
+ at a1 = alias i32* @v1
+
+; CHECK: @a2 = protected alias i32* @v2
+ at a2 = alias i32* @v2
+
+; CHECK: @a3 = hidden alias i32* @v3
+ at a3 = protected alias i32* @v3
+
+
+; Functions
+; CHECK: define hidden void @f1()
+define void @f1() {
+entry:
+ ret void
+}
+
+; CHECK: define protected void @f2()
+define void @f2() {
+entry:
+ ret void
+}
+
+; CHECK: define hidden void @f3()
+define protected void @f3() {
+entry:
+ ret void
+}
Added: llvm/trunk/test/Linker/visibility2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/visibility2.ll?rev=147624&view=auto
==============================================================================
--- llvm/trunk/test/Linker/visibility2.ll (added)
+++ llvm/trunk/test/Linker/visibility2.ll Thu Jan 5 17:02:01 2012
@@ -0,0 +1,27 @@
+; This file is used by visibility1.ll, so it doesn't actually do anything itself
+;
+; RUN: true
+
+; Variables
+ at v1 = weak hidden global i32 0
+ at v2 = weak protected global i32 0
+ at v3 = weak hidden global i32 0
+
+; Aliases
+ at a1 = hidden alias weak i32* @v1
+ at a2 = protected alias weak i32* @v2
+ at a3 = hidden alias weak i32* @v3
+
+; Functions
+define weak hidden void @f1() {
+entry:
+ ret void
+}
+define weak protected void @f2() {
+entry:
+ ret void
+}
+define weak hidden void @f3() {
+entry:
+ ret void
+}
More information about the llvm-commits
mailing list