Index: lib/Driver/AArch64Arch.cpp =================================================================== --- /dev/null +++ lib/Driver/AArch64Arch.cpp @@ -0,0 +1,230 @@ +//===--- AArch64Arch.cpp - AArch64 (not ARM) Helpers for Tools --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are +/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune +/// arguments if they are provided, or to nullptr otherwise. +std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) { + std::string CPU; + // If we have -mtune or -mcpu, use that. + if ((A = Args.getLastArg(options::OPT_mtune_EQ))) { + CPU = StringRef(A->getValue()).lower(); + } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) { + StringRef Mcpu = A->getValue(); + CPU = Mcpu.split("+").first.lower(); + } + + // Handle CPU name is 'native'. + if (CPU == "native") + return llvm::sys::getHostCPUName(); + else if (CPU.size()) + return CPU; + + // Make sure we pick "cyclone" if -arch is used. + // FIXME: Should this be picked by checking the target triple instead? + if (Args.getLastArg(options::OPT_arch)) + return "cyclone"; + + return "generic"; +} + +// Decode AArch64 features from string like +[no]featureA+[no]featureB+... +static bool DecodeAArch64Features(const Driver &D, StringRef text, + std::vector &Features) { + SmallVector Split; + text.split(Split, StringRef("+"), -1, false); + + for (StringRef Feature : Split) { + StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature); + if (!FeatureName.empty()) + Features.push_back(FeatureName); + else if (Feature == "neon" || Feature == "noneon") + D.Diag(diag::err_drv_no_neon_modifier); + else + return false; + } + return true; +} + +// Check if the CPU name and feature modifiers in -mcpu are legal. If yes, +// decode CPU and feature. +static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, + std::vector &Features) { + std::pair Split = Mcpu.split("+"); + CPU = Split.first; + + if (CPU == "generic") { + Features.push_back("+neon"); + } else { + unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU); + if (!llvm::AArch64::getArchFeatures(ArchKind, Features)) + return false; + + unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind); + if (!llvm::AArch64::getExtensionFeatures(Extension, Features)) + return false; + } + + if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) + return false; + + return true; +} + +static bool +getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, + const ArgList &Args, + std::vector &Features) { + std::string MarchLowerCase = March.lower(); + std::pair Split = StringRef(MarchLowerCase).split("+"); + + unsigned ArchKind = llvm::AArch64::parseArch(Split.first); + if (ArchKind == static_cast(llvm::AArch64::ArchKind::AK_INVALID) || + !llvm::AArch64::getArchFeatures(ArchKind, Features) || + (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))) + return false; + + return true; +} + +static bool +getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, + const ArgList &Args, + std::vector &Features) { + StringRef CPU; + std::string McpuLowerCase = Mcpu.lower(); + if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features)) + return false; + + return true; +} + +static bool +getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune, + const ArgList &Args, + std::vector &Features) { + std::string MtuneLowerCase = Mtune.lower(); + // Handle CPU name is 'native'. + if (MtuneLowerCase == "native") + MtuneLowerCase = llvm::sys::getHostCPUName(); + if (MtuneLowerCase == "cyclone") { + Features.push_back("+zcm"); + Features.push_back("+zcz"); + } + return true; +} + +static bool +getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, + const ArgList &Args, + std::vector &Features) { + StringRef CPU; + std::vector DecodedFeature; + std::string McpuLowerCase = Mcpu.lower(); + if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature)) + return false; + + return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features); +} + +void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, + std::vector &Features) { + Arg *A; + bool success = true; + // Enable NEON by default. + Features.push_back("+neon"); + if ((A = Args.getLastArg(options::OPT_march_EQ))) + success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); + else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) + success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); + else if (Args.hasArg(options::OPT_arch)) + success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A), + Args, Features); + + if (success && (A = Args.getLastArg(options::OPT_mtune_EQ))) + success = + getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features); + else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) + success = + getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); + else if (success && Args.hasArg(options::OPT_arch)) + success = getAArch64MicroArchFeaturesFromMcpu( + D, getAArch64TargetCPU(Args, A), Args, Features); + + if (!success) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + + if (Args.getLastArg(options::OPT_mgeneral_regs_only)) { + Features.push_back("-fp-armv8"); + Features.push_back("-crypto"); + Features.push_back("-neon"); + } + + // En/disable crc + if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { + if (A->getOption().matches(options::OPT_mcrc)) + Features.push_back("+crc"); + else + Features.push_back("-crc"); + } + + if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access)) + if (A->getOption().matches(options::OPT_mno_unaligned_access)) + Features.push_back("+strict-align"); + + if (Args.hasArg(options::OPT_ffixed_x18)) + Features.push_back("+reserve-x18"); +} Index: lib/Driver/ARMArch.cpp =================================================================== --- /dev/null +++ lib/Driver/ARMArch.cpp @@ -0,0 +1,478 @@ +//===--- ARMArch.cpp - ARM (not AArch64) Helpers for Tools ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +// Get SubArch (vN). +int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) { + llvm::StringRef Arch = Triple.getArchName(); + return llvm::ARM::parseArchVersion(Arch); +} + +// True if M-profile. +bool arm::isARMMProfile(const llvm::Triple &Triple) { + llvm::StringRef Arch = Triple.getArchName(); + unsigned Profile = llvm::ARM::parseArchProfile(Arch); + return Profile == llvm::ARM::PK_M; +} + +// Get Arch/CPU from args. +void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, + llvm::StringRef &CPU, bool FromAs) { + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + CPU = A->getValue(); + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + Arch = A->getValue(); + if (!FromAs) + return; + + for (const Arg *A : + Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { + StringRef Value = A->getValue(); + if (Value.startswith("-mcpu=")) + CPU = Value.substr(6); + if (Value.startswith("-march=")) + Arch = Value.substr(7); + } +} + +// Handle -mhwdiv=. +// FIXME: Use ARMTargetParser. +static void getARMHWDivFeatures(const Driver &D, const Arg *A, + const ArgList &Args, StringRef HWDiv, + std::vector &Features) { + unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv); + if (!llvm::ARM::getHWDivFeatures(HWDivID, Features)) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} + +// Handle -mfpu=. +static void getARMFPUFeatures(const Driver &D, const Arg *A, + const ArgList &Args, StringRef FPU, + std::vector &Features) { + unsigned FPUID = llvm::ARM::parseFPU(FPU); + if (!llvm::ARM::getFPUFeatures(FPUID, Features)) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} + +// Decode ARM features from string like +[no]featureA+[no]featureB+... +static bool DecodeARMFeatures(const Driver &D, StringRef text, + std::vector &Features) { + SmallVector Split; + text.split(Split, StringRef("+"), -1, false); + + for (StringRef Feature : Split) { + StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature); + if (!FeatureName.empty()) + Features.push_back(FeatureName); + else + return false; + } + return true; +} + +// Check if -march is valid by checking if it can be canonicalised and parsed. +// getARMArch is used here instead of just checking the -march value in order +// to handle -march=native correctly. +static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args, + llvm::StringRef ArchName, + std::vector &Features, + const llvm::Triple &Triple) { + std::pair Split = ArchName.split("+"); + + std::string MArch = arm::getARMArch(ArchName, Triple); + if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID || + (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} + +// Check -mcpu=. Needs ArchName to handle -mcpu=generic. +static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args, + llvm::StringRef CPUName, llvm::StringRef ArchName, + std::vector &Features, + const llvm::Triple &Triple) { + std::pair Split = CPUName.split("+"); + + std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); + if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() || + (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} + +bool arm::useAAPCSForMachO(const llvm::Triple &T) { + // The backend is hardwired to assume AAPCS for M-class processors, ensure + // the frontend matches that. + return T.getEnvironment() == llvm::Triple::EABI || + T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T); +} + +// Select the float ABI as determined by -msoft-float, -mhard-float, and +// -mfloat-abi=. +arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { + const Driver &D = TC.getDriver(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); + auto SubArch = getARMSubArchVersionNumber(Triple); + arm::FloatABI ABI = FloatABI::Invalid; + if (Arg *A = + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { + if (A->getOption().matches(options::OPT_msoft_float)) { + ABI = FloatABI::Soft; + } else if (A->getOption().matches(options::OPT_mhard_float)) { + ABI = FloatABI::Hard; + } else { + ABI = llvm::StringSwitch(A->getValue()) + .Case("soft", FloatABI::Soft) + .Case("softfp", FloatABI::SoftFP) + .Case("hard", FloatABI::Hard) + .Default(FloatABI::Invalid); + if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) { + D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); + ABI = FloatABI::Soft; + } + } + + // It is incorrect to select hard float ABI on MachO platforms if the ABI is + // "apcs-gnu". + if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) && + ABI == FloatABI::Hard) { + D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) + << Triple.getArchName(); + } + } + + // If unspecified, choose the default based on the platform. + if (ABI == FloatABI::Invalid) { + switch (Triple.getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::TvOS: { + // Darwin defaults to "softfp" for v6 and v7. + ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; + ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI; + break; + } + case llvm::Triple::WatchOS: + ABI = FloatABI::Hard; + break; + + // FIXME: this is invalid for WindowsCE + case llvm::Triple::Win32: + ABI = FloatABI::Hard; + break; + + case llvm::Triple::FreeBSD: + switch (Triple.getEnvironment()) { + case llvm::Triple::GNUEABIHF: + ABI = FloatABI::Hard; + break; + default: + // FreeBSD defaults to soft float + ABI = FloatABI::Soft; + break; + } + break; + + default: + switch (Triple.getEnvironment()) { + case llvm::Triple::GNUEABIHF: + case llvm::Triple::MuslEABIHF: + case llvm::Triple::EABIHF: + ABI = FloatABI::Hard; + break; + case llvm::Triple::GNUEABI: + case llvm::Triple::MuslEABI: + case llvm::Triple::EABI: + // EABI is always AAPCS, and if it was not marked 'hard', it's softfp + ABI = FloatABI::SoftFP; + break; + case llvm::Triple::Android: + ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; + break; + default: + // Assume "soft", but warn the user we are guessing. + if (Triple.isOSBinFormatMachO() && + Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) + ABI = FloatABI::Hard; + else + ABI = FloatABI::Soft; + + if (Triple.getOS() != llvm::Triple::UnknownOS || + !Triple.isOSBinFormatMachO()) + D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + break; + } + } + } + + assert(ABI != FloatABI::Invalid && "must select an ABI"); + return ABI; +} + +void arm::getARMTargetFeatures(const ToolChain &TC, + const llvm::Triple &Triple, + const ArgList &Args, + ArgStringList &CmdArgs, + std::vector &Features, + bool ForAS) { + const Driver &D = TC.getDriver(); + + bool KernelOrKext = + Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); + arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); + const Arg *WaCPU = nullptr, *WaFPU = nullptr; + const Arg *WaHDiv = nullptr, *WaArch = nullptr; + + if (!ForAS) { + // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these + // yet (it uses the -mfloat-abi and -msoft-float options), and it is + // stripped out by the ARM target. We should probably pass this a new + // -target-option, which is handled by the -cc1/-cc1as invocation. + // + // FIXME2: For consistency, it would be ideal if we set up the target + // machine state the same when using the frontend or the assembler. We don't + // currently do that for the assembler, we pass the options directly to the + // backend and never even instantiate the frontend TargetInfo. If we did, + // and used its handleTargetFeatures hook, then we could ensure the + // assembler and the frontend behave the same. + + // Use software floating point operations? + if (ABI == arm::FloatABI::Soft) + Features.push_back("+soft-float"); + + // Use software floating point argument passing? + if (ABI != arm::FloatABI::Hard) + Features.push_back("+soft-float-abi"); + } else { + // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down + // to the assembler correctly. + for (const Arg *A : + Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { + StringRef Value = A->getValue(); + if (Value.startswith("-mfpu=")) { + WaFPU = A; + } else if (Value.startswith("-mcpu=")) { + WaCPU = A; + } else if (Value.startswith("-mhwdiv=")) { + WaHDiv = A; + } else if (Value.startswith("-march=")) { + WaArch = A; + } + } + } + + // Check -march. ClangAs gives preference to -Wa,-march=. + const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); + StringRef ArchName; + if (WaArch) { + if (ArchArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << ArchArg->getAsString(Args); + ArchName = StringRef(WaArch->getValue()).substr(7); + checkARMArchName(D, WaArch, Args, ArchName, Features, Triple); + // FIXME: Set Arch. + D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); + } else if (ArchArg) { + ArchName = ArchArg->getValue(); + checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple); + } + + // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. + const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); + StringRef CPUName; + if (WaCPU) { + if (CPUArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << CPUArg->getAsString(Args); + CPUName = StringRef(WaCPU->getValue()).substr(6); + checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple); + } else if (CPUArg) { + CPUName = CPUArg->getValue(); + checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple); + } + + // Add CPU features for generic CPUs + if (CPUName == "native") { + llvm::StringMap HostFeatures; + if (llvm::sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.push_back( + Args.MakeArgString((F.second ? "+" : "-") + F.first())); + } + + // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. + const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); + if (WaFPU) { + if (FPUArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << FPUArg->getAsString(Args); + getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), + Features); + } else if (FPUArg) { + getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); + } + + // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. + const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); + if (WaHDiv) { + if (HDivArg) + D.Diag(clang::diag::warn_drv_unused_argument) + << HDivArg->getAsString(Args); + getARMHWDivFeatures(D, WaHDiv, Args, + StringRef(WaHDiv->getValue()).substr(8), Features); + } else if (HDivArg) + getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); + + // Setting -msoft-float effectively disables NEON because of the GCC + // implementation, although the same isn't true of VFP or VFP3. + if (ABI == arm::FloatABI::Soft) { + Features.push_back("-neon"); + // Also need to explicitly disable features which imply NEON. + Features.push_back("-crypto"); + } + + // En/disable crc code generation. + if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { + if (A->getOption().matches(options::OPT_mcrc)) + Features.push_back("+crc"); + else + Features.push_back("-crc"); + } + + // Look for the last occurrence of -mlong-calls or -mno-long-calls. If + // neither options are specified, see if we are compiling for kernel/kext and + // decide whether to pass "+long-calls" based on the OS and its version. + if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, + options::OPT_mno_long_calls)) { + if (A->getOption().matches(options::OPT_mlong_calls)) + Features.push_back("+long-calls"); + } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) && + !Triple.isWatchOS()) { + Features.push_back("+long-calls"); + } + + // Generate execute-only output (no data access to code sections). + // Supported only on ARMv6T2 and ARMv7 and above. + // Cannot be combined with -mno-movt or -mlong-calls + if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { + if (A->getOption().matches(options::OPT_mexecute_only)) { + if (getARMSubArchVersionNumber(Triple) < 7 && + llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2) + D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); + else if (Arg *B = Args.getLastArg(options::OPT_mno_movt)) + D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); + // Long calls create constant pool entries and have not yet been fixed up + // to play nicely with execute-only. Hence, they cannot be used in + // execute-only code for now + else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { + if (B->getOption().matches(options::OPT_mlong_calls)) + D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); + } + + CmdArgs.push_back("-backend-option"); + CmdArgs.push_back("-arm-execute-only"); + } + } + + // Kernel code has more strict alignment requirements. + if (KernelOrKext) + Features.push_back("+strict-align"); + else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access)) { + if (A->getOption().matches(options::OPT_munaligned_access)) { + // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). + if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) + D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; + // v8M Baseline follows on from v6M, so doesn't support unaligned memory + // access either. + else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) + D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; + } else + Features.push_back("+strict-align"); + } else { + // Assume pre-ARMv6 doesn't support unaligned accesses. + // + // ARMv6 may or may not support unaligned accesses depending on the + // SCTLR.U bit, which is architecture-specific. We assume ARMv6 + // Darwin and NetBSD targets support unaligned accesses, and others don't. + // + // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit + // which raises an alignment fault on unaligned accesses. Linux + // defaults this bit to 0 and handles it as a system-wide (not + // per-process) setting. It is therefore safe to assume that ARMv7+ + // Linux targets support unaligned accesses. The same goes for NaCl. + // + // The above behavior is consistent with GCC. + int VersionNum = getARMSubArchVersionNumber(Triple); + if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { + if (VersionNum < 6 || + Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) + Features.push_back("+strict-align"); + } else if (Triple.isOSLinux() || Triple.isOSNaCl()) { + if (VersionNum < 7) + Features.push_back("+strict-align"); + } else + Features.push_back("+strict-align"); + } + + // llvm does not support reserving registers in general. There is support + // for reserving r9 on ARM though (defined as a platform-specific register + // in ARM EABI). + if (Args.hasArg(options::OPT_ffixed_r9)) + Features.push_back("+reserve-r9"); + + // The kext linker doesn't know how to deal with movw/movt. + if (KernelOrKext || Args.hasArg(options::OPT_mno_movt)) + Features.push_back("+no-movt"); +} Index: lib/Driver/CMakeLists.txt =================================================================== --- lib/Driver/CMakeLists.txt +++ lib/Driver/CMakeLists.txt @@ -9,7 +9,9 @@ endif() add_clang_library(clangDriver + AArch64Arch.cpp Action.cpp + ARMArch.cpp Compilation.cpp CrossWindowsToolChain.cpp Distro.cpp @@ -17,15 +19,20 @@ DriverOptions.cpp Job.cpp MinGWToolChain.cpp + MipsArch.cpp Multilib.cpp MSVCToolChain.cpp Phases.cpp + PPCArch.cpp SanitizerArgs.cpp + SparcArch.cpp + SystemZArch.cpp Tool.cpp ToolChain.cpp ToolChains.cpp Tools.cpp Types.cpp + X86Arch.cpp DEPENDS ClangDriverOptions Index: lib/Driver/MipsArch.cpp =================================================================== --- /dev/null +++ lib/Driver/MipsArch.cpp @@ -0,0 +1,430 @@ +//===--- MipsArch.cpp - Tools Implementations -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +// Get CPU and ABI names. They are not independent +// so we have to calculate them together. +void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, + StringRef &CPUName, StringRef &ABIName) { + const char *DefMips32CPU = "mips32r2"; + const char *DefMips64CPU = "mips64r2"; + + // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the + // default for mips64(el)?-img-linux-gnu. + if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && + Triple.getEnvironment() == llvm::Triple::GNU) { + DefMips32CPU = "mips32r6"; + DefMips64CPU = "mips64r6"; + } + + // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android). + if (Triple.isAndroid()) { + DefMips32CPU = "mips32"; + DefMips64CPU = "mips64r6"; + } + + // MIPS3 is the default for mips64*-unknown-openbsd. + if (Triple.getOS() == llvm::Triple::OpenBSD) + DefMips64CPU = "mips3"; + + if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ)) + CPUName = A->getValue(); + + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + ABIName = A->getValue(); + // Convert a GNU style Mips ABI name to the name + // accepted by LLVM Mips backend. + ABIName = llvm::StringSwitch(ABIName) + .Case("32", "o32") + .Case("64", "n64") + .Default(ABIName); + } + + // Setup default CPU and ABI names. + if (CPUName.empty() && ABIName.empty()) { + switch (Triple.getArch()) { + default: + llvm_unreachable("Unexpected triple arch name"); + case llvm::Triple::mips: + case llvm::Triple::mipsel: + CPUName = DefMips32CPU; + break; + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + CPUName = DefMips64CPU; + break; + } + } + + if (ABIName.empty() && + (Triple.getVendor() == llvm::Triple::MipsTechnologies || + Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { + ABIName = llvm::StringSwitch(CPUName) + .Case("mips1", "o32") + .Case("mips2", "o32") + .Case("mips3", "n64") + .Case("mips4", "n64") + .Case("mips5", "n64") + .Case("mips32", "o32") + .Case("mips32r2", "o32") + .Case("mips32r3", "o32") + .Case("mips32r5", "o32") + .Case("mips32r6", "o32") + .Case("mips64", "n64") + .Case("mips64r2", "n64") + .Case("mips64r3", "n64") + .Case("mips64r5", "n64") + .Case("mips64r6", "n64") + .Case("octeon", "n64") + .Case("p5600", "o32") + .Default(""); + } + + if (ABIName.empty()) { + // Deduce ABI name from the target triple. + if (Triple.getArch() == llvm::Triple::mips || + Triple.getArch() == llvm::Triple::mipsel) + ABIName = "o32"; + else + ABIName = "n64"; + } + + if (CPUName.empty()) { + // Deduce CPU name from ABI name. + CPUName = llvm::StringSwitch(ABIName) + .Case("o32", DefMips32CPU) + .Cases("n32", "n64", DefMips64CPU) + .Default(""); + } + + // FIXME: Warn on inconsistent use of -march and -mabi. +} + +std::string mips::getMipsABILibSuffix(const ArgList &Args, + const llvm::Triple &Triple) { + StringRef CPUName, ABIName; + tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + return llvm::StringSwitch(ABIName) + .Case("o32", "") + .Case("n32", "32") + .Case("n64", "64"); +} + +// Convert ABI name to the GNU tools acceptable variant. +StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { + return llvm::StringSwitch(ABI) + .Case("o32", "32") + .Case("n64", "64") + .Default(ABI); +} + +// Select the MIPS float ABI as determined by -msoft-float, -mhard-float, +// and -mfloat-abi=. +mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { + mips::FloatABI ABI = mips::FloatABI::Invalid; + if (Arg *A = + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { + if (A->getOption().matches(options::OPT_msoft_float)) + ABI = mips::FloatABI::Soft; + else if (A->getOption().matches(options::OPT_mhard_float)) + ABI = mips::FloatABI::Hard; + else { + ABI = llvm::StringSwitch(A->getValue()) + .Case("soft", mips::FloatABI::Soft) + .Case("hard", mips::FloatABI::Hard) + .Default(mips::FloatABI::Invalid); + if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { + D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); + ABI = mips::FloatABI::Hard; + } + } + } + + // If unspecified, choose the default based on the platform. + if (ABI == mips::FloatABI::Invalid) { + // Assume "hard", because it's a default value used by gcc. + // When we start to recognize specific target MIPS processors, + // we will be able to select the default more correctly. + ABI = mips::FloatABI::Hard; + } + + assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); + return ABI; +} + +void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector &Features) { + StringRef CPUName; + StringRef ABIName; + getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + ABIName = getGnuCompatibleMipsABIName(ABIName); + + // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a + // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI + // extension was developed by Richard Sandiford & Code Sourcery to support + // static code calling PIC code (CPIC). For O32 and N32 this means we have + // several combinations of PIC/static and abicalls. Pure static, static + // with the CPIC extension, and pure PIC code. + + // At final link time, O32 and N32 with CPIC will have another section + // added to the binary which contains the stub functions to perform + // any fixups required for PIC code. + + // For N64, the situation is more regular: code can either be static + // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code + // code for N64. Since Clang has already built the relocation model portion + // of the commandline, we pick add +noabicalls feature in the N64 static + // case. + + // The is another case to be accounted for: -msym32, which enforces that all + // symbols have 32 bits in size. In this case, N64 can in theory use CPIC + // but it is unsupported. + + // The combinations for N64 are: + // a) Static without abicalls and 64bit symbols. + // b) Static with abicalls and 32bit symbols. + // c) PIC with abicalls and 64bit symbols. + + // For case (a) we need to add +noabicalls for N64. + + bool IsN64 = ABIName == "64"; + bool NonPIC = false; + + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, + options::OPT_fpic, options::OPT_fno_pic, + options::OPT_fPIE, options::OPT_fno_PIE, + options::OPT_fpie, options::OPT_fno_pie); + if (LastPICArg) { + Option O = LastPICArg->getOption(); + NonPIC = + (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) || + O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie)); + } + + if (IsN64 && NonPIC) { + Features.push_back("+noabicalls"); + } else { + AddTargetFeature(Args, Features, options::OPT_mno_abicalls, + options::OPT_mabicalls, "noabicalls"); + } + + mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args); + if (FloatABI == mips::FloatABI::Soft) { + // FIXME: Note, this is a hack. We need to pass the selected float + // mode to the MipsTargetInfoBase to define appropriate macros there. + // Now it is the only method. + Features.push_back("+soft-float"); + } + + if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { + StringRef Val = StringRef(A->getValue()); + if (Val == "2008") { + if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008) + Features.push_back("+nan2008"); + else { + Features.push_back("-nan2008"); + D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; + } + } else if (Val == "legacy") { + if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy) + Features.push_back("-nan2008"); + else { + Features.push_back("+nan2008"); + D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; + } + } else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; + } + + AddTargetFeature(Args, Features, options::OPT_msingle_float, + options::OPT_mdouble_float, "single-float"); + AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, + "mips16"); + AddTargetFeature(Args, Features, options::OPT_mmicromips, + options::OPT_mno_micromips, "micromips"); + AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, + "dsp"); + AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, + "dspr2"); + AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, + "msa"); + + // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 + // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and + // nooddspreg. + if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, + options::OPT_mfp64)) { + if (A->getOption().matches(options::OPT_mfp32)) + Features.push_back(Args.MakeArgString("-fp64")); + else if (A->getOption().matches(options::OPT_mfpxx)) { + Features.push_back(Args.MakeArgString("+fpxx")); + Features.push_back(Args.MakeArgString("+nooddspreg")); + } else + Features.push_back(Args.MakeArgString("+fp64")); + } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { + Features.push_back(Args.MakeArgString("+fpxx")); + Features.push_back(Args.MakeArgString("+nooddspreg")); + } else if (mips::isFP64ADefault(Triple, CPUName)) { + Features.push_back(Args.MakeArgString("+fp64")); + Features.push_back(Args.MakeArgString("+nooddspreg")); + } + + AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, + options::OPT_modd_spreg, "nooddspreg"); +} + +mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) { + // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008 + // was first introduced in Release 3. However, other compilers have + // traditionally allowed it for Release 2 so we should do the same. + return (NanEncoding)llvm::StringSwitch(CPU) + .Case("mips1", NanLegacy) + .Case("mips2", NanLegacy) + .Case("mips3", NanLegacy) + .Case("mips4", NanLegacy) + .Case("mips5", NanLegacy) + .Case("mips32", NanLegacy) + .Case("mips32r2", NanLegacy | Nan2008) + .Case("mips32r3", NanLegacy | Nan2008) + .Case("mips32r5", NanLegacy | Nan2008) + .Case("mips32r6", Nan2008) + .Case("mips64", NanLegacy) + .Case("mips64r2", NanLegacy | Nan2008) + .Case("mips64r3", NanLegacy | Nan2008) + .Case("mips64r5", NanLegacy | Nan2008) + .Case("mips64r6", Nan2008) + .Default(NanLegacy); +} + +bool mips::hasCompactBranches(StringRef &CPU) { + // mips32r6 and mips64r6 have compact branches. + return llvm::StringSwitch(CPU) + .Case("mips32r6", true) + .Case("mips64r6", true) + .Default(false); +} + +bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} + +bool mips::isUCLibc(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_m_libc_Group); + return A && A->getOption().matches(options::OPT_muclibc); +} + +bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) { + if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) + return llvm::StringSwitch(NaNArg->getValue()) + .Case("2008", true) + .Case("legacy", false) + .Default(false); + + // NaN2008 is the default for MIPS32r6/MIPS64r6. + return llvm::StringSwitch(getCPUName(Args, Triple)) + .Cases("mips32r6", "mips64r6", true) + .Default(false); + + return false; +} + +bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { + if (!Triple.isAndroid()) + return false; + + // Android MIPS32R6 defaults to FP64A. + return llvm::StringSwitch(CPUName) + .Case("mips32r6", true) + .Default(false); +} + +bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, + StringRef ABIName, mips::FloatABI FloatABI) { + if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies && + Triple.getVendor() != llvm::Triple::MipsTechnologies && + !Triple.isAndroid()) + return false; + + if (ABIName != "32") + return false; + + // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is + // present. + if (FloatABI == mips::FloatABI::Soft) + return false; + + return llvm::StringSwitch(CPUName) + .Cases("mips2", "mips3", "mips4", "mips5", true) + .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) + .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) + .Default(false); +} + +bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, + StringRef CPUName, StringRef ABIName, + mips::FloatABI FloatABI) { + bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); + + // FPXX shouldn't be used if -msingle-float is present. + if (Arg *A = Args.getLastArg(options::OPT_msingle_float, + options::OPT_mdouble_float)) + if (A->getOption().matches(options::OPT_msingle_float)) + UseFPXX = false; + + return UseFPXX; +} Index: lib/Driver/PPCArch.cpp =================================================================== --- /dev/null +++ lib/Driver/PPCArch.cpp @@ -0,0 +1,168 @@ +//===--- PPCArch.cpp - PPC Helpers for Tools --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting. +std::string ppc::getPPCTargetCPU(const ArgList &Args) { + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + StringRef CPUName = A->getValue(); + + if (CPUName == "native") { + std::string CPU = llvm::sys::getHostCPUName(); + if (!CPU.empty() && CPU != "generic") + return CPU; + else + return ""; + } + + return llvm::StringSwitch(CPUName) + .Case("common", "generic") + .Case("440", "440") + .Case("440fp", "440") + .Case("450", "450") + .Case("601", "601") + .Case("602", "602") + .Case("603", "603") + .Case("603e", "603e") + .Case("603ev", "603ev") + .Case("604", "604") + .Case("604e", "604e") + .Case("620", "620") + .Case("630", "pwr3") + .Case("G3", "g3") + .Case("7400", "7400") + .Case("G4", "g4") + .Case("7450", "7450") + .Case("G4+", "g4+") + .Case("750", "750") + .Case("970", "970") + .Case("G5", "g5") + .Case("a2", "a2") + .Case("a2q", "a2q") + .Case("e500mc", "e500mc") + .Case("e5500", "e5500") + .Case("power3", "pwr3") + .Case("power4", "pwr4") + .Case("power5", "pwr5") + .Case("power5x", "pwr5x") + .Case("power6", "pwr6") + .Case("power6x", "pwr6x") + .Case("power7", "pwr7") + .Case("power8", "pwr8") + .Case("power9", "pwr9") + .Case("pwr3", "pwr3") + .Case("pwr4", "pwr4") + .Case("pwr5", "pwr5") + .Case("pwr5x", "pwr5x") + .Case("pwr6", "pwr6") + .Case("pwr6x", "pwr6x") + .Case("pwr7", "pwr7") + .Case("pwr8", "pwr8") + .Case("pwr9", "pwr9") + .Case("powerpc", "ppc") + .Case("powerpc64", "ppc64") + .Case("powerpc64le", "ppc64le") + .Default(""); + } + + return ""; +} + +void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group); + + ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); + if (FloatABI == ppc::FloatABI::Soft) + Features.push_back("-hard-float"); + + // Altivec is a bit weird, allow overriding of the Altivec feature here. + AddTargetFeature(Args, Features, options::OPT_faltivec, + options::OPT_fno_altivec, "altivec"); +} + +ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) { + ppc::FloatABI ABI = ppc::FloatABI::Invalid; + if (Arg *A = + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { + if (A->getOption().matches(options::OPT_msoft_float)) + ABI = ppc::FloatABI::Soft; + else if (A->getOption().matches(options::OPT_mhard_float)) + ABI = ppc::FloatABI::Hard; + else { + ABI = llvm::StringSwitch(A->getValue()) + .Case("soft", ppc::FloatABI::Soft) + .Case("hard", ppc::FloatABI::Hard) + .Default(ppc::FloatABI::Invalid); + if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { + D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); + ABI = ppc::FloatABI::Hard; + } + } + } + + // If unspecified, choose the default based on the platform. + if (ABI == ppc::FloatABI::Invalid) { + ABI = ppc::FloatABI::Hard; + } + + return ABI; +} + +bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} Index: lib/Driver/SparcArch.cpp =================================================================== --- /dev/null +++ lib/Driver/SparcArch.cpp @@ -0,0 +1,134 @@ +//===--- SparcArch.cpp - Tools Implementations ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +const char *sparc::getSparcAsmModeForCPU(StringRef Name, + const llvm::Triple &Triple) { + if (Triple.getArch() == llvm::Triple::sparcv9) { + return llvm::StringSwitch(Name) + .Case("niagara", "-Av9b") + .Case("niagara2", "-Av9b") + .Case("niagara3", "-Av9d") + .Case("niagara4", "-Av9d") + .Default("-Av9"); + } else { + return llvm::StringSwitch(Name) + .Case("v8", "-Av8") + .Case("supersparc", "-Av8") + .Case("sparclite", "-Asparclite") + .Case("f934", "-Asparclite") + .Case("hypersparc", "-Av8") + .Case("sparclite86x", "-Asparclite") + .Case("sparclet", "-Asparclet") + .Case("tsc701", "-Asparclet") + .Case("v9", "-Av8plus") + .Case("ultrasparc", "-Av8plus") + .Case("ultrasparc3", "-Av8plus") + .Case("niagara", "-Av8plusb") + .Case("niagara2", "-Av8plusb") + .Case("niagara3", "-Av8plusd") + .Case("niagara4", "-Av8plusd") + .Case("leon2", "-Av8") + .Case("at697e", "-Av8") + .Case("at697f", "-Av8") + .Case("leon3", "-Av8") + .Case("ut699", "-Av8") + .Case("gr712rc", "-Av8") + .Case("leon4", "-Av8") + .Case("gr740", "-Av8") + .Default("-Av8"); + } +} + +sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, + const ArgList &Args) { + sparc::FloatABI ABI = sparc::FloatABI::Invalid; + if (Arg *A = + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { + if (A->getOption().matches(options::OPT_msoft_float)) + ABI = sparc::FloatABI::Soft; + else if (A->getOption().matches(options::OPT_mhard_float)) + ABI = sparc::FloatABI::Hard; + else { + ABI = llvm::StringSwitch(A->getValue()) + .Case("soft", sparc::FloatABI::Soft) + .Case("hard", sparc::FloatABI::Hard) + .Default(sparc::FloatABI::Invalid); + if (ABI == sparc::FloatABI::Invalid && + !StringRef(A->getValue()).empty()) { + D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); + ABI = sparc::FloatABI::Hard; + } + } + } + + // If unspecified, choose the default based on the platform. + // Only the hard-float ABI on Sparc is standardized, and it is the + // default. GCC also supports a nonstandard soft-float ABI mode, also + // implemented in LLVM. However as this is not standard we set the default + // to be hard-float. + if (ABI == sparc::FloatABI::Invalid) { + ABI = sparc::FloatABI::Hard; + } + + return ABI; +} + +void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, + std::vector &Features) { + sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); + if (FloatABI == sparc::FloatABI::Soft) + Features.push_back("+soft-float"); +} Index: lib/Driver/SystemZArch.cpp =================================================================== --- /dev/null +++ lib/Driver/SystemZArch.cpp @@ -0,0 +1,78 @@ +//===--- SystemZArch.cpp - SystemZ Helpers for Tools ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +const char *systemz::getSystemZTargetCPU(const ArgList &Args) { + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + return A->getValue(); + return "z10"; +} + +void systemz::getSystemZTargetFeatures(const ArgList &Args, + std::vector &Features) { + // -m(no-)htm overrides use of the transactional-execution facility. + if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) { + if (A->getOption().matches(options::OPT_mhtm)) + Features.push_back("+transactional-execution"); + else + Features.push_back("-transactional-execution"); + } + // -m(no-)vx overrides use of the vector facility. + if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) { + if (A->getOption().matches(options::OPT_mvx)) + Features.push_back("+vector"); + else + Features.push_back("-vector"); + } +} Index: lib/Driver/Tools.h =================================================================== --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -38,11 +38,23 @@ } using llvm::opt::ArgStringList; +using llvm::opt::ArgList; SmallString<128> getCompilerRT(const ToolChain &TC, const llvm::opt::ArgList &Args, StringRef Component, bool Shared = false); +std::string getCPUName(const ArgList &Args, const llvm::Triple &T, + bool FromAs = false); + +void AddTargetFeature(const ArgList &Args, std::vector &Features, + llvm::opt::OptSpecifier OnOpt, + llvm::opt::OptSpecifier OffOpt, StringRef FeatureName); + +void handleTargetFeaturesGroup(const ArgList &Args, + std::vector &Features, + llvm::opt::OptSpecifier Group); + /// \brief Clang compiler tool. class LLVM_LIBRARY_VISIBILITY Clang : public Tool { public: @@ -321,6 +333,11 @@ void getMipsCPUAndABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef &CPUName, StringRef &ABIName); +void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector &Features); +StringRef getGnuCompatibleMipsABIName(StringRef ABI); +mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args); std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value); @@ -332,6 +349,7 @@ bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, StringRef CPUName, StringRef ABIName, mips::FloatABI FloatABI); + } // end namespace mips namespace ppc { @@ -803,8 +821,23 @@ }; FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args); + +bool useAAPCSForMachO(const llvm::Triple &T); +void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, + llvm::StringRef &CPU, bool FromAs = false); +void getARMTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, + std::vector &Features, bool ForAS); +int getARMSubArchVersionNumber(const llvm::Triple &Triple); +bool isARMMProfile(const llvm::Triple &Triple); } // end namespace arm +namespace aarch64 { +void getAArch64TargetFeatures(const Driver &D, const ArgList &Args, + std::vector &Features); +std::string getAArch64TargetCPU(const ArgList &Args, llvm::opt::Arg *&A); +} // end namespace aarch64 + namespace ppc { enum class FloatABI { Invalid, @@ -813,6 +846,11 @@ }; FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args); + +std::string getPPCTargetCPU(const ArgList &Args); +void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector &Features); } // end namespace ppc namespace sparc { @@ -823,6 +861,11 @@ }; FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args); + +void getSparcTargetFeatures(const Driver &D, const ArgList &Args, + std::vector &Features); +const char *getSparcAsmModeForCPU(StringRef Name, + const llvm::Triple &Triple); } // end namespace sparc namespace XCore { @@ -1003,6 +1046,20 @@ }; } // end namespace AVR +namespace systemz { +const char *getSystemZTargetCPU(const ArgList &Args); +void getSystemZTargetFeatures(const ArgList &Args, + std::vector &Features); +} // end namespace systemz + +namespace x86 { +const char *getX86TargetCPU(const ArgList &Args, + const llvm::Triple &Triple); +void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector &Features); +} // end namespace x86 + } // end namespace tools } // end namespace driver } // end namespace clang Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -53,7 +53,7 @@ using namespace clang; using namespace llvm::opt; -static void handleTargetFeaturesGroup(const ArgList &Args, +void tools::handleTargetFeaturesGroup(const ArgList &Args, std::vector &Features, OptSpecifier Group) { for (const Arg *A : Args.filtered(Group)) { @@ -71,44 +71,6 @@ } } -static const char *getSparcAsmModeForCPU(StringRef Name, - const llvm::Triple &Triple) { - if (Triple.getArch() == llvm::Triple::sparcv9) { - return llvm::StringSwitch(Name) - .Case("niagara", "-Av9b") - .Case("niagara2", "-Av9b") - .Case("niagara3", "-Av9d") - .Case("niagara4", "-Av9d") - .Default("-Av9"); - } else { - return llvm::StringSwitch(Name) - .Case("v8", "-Av8") - .Case("supersparc", "-Av8") - .Case("sparclite", "-Asparclite") - .Case("f934", "-Asparclite") - .Case("hypersparc", "-Av8") - .Case("sparclite86x", "-Asparclite") - .Case("sparclet", "-Asparclet") - .Case("tsc701", "-Asparclet") - .Case("v9", "-Av8plus") - .Case("ultrasparc", "-Av8plus") - .Case("ultrasparc3", "-Av8plus") - .Case("niagara", "-Av8plusb") - .Case("niagara2", "-Av8plusb") - .Case("niagara3", "-Av8plusd") - .Case("niagara4", "-Av8plusd") - .Case("leon2", "-Av8") - .Case("at697e", "-Av8") - .Case("at697f", "-Av8") - .Case("leon3", "-Av8") - .Case("ut699", "-Av8") - .Case("gr712rc", "-Av8") - .Case("leon4", "-Av8") - .Case("gr740", "-Av8") - .Default("-Av8"); - } -} - static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) { if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) && @@ -789,432 +751,6 @@ } } -// ARM tools start. - -// Get SubArch (vN). -static int getARMSubArchVersionNumber(const llvm::Triple &Triple) { - llvm::StringRef Arch = Triple.getArchName(); - return llvm::ARM::parseArchVersion(Arch); -} - -// True if M-profile. -static bool isARMMProfile(const llvm::Triple &Triple) { - llvm::StringRef Arch = Triple.getArchName(); - unsigned Profile = llvm::ARM::parseArchProfile(Arch); - return Profile == llvm::ARM::PK_M; -} - -// Get Arch/CPU from args. -static void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, - llvm::StringRef &CPU, bool FromAs = false) { - if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) - CPU = A->getValue(); - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) - Arch = A->getValue(); - if (!FromAs) - return; - - for (const Arg *A : - Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { - StringRef Value = A->getValue(); - if (Value.startswith("-mcpu=")) - CPU = Value.substr(6); - if (Value.startswith("-march=")) - Arch = Value.substr(7); - } -} - -// Handle -mhwdiv=. -// FIXME: Use ARMTargetParser. -static void getARMHWDivFeatures(const Driver &D, const Arg *A, - const ArgList &Args, StringRef HWDiv, - std::vector &Features) { - unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv); - if (!llvm::ARM::getHWDivFeatures(HWDivID, Features)) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); -} - -// Handle -mfpu=. -static void getARMFPUFeatures(const Driver &D, const Arg *A, - const ArgList &Args, StringRef FPU, - std::vector &Features) { - unsigned FPUID = llvm::ARM::parseFPU(FPU); - if (!llvm::ARM::getFPUFeatures(FPUID, Features)) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); -} - -// Decode ARM features from string like +[no]featureA+[no]featureB+... -static bool DecodeARMFeatures(const Driver &D, StringRef text, - std::vector &Features) { - SmallVector Split; - text.split(Split, StringRef("+"), -1, false); - - for (StringRef Feature : Split) { - StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature); - if (!FeatureName.empty()) - Features.push_back(FeatureName); - else - return false; - } - return true; -} - -// Check if -march is valid by checking if it can be canonicalised and parsed. -// getARMArch is used here instead of just checking the -march value in order -// to handle -march=native correctly. -static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args, - llvm::StringRef ArchName, - std::vector &Features, - const llvm::Triple &Triple) { - std::pair Split = ArchName.split("+"); - - std::string MArch = arm::getARMArch(ArchName, Triple); - if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID || - (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); -} - -// Check -mcpu=. Needs ArchName to handle -mcpu=generic. -static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args, - llvm::StringRef CPUName, llvm::StringRef ArchName, - std::vector &Features, - const llvm::Triple &Triple) { - std::pair Split = CPUName.split("+"); - - std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); - if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() || - (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features))) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); -} - -static bool useAAPCSForMachO(const llvm::Triple &T) { - // The backend is hardwired to assume AAPCS for M-class processors, ensure - // the frontend matches that. - return T.getEnvironment() == llvm::Triple::EABI || - T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T); -} - -// Select the float ABI as determined by -msoft-float, -mhard-float, and -// -mfloat-abi=. -arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { - const Driver &D = TC.getDriver(); - const llvm::Triple &Triple = TC.getEffectiveTriple(); - auto SubArch = getARMSubArchVersionNumber(Triple); - arm::FloatABI ABI = FloatABI::Invalid; - if (Arg *A = - Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, - options::OPT_mfloat_abi_EQ)) { - if (A->getOption().matches(options::OPT_msoft_float)) { - ABI = FloatABI::Soft; - } else if (A->getOption().matches(options::OPT_mhard_float)) { - ABI = FloatABI::Hard; - } else { - ABI = llvm::StringSwitch(A->getValue()) - .Case("soft", FloatABI::Soft) - .Case("softfp", FloatABI::SoftFP) - .Case("hard", FloatABI::Hard) - .Default(FloatABI::Invalid); - if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) { - D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); - ABI = FloatABI::Soft; - } - } - - // It is incorrect to select hard float ABI on MachO platforms if the ABI is - // "apcs-gnu". - if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) && - ABI == FloatABI::Hard) { - D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) - << Triple.getArchName(); - } - } - - // If unspecified, choose the default based on the platform. - if (ABI == FloatABI::Invalid) { - switch (Triple.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: { - // Darwin defaults to "softfp" for v6 and v7. - ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; - ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI; - break; - } - case llvm::Triple::WatchOS: - ABI = FloatABI::Hard; - break; - - // FIXME: this is invalid for WindowsCE - case llvm::Triple::Win32: - ABI = FloatABI::Hard; - break; - - case llvm::Triple::FreeBSD: - switch (Triple.getEnvironment()) { - case llvm::Triple::GNUEABIHF: - ABI = FloatABI::Hard; - break; - default: - // FreeBSD defaults to soft float - ABI = FloatABI::Soft; - break; - } - break; - - default: - switch (Triple.getEnvironment()) { - case llvm::Triple::GNUEABIHF: - case llvm::Triple::MuslEABIHF: - case llvm::Triple::EABIHF: - ABI = FloatABI::Hard; - break; - case llvm::Triple::GNUEABI: - case llvm::Triple::MuslEABI: - case llvm::Triple::EABI: - // EABI is always AAPCS, and if it was not marked 'hard', it's softfp - ABI = FloatABI::SoftFP; - break; - case llvm::Triple::Android: - ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; - break; - default: - // Assume "soft", but warn the user we are guessing. - if (Triple.isOSBinFormatMachO() && - Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) - ABI = FloatABI::Hard; - else - ABI = FloatABI::Soft; - - if (Triple.getOS() != llvm::Triple::UnknownOS || - !Triple.isOSBinFormatMachO()) - D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; - break; - } - } - } - - assert(ABI != FloatABI::Invalid && "must select an ABI"); - return ABI; -} - -static void getARMTargetFeatures(const ToolChain &TC, - const llvm::Triple &Triple, - const ArgList &Args, - ArgStringList &CmdArgs, - std::vector &Features, - bool ForAS) { - const Driver &D = TC.getDriver(); - - bool KernelOrKext = - Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); - arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); - const Arg *WaCPU = nullptr, *WaFPU = nullptr; - const Arg *WaHDiv = nullptr, *WaArch = nullptr; - - if (!ForAS) { - // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these - // yet (it uses the -mfloat-abi and -msoft-float options), and it is - // stripped out by the ARM target. We should probably pass this a new - // -target-option, which is handled by the -cc1/-cc1as invocation. - // - // FIXME2: For consistency, it would be ideal if we set up the target - // machine state the same when using the frontend or the assembler. We don't - // currently do that for the assembler, we pass the options directly to the - // backend and never even instantiate the frontend TargetInfo. If we did, - // and used its handleTargetFeatures hook, then we could ensure the - // assembler and the frontend behave the same. - - // Use software floating point operations? - if (ABI == arm::FloatABI::Soft) - Features.push_back("+soft-float"); - - // Use software floating point argument passing? - if (ABI != arm::FloatABI::Hard) - Features.push_back("+soft-float-abi"); - } else { - // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down - // to the assembler correctly. - for (const Arg *A : - Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { - StringRef Value = A->getValue(); - if (Value.startswith("-mfpu=")) { - WaFPU = A; - } else if (Value.startswith("-mcpu=")) { - WaCPU = A; - } else if (Value.startswith("-mhwdiv=")) { - WaHDiv = A; - } else if (Value.startswith("-march=")) { - WaArch = A; - } - } - } - - // Check -march. ClangAs gives preference to -Wa,-march=. - const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); - StringRef ArchName; - if (WaArch) { - if (ArchArg) - D.Diag(clang::diag::warn_drv_unused_argument) - << ArchArg->getAsString(Args); - ArchName = StringRef(WaArch->getValue()).substr(7); - checkARMArchName(D, WaArch, Args, ArchName, Features, Triple); - // FIXME: Set Arch. - D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); - } else if (ArchArg) { - ArchName = ArchArg->getValue(); - checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple); - } - - // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. - const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); - StringRef CPUName; - if (WaCPU) { - if (CPUArg) - D.Diag(clang::diag::warn_drv_unused_argument) - << CPUArg->getAsString(Args); - CPUName = StringRef(WaCPU->getValue()).substr(6); - checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple); - } else if (CPUArg) { - CPUName = CPUArg->getValue(); - checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple); - } - - // Add CPU features for generic CPUs - if (CPUName == "native") { - llvm::StringMap HostFeatures; - if (llvm::sys::getHostCPUFeatures(HostFeatures)) - for (auto &F : HostFeatures) - Features.push_back( - Args.MakeArgString((F.second ? "+" : "-") + F.first())); - } - - // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. - const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); - if (WaFPU) { - if (FPUArg) - D.Diag(clang::diag::warn_drv_unused_argument) - << FPUArg->getAsString(Args); - getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), - Features); - } else if (FPUArg) { - getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); - } - - // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. - const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); - if (WaHDiv) { - if (HDivArg) - D.Diag(clang::diag::warn_drv_unused_argument) - << HDivArg->getAsString(Args); - getARMHWDivFeatures(D, WaHDiv, Args, - StringRef(WaHDiv->getValue()).substr(8), Features); - } else if (HDivArg) - getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); - - // Setting -msoft-float effectively disables NEON because of the GCC - // implementation, although the same isn't true of VFP or VFP3. - if (ABI == arm::FloatABI::Soft) { - Features.push_back("-neon"); - // Also need to explicitly disable features which imply NEON. - Features.push_back("-crypto"); - } - - // En/disable crc code generation. - if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { - if (A->getOption().matches(options::OPT_mcrc)) - Features.push_back("+crc"); - else - Features.push_back("-crc"); - } - - // Look for the last occurrence of -mlong-calls or -mno-long-calls. If - // neither options are specified, see if we are compiling for kernel/kext and - // decide whether to pass "+long-calls" based on the OS and its version. - if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, - options::OPT_mno_long_calls)) { - if (A->getOption().matches(options::OPT_mlong_calls)) - Features.push_back("+long-calls"); - } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) && - !Triple.isWatchOS()) { - Features.push_back("+long-calls"); - } - - // Generate execute-only output (no data access to code sections). - // Supported only on ARMv6T2 and ARMv7 and above. - // Cannot be combined with -mno-movt or -mlong-calls - if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { - if (A->getOption().matches(options::OPT_mexecute_only)) { - if (getARMSubArchVersionNumber(Triple) < 7 && - llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2) - D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); - else if (Arg *B = Args.getLastArg(options::OPT_mno_movt)) - D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); - // Long calls create constant pool entries and have not yet been fixed up - // to play nicely with execute-only. Hence, they cannot be used in - // execute-only code for now - else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { - if (B->getOption().matches(options::OPT_mlong_calls)) - D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); - } - - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-execute-only"); - } - } - - // Kernel code has more strict alignment requirements. - if (KernelOrKext) - Features.push_back("+strict-align"); - else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) { - if (A->getOption().matches(options::OPT_munaligned_access)) { - // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). - if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) - D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; - // v8M Baseline follows on from v6M, so doesn't support unaligned memory - // access either. - else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) - D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; - } else - Features.push_back("+strict-align"); - } else { - // Assume pre-ARMv6 doesn't support unaligned accesses. - // - // ARMv6 may or may not support unaligned accesses depending on the - // SCTLR.U bit, which is architecture-specific. We assume ARMv6 - // Darwin and NetBSD targets support unaligned accesses, and others don't. - // - // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit - // which raises an alignment fault on unaligned accesses. Linux - // defaults this bit to 0 and handles it as a system-wide (not - // per-process) setting. It is therefore safe to assume that ARMv7+ - // Linux targets support unaligned accesses. The same goes for NaCl. - // - // The above behavior is consistent with GCC. - int VersionNum = getARMSubArchVersionNumber(Triple); - if (Triple.isOSDarwin() || Triple.isOSNetBSD()) { - if (VersionNum < 6 || - Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) - Features.push_back("+strict-align"); - } else if (Triple.isOSLinux() || Triple.isOSNaCl()) { - if (VersionNum < 7) - Features.push_back("+strict-align"); - } else - Features.push_back("+strict-align"); - } - - // llvm does not support reserving registers in general. There is support - // for reserving r9 on ARM though (defined as a platform-specific register - // in ARM EABI). - if (Args.hasArg(options::OPT_ffixed_r9)) - Features.push_back("+reserve-r9"); - - // The kext linker doesn't know how to deal with movw/movt. - if (KernelOrKext || Args.hasArg(options::OPT_mno_movt)) - Features.push_back("+no-movt"); -} - void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, ArgStringList &CmdArgs, bool KernelOrKext) const { // Select the ABI to use. @@ -1224,7 +760,7 @@ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); } else if (Triple.isOSBinFormatMachO()) { - if (useAAPCSForMachO(Triple)) { + if (arm::useAAPCSForMachO(Triple)) { ABIName = "aapcs"; } else if (Triple.isWatchABI()) { ABIName = "aapcs16"; @@ -1292,34 +828,6 @@ options::OPT_mno_implicit_float, true)) CmdArgs.push_back("-no-implicit-float"); } -// ARM tools end. - -/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are -/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune -/// arguments if they are provided, or to nullptr otherwise. -static std::string getAArch64TargetCPU(const ArgList &Args, Arg *&A) { - std::string CPU; - // If we have -mtune or -mcpu, use that. - if ((A = Args.getLastArg(options::OPT_mtune_EQ))) { - CPU = StringRef(A->getValue()).lower(); - } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) { - StringRef Mcpu = A->getValue(); - CPU = Mcpu.split("+").first.lower(); - } - - // Handle CPU name is 'native'. - if (CPU == "native") - return llvm::sys::getHostCPUName(); - else if (CPU.size()) - return CPU; - - // Make sure we pick "cyclone" if -arch is used. - // FIXME: Should this be picked by checking the target triple instead? - if (Args.getLastArg(options::OPT_arch)) - return "cyclone"; - - return "generic"; -} void Clang::AddAArch64TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { @@ -1369,158 +877,7 @@ } } -// Get CPU and ABI names. They are not independent -// so we have to calculate them together. -void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, - StringRef &CPUName, StringRef &ABIName) { - const char *DefMips32CPU = "mips32r2"; - const char *DefMips64CPU = "mips64r2"; - - // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the - // default for mips64(el)?-img-linux-gnu. - if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && - Triple.getEnvironment() == llvm::Triple::GNU) { - DefMips32CPU = "mips32r6"; - DefMips64CPU = "mips64r6"; - } - - // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android). - if (Triple.isAndroid()) { - DefMips32CPU = "mips32"; - DefMips64CPU = "mips64r6"; - } - - // MIPS3 is the default for mips64*-unknown-openbsd. - if (Triple.getOS() == llvm::Triple::OpenBSD) - DefMips64CPU = "mips3"; - - if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ)) - CPUName = A->getValue(); - - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { - ABIName = A->getValue(); - // Convert a GNU style Mips ABI name to the name - // accepted by LLVM Mips backend. - ABIName = llvm::StringSwitch(ABIName) - .Case("32", "o32") - .Case("64", "n64") - .Default(ABIName); - } - - // Setup default CPU and ABI names. - if (CPUName.empty() && ABIName.empty()) { - switch (Triple.getArch()) { - default: - llvm_unreachable("Unexpected triple arch name"); - case llvm::Triple::mips: - case llvm::Triple::mipsel: - CPUName = DefMips32CPU; - break; - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - CPUName = DefMips64CPU; - break; - } - } - - if (ABIName.empty() && - (Triple.getVendor() == llvm::Triple::MipsTechnologies || - Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { - ABIName = llvm::StringSwitch(CPUName) - .Case("mips1", "o32") - .Case("mips2", "o32") - .Case("mips3", "n64") - .Case("mips4", "n64") - .Case("mips5", "n64") - .Case("mips32", "o32") - .Case("mips32r2", "o32") - .Case("mips32r3", "o32") - .Case("mips32r5", "o32") - .Case("mips32r6", "o32") - .Case("mips64", "n64") - .Case("mips64r2", "n64") - .Case("mips64r3", "n64") - .Case("mips64r5", "n64") - .Case("mips64r6", "n64") - .Case("octeon", "n64") - .Case("p5600", "o32") - .Default(""); - } - - if (ABIName.empty()) { - // Deduce ABI name from the target triple. - if (Triple.getArch() == llvm::Triple::mips || - Triple.getArch() == llvm::Triple::mipsel) - ABIName = "o32"; - else - ABIName = "n64"; - } - - if (CPUName.empty()) { - // Deduce CPU name from ABI name. - CPUName = llvm::StringSwitch(ABIName) - .Case("o32", DefMips32CPU) - .Cases("n32", "n64", DefMips64CPU) - .Default(""); - } - - // FIXME: Warn on inconsistent use of -march and -mabi. -} - -std::string mips::getMipsABILibSuffix(const ArgList &Args, - const llvm::Triple &Triple) { - StringRef CPUName, ABIName; - tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); - return llvm::StringSwitch(ABIName) - .Case("o32", "") - .Case("n32", "32") - .Case("n64", "64"); -} - -// Convert ABI name to the GNU tools acceptable variant. -static StringRef getGnuCompatibleMipsABIName(StringRef ABI) { - return llvm::StringSwitch(ABI) - .Case("o32", "32") - .Case("n64", "64") - .Default(ABI); -} - -// Select the MIPS float ABI as determined by -msoft-float, -mhard-float, -// and -mfloat-abi=. -static mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args) { - mips::FloatABI ABI = mips::FloatABI::Invalid; - if (Arg *A = - Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, - options::OPT_mfloat_abi_EQ)) { - if (A->getOption().matches(options::OPT_msoft_float)) - ABI = mips::FloatABI::Soft; - else if (A->getOption().matches(options::OPT_mhard_float)) - ABI = mips::FloatABI::Hard; - else { - ABI = llvm::StringSwitch(A->getValue()) - .Case("soft", mips::FloatABI::Soft) - .Case("hard", mips::FloatABI::Hard) - .Default(mips::FloatABI::Invalid); - if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { - D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); - ABI = mips::FloatABI::Hard; - } - } - } - - // If unspecified, choose the default based on the platform. - if (ABI == mips::FloatABI::Invalid) { - // Assume "hard", because it's a default value used by gcc. - // When we start to recognize specific target MIPS processors, - // we will be able to select the default more correctly. - ABI = mips::FloatABI::Hard; - } - - assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); - return ABI; -} - -static void AddTargetFeature(const ArgList &Args, +void tools::AddTargetFeature(const ArgList &Args, std::vector &Features, OptSpecifier OnOpt, OptSpecifier OffOpt, StringRef FeatureName) { @@ -1532,129 +889,6 @@ } } -static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args, - std::vector &Features) { - StringRef CPUName; - StringRef ABIName; - mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); - ABIName = getGnuCompatibleMipsABIName(ABIName); - - // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a - // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI - // extension was developed by Richard Sandiford & Code Sourcery to support - // static code calling PIC code (CPIC). For O32 and N32 this means we have - // several combinations of PIC/static and abicalls. Pure static, static - // with the CPIC extension, and pure PIC code. - - // At final link time, O32 and N32 with CPIC will have another section - // added to the binary which contains the stub functions to perform - // any fixups required for PIC code. - - // For N64, the situation is more regular: code can either be static - // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code - // code for N64. Since Clang has already built the relocation model portion - // of the commandline, we pick add +noabicalls feature in the N64 static - // case. - - // The is another case to be accounted for: -msym32, which enforces that all - // symbols have 32 bits in size. In this case, N64 can in theory use CPIC - // but it is unsupported. - - // The combinations for N64 are: - // a) Static without abicalls and 64bit symbols. - // b) Static with abicalls and 32bit symbols. - // c) PIC with abicalls and 64bit symbols. - - // For case (a) we need to add +noabicalls for N64. - - bool IsN64 = ABIName == "64"; - bool NonPIC = false; - - Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, - options::OPT_fpic, options::OPT_fno_pic, - options::OPT_fPIE, options::OPT_fno_PIE, - options::OPT_fpie, options::OPT_fno_pie); - if (LastPICArg) { - Option O = LastPICArg->getOption(); - NonPIC = - (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) || - O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie)); - } - - if (IsN64 && NonPIC) { - Features.push_back("+noabicalls"); - } else { - AddTargetFeature(Args, Features, options::OPT_mno_abicalls, - options::OPT_mabicalls, "noabicalls"); - } - - mips::FloatABI FloatABI = getMipsFloatABI(D, Args); - if (FloatABI == mips::FloatABI::Soft) { - // FIXME: Note, this is a hack. We need to pass the selected float - // mode to the MipsTargetInfoBase to define appropriate macros there. - // Now it is the only method. - Features.push_back("+soft-float"); - } - - if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { - StringRef Val = StringRef(A->getValue()); - if (Val == "2008") { - if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008) - Features.push_back("+nan2008"); - else { - Features.push_back("-nan2008"); - D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; - } - } else if (Val == "legacy") { - if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy) - Features.push_back("-nan2008"); - else { - Features.push_back("+nan2008"); - D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; - } - } else - D.Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << Val; - } - - AddTargetFeature(Args, Features, options::OPT_msingle_float, - options::OPT_mdouble_float, "single-float"); - AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, - "mips16"); - AddTargetFeature(Args, Features, options::OPT_mmicromips, - options::OPT_mno_micromips, "micromips"); - AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, - "dsp"); - AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, - "dspr2"); - AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, - "msa"); - - // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 - // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and - // nooddspreg. - if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, - options::OPT_mfp64)) { - if (A->getOption().matches(options::OPT_mfp32)) - Features.push_back(Args.MakeArgString("-fp64")); - else if (A->getOption().matches(options::OPT_mfpxx)) { - Features.push_back(Args.MakeArgString("+fpxx")); - Features.push_back(Args.MakeArgString("+nooddspreg")); - } else - Features.push_back(Args.MakeArgString("+fp64")); - } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { - Features.push_back(Args.MakeArgString("+fpxx")); - Features.push_back(Args.MakeArgString("+nooddspreg")); - } else if (mips::isFP64ADefault(Triple, CPUName)) { - Features.push_back(Args.MakeArgString("+fp64")); - Features.push_back(Args.MakeArgString("+nooddspreg")); - } - - AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, - options::OPT_modd_spreg, "nooddspreg"); -} - void Clang::AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); @@ -1666,7 +900,7 @@ CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); - mips::FloatABI ABI = getMipsFloatABI(D, Args); + mips::FloatABI ABI = mips::getMipsFloatABI(D, Args); if (ABI == mips::FloatABI::Soft) { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); @@ -1723,115 +957,6 @@ } } -/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting. -static std::string getPPCTargetCPU(const ArgList &Args) { - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef CPUName = A->getValue(); - - if (CPUName == "native") { - std::string CPU = llvm::sys::getHostCPUName(); - if (!CPU.empty() && CPU != "generic") - return CPU; - else - return ""; - } - - return llvm::StringSwitch(CPUName) - .Case("common", "generic") - .Case("440", "440") - .Case("440fp", "440") - .Case("450", "450") - .Case("601", "601") - .Case("602", "602") - .Case("603", "603") - .Case("603e", "603e") - .Case("603ev", "603ev") - .Case("604", "604") - .Case("604e", "604e") - .Case("620", "620") - .Case("630", "pwr3") - .Case("G3", "g3") - .Case("7400", "7400") - .Case("G4", "g4") - .Case("7450", "7450") - .Case("G4+", "g4+") - .Case("750", "750") - .Case("970", "970") - .Case("G5", "g5") - .Case("a2", "a2") - .Case("a2q", "a2q") - .Case("e500mc", "e500mc") - .Case("e5500", "e5500") - .Case("power3", "pwr3") - .Case("power4", "pwr4") - .Case("power5", "pwr5") - .Case("power5x", "pwr5x") - .Case("power6", "pwr6") - .Case("power6x", "pwr6x") - .Case("power7", "pwr7") - .Case("power8", "pwr8") - .Case("power9", "pwr9") - .Case("pwr3", "pwr3") - .Case("pwr4", "pwr4") - .Case("pwr5", "pwr5") - .Case("pwr5x", "pwr5x") - .Case("pwr6", "pwr6") - .Case("pwr6x", "pwr6x") - .Case("pwr7", "pwr7") - .Case("pwr8", "pwr8") - .Case("pwr9", "pwr9") - .Case("powerpc", "ppc") - .Case("powerpc64", "ppc64") - .Case("powerpc64le", "ppc64le") - .Default(""); - } - - return ""; -} - -static void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args, - std::vector &Features) { - handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group); - - ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); - if (FloatABI == ppc::FloatABI::Soft) - Features.push_back("-hard-float"); - - // Altivec is a bit weird, allow overriding of the Altivec feature here. - AddTargetFeature(Args, Features, options::OPT_faltivec, - options::OPT_fno_altivec, "altivec"); -} - -ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) { - ppc::FloatABI ABI = ppc::FloatABI::Invalid; - if (Arg *A = - Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, - options::OPT_mfloat_abi_EQ)) { - if (A->getOption().matches(options::OPT_msoft_float)) - ABI = ppc::FloatABI::Soft; - else if (A->getOption().matches(options::OPT_mhard_float)) - ABI = ppc::FloatABI::Hard; - else { - ABI = llvm::StringSwitch(A->getValue()) - .Case("soft", ppc::FloatABI::Soft) - .Case("hard", ppc::FloatABI::Hard) - .Default(ppc::FloatABI::Invalid); - if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { - D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); - ABI = ppc::FloatABI::Hard; - } - } - } - - // If unspecified, choose the default based on the platform. - if (ABI == ppc::FloatABI::Invalid) { - ABI = ppc::FloatABI::Hard; - } - - return ABI; -} - void Clang::AddPPCTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { // Select the ABI to use. @@ -1889,11 +1014,6 @@ } } -bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) { - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - return A && (A->getValue() == StringRef(Value)); -} - /// Get the (LLVM) name of the R600 gpu we are targeting. static std::string getR600TargetGPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { @@ -1918,48 +1038,6 @@ return ""; } -sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, - const ArgList &Args) { - sparc::FloatABI ABI = sparc::FloatABI::Invalid; - if (Arg *A = - Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, - options::OPT_mfloat_abi_EQ)) { - if (A->getOption().matches(options::OPT_msoft_float)) - ABI = sparc::FloatABI::Soft; - else if (A->getOption().matches(options::OPT_mhard_float)) - ABI = sparc::FloatABI::Hard; - else { - ABI = llvm::StringSwitch(A->getValue()) - .Case("soft", sparc::FloatABI::Soft) - .Case("hard", sparc::FloatABI::Hard) - .Default(sparc::FloatABI::Invalid); - if (ABI == sparc::FloatABI::Invalid && - !StringRef(A->getValue()).empty()) { - D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); - ABI = sparc::FloatABI::Hard; - } - } - } - - // If unspecified, choose the default based on the platform. - // Only the hard-float ABI on Sparc is standardized, and it is the - // default. GCC also supports a nonstandard soft-float ABI mode, also - // implemented in LLVM. However as this is not standard we set the default - // to be hard-float. - if (ABI == sparc::FloatABI::Invalid) { - ABI = sparc::FloatABI::Hard; - } - - return ABI; -} - -static void getSparcTargetFeatures(const Driver &D, const ArgList &Args, - std::vector &Features) { - sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); - if (FloatABI == sparc::FloatABI::Soft) - Features.push_back("+soft-float"); -} - void Clang::AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { sparc::FloatABI FloatABI = @@ -1984,119 +1062,6 @@ CmdArgs.push_back("-mbackchain"); } -static const char *getSystemZTargetCPU(const ArgList &Args) { - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) - return A->getValue(); - return "z10"; -} - -static void getSystemZTargetFeatures(const ArgList &Args, - std::vector &Features) { - // -m(no-)htm overrides use of the transactional-execution facility. - if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) { - if (A->getOption().matches(options::OPT_mhtm)) - Features.push_back("+transactional-execution"); - else - Features.push_back("-transactional-execution"); - } - // -m(no-)vx overrides use of the vector facility. - if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) { - if (A->getOption().matches(options::OPT_mvx)) - Features.push_back("+vector"); - else - Features.push_back("-vector"); - } -} - -static const char *getX86TargetCPU(const ArgList &Args, - const llvm::Triple &Triple) { - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (StringRef(A->getValue()) != "native") { - if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h") - return "core-avx2"; - - return A->getValue(); - } - - // FIXME: Reject attempts to use -march=native unless the target matches - // the host. - // - // FIXME: We should also incorporate the detected target features for use - // with -native. - std::string CPU = llvm::sys::getHostCPUName(); - if (!CPU.empty() && CPU != "generic") - return Args.MakeArgString(CPU); - } - - if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { - // Mapping built by referring to X86TargetInfo::getDefaultFeatures(). - StringRef Arch = A->getValue(); - const char *CPU; - if (Triple.getArch() == llvm::Triple::x86) { - CPU = llvm::StringSwitch(Arch) - .Case("IA32", "i386") - .Case("SSE", "pentium3") - .Case("SSE2", "pentium4") - .Case("AVX", "sandybridge") - .Case("AVX2", "haswell") - .Default(nullptr); - } else { - CPU = llvm::StringSwitch(Arch) - .Case("AVX", "sandybridge") - .Case("AVX2", "haswell") - .Default(nullptr); - } - if (CPU) - return CPU; - } - - // Select the default CPU if none was given (or detection failed). - - if (Triple.getArch() != llvm::Triple::x86_64 && - Triple.getArch() != llvm::Triple::x86) - return nullptr; // This routine is only handling x86 targets. - - bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; - - // FIXME: Need target hooks. - if (Triple.isOSDarwin()) { - if (Triple.getArchName() == "x86_64h") - return "core-avx2"; - // macosx10.12 drops support for all pre-Penryn Macs. - // Simulators can still run on 10.11 though, like Xcode. - if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12)) - return "penryn"; - // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah. - return Is64Bit ? "core2" : "yonah"; - } - - // Set up default CPU name for PS4 compilers. - if (Triple.isPS4CPU()) - return "btver2"; - - // On Android use targets compatible with gcc - if (Triple.isAndroid()) - return Is64Bit ? "x86-64" : "i686"; - - // Everything else goes to x86-64 in 64-bit mode. - if (Is64Bit) - return "x86-64"; - - switch (Triple.getOS()) { - case llvm::Triple::FreeBSD: - case llvm::Triple::NetBSD: - case llvm::Triple::OpenBSD: - return "i486"; - case llvm::Triple::Haiku: - return "i586"; - case llvm::Triple::Bitrig: - return "i686"; - default: - // Fallback to p4. - return "pentium4"; - } -} - /// Get the (LLVM) name of the WebAssembly cpu we are targeting. static StringRef getWebAssemblyTargetCPU(const ArgList &Args) { // If we have -mcpu=, use that. @@ -2116,8 +1081,8 @@ return "generic"; } -static std::string getCPUName(const ArgList &Args, const llvm::Triple &T, - bool FromAs = false) { +std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, + bool FromAs) { Arg *A; switch (T.getArch()) { @@ -2126,14 +1091,14 @@ case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - return getAArch64TargetCPU(Args, A); + return aarch64::getAArch64TargetCPU(Args, A); case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: { StringRef MArch, MCPU; - getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs); + arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs); return arm::getARMTargetCPU(MCPU, MArch, T); } case llvm::Triple::mips: @@ -2155,7 +1120,7 @@ case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: { - std::string TargetCPUName = getPPCTargetCPU(Args); + std::string TargetCPUName = ppc::getPPCTargetCPU(Args); // LLVM may default to generating code for the native CPU, // but, like gcc, we default to a more generic option for // each architecture. (except on Darwin) @@ -2179,7 +1144,7 @@ case llvm::Triple::x86: case llvm::Triple::x86_64: - return getX86TargetCPU(Args, T); + return x86::getX86TargetCPU(Args, T); case llvm::Triple::hexagon: return "hexagon" + @@ -2189,7 +1154,7 @@ return getLanaiTargetCPU(Args); case llvm::Triple::systemz: - return getSystemZTargetCPU(Args); + return systemz::getSystemZTargetCPU(Args); case llvm::Triple::r600: case llvm::Triple::amdgcn: @@ -2423,70 +1388,6 @@ OutStrings.push_back(Args.MakeArgString(Out)); } -static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args, - std::vector &Features) { - // If -march=native, autodetect the feature list. - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (StringRef(A->getValue()) == "native") { - llvm::StringMap HostFeatures; - if (llvm::sys::getHostCPUFeatures(HostFeatures)) - for (auto &F : HostFeatures) - Features.push_back( - Args.MakeArgString((F.second ? "+" : "-") + F.first())); - } - } - - if (Triple.getArchName() == "x86_64h") { - // x86_64h implies quite a few of the more modern subtarget features - // for Haswell class CPUs, but not all of them. Opt-out of a few. - Features.push_back("-rdrnd"); - Features.push_back("-aes"); - Features.push_back("-pclmul"); - Features.push_back("-rtm"); - Features.push_back("-hle"); - Features.push_back("-fsgsbase"); - } - - const llvm::Triple::ArchType ArchType = Triple.getArch(); - // Add features to be compatible with gcc for Android. - if (Triple.isAndroid()) { - if (ArchType == llvm::Triple::x86_64) { - Features.push_back("+sse4.2"); - Features.push_back("+popcnt"); - } else - Features.push_back("+ssse3"); - } - - // Set features according to the -arch flag on MSVC. - if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { - StringRef Arch = A->getValue(); - bool ArchUsed = false; - // First, look for flags that are shared in x86 and x86-64. - if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) { - if (Arch == "AVX" || Arch == "AVX2") { - ArchUsed = true; - Features.push_back(Args.MakeArgString("+" + Arch.lower())); - } - } - // Then, look for x86-specific flags. - if (ArchType == llvm::Triple::x86) { - if (Arch == "IA32") { - ArchUsed = true; - } else if (Arch == "SSE" || Arch == "SSE2") { - ArchUsed = true; - Features.push_back(Args.MakeArgString("+" + Arch.lower())); - } - } - if (!ArchUsed) - D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args); - } - - // Now add any that the user explicitly requested on the command line, - // which may override the defaults. - handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group); -} - void Clang::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || @@ -2582,155 +1483,6 @@ } } -// Decode AArch64 features from string like +[no]featureA+[no]featureB+... -static bool DecodeAArch64Features(const Driver &D, StringRef text, - std::vector &Features) { - SmallVector Split; - text.split(Split, StringRef("+"), -1, false); - - for (StringRef Feature : Split) { - StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature); - if (!FeatureName.empty()) - Features.push_back(FeatureName); - else if (Feature == "neon" || Feature == "noneon") - D.Diag(diag::err_drv_no_neon_modifier); - else - return false; - } - return true; -} - -// Check if the CPU name and feature modifiers in -mcpu are legal. If yes, -// decode CPU and feature. -static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, - std::vector &Features) { - std::pair Split = Mcpu.split("+"); - CPU = Split.first; - - if (CPU == "generic") { - Features.push_back("+neon"); - } else { - unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU); - if (!llvm::AArch64::getArchFeatures(ArchKind, Features)) - return false; - - unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind); - if (!llvm::AArch64::getExtensionFeatures(Extension, Features)) - return false; - } - - if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) - return false; - - return true; -} - -static bool -getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, - const ArgList &Args, - std::vector &Features) { - std::string MarchLowerCase = March.lower(); - std::pair Split = StringRef(MarchLowerCase).split("+"); - - unsigned ArchKind = llvm::AArch64::parseArch(Split.first); - if (ArchKind == static_cast(llvm::AArch64::ArchKind::AK_INVALID) || - !llvm::AArch64::getArchFeatures(ArchKind, Features) || - (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))) - return false; - - return true; -} - -static bool -getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, - const ArgList &Args, - std::vector &Features) { - StringRef CPU; - std::string McpuLowerCase = Mcpu.lower(); - if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features)) - return false; - - return true; -} - -static bool -getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune, - const ArgList &Args, - std::vector &Features) { - std::string MtuneLowerCase = Mtune.lower(); - // Handle CPU name is 'native'. - if (MtuneLowerCase == "native") - MtuneLowerCase = llvm::sys::getHostCPUName(); - if (MtuneLowerCase == "cyclone") { - Features.push_back("+zcm"); - Features.push_back("+zcz"); - } - return true; -} - -static bool -getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, - const ArgList &Args, - std::vector &Features) { - StringRef CPU; - std::vector DecodedFeature; - std::string McpuLowerCase = Mcpu.lower(); - if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature)) - return false; - - return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features); -} - -static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args, - std::vector &Features) { - Arg *A; - bool success = true; - // Enable NEON by default. - Features.push_back("+neon"); - if ((A = Args.getLastArg(options::OPT_march_EQ))) - success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); - else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) - success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); - else if (Args.hasArg(options::OPT_arch)) - success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A), - Args, Features); - - if (success && (A = Args.getLastArg(options::OPT_mtune_EQ))) - success = - getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features); - else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) - success = - getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); - else if (success && Args.hasArg(options::OPT_arch)) - success = getAArch64MicroArchFeaturesFromMcpu( - D, getAArch64TargetCPU(Args, A), Args, Features); - - if (!success) - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); - - if (Args.getLastArg(options::OPT_mgeneral_regs_only)) { - Features.push_back("-fp-armv8"); - Features.push_back("-crypto"); - Features.push_back("-neon"); - } - - // En/disable crc - if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { - if (A->getOption().matches(options::OPT_mcrc)) - Features.push_back("+crc"); - else - Features.push_back("-crc"); - } - - if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) - if (A->getOption().matches(options::OPT_mno_unaligned_access)) - Features.push_back("+strict-align"); - - if (Args.hasArg(options::OPT_ffixed_x18)) - Features.push_back("+reserve-x18"); -} - static void getHexagonTargetFeatures(const ArgList &Args, std::vector &Features) { handleTargetFeaturesGroup(Args, Features, @@ -2780,31 +1532,31 @@ case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: - getMIPSTargetFeatures(D, Triple, Args, Features); + mips::getMIPSTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: - getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); + arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); break; case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: - getPPCTargetFeatures(D, Triple, Args, Features); + ppc::getPPCTargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::systemz: - getSystemZTargetFeatures(Args, Features); + systemz::getSystemZTargetFeatures(Args, Features); break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - getAArch64TargetFeatures(D, Args, Features); + aarch64::getAArch64TargetFeatures(D, Args, Features); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - getX86TargetFeatures(D, Triple, Args, Features); + x86::getX86TargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::hexagon: getHexagonTargetFeatures(Args, Features); @@ -2816,7 +1568,7 @@ case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: - getSparcTargetFeatures(D, Args, Features); + sparc::getSparcTargetFeatures(D, Args, Features); break; case llvm::Triple::r600: case llvm::Triple::amdgcn: @@ -7982,112 +6734,10 @@ // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker // to generate BE-8 executables. - if (getARMSubArchVersionNumber(Triple) >= 7 || isARMMProfile(Triple)) + if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple)) CmdArgs.push_back("--be8"); } -mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) { - // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008 - // was first introduced in Release 3. However, other compilers have - // traditionally allowed it for Release 2 so we should do the same. - return (NanEncoding)llvm::StringSwitch(CPU) - .Case("mips1", NanLegacy) - .Case("mips2", NanLegacy) - .Case("mips3", NanLegacy) - .Case("mips4", NanLegacy) - .Case("mips5", NanLegacy) - .Case("mips32", NanLegacy) - .Case("mips32r2", NanLegacy | Nan2008) - .Case("mips32r3", NanLegacy | Nan2008) - .Case("mips32r5", NanLegacy | Nan2008) - .Case("mips32r6", Nan2008) - .Case("mips64", NanLegacy) - .Case("mips64r2", NanLegacy | Nan2008) - .Case("mips64r3", NanLegacy | Nan2008) - .Case("mips64r5", NanLegacy | Nan2008) - .Case("mips64r6", Nan2008) - .Default(NanLegacy); -} - -bool mips::hasCompactBranches(StringRef &CPU) { - // mips32r6 and mips64r6 have compact branches. - return llvm::StringSwitch(CPU) - .Case("mips32r6", true) - .Case("mips64r6", true) - .Default(false); -} - -bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - return A && (A->getValue() == StringRef(Value)); -} - -bool mips::isUCLibc(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_m_libc_Group); - return A && A->getOption().matches(options::OPT_muclibc); -} - -bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) { - if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) - return llvm::StringSwitch(NaNArg->getValue()) - .Case("2008", true) - .Case("legacy", false) - .Default(false); - - // NaN2008 is the default for MIPS32r6/MIPS64r6. - return llvm::StringSwitch(getCPUName(Args, Triple)) - .Cases("mips32r6", "mips64r6", true) - .Default(false); - - return false; -} - -bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { - if (!Triple.isAndroid()) - return false; - - // Android MIPS32R6 defaults to FP64A. - return llvm::StringSwitch(CPUName) - .Case("mips32r6", true) - .Default(false); -} - -bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, - StringRef ABIName, mips::FloatABI FloatABI) { - if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies && - Triple.getVendor() != llvm::Triple::MipsTechnologies && - !Triple.isAndroid()) - return false; - - if (ABIName != "32") - return false; - - // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is - // present. - if (FloatABI == mips::FloatABI::Soft) - return false; - - return llvm::StringSwitch(CPUName) - .Cases("mips2", "mips3", "mips4", "mips5", true) - .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) - .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) - .Default(false); -} - -bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, - StringRef CPUName, StringRef ABIName, - mips::FloatABI FloatABI) { - bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); - - // FPXX shouldn't be used if -msingle-float is present. - if (Arg *A = Args.getLastArg(options::OPT_msingle_float, - options::OPT_mdouble_float)) - if (A->getOption().matches(options::OPT_msingle_float)) - UseFPXX = false; - - return UseFPXX; -} - llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for // archs which Darwin doesn't use. @@ -8924,7 +7574,7 @@ case llvm::Triple::sparcel: { CmdArgs.push_back("-32"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -8932,7 +7582,7 @@ case llvm::Triple::sparcv9: { CmdArgs.push_back("-64"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -8944,7 +7594,7 @@ mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-mabi"); - CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); + CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); @@ -9257,7 +7907,7 @@ CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); - CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); + CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) @@ -9301,7 +7951,7 @@ case llvm::Triple::sparcel: case llvm::Triple::sparcv9: { std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -9528,7 +8178,7 @@ case llvm::Triple::thumb: case llvm::Triple::thumbeb: { StringRef MArch, MCPU; - getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true); + arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true); std::string Arch = arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple()); CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch)); @@ -9547,7 +8197,7 @@ CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); - CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data()); + CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) @@ -9563,7 +8213,7 @@ case llvm::Triple::sparcel: { CmdArgs.push_back("-32"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -9571,7 +8221,7 @@ case llvm::Triple::sparcv9: { CmdArgs.push_back("-64"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -9851,14 +8501,14 @@ case llvm::Triple::sparcel: { CmdArgs.push_back("-32"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::sparcv9: { CmdArgs.push_back("-64"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); - CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); + CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } @@ -9912,7 +8562,7 @@ StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); - ABIName = getGnuCompatibleMipsABIName(ABIName); + ABIName = mips::getGnuCompatibleMipsABIName(ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); @@ -9948,7 +8598,7 @@ A->render(Args, CmdArgs); } else if (mips::shouldUseFPXX( Args, getToolChain().getTriple(), CPUName, ABIName, - getMipsFloatABI(getToolChain().getDriver(), Args))) + mips::getMipsFloatABI(getToolChain().getDriver(), Args))) CmdArgs.push_back("-mfpxx"); // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of @@ -9991,7 +8641,7 @@ case llvm::Triple::systemz: { // Always pass an -march option, since our default of z10 is later // than the GNU assembler's default. - StringRef CPUName = getSystemZTargetCPU(Args); + StringRef CPUName = systemz::getSystemZTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); break; } Index: lib/Driver/X86Arch.cpp =================================================================== --- /dev/null +++ lib/Driver/X86Arch.cpp @@ -0,0 +1,207 @@ +//===--- X86Arch.cpp - X86 Helpers for Tools --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Tools.h" +#include "InputInfo.h" +#include "ToolChains.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Job.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "clang/Driver/ToolChain.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" + +#ifdef LLVM_ON_UNIX +#include // For getuid(). +#endif + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +const char *x86::getX86TargetCPU(const ArgList &Args, + const llvm::Triple &Triple) { + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + if (StringRef(A->getValue()) != "native") { + if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h") + return "core-avx2"; + + return A->getValue(); + } + + // FIXME: Reject attempts to use -march=native unless the target matches + // the host. + // + // FIXME: We should also incorporate the detected target features for use + // with -native. + std::string CPU = llvm::sys::getHostCPUName(); + if (!CPU.empty() && CPU != "generic") + return Args.MakeArgString(CPU); + } + + if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { + // Mapping built by referring to X86TargetInfo::getDefaultFeatures(). + StringRef Arch = A->getValue(); + const char *CPU; + if (Triple.getArch() == llvm::Triple::x86) { + CPU = llvm::StringSwitch(Arch) + .Case("IA32", "i386") + .Case("SSE", "pentium3") + .Case("SSE2", "pentium4") + .Case("AVX", "sandybridge") + .Case("AVX2", "haswell") + .Default(nullptr); + } else { + CPU = llvm::StringSwitch(Arch) + .Case("AVX", "sandybridge") + .Case("AVX2", "haswell") + .Default(nullptr); + } + if (CPU) + return CPU; + } + + // Select the default CPU if none was given (or detection failed). + + if (Triple.getArch() != llvm::Triple::x86_64 && + Triple.getArch() != llvm::Triple::x86) + return nullptr; // This routine is only handling x86 targets. + + bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; + + // FIXME: Need target hooks. + if (Triple.isOSDarwin()) { + if (Triple.getArchName() == "x86_64h") + return "core-avx2"; + // macosx10.12 drops support for all pre-Penryn Macs. + // Simulators can still run on 10.11 though, like Xcode. + if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12)) + return "penryn"; + // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah. + return Is64Bit ? "core2" : "yonah"; + } + + // Set up default CPU name for PS4 compilers. + if (Triple.isPS4CPU()) + return "btver2"; + + // On Android use targets compatible with gcc + if (Triple.isAndroid()) + return Is64Bit ? "x86-64" : "i686"; + + // Everything else goes to x86-64 in 64-bit mode. + if (Is64Bit) + return "x86-64"; + + switch (Triple.getOS()) { + case llvm::Triple::FreeBSD: + case llvm::Triple::NetBSD: + case llvm::Triple::OpenBSD: + return "i486"; + case llvm::Triple::Haiku: + return "i586"; + case llvm::Triple::Bitrig: + return "i686"; + default: + // Fallback to p4. + return "pentium4"; + } +} + +void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector &Features) { + // If -march=native, autodetect the feature list. + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + if (StringRef(A->getValue()) == "native") { + llvm::StringMap HostFeatures; + if (llvm::sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.push_back( + Args.MakeArgString((F.second ? "+" : "-") + F.first())); + } + } + + if (Triple.getArchName() == "x86_64h") { + // x86_64h implies quite a few of the more modern subtarget features + // for Haswell class CPUs, but not all of them. Opt-out of a few. + Features.push_back("-rdrnd"); + Features.push_back("-aes"); + Features.push_back("-pclmul"); + Features.push_back("-rtm"); + Features.push_back("-hle"); + Features.push_back("-fsgsbase"); + } + + const llvm::Triple::ArchType ArchType = Triple.getArch(); + // Add features to be compatible with gcc for Android. + if (Triple.isAndroid()) { + if (ArchType == llvm::Triple::x86_64) { + Features.push_back("+sse4.2"); + Features.push_back("+popcnt"); + } else + Features.push_back("+ssse3"); + } + + // Set features according to the -arch flag on MSVC. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { + StringRef Arch = A->getValue(); + bool ArchUsed = false; + // First, look for flags that are shared in x86 and x86-64. + if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) { + if (Arch == "AVX" || Arch == "AVX2") { + ArchUsed = true; + Features.push_back(Args.MakeArgString("+" + Arch.lower())); + } + } + // Then, look for x86-specific flags. + if (ArchType == llvm::Triple::x86) { + if (Arch == "IA32") { + ArchUsed = true; + } else if (Arch == "SSE" || Arch == "SSE2") { + ArchUsed = true; + Features.push_back(Args.MakeArgString("+" + Arch.lower())); + } + } + if (!ArchUsed) + D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args); + } + + // Now add any that the user explicitly requested on the command line, + // which may override the defaults. + handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group); +}