From 0def3d17cba323e3482809b79f51d592c0d9a36f Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 21 Dec 2009 23:28:17 +0000 Subject: [PATCH] ARM: Honor -mfpu= and set __VFP_FP__ and __ARM_NEON__ "correctly". - Correctly is in quotes, because we are following what I interpreted as GCC's intent (which diverges from practice, naturally). - Also, fix the arch define for arm1136jf-s. llvm-svn: 91855 --- clang/include/clang/Driver/Options.td | 1 + clang/lib/Basic/Targets.cpp | 68 +++++++++++++++++++++++---- clang/lib/Driver/Tools.cpp | 29 ++++++++++++ clang/test/Preprocessor/init.c | 1 - 4 files changed, 89 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7b0ce6702595..182f7bc5c936 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -391,6 +391,7 @@ def mcpu_EQ : Joined<"-mcpu=">, Group, Flags<[DriverOption]>; def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group, Flags<[NoArgumentUnused]>; def mfix_and_continue : Flag<"-mfix-and-continue">, Group; def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group; +def mfpu_EQ : Joined<"-mfpu=">, Group; def mhard_float : Flag<"-mhard-float">, Group; def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group; def mkernel : Flag<"-mkernel">, Group; diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 66d1814bdbc1..3b3279723dcc 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -1183,10 +1183,25 @@ public: namespace { class ARMTargetInfo : public TargetInfo { - static const TargetInfo::GCCRegAlias GCCRegAliases[]; - static const char * const GCCRegNames[]; + // Possible FPU choices. + enum FPUMode { + NoFPU, + VFP2FPU, + VFP3FPU, + NeonFPU + }; + + static bool FPUModeIsVFP(FPUMode Mode) { + return Mode >= VFP2FPU && Mode <= NeonFPU; + } + + static const TargetInfo::GCCRegAlias GCCRegAliases[]; + static const char * const GCCRegNames[]; std::string ABI, CPU; + + unsigned FPU : 3; + unsigned IsThumb : 1; // Initialized via features. @@ -1245,23 +1260,49 @@ public: return true; } + void getDefaultFeatures(const std::string &CPU, + llvm::StringMap &Features) const { + // FIXME: This should not be here. + Features["vfp2"] = false; + Features["vfp3"] = false; + Features["neon"] = false; + + if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore") + Features["vfp2"] = true; + else if (CPU == "cortex-a8" || CPU == "cortex-a9") + Features["neon"] = true; + } + virtual bool setFeatureEnabled(llvm::StringMap &Features, const std::string &Name, bool Enabled) const { - if (Name != "soft-float" && Name != "soft-float-abi") + if (Name == "soft-float" || Name == "soft-float-abi") { + Features[Name] = Enabled; + } else if (Name == "vfp2" || Name == "vfp3" || Name == "neon") { + // These effectively are a single option, reset them when any is enabled. + if (Enabled) + Features["vfp2"] = Features["vfp3"] = Features["neon"] = false; + Features[Name] = Enabled; + } else return false; - Features[Name] = Enabled; return true; } virtual void HandleTargetFeatures(std::vector &Features) { + FPU = NoFPU; SoftFloat = SoftFloatABI = false; for (unsigned i = 0, e = Features.size(); i != e; ++i) { if (Features[i] == "+soft-float") SoftFloat = true; else if (Features[i] == "+soft-float-abi") SoftFloatABI = true; + else if (Features[i] == "+vfp2") + FPU = VFP2FPU; + else if (Features[i] == "+vfp3") + FPU = VFP3FPU; + else if (Features[i] == "+neon") + FPU = NeonFPU; } // Remove front-end specific options which the backend handles differently. @@ -1286,9 +1327,9 @@ public: .Case("arm926ej-s", "5TEJ") .Cases("arm10e", "arm1020e", "arm1022e", "5TE") .Cases("xscale", "iwmmxt", "5TE") - .Cases("arm1136j-s", "arm1136jf-s", "6J") + .Case("arm1136j-s", "6J") .Cases("arm1176jz-s", "arm1176jzf-s", "6ZK") - .Cases("mpcorenovfp", "mpcore", "6K") + .Cases("arm1136jf-s", "mpcorenovfp", "mpcore", "6K") .Cases("arm1156t2-s", "arm1156t2f-s", "6T2") .Cases("cortex-a8", "cortex-a9", "7A") .Default(0); @@ -1334,17 +1375,26 @@ public: if (CPU == "xscale") Define(Defs, "__XSCALE__"); + bool IsThumb2 = IsThumb && (CPUArch == "6T2" || CPUArch.startswith("7")); if (IsThumb) { Define(Defs, "__THUMBEL__"); Define(Defs, "__thumb__"); - if (CPUArch == "6T2" || CPUArch.startswith("7")) + if (IsThumb2) Define(Defs, "__thumb2__"); } // Note, this is always on in gcc, even though it doesn't make sense. Define(Defs, "__APCS_32__"); - // FIXME: This should be conditional on VFP instruction support. - Define(Defs, "__VFP_FP__"); + + if (FPUModeIsVFP((FPUMode) FPU)) + Define(Defs, "__VFP_FP__"); + + // This only gets set when Neon instructions are actually available, unlike + // the VFP define, hence the soft float and arch check. This is subtly + // different from gcc, we follow the intent which was that it should be set + // when Neon instructions are actually available. + if (FPU == NeonFPU && !SoftFloat && IsThumb2) + Define(Defs, "__ARM_NEON__"); if (getTriple().getOS() == llvm::Triple::Darwin) Define(Defs, "__USING_SJLJ_EXCEPTIONS__"); diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 8cdd00c53600..8ac448fdaa81 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -450,6 +450,35 @@ void Clang::AddARMTargetArgs(const ArgList &Args, CmdArgs.push_back("-target-feature"); CmdArgs.push_back("+soft-float-abi"); } + + // Honor -mfpu=. + // + // FIXME: Centralize feature selection, defaulting shouldn't be also in the + // frontend target. + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) { + llvm::StringRef FPU = A->getValue(Args); + + // Set the target features based on the FPU. + if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { + // Disable any default FPU support. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp2"); + } else if (FPU == "vfp3") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + } else if (FPU == "neon") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+neon"); + } else + D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); + } } void Clang::AddX86TargetArgs(const ArgList &Args, diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 074b2a1dcb4e..5796b11e14bd 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -189,7 +189,6 @@ // ARM:#define __THUMB_INTERWORK__ 1 // ARM:#define __UINTMAX_TYPE__ long long unsigned int // ARM:#define __USER_LABEL_PREFIX__ _ -// ARM:#define __VFP_FP__ 1 // ARM:#define __WCHAR_MAX__ 2147483647 // ARM:#define __WCHAR_TYPE__ int // ARM:#define __WCHAR_WIDTH__ 32