Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gcc: if isPower64, add --with-long-double-64 --without-long-double-128 #170857

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
This patch is included upstream in gcc 11.1.0 and later:

https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=cda41ce0e8414aec59e6b9fbe645d96e6e8193e2

From cda41ce0e8414aec59e6b9fbe645d96e6e8193e2 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Sat, 3 Apr 2021 10:05:32 +0200
Subject: [PATCH] rs6000: Fix up libgcc ABI when built with
--with-long-double-format=ieee [PR97653]

__floatunditf and __fixtfdi and a couple of other libgcc{.a,_s.so}
entrypoints for backwards compatibility should mean IBM double double
handling (i.e. IFmode), gcc emits such calls for that format and
form IEEE long double emits *kf* instead.
When gcc is configured without --with-long-double-format=ieee ,
everything is fine, but when it is not, we need to compile those
libgcc sources with -mno-gnu-attribute -mabi=ibmlongdouble.
The following snippet in libgcc/config/rs6000/t-linux was attempting
to ensure that, and for some routines it works fine (e.g. for _powitf2).
But, due to 4 different types of bugs it doesn't work for most of those
functions, which means that in --with-long-double-format=ieee
configured gcc those *tf* entrypoints instead handle the long double
arguments as if they were KFmode.

The bugs are:
1) the first few objs properly use $(objext) as suffix, but
several other contain a typo and use $(object) instead,
which is a variable that isn't set to anything, so we don't
add .o etc. extensions
2) while unsigned fix are properly called _fixuns*, unsigned float
are called _floatun* (without s), but the var was using there
the extra s and so didn't match
3) the variable didn't cover any of the TF <-> TI conversions,
only TF <-> DI conversions
4) nothing in libgcc_s.so was handled, as those object files are
called *_s.o rather than *.o and IBM128_SHARED_OBJS used wrong
syntax of the GNU make substitution reference, which should be
$(var:a=b) standing for $(patsubst a,b,$(var)) but it used
$(var:a:b) instead

2021-04-03 Jakub Jelinek <jakub@redhat.com>

PR target/97653
* config/rs6000/t-linux (IBM128_STATIC_OBJS): Fix spelling, use
$(objext) instead of $(object). Use _floatunditf instead of
_floatunsditf. Add tf <-> ti conversion objects.
(IBM128_SHARED_OBJS): Use proper substitution reference syntax.
---
libgcc/config/rs6000/t-linux | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/libgcc/config/rs6000/t-linux b/libgcc/config/rs6000/t-linux
index 72e9c2770a6..500210ddaf2 100644
--- a/libgcc/config/rs6000/t-linux
+++ b/libgcc/config/rs6000/t-linux
@@ -11,10 +11,12 @@ HOST_LIBGCC2_CFLAGS += -mno-minimal-toc
# the IBM extended double format. Also turn off gnu attributes on the static
# modules.
IBM128_STATIC_OBJS = ibm-ldouble$(objext) _powitf2$(objext) \
- ppc64-fp$(objext) _divtc3$(object) _multc3$(object) \
- _fixtfdi$(object) _fixunstfdi$(object) \
- _floatditf$(objext) _floatunsditf$(objext)
-IBM128_SHARED_OBJS = $(IBM128_STATIC_OBJS:$(objext):_s$(objext))
+ ppc64-fp$(objext) _divtc3$(objext) _multc3$(objext) \
+ _fixtfdi$(objext) _fixunstfdi$(objext) \
+ _floatditf$(objext) _floatunditf$(objext) \
+ _fixtfti$(objext) _fixunstfti$(objext) \
+ _floattitf$(objext) _floatuntitf$(objext)
+IBM128_SHARED_OBJS = $(IBM128_STATIC_OBJS:$(objext)=_s$(objext))
IBM128_OBJS = $(IBM128_STATIC_OBJS) $(IBM128_SHARED_OBJS)

