From 7722a2d4e33da6f5b0569241328a26ba78c2836b Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 25 Jan 2012 22:24:19 +0000 Subject: [PATCH] Properly emit ctors / dtors with priorities into desired sections and let linker handle the rest. This finally fixes PR5329 llvm-svn: 148990 --- llvm/include/llvm/CodeGen/AsmPrinter.h | 2 +- .../CodeGen/TargetLoweringObjectFileImpl.h | 5 +++ llvm/include/llvm/MC/MCObjectFileInfo.h | 15 ------- .../llvm/Target/TargetLoweringObjectFile.h | 13 ++++++- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 39 ++++++++----------- .../CodeGen/TargetLoweringObjectFileImpl.cpp | 26 +++++++++++++ llvm/lib/MC/MCObjectFileInfo.cpp | 8 +--- llvm/lib/Target/ARM/ARMTargetObjectFile.cpp | 35 ++++++++++++++++- llvm/lib/Target/ARM/ARMTargetObjectFile.h | 4 ++ llvm/test/CodeGen/ARM/ctor_order.ll | 10 +++-- llvm/test/CodeGen/X86/2011-08-29-InitOrder.ll | 30 ++++++++------ 11 files changed, 123 insertions(+), 64 deletions(-) diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h index f0d34236c6ad..285c7690ce3d 100644 --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -471,7 +471,7 @@ namespace llvm { const MachineBasicBlock *MBB, unsigned uid) const; void EmitLLVMUsedList(const Constant *List); - void EmitXXStructorList(const Constant *List); + void EmitXXStructorList(const Constant *List, bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; } diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index ca40ccf85378..2a022657bd9e 100644 --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -65,6 +65,11 @@ public: virtual MCSymbol * getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, MachineModuleInfo *MMI) const; + + virtual const MCSection * + getStaticCtorSection(unsigned Priority = 65535) const; + virtual const MCSection * + getStaticDtorSection(unsigned Priority = 65535) const; }; diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h index d91b11b1f77f..c3d2019f37cb 100644 --- a/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -22,10 +22,6 @@ namespace llvm { class MCContext; class MCSection; class Triple; - - namespace Structors { - enum OutputOrder { None, PriorityOrder, ReversePriorityOrder }; - } class MCObjectFileInfo { protected: @@ -167,11 +163,6 @@ protected: const MCSection *DrectveSection; const MCSection *PDataSection; const MCSection *XDataSection; - - /// StructorOutputOrder - Whether the static ctor/dtor list should be output - /// in no particular order, in order of increasing priority or the reverse: - /// in order of decreasing priority (the default). - Structors::OutputOrder StructorOutputOrder; // Default is reverse order. public: void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, @@ -197,8 +188,6 @@ public: const MCSection *getTextSection() const { return TextSection; } const MCSection *getDataSection() const { return DataSection; } const MCSection *getBSSSection() const { return BSSSection; } - const MCSection *getStaticCtorSection() const { return StaticCtorSection; } - const MCSection *getStaticDtorSection() const { return StaticDtorSection; } const MCSection *getLSDASection() const { return LSDASection; } const MCSection *getCompactUnwindSection() const{ return CompactUnwindSection; @@ -300,10 +289,6 @@ public: return EHFrameSection; } - Structors::OutputOrder getStructorOutputOrder() const { - return StructorOutputOrder; - } - private: enum Environment { IsMachO, IsELF, IsCOFF }; Environment Env; diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h index 7d06cec0a4e1..04fe2208b284 100644 --- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -121,7 +121,18 @@ public: const MCExpr * getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; - + + virtual const MCSection * + getStaticCtorSection(unsigned Priority = 65535) const { + (void)Priority; + return StaticCtorSection; + } + virtual const MCSection * + getStaticDtorSection(unsigned Priority = 65535) const { + (void)Priority; + return StaticDtorSection; + } + protected: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 0e6c613f93ba..d67b164fb8d0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1207,12 +1207,8 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { assert(GV->hasInitializer() && "Not a special LLVM global!"); - const TargetData *TD = TM.getTargetData(); - unsigned Align = Log2_32(TD->getPointerPrefAlignment()); if (GV->getName() == "llvm.global_ctors") { - OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); - EmitAlignment(Align); - EmitXXStructorList(GV->getInitializer()); + EmitXXStructorList(GV->getInitializer(), /* isCtor */ true); if (TM.getRelocationModel() == Reloc::Static && MAI->hasStaticCtorDtorReferenceInStaticMode()) { @@ -1224,9 +1220,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { } if (GV->getName() == "llvm.global_dtors") { - OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); - EmitAlignment(Align); - EmitXXStructorList(GV->getInitializer()); + EmitXXStructorList(GV->getInitializer(), /* isCtor */ false); if (TM.getRelocationModel() == Reloc::Static && MAI->hasStaticCtorDtorReferenceInStaticMode()) { @@ -1256,7 +1250,7 @@ void AsmPrinter::EmitLLVMUsedList(const Constant *List) { } } -typedef std::pair Structor; +typedef std::pair Structor; static bool priority_order(const Structor& lhs, const Structor& rhs) { return lhs.first < rhs.first; @@ -1264,7 +1258,7 @@ static bool priority_order(const Structor& lhs, const Structor& rhs) { /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. -void AsmPrinter::EmitXXStructorList(const Constant *List) { +void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { // Should be an array of '{ int, void ()* }' structs. The first value is the // init priority. if (!isa(List)) return; @@ -1290,19 +1284,20 @@ void AsmPrinter::EmitXXStructorList(const Constant *List) { CS->getOperand(1))); } - // Emit the function pointers in reverse priority order. - switch (getObjFileLowering().getStructorOutputOrder()) { - case Structors::None: - break; - case Structors::PriorityOrder: - std::sort(Structors.begin(), Structors.end(), priority_order); - break; - case Structors::ReversePriorityOrder: - std::sort(Structors.rbegin(), Structors.rend(), priority_order); - break; - } - for (unsigned i = 0, e = Structors.size(); i != e; ++i) + // Emit the function pointers in the target-specific order + const TargetData *TD = TM.getTargetData(); + unsigned Align = Log2_32(TD->getPointerPrefAlignment()); + std::stable_sort(Structors.begin(), Structors.end(), priority_order); + for (unsigned i = 0, e = Structors.size(); i != e; ++i) { + const MCSection *OutputSection = + (isCtor ? + getObjFileLowering().getStaticCtorSection(Structors[i].first) : + getObjFileLowering().getStaticDtorSection(Structors[i].first)); + OutStreamer.SwitchSection(OutputSection); + if (OutStreamer.getCurrentSection() != OutStreamer.getPreviousSection()) + EmitAlignment(Align); EmitGlobalConstant(Structors[i].second); + } } //===--------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index a6999f63040f..fd67d628b657 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -340,6 +340,32 @@ getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, Streamer); } +const MCSection * +TargetLoweringObjectFileELF::getStaticCtorSection(unsigned Priority) const { + // The default scheme is .ctor / .dtor, so we have to invert the priority + // numbering. + if (Priority == 65535) + return StaticCtorSection; + + std::string Name = std::string(".ctors.") + utostr(65535 - Priority); + return getContext().getELFSection(Name, ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); +} + +const MCSection * +TargetLoweringObjectFileELF::getStaticDtorSection(unsigned Priority) const { + // The default scheme is .ctor / .dtor, so we have to invert the priority + // numbering. + if (Priority == 65535) + return StaticDtorSection; + + std::string Name = std::string(".dtors.") + utostr(65535 - Priority); + return getContext().getELFSection(Name, ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); +} + //===----------------------------------------------------------------------===// // MachO //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index 32ba92424b72..4c03aaa87329 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -31,8 +31,6 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5)) CommDirectiveSupportsAlignment = false; - StructorOutputOrder = Structors::PriorityOrder; - TextSection // .text = Ctx->getMachOSection("__TEXT", "__text", MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, @@ -260,12 +258,10 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { } } - StructorOutputOrder = Structors::ReversePriorityOrder; - // ELF BSSSection = Ctx->getELFSection(".bss", ELF::SHT_NOBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, + ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getBSS()); TextSection = @@ -389,8 +385,6 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { // COFF - StructorOutputOrder = Structors::ReversePriorityOrder; - TextSection = Ctx->getCOFFSection(".text", COFF::IMAGE_SCN_CNT_CODE | diff --git a/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp b/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp index 721a225183f4..a5ea1c202e2c 100644 --- a/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp +++ b/llvm/lib/Target/ARM/ARMTargetObjectFile.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/ELF.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/StringExtras.h" using namespace llvm; using namespace dwarf; @@ -24,8 +25,9 @@ using namespace dwarf; void ARMElfTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFileELF::Initialize(Ctx, TM); + isAAPCS_ABI = TM.getSubtarget().isAAPCS_ABI(); - if (TM.getSubtarget().isAAPCS_ABI()) { + if (isAAPCS_ABI) { StaticCtorSection = getContext().getELFSection(".init_array", ELF::SHT_INIT_ARRAY, ELF::SHF_WRITE | @@ -36,7 +38,6 @@ void ARMElfTargetObjectFile::Initialize(MCContext &Ctx, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getDataRel()); - StructorOutputOrder = Structors::PriorityOrder; LSDASection = NULL; } @@ -46,3 +47,33 @@ void ARMElfTargetObjectFile::Initialize(MCContext &Ctx, 0, SectionKind::getMetadata()); } + +const MCSection * +ARMElfTargetObjectFile::getStaticCtorSection(unsigned Priority) const { + if (!isAAPCS_ABI) + return TargetLoweringObjectFileELF::getStaticCtorSection(Priority); + + if (Priority == 65535) + return StaticCtorSection; + + // Emit ctors in priority order. + std::string Name = std::string(".init_array.") + utostr(Priority); + return getContext().getELFSection(Name, ELF::SHT_INIT_ARRAY, + ELF::SHF_ALLOC | ELF::SHF_WRITE, + SectionKind::getDataRel()); +} + +const MCSection * +ARMElfTargetObjectFile::getStaticDtorSection(unsigned Priority) const { + if (!isAAPCS_ABI) + return TargetLoweringObjectFileELF::getStaticDtorSection(Priority); + + if (Priority == 65535) + return StaticDtorSection; + + // Emit dtors in priority order. + std::string Name = std::string(".fini_array.") + utostr(Priority); + return getContext().getELFSection(Name, ELF::SHT_FINI_ARRAY, + ELF::SHF_ALLOC | ELF::SHF_WRITE, + SectionKind::getDataRel()); +} diff --git a/llvm/lib/Target/ARM/ARMTargetObjectFile.h b/llvm/lib/Target/ARM/ARMTargetObjectFile.h index c6a7261439d7..ff210604148d 100644 --- a/llvm/lib/Target/ARM/ARMTargetObjectFile.h +++ b/llvm/lib/Target/ARM/ARMTargetObjectFile.h @@ -20,6 +20,7 @@ class TargetMachine; class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF { protected: const MCSection *AttributesSection; + bool isAAPCS_ABI; public: ARMElfTargetObjectFile() : TargetLoweringObjectFileELF(), @@ -31,6 +32,9 @@ public: virtual const MCSection *getAttributesSection() const { return AttributesSection; } + + const MCSection * getStaticCtorSection(unsigned Priority) const; + const MCSection * getStaticDtorSection(unsigned Priority) const; }; } // end namespace llvm diff --git a/llvm/test/CodeGen/ARM/ctor_order.ll b/llvm/test/CodeGen/ARM/ctor_order.ll index 7f00eb31f947..6419292280f1 100644 --- a/llvm/test/CodeGen/ARM/ctor_order.ll +++ b/llvm/test/CodeGen/ARM/ctor_order.ll @@ -6,13 +6,15 @@ ; DARWIN: .long _f151 ; DARWIN-NEXT: .long _f152 -; ELF: .section .ctors,"aw",%progbits +; ELF: .section .ctors.65384,"aw",%progbits +; ELF: .long f151 +; ELF: .section .ctors.65383,"aw",%progbits ; ELF: .long f152 -; ELF-NEXT: .long f151 -; GNUEABI: .section .init_array,"aw",%init_array +; GNUEABI: .section .init_array.151,"aw",%init_array ; GNUEABI: .long f151 -; GNUEABI-NEXT: .long f152 +; GNUEABI: .section .init_array.152,"aw",%init_array +; GNUEABI: .long f152 @llvm.global_ctors = appending global [2 x { i32, void ()* }] [ { i32, void ()* } { i32 151, void ()* @f151 }, { i32, void ()* } { i32 152, void ()* @f152 } ] diff --git a/llvm/test/CodeGen/X86/2011-08-29-InitOrder.ll b/llvm/test/CodeGen/X86/2011-08-29-InitOrder.ll index 72c79d27d026..4d5f8d7857c0 100644 --- a/llvm/test/CodeGen/X86/2011-08-29-InitOrder.ll +++ b/llvm/test/CodeGen/X86/2011-08-29-InitOrder.ll @@ -3,22 +3,28 @@ ; PR5329 @llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @construct_2 }, { i32, void ()* } { i32 3000, void ()* @construct_3 }, { i32, void ()* } { i32 1000, void ()* @construct_1 }] -; CHECK-DEFAULT: construct_3 -; CHECK-DEFAULT: construct_2 -; CHECK-DEFAULT: construct_1 +; CHECK-DEFAULT .section .ctors.64535,"aw",@progbits +; CHECK-DEFAULT: .long construct_1 +; CHECK-DEFAULT: .section .ctors.63535,"aw",@progbits +; CHECK-DEFAULT: .long construct_2 +; CHECK-DEFAULT: .section .ctors.62535,"aw",@progbits +; CHECK-DEFAULT: .long construct_3 -; CHECK-DARWIN: construct_1 -; CHECK-DARWIN: construct_2 -; CHECK-DARWIN: construct_3 +; CHECK-DARWIN: .long _construct_1 +; CHECK-DARWIN-NEXT: .long _construct_2 +; CHECK-DARWIN-NEXT: .long _construct_3 @llvm.global_dtors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @destruct_2 }, { i32, void ()* } { i32 1000, void ()* @destruct_1 }, { i32, void ()* } { i32 3000, void ()* @destruct_3 }] -; CHECK-DEFAULT: destruct_3 -; CHECK-DEFAULT: destruct_2 -; CHECK-DEFAULT: destruct_1 +; CHECK-DEFAULT: .section .dtors.64535,"aw",@progbits +; CHECK-DEFAULT: .long destruct_1 +; CHECK-DEFAULT: .section .dtors.63535,"aw",@progbits +; CHECK-DEFAULT: .long destruct_2 +; CHECK-DEFAULT: .section .dtors.62535,"aw",@progbits +; CHECK-DEFAULT: .long destruct_3 -; CHECK-DARWIN: destruct_1 -; CHECK-DARWIN: destruct_2 -; CHECK-DARWIN: destruct_3 +; CHECK-DARWIN: .long _destruct_1 +; CHECK-DARWIN-NEXT: .long _destruct_2 +; CHECK-DARWIN-NEXT: .long _destruct_3 declare void @construct_1() declare void @construct_2()