diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 48 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 37 | ||||
-rw-r--r-- | llvm/lib/IR/AutoUpgrade.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/CtorUtils.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/ModuleUtils.cpp | 29 |
8 files changed, 173 insertions, 42 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 14546c0fe4c..a2bb52c1e9f 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1700,8 +1700,11 @@ error_code BitcodeReader::GlobalCleanup() { // Look for global variables which need to be renamed. for (Module::global_iterator GI = TheModule->global_begin(), GE = TheModule->global_end(); - GI != GE; ++GI) - UpgradeGlobalVariable(GI); + GI != GE;) { + GlobalVariable *GV = GI++; + UpgradeGlobalVariable(GV); + } + // Force deallocation of memory for these vectors to favor the client that // want lazy deserialization. std::vector<std::pair<GlobalVariable*, unsigned> >().swap(GlobalInits); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 37a2c3220cb..b68438d8425 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1296,6 +1296,15 @@ void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) { } } +namespace { +struct Structor { + Structor() : Priority(0), Func(nullptr), ComdatKey(nullptr) {} + int Priority; + llvm::Constant *Func; + llvm::GlobalValue *ComdatKey; +}; +} // end namespace + /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { @@ -1307,37 +1316,52 @@ void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { const ConstantArray *InitList = dyn_cast<ConstantArray>(List); if (!InitList) return; // Not an array! StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType()); - if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs! + // FIXME: Only allow the 3-field form in LLVM 4.0. + if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3) + return; // Not an array of two or three elements! if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) || !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr). + if (ETy->getNumElements() == 3 && !isa<PointerType>(ETy->getTypeAtIndex(2U))) + return; // Not (int, ptr, ptr). // Gather the structors in a form that's convenient for sorting by priority. - typedef std::pair<unsigned, Constant *> Structor; SmallVector<Structor, 8> Structors; - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i)); + for (Value *O : InitList->operands()) { + ConstantStruct *CS = dyn_cast<ConstantStruct>(O); if (!CS) continue; // Malformed. if (CS->getOperand(1)->isNullValue()) break; // Found a null terminator, skip the rest. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); if (!Priority) continue; // Malformed. - Structors.push_back(std::make_pair(Priority->getLimitedValue(65535), - CS->getOperand(1))); + Structors.push_back(Structor()); + Structor &S = Structors.back(); + S.Priority = Priority->getLimitedValue(65535); + S.Func = CS->getOperand(1); + if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue()) + S.ComdatKey = dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts()); } // Emit the function pointers in the target-specific order const DataLayout *DL = TM.getDataLayout(); unsigned Align = Log2_32(DL->getPointerPrefAlignment()); - std::stable_sort(Structors.begin(), Structors.end(), less_first()); - for (unsigned i = 0, e = Structors.size(); i != e; ++i) { + std::stable_sort(Structors.begin(), Structors.end(), + [](const Structor &L, + const Structor &R) { return L.Priority < R.Priority; }); + for (Structor &S : Structors) { + const TargetLoweringObjectFile &Obj = getObjFileLowering(); + const MCSymbol *KeySym = nullptr; + const MCSection *KeySec = nullptr; + if (S.ComdatKey) { + KeySym = getSymbol(S.ComdatKey); + KeySec = getObjFileLowering().SectionForGlobal(S.ComdatKey, *Mang, TM); + } const MCSection *OutputSection = - (isCtor ? - getObjFileLowering().getStaticCtorSection(Structors[i].first) : - getObjFileLowering().getStaticDtorSection(Structors[i].first)); + (isCtor ? Obj.getStaticCtorSection(S.Priority, KeySym, KeySec) + : Obj.getStaticDtorSection(S.Priority, KeySym, KeySec)); OutStreamer.SwitchSection(OutputSection); if (OutStreamer.getCurrentSection() != OutStreamer.getPreviousSection()) EmitAlignment(Align); - EmitXXStructor(Structors[i].second); + EmitXXStructor(S.Func); } } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 242f9901c21..dda22599d25 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -339,8 +339,8 @@ getSectionForConstant(SectionKind Kind) const { return DataRelROSection; } -const MCSection * -TargetLoweringObjectFileELF::getStaticCtorSection(unsigned Priority) const { +const MCSection *TargetLoweringObjectFileELF::getStaticCtorSection( + unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const { // The default scheme is .ctor / .dtor, so we have to invert the priority // numbering. if (Priority == 65535) @@ -359,8 +359,8 @@ TargetLoweringObjectFileELF::getStaticCtorSection(unsigned Priority) const { } } -const MCSection * -TargetLoweringObjectFileELF::getStaticDtorSection(unsigned Priority) const { +const MCSection *TargetLoweringObjectFileELF::getStaticDtorSection( + unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const { // The default scheme is .ctor / .dtor, so we have to invert the priority // numbering. if (Priority == 65535) @@ -865,3 +865,32 @@ emitModuleFlags(MCStreamer &Streamer, } } } + +static const MCSection *getAssociativeCOFFSection(MCContext &Ctx, + const MCSection *Sec, + const MCSymbol *KeySym, + const MCSection *KeySec) { + // Return the normal section if we don't have to be associative. + if (!KeySym) + return Sec; + + // Make an associative section with the same name and kind as the normal + // section. + const MCSectionCOFF *SecCOFF = cast<MCSectionCOFF>(Sec); + const MCSectionCOFF *KeySecCOFF = cast<MCSectionCOFF>(KeySec); + unsigned Characteristics = + SecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT; + return Ctx.getCOFFSection(SecCOFF->getSectionName(), Characteristics, + SecCOFF->getKind(), KeySym->getName(), + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, KeySecCOFF); +} + +const MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection( + unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const { + return getAssociativeCOFFSection(getContext(), StaticCtorSection, KeySym, KeySec); +} + +const MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection( + unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const { + return getAssociativeCOFFSection(getContext(), StaticDtorSection, KeySym, KeySec); +} diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index a128eedc7d5..d0fb71f341b 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -170,7 +170,59 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) { return Upgraded; } +static bool UpgradeGlobalStructors(GlobalVariable *GV) { + ArrayType *ATy = dyn_cast<ArrayType>(GV->getType()->getElementType()); + StructType *OldTy = + ATy ? dyn_cast<StructType>(ATy->getElementType()) : nullptr; + + // Only upgrade an array of a two field struct with the appropriate field + // types. + if (!OldTy || OldTy->getNumElements() != 2) + return false; + + // 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, /*isPacked=*/false); + + // Build new constants with a null third field filled in. + ConstantArray *OldInit = dyn_cast<ConstantArray>(GV->getInitializer()); + if (!OldInit) + return false; + std::vector<Constant *> Initializers; + for (Use &U : OldInit->operands()) { + ConstantStruct *Init = cast<ConstantStruct>(&U); + Constant *NewInit = + ConstantStruct::get(NewTy, Init->getOperand(0), Init->getOperand(1), + Constant::getNullValue(VoidPtrTy), nullptr); + Initializers.push_back(NewInit); + } + assert(Initializers.size() == ATy->getNumElements()); + + // 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(); + return true; +} + bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { + if (GV->getName() == "llvm.global_ctors" || + GV->getName() == "llvm.global_dtors") + return UpgradeGlobalStructors(GV); + // Nothing to do yet. return false; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 6ab5e58c4cc..80e731ab152 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -396,14 +396,22 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { "invalid linkage for intrinsic global variable", &GV); // Don't worry about emitting an error for it not being an array, // visitGlobalValue will complain on appending non-array. - if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getType())) { + if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getType()->getElementType())) { StructType *STy = dyn_cast<StructType>(ATy->getElementType()); PointerType *FuncPtrTy = FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo(); - Assert1(STy && STy->getNumElements() == 2 && + // FIXME: Reject the 2-field form in LLVM 4.0. + Assert1(STy && (STy->getNumElements() == 2 || + STy->getNumElements() == 3) && STy->getTypeAtIndex(0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy, "wrong type for intrinsic global variable", &GV); + if (STy->getNumElements() == 3) { + Type *ETy = STy->getTypeAtIndex(2); + Assert1(ETy->isPointerTy() && + cast<PointerType>(ETy)->getElementType()->isIntegerTy(8), + "wrong type for intrinsic global variable", &GV); + } } } diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp index 9d36b723b96..1a253916d7c 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp @@ -155,8 +155,8 @@ bool ObjCARCAPElim::runOnModule(Module &M) { for (User::op_iterator OI = Init->op_begin(), OE = Init->op_end(); OI != OE; ++OI) { Value *Op = *OI; - // llvm.global_ctors is an array of pairs where the second members - // are constructor functions. + // llvm.global_ctors is an array of three-field structs where the second + // members are constructor functions. Function *F = dyn_cast<Function>(cast<ConstantStruct>(Op)->getOperand(1)); // If the user used a constructor function with the wrong signature and // it got bitcasted or whatever, look the other way. diff --git a/llvm/lib/Transforms/Utils/CtorUtils.cpp b/llvm/lib/Transforms/Utils/CtorUtils.cpp index 7cf793f6266..a3594248de0 100644 --- a/llvm/lib/Transforms/Utils/CtorUtils.cpp +++ b/llvm/lib/Transforms/Utils/CtorUtils.cpp @@ -29,26 +29,28 @@ namespace { void installGlobalCtors(GlobalVariable *GCL, const std::vector<Function *> &Ctors) { // If we made a change, reassemble the initializer list. - Constant *CSVals[2]; - CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()), 65535); - CSVals[1] = nullptr; + Constant *CSVals[3]; StructType *StructTy = cast<StructType>(GCL->getType()->getElementType()->getArrayElementType()); // Create the new init list. std::vector<Constant *> CAList; - for (unsigned i = 0, e = Ctors.size(); i != e; ++i) { - if (Ctors[i]) { - CSVals[1] = Ctors[i]; + for (Function *F : Ctors) { + Type *Int32Ty = Type::getInt32Ty(GCL->getContext()); + if (F) { + CSVals[0] = ConstantInt::get(Int32Ty, 65535); + CSVals[1] = F; } else { - Type *FTy = FunctionType::get(Type::getVoidTy(GCL->getContext()), false); - PointerType *PFTy = PointerType::getUnqual(FTy); - CSVals[1] = Constant::getNullValue(PFTy); - CSVals[0] = - ConstantInt::get(Type::getInt32Ty(GCL->getContext()), 0x7fffffff); + CSVals[0] = ConstantInt::get(Int32Ty, 0x7fffffff); + CSVals[1] = Constant::getNullValue(StructTy->getElementType(1)); } - CAList.push_back(ConstantStruct::get(StructTy, CSVals)); + // FIXME: Only allow the 3-field form in LLVM 4.0. + size_t NumElts = StructTy->getNumElements(); + if (NumElts > 2) + CSVals[2] = Constant::getNullValue(StructTy->getElementType(2)); + CAList.push_back( + ConstantStruct::get(StructTy, makeArrayRef(CSVals, NumElts))); } // Create the array initializer. diff --git a/llvm/lib/Transforms/Utils/ModuleUtils.cpp b/llvm/lib/Transforms/Utils/ModuleUtils.cpp index ff6e6f9c60d..d9dbbca1c36 100644 --- a/llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ b/llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -24,16 +24,16 @@ static void appendToGlobalArray(const char *Array, Module &M, Function *F, int Priority) { IRBuilder<> IRB(M.getContext()); FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); - StructType *Ty = StructType::get( - IRB.getInt32Ty(), PointerType::getUnqual(FnTy), NULL); - - Constant *RuntimeCtorInit = ConstantStruct::get( - Ty, IRB.getInt32(Priority), F, NULL); // Get the current set of static global constructors and add the new ctor // to the list. SmallVector<Constant *, 16> CurrentCtors; - if (GlobalVariable * GVCtor = M.getNamedGlobal(Array)) { + StructType *EltTy; + if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) { + // If there is a global_ctors array, use the existing struct type, which can + // have 2 or 3 fields. + ArrayType *ATy = cast<ArrayType>(GVCtor->getType()->getElementType()); + EltTy = cast<StructType>(ATy->getElementType()); if (Constant *Init = GVCtor->getInitializer()) { unsigned n = Init->getNumOperands(); CurrentCtors.reserve(n + 1); @@ -41,13 +41,26 @@ static void appendToGlobalArray(const char *Array, CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); } GVCtor->eraseFromParent(); + } else { + // Use a simple two-field struct if there isn't one already. + EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy), + nullptr); } + // Build a 2 or 3 field global_ctor entry. We don't take a comdat key. + Constant *CSVals[3]; + CSVals[0] = IRB.getInt32(Priority); + CSVals[1] = F; + // FIXME: Drop support for the two element form in LLVM 4.0. + if (EltTy->getNumElements() >= 3) + CSVals[2] = llvm::Constant::getNullValue(IRB.getInt8PtrTy()); + Constant *RuntimeCtorInit = + ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements())); + CurrentCtors.push_back(RuntimeCtorInit); // Create a new initializer. - ArrayType *AT = ArrayType::get(RuntimeCtorInit->getType(), - CurrentCtors.size()); + ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size()); Constant *NewInit = ConstantArray::get(AT, CurrentCtors); // Create the new global variable and replace all uses of |