diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index f7de6f88a8..3f4c573291 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -196,6 +196,8 @@ def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<"-munwind-tables">, HelpText<"Generate unwinding tables for all functions">; +def fuse_init_array : Flag<"-fuse-init-array">, + HelpText<"Use .init_array instead of .ctors">; def mconstructor_aliases : Flag<"-mconstructor-aliases">, HelpText<"Emit complete constructors and destructors as aliases when possible">; def mlink_bitcode_file : Separate<"-mlink-bitcode-file">, diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index ff85407a45..72171af163 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -230,6 +230,10 @@ public: virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; + // addClangTargetOptions - Add options that need to be passed to cc1 for + // this target. + virtual void addClangTargetOptions(ArgStringList &CC1Args) const; + // GetRuntimeLibType - Determine the runtime library type to use with the // given compilation arguments. virtual RuntimeLibType GetRuntimeLibType(const ArgList &Args) const; diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index be7f03fe13..6c77e424e7 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -118,6 +118,8 @@ public: unsigned StackRealignment : 1; ///< Control whether to permit stack ///< realignment. + unsigned UseInitArray : 1; ///< Control whether to use .init_array or + ///< .ctors. unsigned StackAlignment; ///< Overrides default stack alignment, ///< if not 0. @@ -228,6 +230,7 @@ public: StackRealignment = 0; StackAlignment = 0; BoundsChecking = 0; + UseInitArray = 0; DebugInfo = NoDebugInfo; Inlining = NoInlining; diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index f889606475..5a97875ef4 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -338,6 +338,9 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, Options.NoFramePointerElimNonLeaf = true; } + if (CodeGenOpts.UseInitArray) + Options.UseInitArray = true; + // Set float ABI type. if (CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp") Options.FloatABIType = llvm::FloatABI::Soft; diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index db4d2a8a47..2e3523cf1d 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -189,6 +189,9 @@ void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, // Each toolchain should provide the appropriate include flags. } +void ToolChain::addClangTargetOptions(ArgStringList &CC1Args) const { +} + ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( const ArgList &Args) const { diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 53b78d238b..7c75583eea 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -2116,6 +2116,12 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA, return *T; } +void Linux::addClangTargetOptions(ArgStringList &CC1Args) const { + const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion(); + if (V >= Generic_GCC::GCCVersion::Parse("4.7.0")) + CC1Args.push_back("-fuse-init-array"); +} + void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { const Driver &D = getDriver(); @@ -2258,7 +2264,7 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, // equivalent to '/usr/include/c++/X.Y' in almost all cases. StringRef LibDir = GCCInstallation.getParentLibPath(); StringRef InstallDir = GCCInstallation.getInstallPath(); - StringRef Version = GCCInstallation.getVersion(); + StringRef Version = GCCInstallation.getVersion().Text; if (!addLibStdCXXIncludePaths(LibDir + "/../include/c++/" + Version, (GCCInstallation.getTriple().str() + GCCInstallation.getMultiarchSuffix()), diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index aabf25884c..3fdcba04dd 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -99,7 +99,7 @@ protected: StringRef getParentLibPath() const { return GCCParentLibPath; } /// \brief Get the detected GCC version string. - StringRef getVersion() const { return Version.Text; } + const GCCVersion &getVersion() const { return Version; } private: static void CollectLibDirsAndTriples( @@ -538,6 +538,7 @@ public: virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; + virtual void addClangTargetOptions(ArgStringList &CC1Args) const; virtual void AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index f354c13a74..1669fd515d 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1814,6 +1814,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, AsynchronousUnwindTables)) CmdArgs.push_back("-munwind-tables"); + getToolChain().addClangTargetOptions(CmdArgs); + if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { CmdArgs.push_back("-mlimit-float-precision"); CmdArgs.push_back(A->getValue(Args)); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index fcc260f013..674299223f 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1229,6 +1229,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ); Opts.BoundsChecking = Args.getLastArgIntValue(OPT_fbounds_checking_EQ, 0, Diags); + Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array); Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections); Opts.DataSections = Args.hasArg(OPT_fdata_sections); diff --git a/test/Driver/constructors.c b/test/Driver/constructors.c new file mode 100644 index 0000000000..ca2cac2293 --- /dev/null +++ b/test/Driver/constructors.c @@ -0,0 +1,14 @@ +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: --sysroot=%S/Inputs/fake_install_tree \ +// RUN: | FileCheck --check-prefix=CHECK-GCC-4-7 %s + +// CHECK-GCC-4-7: -fuse-init-array + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-GCC-4-6 %s + + +// CHECK-GCC-4-6-NOT: -fuse-init-array