diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 96b68c833dc..e2cef7a123a 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -36,6 +36,10 @@ namespace llvm { enum LCOMMType { None, NoAlignment, ByteAlignment }; } + namespace Structors { + enum OutputOrder { None, PriorityOrder, ReversePriorityOrder }; + } + /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. class MCAsmInfo { @@ -68,6 +72,11 @@ namespace llvm { /// the macho-specific .tbss directive for emitting thread local BSS Symbols bool HasMachoTBSSDirective; // Default is false. + /// 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. + /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should /// emit a ".reference .constructors_used" or ".reference .destructors_used" /// directive after the a static ctor/dtor list. This directive is only @@ -395,6 +404,9 @@ namespace llvm { // bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + Structors::OutputOrder getStructorOutputOrder() const { + return StructorOutputOrder; + } bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 6084a3c8f59..ddf5f9ccde6 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1265,7 +1265,16 @@ void AsmPrinter::EmitXXStructorList(const Constant *List) { } // Emit the function pointers in reverse priority order. - std::sort(Structors.rbegin(), Structors.rend(), priority_order); + switch (MAI->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) EmitGlobalConstant(Structors[i].second); } diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index a53c474c15b..365df87d8db 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -29,6 +29,7 @@ MCAsmInfo::MCAsmInfo() { HasSubsectionsViaSymbols = false; HasMachoZeroFillDirective = false; HasMachoTBSSDirective = false; + StructorOutputOrder = Structors::ReversePriorityOrder; HasStaticCtorDtorReferenceInStaticMode = false; LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index 5851cb0391d..61fbd29a285 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -39,6 +39,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. HasMachoZeroFillDirective = true; // Uses .zerofill HasMachoTBSSDirective = true; // Uses .tbss + StructorOutputOrder = Structors::PriorityOrder; HasStaticCtorDtorReferenceInStaticMode = true; // FIXME: Darwin 10 and newer don't need this. diff --git a/test/CodeGen/X86/2011-08-29-InitOrder.ll b/test/CodeGen/X86/2011-08-29-InitOrder.ll index 4bec03c85ca..72c79d27d02 100644 --- a/test/CodeGen/X86/2011-08-29-InitOrder.ll +++ b/test/CodeGen/X86/2011-08-29-InitOrder.ll @@ -1,17 +1,24 @@ -; RUN: llc < %s -mtriple=i386-linux-gnu | FileCheck %s +; RUN: llc < %s -mtriple=i386-linux-gnu | FileCheck %s --check-prefix=CHECK-DEFAULT +; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s --check-prefix=CHECK-DARWIN ; 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: ctors -; CHECK: construct_3 -; CHECK: construct_2 -; CHECK: construct_1 +; CHECK-DEFAULT: construct_3 +; CHECK-DEFAULT: construct_2 +; CHECK-DEFAULT: construct_1 + +; CHECK-DARWIN: construct_1 +; CHECK-DARWIN: construct_2 +; CHECK-DARWIN: 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: dtors -; CHECK: destruct_3 -; CHECK: destruct_2 -; CHECK: destruct_1 +; CHECK-DEFAULT: destruct_3 +; CHECK-DEFAULT: destruct_2 +; CHECK-DEFAULT: destruct_1 + +; CHECK-DARWIN: destruct_1 +; CHECK-DARWIN: destruct_2 +; CHECK-DARWIN: destruct_3 declare void @construct_1() declare void @construct_2()