diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -417,6 +417,8 @@ def warn_drv_unsupported_float_abi_by_lib : Warning< "float ABI '%0' is not supported by current library">, InGroup>; +def warn_drv_no_floating_point_registers: Warning< + "'%0': selected processor lacks floating point registers">; def warn_ignoring_ftabstop_value : Warning< "ignoring invalid -ftabstop value '%0', using default value %1">; def warn_drv_overriding_flag_option : Warning< diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -144,6 +144,22 @@ << A->getSpelling() << A->getValue(); } +// If -mfloat-abi=hard or -mhard-float are specified explicitly then check that +// floating point registers are available on the target CPU. +static void checkARMFloatABI(const Driver &D, const ArgList &Args, + const std::vector &Features) { + if (llvm::find(Features, "-fpregs") == Features.end()) + return; + const Arg *A = + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ); + if (A && (A->getOption().matches(options::OPT_mhard_float) || + (A->getOption().matches(options::OPT_mfloat_abi_EQ) && + A->getValue() == StringRef("hard")))) + D.Diag(clang::diag::warn_drv_no_floating_point_registers) + << 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. @@ -910,6 +926,8 @@ if (Args.getLastArg(options::OPT_mno_bti_at_return_twice)) Features.push_back("+no-bti-at-return-twice"); + + checkARMFloatABI(D, Args, Features); } std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { diff --git a/clang/test/Driver/arm-no-float-regs.c b/clang/test/Driver/arm-no-float-regs.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/arm-no-float-regs.c @@ -0,0 +1,24 @@ +// REQUIRES: arm-registered-target + +// Check that -mfloat-abi=hard gives a warning if FP registers aren't available. +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m0 -mfloat-abi=hard -c %s 2>&1 + +// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m0 -mhard-float -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=HARDFLOAT %s + + +// -mfloat-abi=hard and -march=...+nofp are incompatible in this instance: +// RUN: %clang --target=arm-none-eabi -march=armv8.1-m.main+nofp -mfloat-abi=hard -c %s 2>&1 +// -mfloat-abi=hard and -march=...+nofp are compatible in this instance: +// RUN: %clang --target=arm-none-eabi -march=armv8.1-m.main+mve+nofp -mfloat-abi=hard -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=NOWARN %s + +// Here the float ABI is calculated as "hard" and FP registers are +// calculated to not be available. Since the float ABI wasn't specified +// explicitly, the warning should not be emitted. +// RUN: not %clang -target thumbv5-windows -mcpu=arm10tdmi -c %s -o /dev/null 2>&1 \ +// RUN: | FileCheck -check-prefix=NOWARN %s + +// CHECK: warning: '-mfloat-abi=hard': selected processor lacks floating point registers +// HARDFLOAT: warning: '-mhard-float': selected processor lacks floating point registers +// NOWARN-NOT: selected processor lacks floating point registers