Change how the linker handles the old llvm.global_ctors.

Now instead of changing it to the new format and then linking, it just
handles the old format while copying it over.

The main differences are:

* There is no rauw in the source module.
* An old format input is always upgraded.

The first item helps with having a sane API that passes in a GV list to
the linker.

The second one is a small step in deprecating the old format.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254907 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2015-12-07 13:24:23 +00:00
parent fbb911506e
commit 35ecd26675
2 changed files with 42 additions and 92 deletions

View File

@ -509,9 +509,6 @@ private:
void computeTypeMapping();
void upgradeMismatchedGlobalArray(StringRef Name);
void upgradeMismatchedGlobals();
bool linkIfNeeded(GlobalValue &GV);
Constant *linkAppendingVarProto(GlobalVariable *DstGV,
const GlobalVariable *SrcGV);
@ -1190,83 +1187,6 @@ void ModuleLinker::computeTypeMapping() {
TypeMap.linkDefinedTypeBodies();
}
static void upgradeGlobalArray(GlobalVariable *GV) {
ArrayType *ATy = cast<ArrayType>(GV->getType()->getElementType());
StructType *OldTy = cast<StructType>(ATy->getElementType());
assert(OldTy->getNumElements() == 2 && "Expected to upgrade from 2 elements");
// Get the upgraded 3 element type.
PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo();
Type *Tys[3] = {OldTy->getElementType(0), OldTy->getElementType(1),
VoidPtrTy};
StructType *NewTy = StructType::get(GV->getContext(), Tys, false);
// Build new constants with a null third field filled in.
Constant *OldInitC = GV->getInitializer();
ConstantArray *OldInit = dyn_cast<ConstantArray>(OldInitC);
if (!OldInit && !isa<ConstantAggregateZero>(OldInitC))
// Invalid initializer; give up.
return;
std::vector<Constant *> Initializers;
if (OldInit && OldInit->getNumOperands()) {
Value *Null = Constant::getNullValue(VoidPtrTy);
for (Use &U : OldInit->operands()) {
ConstantStruct *Init = cast<ConstantStruct>(U.get());
Initializers.push_back(ConstantStruct::get(
NewTy, Init->getOperand(0), Init->getOperand(1), Null, nullptr));
}
}
assert(Initializers.size() == ATy->getNumElements() &&
"Failed to copy all array elements");
// Replace the old GV with a new one.
ATy = ArrayType::get(NewTy, Initializers.size());
Constant *NewInit = ConstantArray::get(ATy, Initializers);
GlobalVariable *NewGV = new GlobalVariable(
*GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "",
GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(),
GV->isExternallyInitialized());
NewGV->copyAttributesFrom(GV);
NewGV->takeName(GV);
assert(GV->use_empty() && "program cannot use initializer list");
GV->eraseFromParent();
}
void ModuleLinker::upgradeMismatchedGlobalArray(StringRef Name) {
// Look for the global arrays.
auto *DstGV = dyn_cast_or_null<GlobalVariable>(DstM.getNamedValue(Name));
if (!DstGV)
return;
auto *SrcGV = dyn_cast_or_null<GlobalVariable>(SrcM.getNamedValue(Name));
if (!SrcGV)
return;
// Check if the types already match.
auto *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
auto *SrcTy =
cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
if (DstTy == SrcTy)
return;
// Grab the element types. We can only upgrade an array of a two-field
// struct. Only bother if the other one has three-fields.
auto *DstEltTy = cast<StructType>(DstTy->getElementType());
auto *SrcEltTy = cast<StructType>(SrcTy->getElementType());
if (DstEltTy->getNumElements() == 2 && SrcEltTy->getNumElements() == 3) {
upgradeGlobalArray(DstGV);
return;
}
if (DstEltTy->getNumElements() == 3 && SrcEltTy->getNumElements() == 2)
upgradeGlobalArray(SrcGV);
// We can't upgrade any other differences.
}
void ModuleLinker::upgradeMismatchedGlobals() {
upgradeMismatchedGlobalArray("llvm.global_ctors");
upgradeMismatchedGlobalArray("llvm.global_dtors");
}
static void getArrayElements(const Constant *C,
SmallVectorImpl<Constant *> &Dest) {
unsigned NumElements = cast<ArrayType>(C->getType())->getNumElements();
@ -1279,9 +1199,25 @@ static void getArrayElements(const Constant *C,
/// Return true on error.
Constant *ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
const GlobalVariable *SrcGV) {
ArrayType *SrcTy =
cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
Type *EltTy = SrcTy->getElementType();
Type *EltTy = cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()))
->getElementType();
StringRef Name = SrcGV->getName();
bool IsNewStructor = false;
bool IsOldStructor = false;
if (Name == "llvm.global_ctors" || Name == "llvm.global_dtors") {
if (cast<StructType>(EltTy)->getNumElements() == 3)
IsNewStructor = true;
else
IsOldStructor = true;
}
PointerType *VoidPtrTy = Type::getInt8Ty(SrcGV->getContext())->getPointerTo();
if (IsOldStructor) {
auto &ST = *cast<StructType>(EltTy);
Type *Tys[3] = {ST.getElementType(0), ST.getElementType(1), VoidPtrTy};
EltTy = StructType::get(SrcGV->getContext(), Tys, false);
}
if (DstGV) {
ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
@ -1335,10 +1271,6 @@ Constant *ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
SmallVector<Constant *, 16> SrcElements;
getArrayElements(SrcGV->getInitializer(), SrcElements);
StringRef Name = SrcGV->getName();
bool IsNewStructor =
(Name == "llvm.global_ctors" || Name == "llvm.global_dtors") &&
cast<StructType>(EltTy)->getNumElements() == 3;
if (IsNewStructor)
SrcElements.erase(
std::remove_if(SrcElements.begin(), SrcElements.end(),
@ -1367,8 +1299,21 @@ Constant *ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
ValueMap[SrcGV] = Ret;
for (auto *V : SrcElements) {
DstElements.push_back(
MapValue(V, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer));
Constant *NewV;
if (IsOldStructor) {
auto *S = cast<ConstantStruct>(V);
auto *E1 = MapValue(S->getOperand(0), ValueMap, RF_MoveDistinctMDs,
&TypeMap, &ValMaterializer);
auto *E2 = MapValue(S->getOperand(1), ValueMap, RF_MoveDistinctMDs,
&TypeMap, &ValMaterializer);
Value *Null = Constant::getNullValue(VoidPtrTy);
NewV =
ConstantStruct::get(cast<StructType>(EltTy), E1, E2, Null, nullptr);
} else {
NewV =
MapValue(V, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
}
DstElements.push_back(NewV);
}
NG->setInitializer(ConstantArray::get(NewType, DstElements));
@ -1877,9 +1822,6 @@ bool ModuleLinker::run() {
ComdatsChosen[&C] = std::make_pair(SK, LinkFromSrc);
}
// Upgrade mismatched global arrays.
upgradeMismatchedGlobals();
for (GlobalVariable &GV : SrcM.globals())
if (const Comdat *SC = GV.getComdat())
ComdatMembers[SC].push_back(&GV);

8
test/Linker/ctors5.ll Normal file
View File

@ -0,0 +1,8 @@
; RUN: llvm-link -S %s | FileCheck %s
@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }]
; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }]
define void @f() {
ret void
}