IBM128_CFLAGS = -Wno-psabi -mabi=ibmlongdouble -mno-gnu-attribute
--
2.27.0

1 change: 1 addition & 0 deletions pkgs/development/compilers/gcc/10/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ let majorVersion = "10";
++ optional langAda ../gnat-cflags.patch
++ optional langFortran ../gfortran-driving.patch
++ optional (targetPlatform.libc == "musl" && targetPlatform.isPower) ../ppc-musl.patch
++ optional (targetPlatform.isMusl && targetPlatform.isPower64) ./backport-libgcc-fix-PR97653.patch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it would help to instead default the platform to gcc11? (like x86_64-linux and some others)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try that as soon as my current rebuild-the-world finishes.

However even in that case could we still keep the line above? At least that way if somebody needs gcc10 for some reason it will work.

PS, that line is actually from #170400, which this PR builds on top of. That PR is ready for review and possible merge; this one is still WIP but getting very close.


# Obtain latest patch with ../update-mcfgthread-patches.sh
++ optional (!crossStageStatic && targetPlatform.isMinGW) ./Added-mcf-thread-model-support-from-mcfgthread.patch
Expand Down
46 changes: 43 additions & 3 deletions pkgs/development/compilers/gcc/common/platform-flags.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,47 @@ in lib.concatLists [
(lib.optional (p ? fpu) "--with-fpu=${p.fpu}")
(lib.optional (p ? float) "--with-float=${p.float}")
(lib.optional (p ? mode) "--with-mode=${p.mode}")
(lib.optional
(let tp = targetPlatform; in tp.isPower && tp.libc == "glibc" && tp.is64bit)
"--with-long-double-128")

# The powerpc64 ABI has an IBM-specific, non-IEEE "long double" type
# which causes many some test failures. GCC and glibc have been
# working on migrating to 128-bit IEEE long doubles using a complex
# "fat binary" scheme that avoids having a new multiarch tuple.
# Progress with this scheme has been exceptionally slow: Fedora has
# been trying to "flip the switch" since Fedora 31 without success.
#
# As of version 2.34 glibc refuses to build using *only* the IEEE
# standard long-double type, and implementation of the "fat binary"
# scheme to support both IEEE and IBM long doubles simultaneously is
# troublesome and unreliable. Therefore, we use the same approach
# with glibc that musl uses: simply have `long double` be the same
# size as `double`: 64 bits. This is already the case on
# aarch64-darwin, 32-bit ARM, 32-bit MIPS, and Microsoft's C/C++
# compiler for both 64-bit ARM and 32-bit x86, so it is
# well-supported by the build scripts for essentially everything in
# nixpkgs.
#
# Musl specifically checks for non-IEEE `long double`s on powerpc
# and will refuse to build if they are found to be present:
#
# https://git.musl-libc.org/cgit/musl/tree/configure#n732
#
# This has saved musl as great deal of trouble that glibc is
# currently struggling with. By using the same approach for both
# musl and glibc we avoid a lot of headaches that come up when
# "cross-compiling" from *-linux-gnu to *-linux-musl due to the
# libgcc bundled into *-linux-gnu's being linked with the emitted
# binaries.
#
# More details:
#
# https://gcc.gnu.org/wiki/Ieee128PowerPC
# https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
# https://fedoraproject.org/wiki/Changes/PPC64LE_Float128_Transition
# https://en.m.wikipedia.org/wiki/Long_double
# https://gcc.gnu.org/install/configure.html
#
# Below are the three possible valid combinations of options, with
# two commented out:
#
(lib.optionals targetPlatform.isPower64 [ "--without-long-double-128" "--with-long-double-64" ])
]
5 changes: 5 additions & 0 deletions pkgs/stdenv/adapters.nix
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ rec {
];
cmakeFlags = (args.cmakeFlags or []) ++ [ "-DBUILD_SHARED_LIBS:BOOL=OFF" ];
mesonFlags = (args.mesonFlags or []) ++ [ "-Ddefault_library=static" ];
} // lib.optionalAttrs stdenv.hostPlatform.isPower64 {
# this is an artifact of the bootstrap-files being built prior
# to moving to IEEE doubles on powerpc64le; it would go away
# if we regenerated the bootstrap-files
hardeningDisable = (args.hardeningDisable or []) ++ [ "stackprotector" ];
});
});

