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