[PATCH v3 4/7] libgcc: build and export the float128 helpers for powerpc64*-*-freebsd*
Piotr Kubaj <[email protected]> Wed, 15 Jul 2026 08:24:19 +0200
| Newsgroups | gmane.comp.gcc.patches,gmane.comp.gcc.fortran |
|---|---|
| Message-ID | <[email protected]> |
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