Commit b6be8a03 authored by Emily's avatar Emily
Browse files

haskell.compiler.ghc{948,967,984,9102,9103,9121,9122}: backport patches for LLVM support

LLVM 12–17 have been dropped for Nixpkgs 25.11. As discussed recently
on Matrix, this backports upstream changes to allow the use of
LLVM 20 for all GHC versions from 9.4.8 onward.

I looked over GHC commits mentioning LLVM since the release of 9.4.8,
and read the discussions and issues around the relevant bumps, and
attempted to be quite thorough, but I obviously cannot guarantee that
this is wholly comprehensive. It seems like upstream generally bumps
the upper bound on the basis of “it builds successfully for me”,
with specific adaptations for new versions being fairly uncommon and
only coming for obvious build blockers or reactively in response to
bug reports. I have backported both kinds of changes here.

For some commits, trivial conflict resolutions and adaptations
were required. It would be possible to pass the affected files to
`fetchpatch` as `excludes` and keep smaller fix‐up patches in tree in
some cases, but I opted to keep it simple and vendor complete backport
patches instead. I did not attempt to backport every single change to
the LLVM backend, only those that seemed directly relevant to support
for newer versions; if you’d get the same issue with the older LLVM,
that’s just a GHC bug.

These changes should actually make it easier to cross‐compile for
new architectures, as more recent LLVMs will have better support for
newer platforms, and it will be easier to backport GHC changes to
enable new platforms with less drift in the backend.

These patches do result in two breaking changes. Firstly, the minimum
LLVM version is bumped to 13 across the board. This is irrelevant for
Nixpkgs as we pin a specific LLVM version anyway, and versions below
LLVM 18 will be removed imminently. Secondly, support for the hidden
`-fno-llvm-tbaa` flag is dropped. This can be replaced with custom
`-optlo` flags to control the passes more directly, but the main
use of this undocumented flag appears to have been to [work around]
the lack of support for newer LLVM versions, anyway.

[work around]: <https://gitlab.haskell.org/ghc/ghc/-/issues/22220>

I successfully built the following on `aarch64-linux`:

* `pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc948`
* `pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc967`
* `pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc984`
* `pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc9102`
* `pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc9121`
* `pkgsCross.armv7l-hf-multiplatform.buildPackages.haskell.compiler.ghc9122`
* `pkgsCross.riscv64.haskell.compiler.ghc948`

The GHC 9.4.8 with an ARMv7 host platform segfaults when I try to run
GHC, though e.g. `ghc-pkg --help` runs successfully. The GHC 9.10.3
build targeting ARMv7 crashed inside `llc(1)`, so I tried RISC‐V,
which has some platform mismatch issue relating to `libffi`, so I
tried z/Architecture, which failed with an invalid floating point
constant in the LLVM IR, so I tried 64‐bit MIPS, which failed with
a different `libffi` issue, so I tried 32‐bit MIPS, which failed
to compile `compiler-rt`, so I gave up. I confirmed that both of the
ARMv7 issues reproduce with 944e8fd4,
the revision before they were bumped from their old versions of LLVM,
so these are not regressions.

I built a test program with the ARMv7 cross‐compilers and
confirmed that they run on the AArch64 builder. I also confirmed
that the cross‐compiled RISC‐V GHC successfully runs under
`qemu-riscv64(1)`. It will only try to build programs via the C
backend, though, as that is the only option for unregisterised™
targets, so it’s not clear to me how useful LLVM support in 9.4.8
really is for bootstrapping new platforms; I guess even RISC‐V
would require more backporting work to produce a cross‐compiled
GHC that will use LLVM to compile its own input. I didn’t bother
setting up all the binfmt machinery to get it through compiling and
running a test program, but it at least makes the attempt.
parent 5923f1f1
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -269,7 +269,9 @@
      # Missing ELF symbols
      ++ lib.optionals stdenv.targetPlatform.isAndroid [
        ./ghc-define-undefined-elf-st-visibility.patch
      ];
      ]

      ++ (import ./common-llvm-patches.nix { inherit lib version fetchpatch; });

    stdenv = stdenvNoCC;
  },
@@ -859,8 +861,6 @@ stdenv.mkDerivation (
      timeout = 24 * 3600;
      platforms = lib.platforms.all;
      inherit (bootPkgs.ghc.meta) license;
      # To be fixed by <https://github.com/NixOS/nixpkgs/pull/440774>.
      broken = useLLVM;
    };

    dontStrip = targetPlatform.useAndroidPrebuilt || targetPlatform.isWasm;
+126 −0
Original line number Diff line number Diff line
{
  lib,
  version,
  fetchpatch,
}:

# Backports for LLVM support.
#
# These primarily focus on backporting patches that are relevant to
# supporting newer LLVM versions, rather than aiming to backport every
# LLVM backend bug fix or improvement from newer GHC releases.
#
# Potentially of interest for cross‐compiling GHC 9.4.8 to LoongArch64:
#
# * <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9292>
# * <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13620>

