Skip to content

PHONY: stable-ghc-9.14 additions#119

Draft
angerman wants to merge 135 commits into
ghc-9.14from
stable-ghc-9.14
Draft

PHONY: stable-ghc-9.14 additions#119
angerman wants to merge 135 commits into
ghc-9.14from
stable-ghc-9.14

Conversation

@angerman

@angerman angerman commented Nov 29, 2025

Copy link
Copy Markdown

Summary

This PR tracks all additions in stable-ghc-9.14 relative to upstream ghc-9.14.

Cabal-based Multi-Stage Build System

  • Modularize RTS: extract headers (rts-headers) and filesystem utilities (rts-fs) into separate packages
  • Implement cabal-based multi-stage build system (stage0 → stage1 → stage2)
  • Split RTS into sub-libraries (threaded/non-threaded, debug/nodebug variants)
  • Add -no-rts compiler flag for bootstrap builds

Static Linking Improvements

  • Add -fully-static and -exclude-static-external flags
  • Proper support for statically linking executables
  • Better error handling when linking statically
  • Ensure extra-libraries-static is consistently defined

Bundled libffi

  • Add libffi-clib as bundled library (replaces system libffi dependency)
  • Enable PIC on linux/freebsd x86_64

Build System & Tooling

  • Add ghc-toolchain --output-settings support
  • Add genprimopcode --wrappers/--prim-module options
  • Add ghc-config additional fields
  • Add ghc-pkg --target support and mermaid diagram generation
  • Better "could not execute" error messages

CI & Testing

  • Add release workflow
  • Fix various test fragility (T13786, T7040_ghci, T25240, T20604)
  • Skip problematic tests (T14999, uniques test without git repo)
  • Testsuite adjustments for RTS split

Fixes

  • Fix FreeBSD stage2/stage3 builds
  • Fix header copying in Makefile
  • Fix preprocessor flags in RTS
  • Allow building with boot compiler lacking ghc-internal
  • Warn when -dynamic is mixed with -staticlib

angerman and others added 28 commits March 5, 2026 12:35
This change reverts part of !14544, which forces the bootstrap
compiler to have ghc-internal.  As such it breaks booting with
ghc 9.8.4. A better solution would be to make this conditional
on the ghc version in the cabal file!
…ernal

If the boot compiler doesn't have ghc-internal use "<unavailble>" as the
`cGhcInternalUnitId`.  This allows booting with older compilers. The
subsequent stage2 compilers will have the proper ghc-internal id from
their stage1 compiler, that boots them.
Make the first simple optimization pass after desugaring a real CoreToDo
pass. This allows CorePlugins to decide whether they want to be executed
before or after this pass.
It's more user-friendly to directly print the right thing instead of
requiring the user to retry with the additional `-dppr-debug` flag.
mermaid is a common diagram format that can be inlined in markdown
files, and e.g. github will even render it.  This change adds
support for mermaid diagram output to ghc-pkg.
This adds support to ghc-pkg to infer a package-db from a target name.
Add a new optional unitDataDir field to GhcPkg.InstalledPackageInfo
and populate it in ghc-pkg's convertPackageInfoToCacheFormat.

This is needed by the WASM linker to locate per-package data files
(specifically WasmGlobalRegs.S) via GHC.Unit.Database.unitDataDir
at link time, without requiring a file-system search.
By mistake we tried to use deriveConstant without passing
`--gcc-flag -fcommon` (which Hadrian does) and it failed.

This patch adds deriveConstant support for constants stored in the .bss
section so that deriveConstant works without passing `-fcommon` to the C
compiler.
Apple's LLVM toolchain uses `arm64` as the canonical architecture name
for AArch64 on Apple platforms, while GNU config.sub normalises to
`aarch64`. This mismatch causes `--target=aarch64-apple-darwin` to be
passed to clang, which conflicts with toolchain wrappers (e.g. nix
cc-wrapper) that expect `arm64-apple-darwin`.

The result is thousands of test failures on aarch64-darwin because the
cc-wrapper warning pollutes compiler output and the target flag
interaction breaks compilation.