Expand Down
39 changes: 28 additions & 11 deletions pkgs/stdenv/linux/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,24 @@ in
binutils coreutils gnugrep
perl patchelf linuxHeaders gnum4 bison libidn2 libunistring;
${localSystem.libc} = getLibc prevStage;
# Link GCC statically against GMP etc. This makes sense because
# these builds of the libraries are only used by GCC, so it
# reduces the size of the stdenv closure.
gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; };
mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; };
libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; };
isl_0_20 = super.isl_0_20.override { stdenv = self.makeStaticLibraries self.stdenv; };
gcc-unwrapped = super.gcc-unwrapped.override {
isl = isl_0_20;
gcc-unwrapped =
let makeStaticLibrariesAndMark = pkg:
lib.makeOverridable (pkg.override { stdenv = self.makeStaticLibraries self.stdenv; })
.overrideAttrs (a: {
# this is an artifact of the bootstrap-files being built prior
# to moving to IEEE doubles on powerpc64le; it would go away
# if we regenerated the bootstrap-files
NIX_CFLAGS_COMPILE = (a.NIX_CFLAGS_COMPILE or "") + " -mlong-double-64";
pname = "${a.pname}-stage3";
});
in super.gcc-unwrapped.override {
# Link GCC statically against GMP etc. This makes sense because
# these builds of the libraries are only used by GCC, so it
# reduces the size of the stdenv closure.
gmp = makeStaticLibrariesAndMark super.gmp;
mpfr = makeStaticLibrariesAndMark super.mpfr;
libmpc = lib.makeOverridable (makeStaticLibrariesAndMark super.libmpc).overrideAttrs (_: { doCheck = false; });
isl = makeStaticLibrariesAndMark super.isl_0_20;
# Use a deterministically built compiler
# see https://github.com/NixOS/nixpkgs/issues/108475 for context
reproducibleBuild = true;
Expand All @@ -332,7 +341,7 @@ in
# because gcc (since JAR support) already depends on zlib, and
# then if we already have a zlib we want to use that for the
# other purposes (binutils and top-level pkgs) too.
inherit (prevStage) gettext gnum4 bison gmp perl texinfo zlib linuxHeaders libidn2 libunistring;
inherit (prevStage) gettext gnum4 bison perl texinfo zlib linuxHeaders libidn2 libunistring;
${localSystem.libc} = getLibc prevStage;
binutils = super.binutils.override {
# Don't use stdenv's shell but our own
Expand All @@ -343,6 +352,14 @@ in
};
};

# force gmp to rebuild so we have the option of dynamically linking
# libgmp without creating a reference path from:
# stage5.gcc -> stage4.coreutils -> stage3.glibc -> bootstrap
gmp = lib.makeOverridable (super.gmp.override { stdenv = self.stdenv; }).overrideAttrs (a: { pname = "${a.pname}-stage4"; });

# coreutils gets rebuilt both here and also in the final stage; we rename this one to avoid confusion
coreutils = super.coreutils.overrideAttrs (a: { pname = "${a.pname}-stage4"; });

gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) {
nativeTools = false;
nativeLibc = false;
Expand Down Expand Up @@ -410,7 +427,7 @@ in
# Simple executable tools
concatMap (p: [ (getBin p) (getLib p) ]) [
gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils
gawk gnumake gnused gnutar gnugrep gnupatch patchelf ed
gawk gmp gnumake gnused gnutar gnugrep gnupatch patchelf ed
]
# Library dependencies
++ map getLib (
Expand Down