1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00

Correctly handle llvm.global_ctors merging.

We were not handling the case where an entry must be dropped and the
destination module has no llvm.global_ctors.

llvm-svn: 254241
This commit is contained in:
Rafael Espindola 2015-11-29 03:29:42 +00:00
parent cff4b2f76a
commit 6e56ab6340
3 changed files with 56 additions and 37 deletions

View File

@ -1314,54 +1314,57 @@ void ModuleLinker::upgradeMismatchedGlobals() {
/// Return true on error.
bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
const GlobalVariable *SrcGV) {
if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage())
return emitError("Linking globals named '" + SrcGV->getName() +
"': can only link appending global with another appending global!");
ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
ArrayType *SrcTy =
cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
Type *EltTy = DstTy->getElementType();
cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
Type *EltTy = SrcTy->getElementType();
// Check to see that they two arrays agree on type.
if (EltTy != SrcTy->getElementType())
return emitError("Appending variables with different element types!");
if (DstGV->isConstant() != SrcGV->isConstant())
return emitError("Appending variables linked with different const'ness!");
uint64_t NewSize = SrcTy->getNumElements();
if (DstGV) {
ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
NewSize += DstTy->getNumElements();
if (DstGV->getAlignment() != SrcGV->getAlignment())
return emitError(
"Appending variables with different alignment need to be linked!");
if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage())
return emitError(
"Linking globals named '" + SrcGV->getName() +
"': can only link appending global with another appending global!");
if (DstGV->getVisibility() != SrcGV->getVisibility())
return emitError(
"Appending variables with different visibility need to be linked!");
// Check to see that they two arrays agree on type.
if (EltTy != DstTy->getElementType())
return emitError("Appending variables with different element types!");
if (DstGV->isConstant() != SrcGV->isConstant())
return emitError("Appending variables linked with different const'ness!");
if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr())
return emitError(
"Appending variables with different unnamed_addr need to be linked!");
if (DstGV->getAlignment() != SrcGV->getAlignment())
return emitError(
"Appending variables with different alignment need to be linked!");
if (StringRef(DstGV->getSection()) != SrcGV->getSection())
return emitError(
if (DstGV->getVisibility() != SrcGV->getVisibility())
return emitError(
"Appending variables with different visibility need to be linked!");
if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr())
return emitError(
"Appending variables with different unnamed_addr need to be linked!");
if (StringRef(DstGV->getSection()) != SrcGV->getSection())
return emitError(
"Appending variables with different section name need to be linked!");
}
uint64_t NewSize = DstTy->getNumElements() + SrcTy->getNumElements();
ArrayType *NewType = ArrayType::get(EltTy, NewSize);
// Create the new global variable.
GlobalVariable *NG =
new GlobalVariable(*DstGV->getParent(), NewType, SrcGV->isConstant(),
DstGV->getLinkage(), /*init*/nullptr, /*name*/"", DstGV,
DstGV->getThreadLocalMode(),
DstGV->getType()->getAddressSpace());
GlobalVariable *NG = new GlobalVariable(
*DstM, NewType, SrcGV->isConstant(), SrcGV->getLinkage(),
/*init*/ nullptr, /*name*/ "", DstGV, SrcGV->getThreadLocalMode(),
SrcGV->getType()->getAddressSpace());
// Propagate alignment, visibility and section info.
copyGVAttributes(NG, DstGV);
copyGVAttributes(NG, SrcGV);
AppendingVarInfo AVI;
AVI.NewGV = NG;
AVI.DstInit = DstGV->getInitializer();
AVI.DstInit = DstGV ? DstGV->getInitializer() : nullptr;
AVI.SrcInit = SrcGV->getInitializer();
AppendingVars.push_back(AVI);
@ -1369,8 +1372,10 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
// global.
ValueMap[SrcGV] = ConstantExpr::getBitCast(NG, TypeMap.get(SrcGV->getType()));
DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
DstGV->eraseFromParent();
if (DstGV) {
DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
DstGV->eraseFromParent();
}
// Track the source variable so we don't try to link it.
DoNotLinkFromSource.insert(SrcGV);
@ -1391,8 +1396,8 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) {
DoNotLinkFromSource.insert(SGV);
return false;
}
if (DGV && DGV->hasAppendingLinkage())
return linkAppendingVarProto(cast<GlobalVariable>(DGV),
if (SGV->hasAppendingLinkage())
return linkAppendingVarProto(cast_or_null<GlobalVariable>(DGV),
cast<GlobalVariable>(SGV));
bool LinkFromSrc = true;
@ -1496,7 +1501,8 @@ static void getArrayElements(const Constant *C,
void ModuleLinker::linkAppendingVarInit(AppendingVarInfo &AVI) {
// Merge the initializer.
SmallVector<Constant *, 16> DstElements;
getArrayElements(AVI.DstInit, DstElements);
if (AVI.DstInit)
getArrayElements(AVI.DstInit, DstElements);
SmallVector<Constant *, 16> SrcElements;
getArrayElements(AVI.SrcInit, SrcElements);

View File

@ -0,0 +1,6 @@
$foo = comdat any
@foo = global i8 1, comdat
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @bar, i8* @foo }]
define void @bar() comdat($foo) {
ret void
}

7
test/Linker/ctors2.ll Normal file
View File

@ -0,0 +1,7 @@
; RUN: llvm-link -S %s %p/Inputs/ctors2.ll -o - | FileCheck %s
$foo = comdat any
@foo = global i8 0, comdat
; CHECK: @foo = global i8 0, comdat
; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer