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:
parent
cff4b2f76a
commit
6e56ab6340
@ -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);
|
||||
|
6
test/Linker/Inputs/ctors2.ll
Normal file
6
test/Linker/Inputs/ctors2.ll
Normal 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
7
test/Linker/ctors2.ll
Normal 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
|
Loading…
Reference in New Issue
Block a user