[ ]

++ lib.optionals (lib.versionOlder version "9.6") [
  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9857>
  (fetchpatch {
    name = "ghc-9.4-llvm-support-15.patch";
    url = "https://gitlab.haskell.org/ghc/ghc/-/commit/0cc16aaf89d7dc3963764b7193ceac73e4e3329b.patch";
    hash = "sha256-G0gqrj5iPuQ5JuC2+d151yka72XZMbrqMWPZd4EuT04=";
  })

  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13763>
  ./ghc-9.4-llvm-fix-version-detection.patch
]

++ lib.optionals (lib.versionOlder version "9.8") [
  (
    # The upstream backport of !13763 in 9.6.7 removed an unused import
    # that is required by the next series.
    if lib.versionOlder version "9.6" then null else ./ghc-9.6-llvm-restore-import.patch
  )
]

++ lib.optionals (lib.versionOlder version "9.10") [
  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11124>
  (
    if lib.versionOlder version "9.8" then
      ./ghc-9.4-llvm-add-metadata-exports.patch
    else
      fetchpatch {
        name = "ghc-9.8-llvm-add-metadata-exports.patch";
        url = "https://gitlab.haskell.org/ghc/ghc/-/commit/fcfc1777c22ad47613256c3c5e7304cfd29bc761.patch";
        hash = "sha256-9rpyeH8TUVeKoW4PA6qn7DG2+P9MhBCywmbi1O/NsTQ=";
      }
  )
  (
    if lib.versionOlder version "9.8" then
      ./ghc-9.4-llvm-allow-llvmlits-in-metaexprs.patch
    else
      fetchpatch {
        name = "ghc-9.8-llvm-allow-llvmlits-in-metaexprs.patch";
        url = "https://gitlab.haskell.org/ghc/ghc/-/commit/5880fff6d353a14785c457999fded5a7100c9514.patch";
        hash = "sha256-NDMGNc0PYpWJUW+nI2YvMsBOWRIfNix4oWHQZAIxrVY=";
      }
  )
  (
    # `GHC.Driver.DynFlags` was not split out until 9.8, so this can be
    # omitted with no functional effect on the rest of the series on
    # earlier versions.
    if lib.versionOlder version "9.8" then
      null
    else
      fetchpatch {
        name = "ghc-9.8-move-feature-predicates-to-dynflags.patch";
        url = "https://gitlab.haskell.org/ghc/ghc/-/commit/86ce92a2f81a04aa980da2891d0e300cb3cb7efd.patch";
        hash = "sha256-SzJgzq4b5wAMPz+/QSa67iSOxB2enqejvV0lsF0+9L8=";
      }
  )
  (fetchpatch {
    name = "ghc-9.4-llvm-add-module-flag-metadata-infra.patch";
    url = "https://gitlab.haskell.org/ghc/ghc/-/commit/a6a3874276ced1b037365c059dcd0a758e813a5b.patch";
    hash = "sha256-tAYDRNXmpp5cZtyONpO8vlsDmnNEBbh4J3oSCy/uWWc=";
  })
  (
    if lib.versionOlder version "9.8" then
      ./ghc-9.4-llvm-fix-stack-alignment.patch
    else
      fetchpatch {
        name = "ghc-9.8-llvm-fix-stack-alignment.patch";
        url = "https://gitlab.haskell.org/ghc/ghc/-/commit/e9af2cf3f16ab60b5c79ed91df95359b11784df6.patch";
        hash = "sha256-RmYwFN3c3AgJxF9KXWQLdwOgugzepCW1wcTdJX1h0C4=";
      }
  )

  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/8999>
  (
    if lib.versionOlder version "9.6" then
      ./ghc-9.4-llvm-use-new-pass-manager.patch
    else if lib.versionOlder version "9.8" then
      ./ghc-9.6-llvm-use-new-pass-manager.patch
    else
      ./ghc-9.8-llvm-use-new-pass-manager.patch
  )
]

++ lib.optionals (lib.versionOlder version "9.12") [
  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12726>
  (fetchpatch {
    name = "ghc-9.4-llvm-support-16-17-18.patch";
    url = "https://gitlab.haskell.org/ghc/ghc/-/commit/ae170155e82f1e5f78882f7a682d02a8e46a5823.patch";
    hash = "sha256-U1znWqXZTORmAg480p5TjTL53T2Zn+1+9Fnk2V1Drfs=";
  })

  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13311>
  (fetchpatch {
    name = "ghc-9.4-llvm-support-19.patch";
    url = "https://gitlab.haskell.org/ghc/ghc/-/commit/36bbb167f354a2fbc6c4842755f2b1e374e3580e.patch";
    excludes = [ ".gitlab-ci.yml" ];
    hash = "sha256-v8T/FtriDPbibcIDZmU2yotBoDVo+wU2+gw+CCdQlm0=";
  })
]

