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, + bool HasFPRegs) { + if (HasFPRegs) + 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. @@ -636,13 +652,15 @@ // -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. + bool HasFPRegs = true; 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"}); + Features.insert(Features.end(), + {"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"}); + HasFPRegs = false; } else if (FPUKind == llvm::ARM::FK_NONE || ArchArgFPUKind == llvm::ARM::FK_NONE || CPUArgFPUKind == llvm::ARM::FK_NONE) { @@ -652,9 +670,10 @@ // latter, is still supported. Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"}); - if (!hasIntegerMVE(Features)) - Features.emplace_back("-fpregs"); + HasFPRegs = hasIntegerMVE(Features); } + if (!HasFPRegs) + Features.emplace_back("-fpregs"); // En/disable crc code generation. if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { @@ -910,6 +929,8 @@ if (Args.getLastArg(options::OPT_mno_bti_at_return_twice)) Features.push_back("+no-bti-at-return-twice"); + + checkARMFloatABI(D, Args, HasFPRegs); } 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,23 @@ +// 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: %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