From 35ecd26675997eeb0954dfb0edffb4ce85cf20f1 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 7 Dec 2015 13:24:23 +0000 Subject: [PATCH] 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 --- lib/Linker/LinkModules.cpp | 126 ++++++++++--------------------------- test/Linker/ctors5.ll | 8 +++ 2 files changed, 42 insertions(+), 92 deletions(-) create mode 100644 test/Linker/ctors5.ll diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 627137ba3ab..a1c3162bf79 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -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(GV->getType()->getElementType()); - StructType *OldTy = cast(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(OldInitC); - if (!OldInit && !isa(OldInitC)) - // Invalid initializer; give up. - return; - std::vector Initializers; - if (OldInit && OldInit->getNumOperands()) { - Value *Null = Constant::getNullValue(VoidPtrTy); - for (Use &U : OldInit->operands()) { - ConstantStruct *Init = cast(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(DstM.getNamedValue(Name)); - if (!DstGV) - return; - auto *SrcGV = dyn_cast_or_null(SrcM.getNamedValue(Name)); - if (!SrcGV) - return; - - // Check if the types already match. - auto *DstTy = cast(DstGV->getType()->getElementType()); - auto *SrcTy = - cast(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(DstTy->getElementType()); - auto *SrcEltTy = cast(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 &Dest) { unsigned NumElements = cast(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(TypeMap.get(SrcGV->getType()->getElementType())); - Type *EltTy = SrcTy->getElementType(); + Type *EltTy = cast(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(EltTy)->getNumElements() == 3) + IsNewStructor = true; + else + IsOldStructor = true; + } + + PointerType *VoidPtrTy = Type::getInt8Ty(SrcGV->getContext())->getPointerTo(); + if (IsOldStructor) { + auto &ST = *cast(EltTy); + Type *Tys[3] = {ST.getElementType(0), ST.getElementType(1), VoidPtrTy}; + EltTy = StructType::get(SrcGV->getContext(), Tys, false); + } if (DstGV) { ArrayType *DstTy = cast(DstGV->getType()->getElementType()); @@ -1335,10 +1271,6 @@ Constant *ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, SmallVector SrcElements; getArrayElements(SrcGV->getInitializer(), SrcElements); - StringRef Name = SrcGV->getName(); - bool IsNewStructor = - (Name == "llvm.global_ctors" || Name == "llvm.global_dtors") && - cast(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(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(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); diff --git a/test/Linker/ctors5.ll b/test/Linker/ctors5.ll new file mode 100644 index 00000000000..99124061bb3 --- /dev/null +++ b/test/Linker/ctors5.ll @@ -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 +} -- 2.34.1