Home | History | Annotate | Download | only in llvm
      1 From 07af31d3d65a13531ed1c30616b75b7a83eb4d9b Mon Sep 17 00:00:00 2001
      2 From: Logan Chien <loganchien (a] google.com>
      3 Date: Thu, 30 Aug 2012 17:13:39 +0800
      4 Subject: [PATCH 2/2] Backport .init_array/.fini_array work.
      5 
      6 Android requires ".init_array" and ".fini_array" for
      7 X86/MIPS as well, regardless the gcc version.  This
      8 patch is basing on following patches:
      9 
     10 commit d6b43a317e71246380db55a50b799b062b53cdce
     11 Author: Rafael Espindola <rafael.espindola (a] gmail.com>
     12 Date:   Tue Jun 19 00:48:28 2012 +0000
     13 
     14   Move the support for using .init_array from ARM to the generic
     15   TargetLoweringObjectFileELF. Use this to support it on X86. Unlike ARM,
     16   on X86 it is not easy to find out if .init_array should be used or not, so
     17   the decision is made via TargetOptions and defaults to off.
     18 
     19   Add a command line option to llc that enables it.
     20 
     21 commit 8af669f2f1d92436fe6dc43144bb084a620e7516
     22 Author: Rafael Espindola <rafael.espindola (a] gmail.com>
     23 Date:   Tue Jun 19 01:26:10 2012 +0000
     24 
     25   Add a -fuse-init-array option to cc1 and map to the UseInitArray target
     26   option. On the driver, check if we are using libraries from gcc 4.7 or newer
     27   and if so pass -fuse-init-array to the frontend.
     28   The crtbegin*.o files in gcc 4.7 no longer call the constructors listed in
     29   .ctors, so we have to use .init_array.
     30 ---
     31  .../llvm/CodeGen/TargetLoweringObjectFileImpl.h    |    3 +
     32  llvm-3.1/include/llvm/Target/TargetOptions.h       |    6 ++-
     33  .../lib/CodeGen/TargetLoweringObjectFileImpl.cpp   |   48 ++++++++++++++++---
     34  llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.cpp    |   43 +-----------------
     35  llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.h      |    4 --
     36  llvm-3.1/lib/Target/Mips/MipsTargetObjectFile.cpp  |    1 +
     37  llvm-3.1/lib/Target/X86/X86ISelLowering.cpp        |    2 +
     38  llvm-3.1/lib/Target/X86/X86TargetObjectFile.cpp    |    9 ++++
     39  llvm-3.1/lib/Target/X86/X86TargetObjectFile.h      |    6 +++
     40  llvm-3.1/test/CodeGen/X86/constructor.ll           |   27 +++++++++++
     41  .../tools/clang/include/clang/Driver/CC1Options.td |    2 +
     42  .../tools/clang/include/clang/Driver/ToolChain.h   |    4 ++
     43  .../clang/include/clang/Frontend/CodeGenOptions.h  |    5 ++
     44  llvm-3.1/tools/clang/lib/CodeGen/BackendUtil.cpp   |    3 +
     45  llvm-3.1/tools/clang/lib/Driver/ToolChain.cpp      |    3 +
     46  llvm-3.1/tools/clang/lib/Driver/ToolChains.cpp     |    9 +++-
     47  llvm-3.1/tools/clang/lib/Driver/ToolChains.h       |    3 +-
     48  llvm-3.1/tools/clang/lib/Driver/Tools.cpp          |    2 +
     49  .../clang/lib/Frontend/CompilerInvocation.cpp      |    1 +
     50  llvm-3.1/tools/clang/test/Driver/constructors.c    |   14 ++++++
     51  llvm-3.1/tools/llc/llc.cpp                         |    5 ++
     52  21 files changed, 144 insertions(+), 56 deletions(-)
     53  create mode 100644 llvm-3.1/test/CodeGen/X86/constructor.ll
     54  create mode 100644 llvm-3.1/tools/clang/test/Driver/constructors.c
     55 
     56 diff --git a/llvm-3.1/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm-3.1/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
     57 index 5a42136..9849e92 100644
     58 --- a/llvm-3.1/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
     59 +++ b/llvm-3.1/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
     60 @@ -33,6 +33,8 @@ namespace llvm {
     61  
     62  
     63  class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
     64 +  bool UseInitArray;
     65 +
     66  public:
     67    virtual ~TargetLoweringObjectFileELF() {}
     68  
     69 @@ -66,6 +68,7 @@ public:
     70    getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang,
     71                            MachineModuleInfo *MMI) const;
     72  
     73 +  void InitializeELF(bool UseInitArray_);
     74    virtual const MCSection *
     75    getStaticCtorSection(unsigned Priority = 65535) const;
     76    virtual const MCSection *
     77 diff --git a/llvm-3.1/include/llvm/Target/TargetOptions.h b/llvm-3.1/include/llvm/Target/TargetOptions.h
     78 index 12a2757..bc60673 100644
     79 --- a/llvm-3.1/include/llvm/Target/TargetOptions.h
     80 +++ b/llvm-3.1/include/llvm/Target/TargetOptions.h
     81 @@ -43,7 +43,7 @@ namespace llvm {
     82            StackAlignmentOverride(0), RealignStack(true),
     83            DisableJumpTables(false), EnableFastISel(false),
     84            PositionIndependentExecutable(false), EnableSegmentedStacks(false),
     85 -          TrapFuncName(""), FloatABIType(FloatABI::Default)
     86 +          UseInitArray(false), TrapFuncName(""), FloatABIType(FloatABI::Default)
     87      {}
     88  
     89      /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
     90 @@ -172,6 +172,10 @@ namespace llvm {
     91  
     92      unsigned EnableSegmentedStacks : 1;
     93  
     94 +    /// UseInitArray - Use .init_array instead of .ctors for static
     95 +    /// constructors.
     96 +    unsigned UseInitArray : 1;
     97 +
     98      /// getTrapFunctionName - If this returns a non-empty string, this means
     99      /// isel should lower Intrinsic::trap to a call to the specified function
    100      /// name instead of an ISD::TRAP node.
    101 diff --git a/llvm-3.1/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm-3.1/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    102 index 9925185..3660cf7 100644
    103 --- a/llvm-3.1/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    104 +++ b/llvm-3.1/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    105 @@ -349,10 +349,17 @@ TargetLoweringObjectFileELF::getStaticCtorSection(unsigned Priority) const {
    106    if (Priority == 65535)
    107      return StaticCtorSection;
    108  
    109 -  std::string Name = std::string(".ctors.") + utostr(65535 - Priority);
    110 -  return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
    111 -                                    ELF::SHF_ALLOC |ELF::SHF_WRITE,
    112 -                                    SectionKind::getDataRel());
    113 +  if (UseInitArray) {
    114 +    std::string Name = std::string(".init_array.") + utostr(Priority);
    115 +    return getContext().getELFSection(Name, ELF::SHT_INIT_ARRAY,
    116 +                                      ELF::SHF_ALLOC | ELF::SHF_WRITE,
    117 +                                      SectionKind::getDataRel());
    118 +  } else {
    119 +    std::string Name = std::string(".ctors.") + utostr(65535 - Priority);
    120 +    return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
    121 +                                      ELF::SHF_ALLOC |ELF::SHF_WRITE,
    122 +                                      SectionKind::getDataRel());
    123 +  }
    124  }
    125  
    126  const MCSection *
    127 @@ -362,10 +369,35 @@ TargetLoweringObjectFileELF::getStaticDtorSection(unsigned Priority) const {
    128    if (Priority == 65535)
    129      return StaticDtorSection;
    130  
    131 -  std::string Name = std::string(".dtors.") + utostr(65535 - Priority);
    132 -  return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
    133 -                                    ELF::SHF_ALLOC |ELF::SHF_WRITE,
    134 -                                    SectionKind::getDataRel());
    135 +  if (UseInitArray) {
    136 +    std::string Name = std::string(".fini_array.") + utostr(Priority);
    137 +    return getContext().getELFSection(Name, ELF::SHT_FINI_ARRAY,
    138 +                                      ELF::SHF_ALLOC | ELF::SHF_WRITE,
    139 +                                      SectionKind::getDataRel());
    140 +  } else {
    141 +    std::string Name = std::string(".dtors.") + utostr(65535 - Priority);
    142 +    return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
    143 +                                      ELF::SHF_ALLOC |ELF::SHF_WRITE,
    144 +                                      SectionKind::getDataRel());
    145 +  }
    146 +}
    147 +
    148 +void
    149 +TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) {
    150 +  UseInitArray = UseInitArray_;
    151 +  if (!UseInitArray)
    152 +    return;
    153 +
    154 +  StaticCtorSection =
    155 +    getContext().getELFSection(".init_array", ELF::SHT_INIT_ARRAY,
    156 +                               ELF::SHF_WRITE |
    157 +                               ELF::SHF_ALLOC,
    158 +                               SectionKind::getDataRel());
    159 +  StaticDtorSection =
    160 +    getContext().getELFSection(".fini_array", ELF::SHT_FINI_ARRAY,
    161 +                               ELF::SHF_WRITE |
    162 +                               ELF::SHF_ALLOC,
    163 +                               SectionKind::getDataRel());
    164  }
    165  
    166  //===----------------------------------------------------------------------===//
    167 diff --git a/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.cpp b/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.cpp
    168 index a5ea1c2..3d85ca7 100644
    169 --- a/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.cpp
    170 +++ b/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.cpp
    171 @@ -24,20 +24,11 @@ using namespace dwarf;
    172  
    173  void ARMElfTargetObjectFile::Initialize(MCContext &Ctx,
    174                                          const TargetMachine &TM) {
    175 +  bool isAAPCS_ABI = TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI();
    176    TargetLoweringObjectFileELF::Initialize(Ctx, TM);
    177 -  isAAPCS_ABI = TM.getSubtarget<ARMSubtarget>().isAAPCS_ABI();
    178 +  InitializeELF(isAAPCS_ABI);
    179  
    180    if (isAAPCS_ABI) {
    181 -    StaticCtorSection =
    182 -      getContext().getELFSection(".init_array", ELF::SHT_INIT_ARRAY,
    183 -                                 ELF::SHF_WRITE |
    184 -                                 ELF::SHF_ALLOC,
    185 -                                 SectionKind::getDataRel());
    186 -    StaticDtorSection =
    187 -      getContext().getELFSection(".fini_array", ELF::SHT_FINI_ARRAY,
    188 -                                 ELF::SHF_WRITE |
    189 -                                 ELF::SHF_ALLOC,
    190 -                                 SectionKind::getDataRel());
    191      LSDASection = NULL;
    192    }
    193  
    194 @@ -47,33 +38,3 @@ void ARMElfTargetObjectFile::Initialize(MCContext &Ctx,
    195                                 0,
    196                                 SectionKind::getMetadata());
    197  }
    198 -
    199 -const MCSection *
    200 -ARMElfTargetObjectFile::getStaticCtorSection(unsigned Priority) const {
    201 -  if (!isAAPCS_ABI)
    202 -    return TargetLoweringObjectFileELF::getStaticCtorSection(Priority);
    203 -
    204 -  if (Priority == 65535)
    205 -    return StaticCtorSection;
    206 -
    207 -  // Emit ctors in priority order.
    208 -  std::string Name = std::string(".init_array.") + utostr(Priority);
    209 -  return getContext().getELFSection(Name, ELF::SHT_INIT_ARRAY,
    210 -                                    ELF::SHF_ALLOC | ELF::SHF_WRITE,
    211 -                                    SectionKind::getDataRel());
    212 -}
    213 -
    214 -const MCSection *
    215 -ARMElfTargetObjectFile::getStaticDtorSection(unsigned Priority) const {
    216 -  if (!isAAPCS_ABI)
    217 -    return TargetLoweringObjectFileELF::getStaticDtorSection(Priority);
    218 -
    219 -  if (Priority == 65535)
    220 -    return StaticDtorSection;
    221 -
    222 -  // Emit dtors in priority order.
    223 -  std::string Name = std::string(".fini_array.") + utostr(Priority);
    224 -  return getContext().getELFSection(Name, ELF::SHT_FINI_ARRAY,
    225 -                                    ELF::SHF_ALLOC | ELF::SHF_WRITE,
    226 -                                    SectionKind::getDataRel());
    227 -}
    228 diff --git a/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.h b/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.h
    229 index ff21060..c6a7261 100644
    230 --- a/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.h
    231 +++ b/llvm-3.1/lib/Target/ARM/ARMTargetObjectFile.h
    232 @@ -20,7 +20,6 @@ class TargetMachine;
    233  class ARMElfTargetObjectFile : public TargetLoweringObjectFileELF {
    234  protected:
    235    const MCSection *AttributesSection;
    236 -  bool isAAPCS_ABI;
    237  public:
    238    ARMElfTargetObjectFile() :
    239      TargetLoweringObjectFileELF(),
    240 @@ -32,9 +31,6 @@ public:
    241    virtual const MCSection *getAttributesSection() const {
    242      return AttributesSection;
    243    }
    244 -
    245 -  const MCSection * getStaticCtorSection(unsigned Priority) const;
    246 -  const MCSection * getStaticDtorSection(unsigned Priority) const;
    247  };
    248  
    249  } // end namespace llvm
    250 diff --git a/llvm-3.1/lib/Target/Mips/MipsTargetObjectFile.cpp b/llvm-3.1/lib/Target/Mips/MipsTargetObjectFile.cpp
    251 index 04dc60a..4ee79e1 100644
    252 --- a/llvm-3.1/lib/Target/Mips/MipsTargetObjectFile.cpp
    253 +++ b/llvm-3.1/lib/Target/Mips/MipsTargetObjectFile.cpp
    254 @@ -26,6 +26,7 @@ SSThreshold("mips-ssection-threshold", cl::Hidden,
    255  
    256  void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){
    257    TargetLoweringObjectFileELF::Initialize(Ctx, TM);
    258 +  InitializeELF(TM.Options.UseInitArray);
    259  
    260    SmallDataSection =
    261      getContext().getELFSection(".sdata", ELF::SHT_PROGBITS,
    262 diff --git a/llvm-3.1/lib/Target/X86/X86ISelLowering.cpp b/llvm-3.1/lib/Target/X86/X86ISelLowering.cpp
    263 index 04299f3..eaebc59 100644
    264 --- a/llvm-3.1/lib/Target/X86/X86ISelLowering.cpp
    265 +++ b/llvm-3.1/lib/Target/X86/X86ISelLowering.cpp
    266 @@ -144,6 +144,8 @@ static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) {
    267      return new TargetLoweringObjectFileMachO();
    268    }
    269  
    270 +  if (Subtarget->isTargetLinux())
    271 +    return new X86LinuxTargetObjectFile();
    272    if (Subtarget->isTargetELF())
    273      return new TargetLoweringObjectFileELF();
    274    if (Subtarget->isTargetCOFF() && !Subtarget->isTargetEnvMacho())
    275 diff --git a/llvm-3.1/lib/Target/X86/X86TargetObjectFile.cpp b/llvm-3.1/lib/Target/X86/X86TargetObjectFile.cpp
    276 index 718f35e..b8d673f 100644
    277 --- a/llvm-3.1/lib/Target/X86/X86TargetObjectFile.cpp
    278 +++ b/llvm-3.1/lib/Target/X86/X86TargetObjectFile.cpp
    279 @@ -9,12 +9,15 @@
    280  
    281  #include "X86TargetObjectFile.h"
    282  #include "X86TargetMachine.h"
    283 +#include "llvm/ADT/StringExtras.h"
    284  #include "llvm/CodeGen/MachineModuleInfoImpls.h"
    285  #include "llvm/MC/MCContext.h"
    286  #include "llvm/MC/MCExpr.h"
    287 +#include "llvm/MC/MCSectionELF.h"
    288  #include "llvm/MC/MCSectionMachO.h"
    289  #include "llvm/Target/Mangler.h"
    290  #include "llvm/Support/Dwarf.h"
    291 +#include "llvm/Support/ELF.h"
    292  using namespace llvm;
    293  using namespace dwarf;
    294  
    295 @@ -42,3 +45,9 @@ getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang,
    296                          MachineModuleInfo *MMI) const {
    297    return Mang->getSymbol(GV);
    298  }
    299 +
    300 +void
    301 +X86LinuxTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) {
    302 +  TargetLoweringObjectFileELF::Initialize(Ctx, TM);
    303 +  InitializeELF(TM.Options.UseInitArray);
    304 +}
    305 diff --git a/llvm-3.1/lib/Target/X86/X86TargetObjectFile.h b/llvm-3.1/lib/Target/X86/X86TargetObjectFile.h
    306 index a02a368..7698b59 100644
    307 --- a/llvm-3.1/lib/Target/X86/X86TargetObjectFile.h
    308 +++ b/llvm-3.1/lib/Target/X86/X86TargetObjectFile.h
    309 @@ -32,6 +32,12 @@ namespace llvm {
    310                              MachineModuleInfo *MMI) const;
    311    };
    312  
    313 +  /// X86LinuxTargetObjectFile - This implementation is used for linux x86
    314 +  /// and x86-64.
    315 +  class X86LinuxTargetObjectFile : public TargetLoweringObjectFileELF {
    316 +    virtual void Initialize(MCContext &Ctx, const TargetMachine &TM);
    317 +  };
    318 +
    319  } // end namespace llvm
    320  
    321  #endif
    322 diff --git a/llvm-3.1/test/CodeGen/X86/constructor.ll b/llvm-3.1/test/CodeGen/X86/constructor.ll
    323 new file mode 100644
    324 index 0000000..f6dec16
    325 --- /dev/null
    326 +++ b/llvm-3.1/test/CodeGen/X86/constructor.ll
    327 @@ -0,0 +1,27 @@
    328 +; RUN: llc < %s | FileCheck --check-prefix=CTOR %s
    329 +; RUN: llc -use-init-array < %s | FileCheck --check-prefix=INIT-ARRAY %s
    330 +@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }, { i32, void ()* } { i32 15, void ()* @g }]
    331 +
    332 +define void @f() {
    333 +entry:
    334 +  ret void
    335 +}
    336 +
    337 +define void @g() {
    338 +entry:
    339 +  ret void
    340 +}
    341 +
    342 +; CTOR:		.section	.ctors.65520,"aw",@progbits
    343 +; CTOR-NEXT:	.align	8
    344 +; CTOR-NEXT:	.quad	g
    345 +; CTOR-NEXT:	.section	.ctors,"aw",@progbits
    346 +; CTOR-NEXT:	.align	8
    347 +; CTOR-NEXT:	.quad	f
    348 +
    349 +; INIT-ARRAY:		.section	.init_array.15,"aw",@init_array
    350 +; INIT-ARRAY-NEXT:	.align	8
    351 +; INIT-ARRAY-NEXT:	.quad	g
    352 +; INIT-ARRAY-NEXT:	.section	.init_array,"aw",@init_array
    353 +; INIT-ARRAY-NEXT:	.align	8
    354 +; INIT-ARRAY-NEXT:	.quad	f
    355 diff --git a/llvm-3.1/tools/clang/include/clang/Driver/CC1Options.td b/llvm-3.1/tools/clang/include/clang/Driver/CC1Options.td
    356 index 83c988a..fde33d0 100644
    357 --- a/llvm-3.1/tools/clang/include/clang/Driver/CC1Options.td
    358 +++ b/llvm-3.1/tools/clang/include/clang/Driver/CC1Options.td
    359 @@ -241,6 +241,8 @@ def mrelocation_model : Separate<"-mrelocation-model">,
    360    HelpText<"The relocation model to use">;
    361  def munwind_tables : Flag<"-munwind-tables">,
    362    HelpText<"Generate unwinding tables for all functions">;
    363 +def fuse_init_array : Flag<"-fuse-init-array">,
    364 +  HelpText<"Use .init_array instead of .ctors">;
    365  def mconstructor_aliases : Flag<"-mconstructor-aliases">,
    366    HelpText<"Emit complete constructors and destructors as aliases when possible">;
    367  def mms_bitfields : Flag<"-mms-bitfields">,
    368 diff --git a/llvm-3.1/tools/clang/include/clang/Driver/ToolChain.h b/llvm-3.1/tools/clang/include/clang/Driver/ToolChain.h
    369 index c35cf67..02d28f2 100644
    370 --- a/llvm-3.1/tools/clang/include/clang/Driver/ToolChain.h
    371 +++ b/llvm-3.1/tools/clang/include/clang/Driver/ToolChain.h
    372 @@ -227,6 +227,10 @@ public:
    373    virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    374                                           ArgStringList &CC1Args) const;
    375  
    376 +  // AddClangTargetOptions - Add options that need to be passed to cc1 for
    377 +  // this target.
    378 +  virtual void AddClangTargetOptions(ArgStringList &CC1Args) const;
    379 +
    380    // GetRuntimeLibType - Determine the runtime library type to use with the
    381    // given compilation arguments.
    382    virtual RuntimeLibType GetRuntimeLibType(const ArgList &Args) const;
    383 diff --git a/llvm-3.1/tools/clang/include/clang/Frontend/CodeGenOptions.h b/llvm-3.1/tools/clang/include/clang/Frontend/CodeGenOptions.h
    384 index e844f88..f6eb786 100644
    385 --- a/llvm-3.1/tools/clang/include/clang/Frontend/CodeGenOptions.h
    386 +++ b/llvm-3.1/tools/clang/include/clang/Frontend/CodeGenOptions.h
    387 @@ -111,6 +111,10 @@ public:
    388  
    389    unsigned StackRealignment  : 1; /// Control whether to permit stack
    390                                    /// realignment.
    391 +
    392 +  unsigned UseInitArray      : 1; ///< Control whether to use .init_array or
    393 +                                  ///< .ctors.
    394 +
    395    unsigned StackAlignment;        /// Overrides default stack alignment,
    396                                    /// if not 0.
    397  
    398 @@ -215,6 +219,7 @@ public:
    399      UseRegisterSizedBitfieldAccess = 0;
    400      VerifyModule = 1;
    401      StackRealignment = 0;
    402 +    UseInitArray = 0;
    403      StackAlignment = 0;
    404  
    405      Inlining = NoInlining;
    406 diff --git a/llvm-3.1/tools/clang/lib/CodeGen/BackendUtil.cpp b/llvm-3.1/tools/clang/lib/CodeGen/BackendUtil.cpp
    407 index 2f44711..ed261c2 100644
    408 --- a/llvm-3.1/tools/clang/lib/CodeGen/BackendUtil.cpp
    409 +++ b/llvm-3.1/tools/clang/lib/CodeGen/BackendUtil.cpp
    410 @@ -324,6 +324,9 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action,
    411      Options.NoFramePointerElimNonLeaf = true;
    412    }
    413  
    414 +  if (CodeGenOpts.UseInitArray)
    415 +    Options.UseInitArray = true;
    416 +
    417    // Set float ABI type.
    418    if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp")
    419      Options.FloatABIType = llvm::FloatABI::Soft;
    420 diff --git a/llvm-3.1/tools/clang/lib/Driver/ToolChain.cpp b/llvm-3.1/tools/clang/lib/Driver/ToolChain.cpp
    421 index db4d2a8..bb7a8de 100644
    422 --- a/llvm-3.1/tools/clang/lib/Driver/ToolChain.cpp
    423 +++ b/llvm-3.1/tools/clang/lib/Driver/ToolChain.cpp
    424 @@ -189,6 +189,9 @@ void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    425    // Each toolchain should provide the appropriate include flags.
    426  }
    427  
    428 +void ToolChain::AddClangTargetOptions(ArgStringList &CC1Args) const {
    429 +}
    430 +
    431  ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
    432    const ArgList &Args) const
    433  {
    434 diff --git a/llvm-3.1/tools/clang/lib/Driver/ToolChains.cpp b/llvm-3.1/tools/clang/lib/Driver/ToolChains.cpp
    435 index a2217f5..fc7a818 100644
    436 --- a/llvm-3.1/tools/clang/lib/Driver/ToolChains.cpp
    437 +++ b/llvm-3.1/tools/clang/lib/Driver/ToolChains.cpp
    438 @@ -2143,6 +2143,13 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA,
    439    return *T;
    440  }
    441  
    442 +void Linux::AddClangTargetOptions(ArgStringList &CC1Args) const {
    443 +  const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
    444 +  if (V >= Generic_GCC::GCCVersion::Parse("4.7.0") ||
    445 +      getTriple().getEnvironment() == llvm::Triple::ANDROID)
    446 +    CC1Args.push_back("-fuse-init-array");
    447 +}
    448 +
    449  void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    450                                        ArgStringList &CC1Args) const {
    451    const Driver &D = getDriver();
    452 @@ -2285,7 +2292,7 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
    453    // equivalent to '/usr/include/c++/X.Y' in almost all cases.
    454    StringRef LibDir = GCCInstallation.getParentLibPath();
    455    StringRef InstallDir = GCCInstallation.getInstallPath();
    456 -  StringRef Version = GCCInstallation.getVersion();
    457 +  StringRef Version = GCCInstallation.getVersion().Text;
    458    if (!addLibStdCXXIncludePaths(LibDir + "/../include/c++/" + Version,
    459                                  (GCCInstallation.getTriple().str() +
    460                                   GCCInstallation.getMultiarchSuffix()),
    461 diff --git a/llvm-3.1/tools/clang/lib/Driver/ToolChains.h b/llvm-3.1/tools/clang/lib/Driver/ToolChains.h
    462 index eaa6be1..9aa1c0a 100644
    463 --- a/llvm-3.1/tools/clang/lib/Driver/ToolChains.h
    464 +++ b/llvm-3.1/tools/clang/lib/Driver/ToolChains.h
    465 @@ -99,7 +99,7 @@ protected:
    466      StringRef getParentLibPath() const { return GCCParentLibPath; }
    467  
    468      /// \brief Get the detected GCC version string.
    469 -    StringRef getVersion() const { return Version.Text; }
    470 +    const GCCVersion &getVersion() const { return Version; }
    471  
    472    private:
    473      static void CollectLibDirsAndTriples(
    474 @@ -536,6 +536,7 @@ public:
    475  
    476    virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    477                                           ArgStringList &CC1Args) const;
    478 +  virtual void AddClangTargetOptions(ArgStringList &CC1Args) const;
    479    virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
    480                                              ArgStringList &CC1Args) const;
    481  
    482 diff --git a/llvm-3.1/tools/clang/lib/Driver/Tools.cpp b/llvm-3.1/tools/clang/lib/Driver/Tools.cpp
    483 index cdbd1ff..80e3fcd 100644
    484 --- a/llvm-3.1/tools/clang/lib/Driver/Tools.cpp
    485 +++ b/llvm-3.1/tools/clang/lib/Driver/Tools.cpp
    486 @@ -1711,6 +1711,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
    487                     AsynchronousUnwindTables))
    488      CmdArgs.push_back("-munwind-tables");
    489  
    490 +  getToolChain().AddClangTargetOptions(CmdArgs);
    491 +
    492    if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
    493      CmdArgs.push_back("-mlimit-float-precision");
    494      CmdArgs.push_back(A->getValue(Args));
    495 diff --git a/llvm-3.1/tools/clang/lib/Frontend/CompilerInvocation.cpp b/llvm-3.1/tools/clang/lib/Frontend/CompilerInvocation.cpp
    496 index 4c5b063..bf45e5e 100644
    497 --- a/llvm-3.1/tools/clang/lib/Frontend/CompilerInvocation.cpp
    498 +++ b/llvm-3.1/tools/clang/lib/Frontend/CompilerInvocation.cpp
    499 @@ -1159,6 +1159,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
    500    Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
    501    Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
    502    Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
    503 +  Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array);
    504    Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
    505    if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) {
    506      StringRef Val = A->getValue(Args);
    507 diff --git a/llvm-3.1/tools/clang/test/Driver/constructors.c b/llvm-3.1/tools/clang/test/Driver/constructors.c
    508 new file mode 100644
    509 index 0000000..ca2cac2
    510 --- /dev/null
    511 +++ b/llvm-3.1/tools/clang/test/Driver/constructors.c
    512 @@ -0,0 +1,14 @@
    513 +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1       \
    514 +// RUN:     -target i386-unknown-linux \
    515 +// RUN:     --sysroot=%S/Inputs/fake_install_tree \
    516 +// RUN:   | FileCheck --check-prefix=CHECK-GCC-4-7 %s
    517 +
    518 +// CHECK-GCC-4-7: -fuse-init-array
    519 +
    520 +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1       \
    521 +// RUN:     -target i386-unknown-linux \
    522 +// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
    523 +// RUN:   | FileCheck --check-prefix=CHECK-GCC-4-6 %s
    524 +
    525 +
    526 +// CHECK-GCC-4-6-NOT:  -fuse-init-array
    527 diff --git a/llvm-3.1/tools/llc/llc.cpp b/llvm-3.1/tools/llc/llc.cpp
    528 index ceff8a6..9660e95 100644
    529 --- a/llvm-3.1/tools/llc/llc.cpp
    530 +++ b/llvm-3.1/tools/llc/llc.cpp
    531 @@ -249,6 +249,10 @@ SegmentedStacks("segmented-stacks",
    532    cl::desc("Use segmented stacks if possible."),
    533    cl::init(false));
    534  
    535 +static cl::opt<bool>
    536 +UseInitArray("use-init-array",
    537 +  cl::desc("Use .init_array instead of .ctors."),
    538 +  cl::init(false));
    539  
    540  // GetFileNameRoot - Helper function to get the basename of a filename.
    541  static inline std::string
    542 @@ -448,6 +452,7 @@ int main(int argc, char **argv) {
    543    Options.TrapFuncName = TrapFuncName;
    544    Options.PositionIndependentExecutable = EnablePIE;
    545    Options.EnableSegmentedStacks = SegmentedStacks;
    546 +  Options.UseInitArray = UseInitArray;
    547  
    548    std::auto_ptr<TargetMachine>
    549      target(TheTarget->createTargetMachine(TheTriple.getTriple(),
    550 -- 
    551 1.7.7.3
    552 
    553