With -mfpu set to auto, an architecture specification that lacks
floating-point, but has -mfloat-abi=softfp will cause a misleading
error. Specifically, if we have
gcc -c test.c -mfloat-abi=softfp -march=armv7-a -mfpu=auto
where test.c contains #include <arm_neon.h>
then we get a misleading error:
test.c:11:2: error: #error "NEON intrinsics not available with the
soft-float ABI. Please use -mfloat-abi=softfp or -mfloat-abi=hard"
... the error message is advising us to add -mfloat-abi=softfp when we
already have it.
The difficulty is that we can't directly detect the softfp abi from
the available set of pre-defines.
Consider the options in this table, assuming -mfpu=auto:
-mfloat-abi
hard softfp soft
+-----------------------------------------------
-march=armv7-a | *build-error* __ARM_FP=0 __ARM_FP=0
-march=armv7-a+fp | __ARM_FP=12 __ARM_FP=12 __ARM_FP=0
However, for the first line, if we subsequently add
#pragma GCC target ("fpu=vfp")
then the value of __ARM_FP will change as follows:
-mfloat-abi
hard softfp soft
+-----------------------------------------------
-march=armv7-a | *build-error* __ARM_FP=12 __ARM_FP=0
-march=armv7-a+fp | __ARM_FP=12 __ARM_FP=12 __ARM_FP=0
We can therefore distinguish between the soft and softfp ABIs by
temporarily forcing VFP instructions into the ISA. If __ARM_FP is
still zero after doing this then we must be using the soft ABI.
gcc:
* config/arm/arm_neon.h: Try harder to detect if we have
the softfp ABI enabled.
#ifndef _GCC_ARM_NEON_H
#define _GCC_ARM_NEON_H 1
+/* This header is only useful if we're compiling with -mfloat-abi=hard or
+ -mfloat-abi=softfp. But we can't detect that directly here as the
+ compiler does not provide a pre-define for it. However, we can check
+ whether forcing VFP will cause __ARM_FP to become defined and use that. */
+
+#pragma GCC push_options
+#pragma GCC target ("fpu=vfp")
#ifndef __ARM_FP
+#define __ARM_SOFT_ABI 1
+#else
+#define __ARM_SOFT_ABI 0
+#endif
+#pragma GCC pop_options
+
+#if __ARM_SOFT_ABI
#error "NEON intrinsics not available with the soft-float ABI. Please use -mfloat-abi=softfp or -mfloat-abi=hard"
#else
#pragma GCC pop_options
#endif
+
+#undef __ARM_SOFT_ABI
+
#endif