++ lib.optionals (lib.versionOlder version "9.14") [
  # <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14600>
  (fetchpatch {
    name = "ghc-9.4-llvm-support-20.patch";
    url = "https://gitlab.haskell.org/ghc/ghc/-/commit/ca03226db2db2696460bfcb8035dd3268d546706.patch";
    hash = "sha256-7cO049DQtJHUAhwPujoFO+zQtXsMg6VFTHtMDwenrKs=";
  })
]
+3 −3
Original line number Diff line number Diff line
@@ -386,7 +386,9 @@ stdenv.mkDerivation (
      # elimination on aarch64-darwin. (see
      # https://github.com/NixOS/nixpkgs/issues/140774 for details).
      ./Cabal-at-least-3.6-paths-fix-cycle-aarch64-darwin.patch
    ];
    ]

    ++ (import ./common-llvm-patches.nix { inherit lib version fetchpatch; });

    postPatch = "patchShebangs .";

@@ -671,8 +673,6 @@ stdenv.mkDerivation (
      timeout = 24 * 3600;
      platforms = lib.platforms.all;
      inherit (bootPkgs.ghc.meta) license;
      # To be fixed by <https://github.com/NixOS/nixpkgs/pull/440774>.
      broken = useLLVM;
    };

  }
+31 −0
Original line number Diff line number Diff line
From 701154fdbceff2edb121768eb660713a98580af8 Mon Sep 17 00:00:00 2001
From: Ben Gamari <ben@smart-cactus.org>
Date: Tue, 22 Aug 2023 12:23:26 -0400
Subject: [PATCH] llvmGen: Add export list to GHC.Llvm.MetaData

(cherry picked from commit fcfc1777c22ad47613256c3c5e7304cfd29bc761)
---
 compiler/GHC/Llvm/MetaData.hs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/compiler/GHC/Llvm/MetaData.hs b/compiler/GHC/Llvm/MetaData.hs
index f46ae0a101..3526c11bc3 100644
--- a/compiler/GHC/Llvm/MetaData.hs
+++ b/compiler/GHC/Llvm/MetaData.hs
@@ -1,6 +1,12 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
-module GHC.Llvm.MetaData where
+module GHC.Llvm.MetaData
+  ( MetaId(..)
+  , ppr
+  , MetaExpr(..)
+  , MetaAnnot(..)
+  , MetaDecl(..)
+  ) where
 
 import GHC.Prelude
 
-- 
2.50.1
+40 −0
Original line number Diff line number Diff line
From 51765e343e9829f1d3e95d1d7303fa3594ae91cc Mon Sep 17 00:00:00 2001
From: Ben Gamari <ben@smart-cactus.org>
Date: Tue, 22 Aug 2023 12:24:53 -0400
Subject: [PATCH] llvmGen: Allow LlvmLits in MetaExprs

This omission appears to be an oversight.

(cherry picked from commit 5880fff6d353a14785c457999fded5a7100c9514)
---
 compiler/GHC/Llvm/MetaData.hs | 1 +
 compiler/GHC/Llvm/Ppr.hs      | 1 +
 2 files changed, 2 insertions(+)

diff --git a/compiler/GHC/Llvm/MetaData.hs b/compiler/GHC/Llvm/MetaData.hs
index f46ae0a101..121cdd5788 100644
--- a/compiler/GHC/Llvm/MetaData.hs
+++ b/compiler/GHC/Llvm/MetaData.hs
@@ -68,6 +68,7 @@ instance Outputable MetaId where
 
 -- | LLVM metadata expressions
 data MetaExpr = MetaStr !LMString
+              | MetaLit !LlvmLit
               | MetaNode !MetaId
               | MetaVar !LlvmVar
               | MetaStruct [MetaExpr]
diff --git a/compiler/GHC/Llvm/Ppr.hs b/compiler/GHC/Llvm/Ppr.hs
index f48e7aa034..bc88a13439 100644
--- a/compiler/GHC/Llvm/Ppr.hs
+++ b/compiler/GHC/Llvm/Ppr.hs
@@ -256,6 +256,7 @@ ppMetaExpr :: LlvmCgConfig -> MetaExpr -> SDoc
 ppMetaExpr opts = \case
   MetaVar (LMLitVar (LMNullLit _)) -> text "null"
   MetaStr    s                     -> char '!' <> doubleQuotes (ftext s)
+  MetaLit    l                     -> ppTypeLit opts l
   MetaNode   n                     -> ppr n
   MetaVar    v                     -> ppVar opts v
   MetaStruct es                    -> char '!' <> braces (ppCommaJoin (map (ppMetaExpr opts) es))
-- 
2.50.1
Loading