mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-21 19:20:50 +00:00
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:
parent
fbb911506e
commit
35ecd26675
@ -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
8
test/Linker/ctors5.ll
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user