Wire the t-float128 fragment into the FreeBSD powerpc64 configuration so
the KFmode soft-float functions are built.
On glibc the plain __*kf* entry points are exported from libgcc_s.so by
the float128 IFUNC in t-float128-hw. That fragment is unusable on
FreeBSD (its runtime dispatch needs the Linux AT_PLATFORM auxv entry), so
t-float128 alone puts the software functions only into the static
libgcc.a via LIB2ADD_ST, and hidden. A gcc-built shared object such as
libstdc++.so then references e.g. __eqkf2 (for IEEE-128 long double) with
no shared provider, and linking an executable against it fails with
"hidden symbol `__eqkf2' ... is referenced by DSO".
Add a FreeBSD-only t-float128-freebsd fragment that routes the software
functions into libgcc_s.so (LIB2ADD) and a version script that exports
them under GCC_7.0.0. __mulkc3/__divkc3 are excluded from the shared
addition: under -mabi=ieeelongdouble libgcc2.c's __multc3/__divtc3 are
already mangled to those names, so the version script just exports the
libgcc2.c copies.
clang does not perform that mangling; it emits __multc3/__divtc3 (TCmode) for
complex long double. A clang-built shared object that uses complex long double
and links gcc's libgcc_s needs those names, so also add freebsd-tc-alias.c,
which defines __multc3/__divtc3 as forwarders to __mulkc3/__divkc3. Being real
symbols they are exported by gcc's default version script.
libgcc/ChangeLog:
* config.host (powerpc64*-*-freebsd*): Add rs6000/t-float128 and
rs6000/t-float128-freebsd to tmake_file when float128 is supported,
and rs6000/t-float128-hw when hardware float128 is supported.
* config/rs6000/freebsd-tc-alias.c: New file.
* config/rs6000/t-float128-freebsd: New file.
* config/rs6000/libgcc-freebsd-float128.ver: New file.
Signed-off-by: Piotr Kubaj <[email protected]>
---
libgcc/config.host | 6 ++++++
libgcc/config/rs6000/freebsd-tc-alias.c | 30
++++++++++++++++++++++++++++++
libgcc/config/rs6000/t-float128-freebsd | 22 ++++++++++++++++++++++
libgcc/config/rs6000/libgcc-freebsd-float128.ver | 35
+++++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+)
diff --git a/libgcc/config.host b/libgcc/config.host
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -1230,6 +1230,12 @@
powerpc64*)
tmake_file="${tmake_file} rs6000/t-freebsd64"
md_unwind_header=rs6000/freebsd-unwind.h
+ if test $libgcc_cv_powerpc_float128 = yes; then
+ tmake_file="${tmake_file} rs6000/t-float128
rs6000/t-float128-freebsd"
+ fi
+ if test $libgcc_cv_powerpc_float128_hw = yes; then
+ tmake_file="${tmake_file} rs6000/t-float128-hw"
+ fi
;;
esac
;;
diff --git a/libgcc/config/rs6000/t-float128-freebsd
b/libgcc/config/rs6000/t-float128-freebsd
new file mode 100644
--- /dev/null
+++ b/libgcc/config/rs6000/t-float128-freebsd
@@ -0,0 +1,22 @@
+# On FreeBSD there is no float128 IFUNC (rs6000/t-float128-hw needs the Linux
+# AT_PLATFORM auxv entry, absent on FreeBSD), so the software __float128/KFmode
+# helpers built by rs6000/t-float128 would only land in the static libgcc.a
+# (hidden) via LIB2ADD_ST. Put them in the shared libgcc_s.so and export them
+# (see libgcc-freebsd-float128.ver) so gcc-built DSOs -- notably libstdc++.so,
+# which references e.g. __eqkf2 for IEEE-128 long double -- resolve them.
+#
+# Exclude __mulkc3/__divkc3: under -mabi=ieeelongdouble libgcc2.c's __multc3/
+# __divtc3 are already mangled to those names in libgcc_s.so, so adding
rs6000's
+# own copies to the shared library would multiply-define them. They stay
+# static-only; the .ver exports the libgcc2.c-provided ones.
+fp128_shared_src := $(filter-out %/_mulkc3.c %/_divkc3.c,$(fp128_src))
+LIB2ADD_ST := $(filter-out $(fp128_shared_src),$(LIB2ADD_ST))
+LIB2ADD += $(fp128_shared_src)
+SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-freebsd-float128.ver
+
+# clang emits the complex IEEE-128 helpers as __multc3/__divtc3 (TCmode) where
+# gcc uses the KCmode names __mulkc3/__divkc3. Provide real TCmode forwarders
+# (freebsd-tc-alias.c) so a clang-built shared object that uses complex long
+# double and links gcc's libgcc_s resolves them; gcc's default version script
+# exports them once they exist as symbols.
+LIB2ADD += $(srcdir)/config/rs6000/freebsd-tc-alias.c
diff --git a/libgcc/config/rs6000/freebsd-tc-alias.c
b/libgcc/config/rs6000/freebsd-tc-alias.c
new file mode 100644
--- /dev/null
+++ b/libgcc/config/rs6000/freebsd-tc-alias.c
@@ -0,0 +1,30 @@
+/* clang emits __multc3/__divtc3 (TCmode) for complex IEEE-128 long double,
+ where gcc uses the KCmode names __mulkc3/__divkc3. A clang-built shared
+ object that uses complex long double and links gcc's libgcc_s therefore
+ needs __multc3/__divtc3. Provide them as forwarders to the KCmode helpers;
+ being real symbols, they are exported by gcc's default version script.
+
+ The __asm__ names are not rewritten: the rs6000 IEEE-128 assembler-name
+ mangling is inactive on FreeBSD, and only libgcc2.c's own mode-based naming
+ turns its __multc3/__divtc3 into __mulkc3/__divkc3. */
+
+extern _Complex long double __mulkc3 (_Complex long double, _Complex long
double);
+extern _Complex long double __divkc3 (_Complex long double, _Complex long
double);
+
+__attribute__ ((visibility ("default")))
+_Complex long double __freebsd_multc3 (_Complex long double, _Complex long
double) __asm__ ("__multc3");
+
+_Complex long double
+__freebsd_multc3 (_Complex long double a, _Complex long double b)
+{
+ return __mulkc3 (a, b);
+}
+
+__attribute__ ((visibility ("default")))
+_Complex long double __freebsd_divtc3 (_Complex long double, _Complex long
double) __asm__ ("__divtc3");
+
+_Complex long double
+__freebsd_divtc3 (_Complex long double a, _Complex long double b)
+{
+ return __divkc3 (a, b);
+}
diff --git a/libgcc/config/rs6000/libgcc-freebsd-float128.ver
b/libgcc/config/rs6000/libgcc-freebsd-float128.ver
new file mode 100644
--- /dev/null
+++ b/libgcc/config/rs6000/libgcc-freebsd-float128.ver
@@ -0,0 +1,35 @@
+# IEEE-128 (__float128 / KFmode) software helpers exported from libgcc_s.so on
+# FreeBSD, where there is no float128 IFUNC. Attached to GCC_7.0.0, the
version
+# where PowerPC __float128 support was introduced.
+GCC_7.0.0 {
+ __addkf3
+ __subkf3
+ __mulkf3
+ __divkf3
+ __negkf2
+ __unordkf2
+ __eqkf2
+ __gekf2
+ __lekf2
+ __extendsfkf2
+ __extenddfkf2
+ __trunckfsf2
+ __trunckfdf2
+ __fixkfsi
+ __fixkfdi
+ __fixunskfsi
+ __fixunskfdi
+ __floatsikf
+ __floatdikf
+ __floatunsikf
+ __floatundikf
+ __floattikf
+ __floatuntikf
+ __fixkfti
+ __fixunskfti
+ __extendkftf2
+ __trunctfkf2
+ __mulkc3
+ __divkc3
+ __powikf2
+}
--
2.49.0