diff --git a/pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch b/pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch new file mode 100644 index 0000000000000..ee0318eecf0a0 --- /dev/null +++ b/pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch @@ -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 +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 + + 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 + diff --git a/pkgs/development/compilers/gcc/10/default.nix b/pkgs/development/compilers/gcc/10/default.nix index 1e8917ef6cf16..d12e0f216d445 100644 --- a/pkgs/development/compilers/gcc/10/default.nix +++ b/pkgs/development/compilers/gcc/10/default.nix @@ -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 # Obtain latest patch with ../update-mcfgthread-patches.sh ++ optional (!crossStageStatic && targetPlatform.isMinGW) ./Added-mcf-thread-model-support-from-mcfgthread.patch diff --git a/pkgs/development/compilers/gcc/common/platform-flags.nix b/pkgs/development/compilers/gcc/common/platform-flags.nix index bd5a72f960364..f53457325204b 100644 --- a/pkgs/development/compilers/gcc/common/platform-flags.nix +++ b/pkgs/development/compilers/gcc/common/platform-flags.nix @@ -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" ]) ] diff --git a/pkgs/stdenv/adapters.nix b/pkgs/stdenv/adapters.nix index 9884c219ff609..62652b3183b97 100644 --- a/pkgs/stdenv/adapters.nix +++ b/pkgs/stdenv/adapters.nix @@ -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" ]; }); }); diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index e9104dd88cfa1..bd87d264269fd 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -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; @@ -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 @@ -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; @@ -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 (