mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 17:24:48 +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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147624 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -17,6 +17,7 @@
|
|||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Transforms/Utils/Cloning.h"
|
#include "llvm/Transforms/Utils/Cloning.h"
|
||||||
@ -379,7 +380,9 @@ namespace {
|
|||||||
/// getLinkageResult - This analyzes the two global values and determines
|
/// getLinkageResult - This analyzes the two global values and determines
|
||||||
/// what the result will look like in the destination module.
|
/// what the result will look like in the destination module.
|
||||||
bool getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
|
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
|
/// getLinkedToGlobal - Given a global in the source module, return the
|
||||||
/// global in the destination module that is being linked to, if any.
|
/// 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());
|
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
|
/// getLinkageResult - This analyzes the two global values and determines what
|
||||||
/// the result will look like in the destination module. In particular, it
|
/// the result will look like in the destination module. In particular, it
|
||||||
/// computes the resultant linkage type, computes whether the global in the
|
/// computes the resultant linkage type and visibility, computes whether the
|
||||||
/// source should be copied over to the destination (replacing the existing
|
/// global in the source should be copied over to the destination (replacing
|
||||||
/// one), and computes whether this linkage is an error or not. It also performs
|
/// the existing one), and computes whether this linkage is an error or not.
|
||||||
/// visibility checks: we cannot link together two symbols with different
|
|
||||||
/// visibilities.
|
|
||||||
bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
|
bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
|
||||||
GlobalValue::LinkageTypes <,
|
GlobalValue::LinkageTypes <,
|
||||||
|
GlobalValue::VisibilityTypes &Vis,
|
||||||
bool &LinkFromSrc) {
|
bool &LinkFromSrc) {
|
||||||
assert(Dest && "Must have two globals being queried");
|
assert(Dest && "Must have two globals being queried");
|
||||||
assert(!Src->hasLocalLinkage() &&
|
assert(!Src->hasLocalLinkage() &&
|
||||||
@ -521,13 +536,10 @@ bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
|
|||||||
"': symbol multiply defined!");
|
"': symbol multiply defined!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check visibility
|
// Compute the visibility. We follow the rules in the System V Application
|
||||||
if (Src->getVisibility() != Dest->getVisibility() &&
|
// Binary Interface.
|
||||||
!SrcIsDeclaration && !DestIsDeclaration &&
|
Vis = isLessConstraining(Src->getVisibility(), Dest->getVisibility()) ?
|
||||||
!Src->hasAvailableExternallyLinkage() &&
|
Dest->getVisibility() : Src->getVisibility();
|
||||||
!Dest->hasAvailableExternallyLinkage())
|
|
||||||
return emitError("Linking globals named '" + Src->getName() +
|
|
||||||
"': symbols have different visibilities!");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,6 +677,7 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
|
|||||||
/// merge them into the dest module.
|
/// merge them into the dest module.
|
||||||
bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
|
bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
|
||||||
GlobalValue *DGV = getLinkedToGlobal(SGV);
|
GlobalValue *DGV = getLinkedToGlobal(SGV);
|
||||||
|
llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
|
||||||
|
|
||||||
if (DGV) {
|
if (DGV) {
|
||||||
// Concatenation of appending linkage variables is magic and handled later.
|
// 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
|
// Determine whether linkage of these two globals follows the source
|
||||||
// module's definition or the destination module's definition.
|
// module's definition or the destination module's definition.
|
||||||
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
|
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
|
||||||
|
GlobalValue::VisibilityTypes NV;
|
||||||
bool LinkFromSrc = false;
|
bool LinkFromSrc = false;
|
||||||
if (getLinkageResult(DGV, SGV, NewLinkage, LinkFromSrc))
|
if (getLinkageResult(DGV, SGV, NewLinkage, NV, LinkFromSrc))
|
||||||
return true;
|
return true;
|
||||||
|
NewVisibility = NV;
|
||||||
|
|
||||||
// If we're not linking from the source, then keep the definition that we
|
// If we're not linking from the source, then keep the definition that we
|
||||||
// have.
|
// have.
|
||||||
@ -686,9 +701,10 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
|
|||||||
if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
|
if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
|
||||||
DGVar->setConstant(true);
|
DGVar->setConstant(true);
|
||||||
|
|
||||||
// Set calculated linkage.
|
// Set calculated linkage and visibility.
|
||||||
DGV->setLinkage(NewLinkage);
|
DGV->setLinkage(NewLinkage);
|
||||||
|
DGV->setVisibility(*NewVisibility);
|
||||||
|
|
||||||
// Make sure to remember this mapping.
|
// Make sure to remember this mapping.
|
||||||
ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType()));
|
ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType()));
|
||||||
|
|
||||||
@ -711,6 +727,8 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
|
|||||||
SGV->getType()->getAddressSpace());
|
SGV->getType()->getAddressSpace());
|
||||||
// Propagate alignment, visibility and section info.
|
// Propagate alignment, visibility and section info.
|
||||||
CopyGVAttributes(NewDGV, SGV);
|
CopyGVAttributes(NewDGV, SGV);
|
||||||
|
if (NewVisibility)
|
||||||
|
NewDGV->setVisibility(*NewVisibility);
|
||||||
|
|
||||||
if (DGV) {
|
if (DGV) {
|
||||||
DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, DGV->getType()));
|
DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, DGV->getType()));
|
||||||
@ -726,17 +744,21 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
|
|||||||
/// destination module if needed, setting up mapping information.
|
/// destination module if needed, setting up mapping information.
|
||||||
bool ModuleLinker::linkFunctionProto(Function *SF) {
|
bool ModuleLinker::linkFunctionProto(Function *SF) {
|
||||||
GlobalValue *DGV = getLinkedToGlobal(SF);
|
GlobalValue *DGV = getLinkedToGlobal(SF);
|
||||||
|
llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
|
||||||
|
|
||||||
if (DGV) {
|
if (DGV) {
|
||||||
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
|
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
|
||||||
bool LinkFromSrc = false;
|
bool LinkFromSrc = false;
|
||||||
if (getLinkageResult(DGV, SF, NewLinkage, LinkFromSrc))
|
GlobalValue::VisibilityTypes NV;
|
||||||
|
if (getLinkageResult(DGV, SF, NewLinkage, NV, LinkFromSrc))
|
||||||
return true;
|
return true;
|
||||||
|
NewVisibility = NV;
|
||||||
|
|
||||||
if (!LinkFromSrc) {
|
if (!LinkFromSrc) {
|
||||||
// Set calculated linkage
|
// Set calculated linkage
|
||||||
DGV->setLinkage(NewLinkage);
|
DGV->setLinkage(NewLinkage);
|
||||||
|
DGV->setVisibility(*NewVisibility);
|
||||||
|
|
||||||
// Make sure to remember this mapping.
|
// Make sure to remember this mapping.
|
||||||
ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType()));
|
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()),
|
Function *NewDF = Function::Create(TypeMap.get(SF->getFunctionType()),
|
||||||
SF->getLinkage(), SF->getName(), DstM);
|
SF->getLinkage(), SF->getName(), DstM);
|
||||||
CopyGVAttributes(NewDF, SF);
|
CopyGVAttributes(NewDF, SF);
|
||||||
|
if (NewVisibility)
|
||||||
|
NewDF->setVisibility(*NewVisibility);
|
||||||
|
|
||||||
if (DGV) {
|
if (DGV) {
|
||||||
// Any uses of DF need to change to NewDF, with cast.
|
// Any uses of DF need to change to NewDF, with cast.
|
||||||
@ -775,17 +799,21 @@ bool ModuleLinker::linkFunctionProto(Function *SF) {
|
|||||||
/// source module.
|
/// source module.
|
||||||
bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
|
bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
|
||||||
GlobalValue *DGV = getLinkedToGlobal(SGA);
|
GlobalValue *DGV = getLinkedToGlobal(SGA);
|
||||||
|
llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
|
||||||
|
|
||||||
if (DGV) {
|
if (DGV) {
|
||||||
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
|
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
|
||||||
|
GlobalValue::VisibilityTypes NV;
|
||||||
bool LinkFromSrc = false;
|
bool LinkFromSrc = false;
|
||||||
if (getLinkageResult(DGV, SGA, NewLinkage, LinkFromSrc))
|
if (getLinkageResult(DGV, SGA, NewLinkage, NV, LinkFromSrc))
|
||||||
return true;
|
return true;
|
||||||
|
NewVisibility = NV;
|
||||||
|
|
||||||
if (!LinkFromSrc) {
|
if (!LinkFromSrc) {
|
||||||
// Set calculated linkage.
|
// Set calculated linkage.
|
||||||
DGV->setLinkage(NewLinkage);
|
DGV->setLinkage(NewLinkage);
|
||||||
|
DGV->setVisibility(*NewVisibility);
|
||||||
|
|
||||||
// Make sure to remember this mapping.
|
// Make sure to remember this mapping.
|
||||||
ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
|
ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
|
||||||
|
|
||||||
@ -802,6 +830,8 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
|
|||||||
SGA->getLinkage(), SGA->getName(),
|
SGA->getLinkage(), SGA->getName(),
|
||||||
/*aliasee*/0, DstM);
|
/*aliasee*/0, DstM);
|
||||||
CopyGVAttributes(NewDA, SGA);
|
CopyGVAttributes(NewDA, SGA);
|
||||||
|
if (NewVisibility)
|
||||||
|
NewDA->setVisibility(*NewVisibility);
|
||||||
|
|
||||||
if (DGV) {
|
if (DGV) {
|
||||||
// Any uses of DGV need to change to NewDA, with cast.
|
// Any uses of DGV need to change to NewDA, with cast.
|
||||||
|
46
test/Linker/visibility1.ll
Normal file
46
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
test/Linker/visibility2.ll
Normal file
27
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
|
||||||
|
}
|
Reference in New Issue
Block a user