Skip to content

Commit 1d511e1

Browse files
committed
[ARM][Driver] Warn if -mhard-float is incompatible
Mixing -mfloat-abi=hard with a CPU that doesn't have floating point registers is an error in GCC: cc1: error: '-mfloat-abi=hard': selected processor lacks an FPU Since there is code in the wild (including in clang tests) that relies on Clang's current behaviour, emit a warning instead of an error. Unlike the GCC error, the new warning refers to floating point registers instead of an FPU. This is because -mfloat-abi=hard and -march=armv8.1-m.main+mve+nofp are compatible - in that case floating point registers are required, but an FPU is not required. My initial thought was to use the floating point ABI calculated by arm::getARMFloatABI() but in invalid cases which error for other reasons the ABI is miscalculated and the warning would cause confusion. Therefore only warn if the user specifies the float ABI explicitly. Fixes part of #55755 Differential Revision: https://reviews.llvm.org/D150902
1 parent 10e7899 commit 1d511e1

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ def warn_drv_assuming_mfloat_abi_is : Warning<
417417
def warn_drv_unsupported_float_abi_by_lib : Warning<
418418
"float ABI '%0' is not supported by current library">,
419419
InGroup<DiagGroup<"unsupported-abi">>;
420+
def warn_drv_no_floating_point_registers: Warning<
421+
"'%0': selected processor lacks floating point registers">;
420422
def warn_ignoring_ftabstop_value : Warning<
421423
"ignoring invalid -ftabstop value '%0', using default value %1">;
422424
def warn_drv_overriding_flag_option : Warning<

clang/lib/Driver/ToolChains/Arch/ARM.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,22 @@ static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
144144
<< A->getSpelling() << A->getValue();
145145
}
146146

147+
// If -mfloat-abi=hard or -mhard-float are specified explicitly then check that
148+
// floating point registers are available on the target CPU.
149+
static void checkARMFloatABI(const Driver &D, const ArgList &Args,
150+
bool HasFPRegs) {
151+
if (HasFPRegs)
152+
return;
153+
const Arg *A =
154+
Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
155+
options::OPT_mfloat_abi_EQ);
156+
if (A && (A->getOption().matches(options::OPT_mhard_float) ||
157+
(A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
158+
A->getValue() == StringRef("hard"))))
159+
D.Diag(clang::diag::warn_drv_no_floating_point_registers)
160+
<< A->getAsString(Args);
161+
}
162+
147163
bool arm::useAAPCSForMachO(const llvm::Triple &T) {
148164
// The backend is hardwired to assume AAPCS for M-class processors, ensure
149165
// the frontend matches that.
@@ -636,13 +652,15 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
636652
// -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
637653
// this case). Note that the ABI can also be set implicitly by the target
638654
// selected.
655+
bool HasFPRegs = true;
639656
if (ABI == arm::FloatABI::Soft) {
640657
llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
641658

642659
// Disable all features relating to hardware FP, not already disabled by the
643660
// above call.
644-
Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
645-
"-mve.fp", "-fpregs"});
661+
Features.insert(Features.end(),
662+
{"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"});
663+
HasFPRegs = false;
646664
} else if (FPUKind == llvm::ARM::FK_NONE ||
647665
ArchArgFPUKind == llvm::ARM::FK_NONE ||
648666
CPUArgFPUKind == llvm::ARM::FK_NONE) {
@@ -652,9 +670,10 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
652670
// latter, is still supported.
653671
Features.insert(Features.end(),
654672
{"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
655-
if (!hasIntegerMVE(Features))
656-
Features.emplace_back("-fpregs");
673+
HasFPRegs = hasIntegerMVE(Features);
657674
}
675+
if (!HasFPRegs)
676+
Features.emplace_back("-fpregs");
658677

659678
// En/disable crc code generation.
660679
if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
@@ -910,6 +929,8 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
910929

911930
if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
912931
Features.push_back("+no-bti-at-return-twice");
932+
933+
checkARMFloatABI(D, Args, HasFPRegs);
913934
}
914935

915936
std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {

clang/test/Driver/arm-no-float-regs.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// REQUIRES: arm-registered-target
2+
3+
// Check that -mfloat-abi=hard gives a warning if FP registers aren't available.
4+
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m0 -mfloat-abi=hard -### -c %s 2>&1
5+
6+
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m0 -mhard-float -### -c %s 2>&1 \
7+
// RUN: | FileCheck -check-prefix=HARDFLOAT %s
8+
9+
// -mfloat-abi=hard and -march=...+nofp are incompatible in this instance:
10+
// RUN: %clang --target=arm-none-eabi -march=armv8.1-m.main+nofp -mfloat-abi=hard -### -c %s 2>&1
11+
// -mfloat-abi=hard and -march=...+nofp are compatible in this instance:
12+
// RUN: %clang --target=arm-none-eabi -march=armv8.1-m.main+mve+nofp -mfloat-abi=hard -### -c %s 2>&1 \
13+
// RUN: | FileCheck -check-prefix=NOWARN %s
14+
15+
// Here the float ABI is calculated as "hard" and FP registers are
16+
// calculated to not be available. Since the float ABI wasn't specified
17+
// explicitly, the warning should not be emitted.
18+
// RUN: %clang -target thumbv5-windows -mcpu=arm10tdmi -### -c %s -o /dev/null 2>&1 \
19+
// RUN: | FileCheck -check-prefix=NOWARN %s
20+
21+
// CHECK: warning: '-mfloat-abi=hard': selected processor lacks floating point registers
22+
// HARDFLOAT: warning: '-mhard-float': selected processor lacks floating point registers
23+
// NOWARN-NOT: selected processor lacks floating point registers

0 commit comments

Comments
 (0)