Fix by adding normaliseLlvmTarget that rewrites `aarch64-apple-*` to
`arm64-apple-*` for the LLVM target triple, matching Apple conventions
and the existing llvm-targets file which already uses arm64-apple-darwin.
Add AC_ARG_WITH([compiler]) to allow specifying the Haskell compiler
via the --with-compiler flag, consistent with standard autoconf practices
for tool configuration.

This provides an alternative to setting the GHC environment variable,
making the build system more flexible and consistent with other
configure scripts that accept --with-* options for tools.
Add entries to prevent AI agent config files from being accidentally
committed. These files contain project-specific instructions for various
AI coding assistants and should remain local.

Covers: Claude Code, GitHub Copilot, Cursor, Gemini CLI/Jules,
OpenAI Codex, and JetBrains Junie.

See: https://agents.md/ for the AGENTS.md standard
Fixes #26434

In detail, this does a number of things:
* Makes GHC aware of 'extra-libraries-static' (this changes the package
  database format).
* Adds a switch '-static-external' that will honour 'extra-libraries-static'
  to link external system dependencies statically.
* Adds a new field to settings/targets: "ld supports verbatim namespace".
  This field is used by '-static-external' to conditionally use '-l:foo.a'
  syntax during linking, which is more robust than trying to find the
  absolute path to an archive on our own.
* Adds a switch '-fully-static' that is meant as a high-level interface
  for e.g. cabal. This also honours 'extra-libraries-static'.

This also attempts to clean up the confusion around library search directories.
At the moment, we have 3 types of directories in the package database
format:
* library-dirs
* library-dirs-static
* dynamic-library-dirs

However, we only have two types of linking: dynamic or static. Given the
existing logic in 'mungeDynLibFields', this patch assumes that
'library-dirs' is really just nothing but a fallback and always
prefers the more specific variants if they exist and are non-empty.

Conceptually, we should be ok with even just one search dirs variant.
Haskell libraries are named differently depending on whether they're
static or dynamic, so GHC can conveniently pick the right one depending
on the linking needs. That means we don't really need to play tricks
with search paths to convince the compiler to do linking as we want it.
For system C libraries, the convention has been anyway to place static and
dynamic libs next to each other, so we need to deal with that issue
anyway and it is outside of our control. But this is out of the scope
of this patch.

This patch is backwards compatible with cabal. Cabal should however
be patched to use the new '-fully-static' switch.
"Executable" seems more appropriate.
This patch teaches GHC how to build the external interpreter program
when it is missing. As long as we have the `ghci` library, doing this is
trivial so most of this patch is refactoring for doing it sanely.

(cherry picked from commit 55eab80)
The comment still referenced the old `linkBinary` name after
the rename to `linkExecutable` in 55ff022.
sheaf and others added 29 commits March 10, 2026 06:40
When we are simplifying the RHS of a rule, we make sure to only apply
rewrites from rules that are active throughout the original rule's
range of active phases.

For example, if a rule is always active, we only fire rules that are
themselves always active when simplifying the RHS. Ditto for inline
activations.

This is achieved by setting the simplifier phase to a range of phases,
using the new SimplPhaseRange constructor. Then:

  1. When simplifying the RHS of a rule, or of a stable unfolding,
     we set the simplifier phase to a range of phases, computed from
     the activation of the RULE/unfolding activation, using the
     function 'phaseFromActivation'.

     The details are explained in Note [What is active in the RHS of a RULE?]
     in GHC.Core.Opt.Simplify.Utils.

  2. The activation check for other rules and inlinings is then:
     does the activation of the other rule/inlining cover the whole
     phase range set in sm_phase? This continues to use the 'isActive'
     function, which now accounts for phase ranges.

On the way, this commit also moves the exact-print SourceText annotation
from the Activation datatype to the ActivationAnn type. This keeps the
main Activation datatype free of any extra cruft.

Fixes #26323
See (CWw4) in Note [Cast worker/wrapper].

The true payload is in the change to the definition of
   GHC.Types.Id.Info.hasInlineUnfolding
Everthing else is just documentation.

There is a 2% compile time decrease for T13056;
I'll take the win!

Metric Decrease:
    T13056
