aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/ToolChains/Arch/ARM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/ToolChains/Arch/ARM.cpp')
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.cpp261
1 files changed, 153 insertions, 108 deletions
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index afe896b4a65b..ef590db1eecd 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -32,6 +32,12 @@ bool arm::isARMMProfile(const llvm::Triple &Triple) {
return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;
}
+// True if A-profile.
+bool arm::isARMAProfile(const llvm::Triple &Triple) {
+ llvm::StringRef Arch = Triple.getArchName();
+ return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A;
+}
+
// Get Arch/CPU from args.
void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
llvm::StringRef &CPU, bool FromAs) {
@@ -73,14 +79,15 @@ static unsigned getARMFPUFeatures(const Driver &D, const Arg *A,
}
// Decode ARM features from string like +[no]featureA+[no]featureB+...
-static bool DecodeARMFeatures(const Driver &D, StringRef text,
- StringRef CPU, llvm::ARM::ArchKind ArchKind,
- std::vector<StringRef> &Features) {
+static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,
+ llvm::ARM::ArchKind ArchKind,
+ std::vector<StringRef> &Features,
+ unsigned &ArgFPUID) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
for (StringRef Feature : Split) {
- if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features))
+ if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUID))
return false;
}
return true;
@@ -102,14 +109,14 @@ static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef ArchName, llvm::StringRef CPUName,
std::vector<StringRef> &Features,
- const llvm::Triple &Triple) {
+ const llvm::Triple &Triple, unsigned &ArgFPUID) {
std::pair<StringRef, StringRef> Split = ArchName.split("+");
std::string MArch = arm::getARMArch(ArchName, Triple);
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
- (Split.second.size() && !DecodeARMFeatures(
- D, Split.second, CPUName, ArchKind, Features)))
+ (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName,
+ ArchKind, Features, ArgFPUID)))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -117,15 +124,15 @@ static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
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) {
+ const llvm::Triple &Triple, unsigned &ArgFPUID) {
std::pair<StringRef, StringRef> Split = CPUName.split("+");
std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
llvm::ARM::ArchKind ArchKind =
arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
- (Split.second.size() && !DecodeARMFeatures(
- D, Split.second, CPU, ArchKind, Features)))
+ (Split.second.size() &&
+ !DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID)))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -133,6 +140,7 @@ 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.getEnvironment() == llvm::Triple::EABIHF ||
T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
}
@@ -159,11 +167,73 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);
}
+arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
+ auto SubArch = getARMSubArchVersionNumber(Triple);
+ 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.
+ if (Triple.isWatchABI())
+ return FloatABI::Hard;
+ else
+ return (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
+
+ case llvm::Triple::WatchOS:
+ return FloatABI::Hard;
+
+ // FIXME: this is invalid for WindowsCE
+ case llvm::Triple::Win32:
+ return FloatABI::Hard;
+
+ case llvm::Triple::NetBSD:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::EABIHF:
+ case llvm::Triple::GNUEABIHF:
+ return FloatABI::Hard;
+ default:
+ return FloatABI::Soft;
+ }
+ break;
+
+ case llvm::Triple::FreeBSD:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ return FloatABI::Hard;
+ default:
+ // FreeBSD defaults to soft float
+ return FloatABI::Soft;
+ }
+ break;
+
+ case llvm::Triple::OpenBSD:
+ return FloatABI::SoftFP;
+
+ default:
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABIHF:
+ case llvm::Triple::MuslEABIHF:
+ case llvm::Triple::EABIHF:
+ return FloatABI::Hard;
+ 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
+ return FloatABI::SoftFP;
+ case llvm::Triple::Android:
+ return (SubArch >= 7) ? FloatABI::SoftFP : FloatABI::Soft;
+ default:
+ return FloatABI::Invalid;
+ }
+ }
+ return FloatABI::Invalid;
+}
+
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args) {
- auto SubArch = getARMSubArchVersionNumber(Triple);
arm::FloatABI ABI = FloatABI::Invalid;
if (Arg *A =
Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
@@ -183,95 +253,23 @@ arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
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;
+ if (ABI == FloatABI::Invalid)
+ ABI = arm::getDefaultFloatABI(Triple);
- // FIXME: this is invalid for WindowsCE
- case llvm::Triple::Win32:
+ if (ABI == FloatABI::Invalid) {
+ // Assume "soft", but warn the user we are guessing.
+ if (Triple.isOSBinFormatMachO() &&
+ Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
ABI = FloatABI::Hard;
- break;
-
- case llvm::Triple::NetBSD:
- switch (Triple.getEnvironment()) {
- case llvm::Triple::EABIHF:
- case llvm::Triple::GNUEABIHF:
- ABI = FloatABI::Hard;
- break;
- default:
- ABI = FloatABI::Soft;
- break;
- }
- 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;
-
- case llvm::Triple::OpenBSD:
- ABI = FloatABI::SoftFP;
- break;
+ else
+ ABI = FloatABI::Soft;
- 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;
- }
- }
+ if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ !Triple.isOSBinFormatMachO())
+ D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
}
assert(ABI != FloatABI::Invalid && "must select an ABI");
@@ -347,6 +345,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
StringRef ArchName;
StringRef CPUName;
+ unsigned ArchArgFPUID = llvm::ARM::FK_INVALID;
+ unsigned CPUArgFPUID = llvm::ARM::FK_INVALID;
// Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
if (WaCPU) {
@@ -364,14 +364,14 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
D.Diag(clang::diag::warn_drv_unused_argument)
<< ArchArg->getAsString(Args);
ArchName = StringRef(WaArch->getValue()).substr(7);
- checkARMArchName(D, WaArch, Args, ArchName, CPUName,
- ExtensionFeatures, Triple);
+ checkARMArchName(D, WaArch, Args, ArchName, CPUName, ExtensionFeatures,
+ Triple, ArchArgFPUID);
// 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, CPUName,
- ExtensionFeatures, Triple);
+ checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
+ Triple, ArchArgFPUID);
}
// Add CPU features for generic CPUs
@@ -390,8 +390,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
}
if (CPUArg)
- checkARMCPUName(D, CPUArg, Args, CPUName, ArchName,
- ExtensionFeatures, Triple);
+ checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,
+ Triple, CPUArgFPUID);
// Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
unsigned FPUID = llvm::ARM::FK_INVALID;
const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
@@ -455,20 +455,26 @@ fp16_fml_fallthrough:
Features.push_back("+fullfp16");
}
- // Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC
- // ignores the -mfpu options in this case).
- // Note that the ABI can also be set implicitly by the target selected.
+ // Setting -msoft-float/-mfloat-abi=soft, -mfpu=none, or adding +nofp to
+ // -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
+ // this case). Note that the ABI can also be set implicitly by the target
+ // selected.
if (ABI == arm::FloatABI::Soft) {
llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
// Disable all features relating to hardware FP, not already disabled by the
// above call.
+ Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
+ "-mve.fp", "-fpregs"});
+ } else if (FPUID == llvm::ARM::FK_NONE ||
+ ArchArgFPUID == llvm::ARM::FK_NONE ||
+ CPUArgFPUID == llvm::ARM::FK_NONE) {
+ // -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to
+ // -mfloat-abi=soft, only that it should not disable MVE-I. They disable the
+ // FPU, but not the FPU registers, thus MVE-I, which depends only on the
+ // latter, is still supported.
Features.insert(Features.end(),
- {"-dotprod", "-fp16fml", "-mve", "-mve.fp", "-fpregs"});
- } else if (FPUID == llvm::ARM::FK_NONE) {
- // -mfpu=none is *very* similar to -mfloat-abi=soft, only that it should not
- // disable MVE-I.
- Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-mve.fp"});
+ {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
if (!hasIntegerMVE(Features))
Features.emplace_back("-fpregs");
}
@@ -606,6 +612,45 @@ fp16_fml_fallthrough:
if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
+
+ // Enable/disable straight line speculation hardening.
+ if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
+ StringRef Scope = A->getValue();
+ bool EnableRetBr = false;
+ bool EnableBlr = false;
+ if (Scope != "none" && Scope != "all") {
+ SmallVector<StringRef, 4> Opts;
+ Scope.split(Opts, ",");
+ for (auto Opt : Opts) {
+ Opt = Opt.trim();
+ if (Opt == "retbr") {
+ EnableRetBr = true;
+ continue;
+ }
+ if (Opt == "blr") {
+ EnableBlr = true;
+ continue;
+ }
+ D.Diag(diag::err_invalid_sls_hardening)
+ << Scope << A->getAsString(Args);
+ break;
+ }
+ } else if (Scope == "all") {
+ EnableRetBr = true;
+ EnableBlr = true;
+ }
+
+ if (EnableRetBr || EnableBlr)
+ if (!(isARMAProfile(Triple) && getARMSubArchVersionNumber(Triple) >= 7))
+ D.Diag(diag::err_sls_hardening_arm_not_supported)
+ << Scope << A->getAsString(Args);
+
+ if (EnableRetBr)
+ Features.push_back("+harden-sls-retbr");
+ if (EnableBlr)
+ Features.push_back("+harden-sls-blr");
+ }
+
}
const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {