Properly emit ctors / dtors with priorities into desired sections
authorAnton Korobeynikov <asl@math.spbu.ru>
Wed, 25 Jan 2012 22:24:19 +0000 (22:24 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Wed, 25 Jan 2012 22:24:19 +0000 (22:24 +0000)
and let linker handle the rest.

This finally fixes PR5329

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148990 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/AsmPrinter.h
include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
include/llvm/MC/MCObjectFileInfo.h
include/llvm/Target/TargetLoweringObjectFile.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/TargetLoweringObjectFileImpl.cpp
lib/MC/MCObjectFileInfo.cpp
lib/Target/ARM/ARMTargetObjectFile.cpp
lib/Target/ARM/ARMTargetObjectFile.h
test/CodeGen/ARM/ctor_order.ll
test/CodeGen/X86/2011-08-29-InitOrder.ll

index f0d34236c6adb8afedc3a442b4cf2274750ca194..285c7690ce3d7188d42bc3fdc29d4f33df3f7c56 100644 (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);
   };
 }
index ca40ccf85378271ef6c62a5c52aaadc8582b61a1..2a022657bd9e2c703be8fcbfd9f8d1392d863fc6 100644 (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;
 };
 
 
index d91b11b1f77f61c05c5be7a0f1c25e28c50e649e..c3d2019f37cb79a3e0cbae6ca1e531ad310676f3 100644 (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;
index 7d06cec0a4e1f9903ceed05ff309e3230b29352c..04fe2208b2841b4f01f324560bb9e2859221d422 100644 (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,
index 0e6c613f93ba06122cbda73525a988e98bd548b4..d67b164fb8d08aa1ad0e8d16987c304fd838b44a 100644 (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);
+  }
 }
 
 //===--------------------------------------------------------------------===//
index a6999f63040ffe14aab109e2b139393857dad78e..fd67d628b657a7e3aec3f1552b454d61262606d6 100644 (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
 //===----------------------------------------------------------------------===//
index 32ba92424b724f335b748fa8c9dd39c7ca47c604..4c03aaa87329379fac9f95f5c5d3a9cdea4bf122 100644 (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 |
index 721a225183f436f1047dba799efa6344da399e95..a5ea1c202e2cc4de1a8c5287b5d42f2e83a2d376 100644 (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());
+}
index c6a7261439d7b084166fc908e7e970214ebea90f..ff210604148d14b30ba2940195dde7e9d7c69998 100644 (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
index 7f00eb31f94765fb2393b300f1e2d2ca89503003..6419292280f1ca194d4ce5a9a823cf0fed2eaa33 100644 (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 } ]
index 72c79d27d0264199abf6c274fce447fe54eda3a5..4d5f8d7857c05fe5070e3f07e5fde5645c75785f 100644 (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-DARWINconstruct_2
-; CHECK-DARWINconstruct_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-DARWINdestruct_2
-; CHECK-DARWINdestruct_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()