Cabal-syntax's Distribution.PackageDescription.FieldGrammar triggers a
near-infinite simplifier loop with the backported simplifier fixes
(#26323, #26903). Setting -O0 for the Cabal-syntax package avoids this
issue with minimal impact since it's only used at configure time.
…ranch

Add .hs and .stderr files for tests T8331, T26349, T26709, T26615, T26615a, T26722, T26805, T26826 from upstream GHC.

Update expected output to match stable branch compiler behavior (different optimization pipeline state, module paths, specialisation results).

Add -dsuppress-uniques to T26349 to fix cross-platform stderr mismatch (unique suffixes differ between Linux and Windows).
MOVK (move with keep) modifies only a 16-bit slice of the destination
register, so the destination is both read and written. The register
allocator must know this to avoid clobbering live values. Update
regUsageOfInstr to list the destination in both src and dst sets.

No regression test: triggering the misallocation requires specific
register pressure around a MOVK sequence, which is difficult to
reliably provoke from Haskell source.
signExtendReg was using SXTH (sign-extend halfword, 16-bit) for
W32-to-W64 sign extension. This should be SXTW (sign-extend word,
32-bit). SXTH only sign-extends the lower 16 bits, producing wrong
results for 32-bit values whose bit 15 differs from bit 31.

Uncomment the SXTW constructor in the Instr type and wire it through
regUsageOfInstr, patchRegsOfInstr, Ppr, and instructionName.

Includes assembly output test (grep for sxtw) and runtime test
verifying sign extension of negative Int32 values to Int64.

Made-with: Cursor
The unsigned right shift (MO_U_Shr) for sub-word widths (W8, W16)
with a variable shift amount was emitting ASR (arithmetic/signed shift
right) after zero-extending with UXTB/UXTH. This should be LSR
(logical/unsigned shift right). After zero-extension the upper bits
happen to be 0 so ASR produces the same result, but it is semantically
wrong and would break if the zero-extension were ever optimized away.

Includes assembly output test (grep for lsr) and runtime test
verifying unsigned right shift of Word8 and Word16 values.

Made-with: Cursor
This commit adds a simple occurs check to the deep subsumption code,
more specifically to the FunTy vs non-FunTy case of
GHC.Tc.Utils.Unify.tc_sub_type_deep.

See the new Wrinkle [tc_sub_type_deep occurs check] in
Note [FunTy vs non-FunTy case in tc_sub_type_deep] in GHC.Tc.Utils.Unify.

Fixes #26823
This new flag automatically adds all loaded targets to the GHCi session
by adding an `InteractiveImport` for the loaded targets.

By default, this flag is disabled, as it potentially increases memory-usage.

This interacts with the flag `-fno-load-initial-targets` as follows:

* If no module is loaded, no module is added as an interactive import.
* If a reload loads up to a module, all loaded modules are added as
  interactive imports.
* Unloading modules removes them from the interactive context.

Fixes #26866 by rendering the use of a `-ghci-script` to achieve the
same thing redundant.
Remove test entries where source files don't exist on this branch (T26330, T23162a-d, T26861, T26862, msse-option-order, avx512 tests).

Update expected output for tests that differ on stable: GHCi 'import (implicit)' instead of 'import (generated)', and T26823 truncated context display.
The T21651 concurrency stress test times out on aarch64-darwin CI
runners. Mark it fragile since it's a CI environment issue, not a
code regression.
ss_conv was emitting raw SBFM for all MO_SS_Conv cases. For widening conversions (e.g. W32->W64), emit the canonical SXTB/SXTH/SXTW instructions instead, with the correct source register width (Wn not Xn).

Also fix signExtendReg to use source register width for the source operand of SXTW/SXTH/SXTB instructions (latent bug: source always used destination width).
FP_VISIBILITY_HIDDEN was called in rts/configure.ac but the macro
definition was removed in an earlier commit. Remove the orphaned
call to fix autoconf warnings.
The macOS-13 GitHub Actions runner now ships with Homebrew llvm@18,
whose libunwind triggers a linker warning on every invocation:

  ld: warning: reexported library with install name
  '/usr/local/opt/llvm@18/lib/libunwind.1.dylib' ... couldn't be
  matched with any parent library and will be linked directly

This causes ~190 spurious test failures (bad stderr / stderr mismatch)
on the Mac x86_64 CI. Filter the warning in both normalise_errmsg and
normalise_output, alongside the existing macOS ld warning patterns.
Recent macOS and Windows CI runner images set CC to include flags
(e.g. "/usr/bin/cc -std=gnu23"). The --gcc-program argument was
passed directly to rawSystem which treats the entire string as an
executable path, causing:

  deriveConstants: /usr/bin/cc -std=gnu23: rawSystem: posix_spawnp:
  does not exist (No such file or directory)

Split the --gcc-program value on whitespace: the first word becomes
the program path, remaining words are prepended to the gcc flags.
On Windows (MSYS2/CLANG64), the _utime function expects a
struct _utimbuf pointer. The CUtimbuf CTYPE was declared as
"struct utimbuf" which worked when clang treated them as compatible,
but with -std=gnu23 (now the default on updated CI runner images)
clang errors on the type mismatch:

  incompatible pointer types passing 'struct utimbuf *' to
  parameter of type 'struct _utimbuf *'

Use the correct Windows type name in the CTYPE pragma.
Point all stage cabal.project files at stable-haskell/cabal
wip/angerman/compile-less (44817477ff6d22de4bfa4307e061df58f319d3b6),
which is based on Andrea Bedini's wip/andrea/compile-less and includes:

- Cross-compilation support (Stage/Toolchain architecture)
- Local store (replaces in-place builds)
- Recompilation avoidance (file monitor tracking for installed packages)
- hasufell's "Stop stealing the vowels" and "Fix caching of remote source tarballs"
- TOCTOU race fix for BuildInplaceOnly tarball extraction
wip/angerman/compile-less has been renamed to stable-haskell/master
…split

Cabal 3.17 (commit edb808a0b8b, "allow setting the logging handle")
split the old Verbosity type into VerbosityFlags (the CLI-passable
part) plus VerbosityHandles. configVerbosity now yields a Flag
VerbosityFlags, which must be wrapped back into a Verbosity via
mkVerbosity before being passed to Cabal library functions such as
requireProgram, getProgramOutput and info.

Add a CPP-guarded configVerbosity' helper to both Setup.hs files, and
in compiler/Setup.hs replace the bare 'normal' literal (now a
VerbosityFlags) with the in-scope 'verbosity' parameter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
It's required since cabal commit 6867dd5da57194337bab0079bbe2f1c21e11662f
It's required since cabal commit 6867dd5da57194337bab0079bbe2f1c21e11662f
Statically-linked executables link only system libraries (libc/libm) and
load nothing from ../lib, so they need no rpath. patchelf also cannot
rewrite the large statically-linked ghc/haddock/ghc-iserv binaries (it
fails with "virtual address space underrun"). Gate the dist binary rpath
loop under DYNAMIC=1, matching the existing gating of the shared-library
rpath step.
The hackage-security package is only ever used in stage0 to build cabal-install.
…igure

Replace the configure-driven static/dynamic selection for stage2 with
explicit cabal project files.

Previously a `--enable-dynamic` autoconf toggle, together with the
`m4/accumulate.m4` helper macros, generated cabal.project.stage2.settings
from a .in template, while the Makefile separately appended
--enable-dynamic to GHC_CONFIGURE_ARGS when DYNAMIC=1. Keeping these two
mechanisms in sync was fragile.

Now the stage2 configuration is split into a shared
cabal.project.stage2.common plus two thin variants that import it:

  - cabal.project.stage2.static  (default; shared: False)
  - cabal.project.stage2.dynamic (shared: True, executable-dynamic: True,
                                  rts +dynamic)

The Makefile selects the project file directly through DYNAMIC_SUFFIX and
the new CABAL_PROJECT_FILE variable, so DYNAMIC=1 picks the dynamic file
without any configure round-trip.

Removed as no longer needed:
  - the --enable-dynamic configure option and its substitution logic
  - cabal.project.stage2.settings(.in) template
  - m4/accumulate.m4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.