Windows differs slightly from the standard aarch64 ABI in that
sizeof(long double) == sizeof(double),[0] which is followed on MSVC and
Clang but not GCC:
$ cat ld.c
static_assert(sizeof(long double) == sizeof(double));
$ /opt/msvc/bin/arm64/cl.exe /c /nologo ld.c
ld.c
$ clang -target aarch64-w64-mingw32 -std=c23 -c ld.c
$ aarch64-w64-mingw32-gcc -c ld.c
ld.c:1:1: error: static assertion failed
1 | static_assert(sizeof(long double) == sizeof(double));
The biggest casualty of this is mingw64-runtime, which assumes that if
these types are different sizes it needs to do x87 emulation. As this
package is essential to compile pretty much anything, it's safe to say that
nobody is yet using aarch64-w64-mingw32 in earnest and this change won't
break anybody's workflow.
Change long double so that it is DFmode rather than TFmode, and disable
the soft-fp code that's now broken due to the lack of a TFmode type.
[0] https://learn.microsoft.com/en-us/cpp/c-language/type-long-double
gcc/ChangeLog:
* config/aarch64/aarch64.cc (aarch64_c_mode_for_floating_type): Set
long double to DFmode if LONG_DOUBLE_IS_64BIT set.
* config/aarch64/cygming.h (LONG_DOUBLE_IS_64_BIT): Define.
libgcc/ChangeLog:
* config.host: Replace aarch64/t-softfp with aarch64/t-softfp-mingw
for mingw.
* config/aarch64/t-soft-mingw: New file.
---
gcc/config/aarch64/aarch64.cc | 8 +++++++-
gcc/config/aarch64/cygming.h | 2 ++
libgcc/config.host | 2 +-
libgcc/config/aarch64/t-softfp-mingw | 12 ++++++++++++
4 files changed, 22 insertions(+), 2 deletions(-)
create mode 100644 libgcc/config/aarch64/t-softfp-mingw
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 6f6dea67e0d..1b872564c0c 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -29700,7 +29700,13 @@ static machine_mode
aarch64_c_mode_for_floating_type (enum tree_index ti)
{
if (ti == TI_LONG_DOUBLE_TYPE)
- return TFmode;
+ {
+#ifdef LONG_DOUBLE_IS_64BIT
+ return DFmode;
+#else
+ return TFmode;
+#endif
+ }
return default_mode_for_floating_type (ti);
}
diff --git a/gcc/config/aarch64/cygming.h b/gcc/config/aarch64/cygming.h
index 7e2203c3e92..efa1a0c62b6 100644
--- a/gcc/config/aarch64/cygming.h
+++ b/gcc/config/aarch64/cygming.h
@@ -136,6 +136,8 @@ still needed for compilation. */
#undef LONG_TYPE_SIZE
#define LONG_TYPE_SIZE 32
+#define LONG_DOUBLE_IS_64BIT
+
#undef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR 1
diff --git a/libgcc/config.host b/libgcc/config.host
index 82ea1772f51..3c89ffe586d 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -468,7 +468,7 @@ aarch64-*-mingw*)
tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
tmake_file="${tmake_file} ${cpu_type}/t-mingw"
tmake_file="${tmake_file} ${cpu_type}/t-lse"
- tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+ tmake_file="${tmake_file} ${cpu_type}/t-softfp-mingw t-softfp t-crtfm"
;;
alpha*-*-linux*)
tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm
alpha/t-linux"
diff --git a/libgcc/config/aarch64/t-softfp-mingw
b/libgcc/config/aarch64/t-softfp-mingw
new file mode 100644
index 00000000000..143486b2774
--- /dev/null
+++ b/libgcc/config/aarch64/t-softfp-mingw
@@ -0,0 +1,12 @@
+softfp_int_modes := si di ti
+softfp_extensions := bfsf
+softfp_truncations := dfbf sfbf hfbf
+softfp_exclude_libgcc2 := n
+softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
+ floatdibf floatundibf floattibf floatuntibf \
+ floatbitinthf floatbitintbf
+
+TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
+
+LIB2ADD += $(srcdir)/config/aarch64/sfp-exceptions.c
+SHLIB_MAPFILES += $(srcdir)/config/aarch64/libgcc-softfp.ver
--
2.51.0