mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-10 10:01:42 +00:00
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. llvm-svn: 147624
This commit is contained in:
parent
5267211899
commit
23f8d64b58
@ -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 <, 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 @@ 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 <,
|
||||
GlobalValue::LinkageTypes <,
|
||||
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.
|
||||
|
46
llvm/test/Linker/visibility1.ll
Normal file
46
llvm/test/Linker/visibility1.ll
Normal file
@ -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
|
||||
@v1 = global i32 0
|
||||
|
||||
; CHECK: @v2 = protected global i32 0
|
||||
@v2 = global i32 0
|
||||
|
||||
; CHECK: @v3 = hidden global i32 0
|
||||
@v3 = protected global i32 0
|
||||
|
||||
|
||||
; Aliases
|
||||
; CHECK: @a1 = hidden alias i32* @v1
|
||||
@a1 = alias i32* @v1
|
||||
|
||||
; CHECK: @a2 = protected alias i32* @v2
|
||||
@a2 = alias i32* @v2
|
||||
|
||||
; CHECK: @a3 = hidden alias i32* @v3
|
||||
@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
|
||||
}
|
27
llvm/test/Linker/visibility2.ll
Normal file
27
llvm/test/Linker/visibility2.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; This file is used by visibility1.ll, so it doesn't actually do anything itself
|
||||
;
|
||||
; RUN: true
|
||||
|
||||
; Variables
|
||||
@v1 = weak hidden global i32 0
|
||||
@v2 = weak protected global i32 0
|
||||
@v3 = weak hidden global i32 0
|
||||
|
||||
; Aliases
|
||||
@a1 = hidden alias weak i32* @v1
|
||||
@a2 = protected alias weak i32* @v2
|
||||
@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
|
||||
}
|
Loading…
Reference in New Issue
Block a user