--- /dev/null
+//===--- ARM.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 "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/TargetParser.h"
+
+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(clang::driver::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<StringRef> &Features) {
+ unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
+ if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
+ D.Diag(clang::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<StringRef> &Features) {
+ unsigned FPUID = llvm::ARM::parseFPU(FPU);
+ if (!llvm::ARM::getFPUFeatures(FPUID, Features))
+ D.Diag(clang::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<StringRef> &Features) {
+ SmallVector<StringRef, 8> 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<StringRef> &Features,
+ const llvm::Triple &Triple) {
+ std::pair<StringRef, StringRef> 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(clang::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<StringRef> &Features,
+ const llvm::Triple &Triple) {
+ std::pair<StringRef, StringRef> 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(clang::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<arm::FloatABI>(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<StringRef> &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<bool> 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");
+}
--- /dev/null
+//===--- Mips.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 "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+
+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(clang::driver::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<llvm::StringRef>(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<const char *>(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<const char *>(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<std::string>(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<llvm::StringRef>(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<mips::FloatABI>(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(clang::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<StringRef> &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<int>(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<bool>(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<bool>(NaNArg->getValue())
+ .Case("2008", true)
+ .Case("legacy", false)
+ .Default(false);
+
+ // NaN2008 is the default for MIPS32r6/MIPS64r6.
+ return llvm::StringSwitch<bool>(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<bool>(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<bool>(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;
+}
using namespace clang;
using namespace llvm::opt;
-static void handleTargetFeaturesGroup(const ArgList &Args,
+void tools::handleTargetFeaturesGroup(const ArgList &Args,
std::vector<StringRef> &Features,
OptSpecifier Group) {
for (const Arg *A : Args.filtered(Group)) {
}
}
-static const char *getSparcAsmModeForCPU(StringRef Name,
- const llvm::Triple &Triple) {
- if (Triple.getArch() == llvm::Triple::sparcv9) {
- return llvm::StringSwitch<const char *>(Name)
- .Case("niagara", "-Av9b")
- .Case("niagara2", "-Av9b")
- .Case("niagara3", "-Av9d")
- .Case("niagara4", "-Av9d")
- .Default("-Av9");
- } else {
- return llvm::StringSwitch<const char *>(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) &&
}
}
-// 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<StringRef> &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<StringRef> &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<StringRef> &Features) {
- SmallVector<StringRef, 8> 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<StringRef> &Features,
- const llvm::Triple &Triple) {
- std::pair<StringRef, StringRef> 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<StringRef> &Features,
- const llvm::Triple &Triple) {
- std::pair<StringRef, StringRef> 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<arm::FloatABI>(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<StringRef> &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<bool> 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.
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";
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 {
}
}
-// 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<llvm::StringRef>(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<const char *>(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<const char *>(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<std::string>(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<llvm::StringRef>(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<mips::FloatABI>(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<StringRef> &Features,
OptSpecifier OnOpt, OptSpecifier OffOpt,
StringRef FeatureName) {
}
}
-static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args,
- std::vector<StringRef> &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();
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");
}
}
-/// 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<const char *>(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<StringRef> &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<ppc::FloatABI>(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.
}
}
-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)) {
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<sparc::FloatABI>(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<StringRef> &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 =
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<StringRef> &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<const char *>(Arch)
- .Case("IA32", "i386")
- .Case("SSE", "pentium3")
- .Case("SSE2", "pentium4")
- .Case("AVX", "sandybridge")
- .Case("AVX2", "haswell")
- .Default(nullptr);
- } else {
- CPU = llvm::StringSwitch<const char *>(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.
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()) {
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:
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)
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- return getX86TargetCPU(Args, T);
+ return x86::getX86TargetCPU(Args, T);
case llvm::Triple::hexagon:
return "hexagon" +
return getLanaiTargetCPU(Args);
case llvm::Triple::systemz:
- return getSystemZTargetCPU(Args);
+ return systemz::getSystemZTargetCPU(Args);
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
OutStrings.push_back(Args.MakeArgString(Out));
}
-static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args,
- std::vector<StringRef> &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<bool> 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) ||
}
}
-// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
-static bool DecodeAArch64Features(const Driver &D, StringRef text,
- std::vector<StringRef> &Features) {
- SmallVector<StringRef, 8> 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<StringRef> &Features) {
- std::pair<StringRef, StringRef> 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<StringRef> &Features) {
- std::string MarchLowerCase = March.lower();
- std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
-
- unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
- if (ArchKind == static_cast<unsigned>(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<StringRef> &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<StringRef> &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<StringRef> &Features) {
- StringRef CPU;
- std::vector<StringRef> 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<StringRef> &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<StringRef> &Features) {
handleTargetFeaturesGroup(Args, Features,
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);
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:
// 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<int>(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<bool>(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<bool>(NaNArg->getValue())
- .Case("2008", true)
- .Case("legacy", false)
- .Default(false);
-
- // NaN2008 is the default for MIPS32r6/MIPS64r6.
- return llvm::StringSwitch<bool>(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<bool>(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<bool>(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.
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;
}
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");
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)
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;
}
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));
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)
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;
}
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;
}
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());
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
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;
}