Properly emit ctors / dtors with priorities into desired sections

and let linker handle the rest.

This finally fixes PR5329

llvm-svn: 148990
This commit is contained in:
Anton Korobeynikov 2012-01-25 22:24:19 +00:00
parent f7f102f81a
commit 7722a2d4e3
11 changed files with 123 additions and 64 deletions

View File

@ -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);
};
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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,

View File

@ -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<int, Constant*> Structor;
typedef std::pair<unsigned, Constant*> 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<ConstantArray>(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);
}
}
//===--------------------------------------------------------------------===//

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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 |

View File

@ -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<ARMSubtarget>().isAAPCS_ABI();
if (TM.getSubtarget<ARMSubtarget>().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());
}

View File

@ -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

View File

@ -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 } ]

View File

@ -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()