[Git][ghc/ghc][wip/backports-9.12.4] 65 commits: wasm: ensure setKeepCAFs() is called in ghci
by Zubin (@wz1000) 03 Mar '26
by Zubin (@wz1000) 03 Mar '26
03 Mar '26
Zubin pushed to branch wip/backports-9.12.4 at Glasgow Haskell Compiler / GHC
Commits:
5d01c3f3 by Cheng Shao at 2026-03-03T14:34:13+05:30
wasm: ensure setKeepCAFs() is called in ghci
This patch is a critical bugfix for #26106, see comment and linked
issue for details.
(cherry picked from commit 10f06163d9adcb3b6e6438f1524faaca3bf6c3b2)
- - - - -
fe0d547c by sheaf at 2026-03-03T14:34:13+05:30
Use tcMkScaledFunTys in matchExpectedFunTys
We should use tcMkScaledFunTys rather than mkScaledFunTys in
GHC.Tc.Utils.Unify.matchExpectedFunTys, as the latter crashes
when the kind of the result type is a bare metavariable.
We know the result is always Type-like, so we don't need scaledFunTys
to try to rediscover that from the kind.
Fixes #26277
(cherry picked from commit 624afa4a65caa8ec23f85e70574dfb606f90c173)
- - - - -
f8b1b628 by sheaf at 2026-03-03T14:34:13+05:30
Improve Notes about disambiguating record updates
This commit updates the notes [Disambiguating record updates] and
[Type-directed record disambiguation], in particular adding more
information about the deprecation status of type-directed disambiguation
of record updates.
(cherry picked from commit a2d9d7c2073867ee0cabb8d49f93246d95ec0b09)
- - - - -
86a1c629 by sheaf at 2026-03-03T14:34:13+05:30
Add test for #26216
(cherry picked from commit 2e73f3426ab6e3cf1938b53831005593f3fd351c)
- - - - -
01e90a97 by Vladislav Zavialov at 2026-03-03T14:34:13+05:30
Fix PREP_MAYBE_LIBRARY in prep_target_file.m4
This change fixes a configure error introduced in:
commit 8235dd8c4945db9cb03e3be3c388d729d576ed1e
ghc-toolchain: Move UseLibdw to per-Target file
Now the build no longer fails with:
acghc-toolchain: Failed to read a valid Target value from hadrian/cfg/default.target
(cherry picked from commit 1480872af6b80db1b035a44409188416df041048)
- - - - -
6bad23d7 by Cheng Shao at 2026-03-03T14:34:13+05:30
rts: remove obsolete CC_SUPPORTS_TLS logic
This patch removes obsolete CC_SUPPORTS_TLS logic throughout the rts,
given __thread is now uniformly supported by C toolchains of all
platforms we currently support.
(cherry picked from commit 0f034942724233e1457549123b46880f7b93e805)
- - - - -
3b9b5510 by Cheng Shao at 2026-03-03T14:34:14+05:30
rts: remove obsolete HAS_VISIBILITY_HIDDEN logic
This patch removes obsolete HAS_VISIBILITY_HIDDEN logic throughout the
rts, given __attribute__((visibility("hidden"))) is uniformly
supported by C toolchains of all platforms we currently support.
(cherry picked from commit ef7056554df5603ec4d1e33193abe953970e6ab3)
- - - - -
b44110fd by Cheng Shao at 2026-03-03T14:34:14+05:30
rts: remove -O3 pragma hack in Hash.c
This patch removes an obsolete gcc pragma to specify -O3 in Hash.c.
Hadrian already passes the right flag.
(cherry picked from commit 9fdc1f7d855cc61f90de909875f6ae0d6798dca7)
- - - - -
528eef23 by Cheng Shao at 2026-03-03T14:34:14+05:30
wasm: fix dyld handling for forward declared GOT.func items
This patch fixes wasm shared linker's handling of forward declared
GOT.func items, see linked issue for details. Also adds T26430 test to
witness the fix. Fixes #26430.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 867c26755e8855c6df949e65df0c2aebc9da64c3)
- - - - -
d7b7bf7f by Cheng Shao at 2026-03-03T14:34:14+05:30
rts: remove obsolete __GNUC__ related logic
This patch removes obsolete `__GNUC__` related logic, given on any
currently supported platform and toolchain, `__GNUC__ >= 4` is
universally true. Also pulls some other weeds and most notably, use
`__builtin___clear_cache` for clang as well, since clang has supported
this gcc intrinsic since 2014, see
https://github.com/llvm/llvm-project/commit/c491a8d4577052bc6b3b4c72a7db6a7….
(cherry picked from commit 67de53a6ced23caad640d2c7421089242f0dfb76)
- - - - -
a9e16d30 by Cheng Shao at 2026-03-03T14:34:14+05:30
hadrian: fix GHC.Platform.Host generation for cross stage1
This patch fixes incorrectly GHC.Platform.Host generation logic for
cross stage1 in hadrian (#26449). Also adds T26449 test case to
witness the fix.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 8cbe006ad09d5a64e4a3cdf4c91a8b81ff1511be)
- - - - -
837611d4 by Luite Stegeman at 2026-03-03T14:34:14+05:30
rts: Fix lost wakeups in threadPaused for threads blocked on black holes
The lazy blackholing code in threadPaused could overwrite closures
that were already eagerly blackholed, and as such wouldn't have a
marked update frame. If the black hole was overwritten by its
original owner, this would lead to an undetected collision, and
the contents of any existing blocking queue being lost.
This adds a check for eagerly blackholed closures and avoids
overwriting their contents.
Fixes #26324
(cherry picked from commit a1de535f762bc23d4cf23a5b1853591dda12cdc9)
- - - - -
2458e684 by Luite Stegeman at 2026-03-03T14:34:14+05:30
rts: push the correct update frame in stg_AP_STACK
The frame contains an eager black hole (__stg_EAGER_BLACKHOLE_info) so
we should push an stg_bh_upd_frame_info instead of an stg_upd_frame_info.
(cherry picked from commit b7e21e498d39e0ee764e3237544b4c39ddf98467)
- - - - -
cc929fbb by Cheng Shao at 2026-03-03T14:34:14+05:30
testsuite: remove unused expected output files
This patch removes unused expected output files in the testsuites on
platforms that we no longer support.
(cherry picked from commit 6992ac097b9da989f125f896afe21b75dba8b4c9)
- - - - -
5f00f932 by Ben Gamari at 2026-03-03T14:34:14+05:30
rts/posix: Enforce iteration limit on heap reservation logic
Previously we could loop indefinitely when attempting to get an address
space reservation for our heap. Limit the logic to 8 iterations to
ensure we instead issue a reasonable error message.
Addresses #26151.
(cherry picked from commit ff1650c96c61af02e193854312a9ccd303968e47)
- - - - -
c04e42cf by Ben Gamari at 2026-03-03T14:34:14+05:30
rts/posix: Hold on to low reservations when reserving heap
Previously when the OS gave us an address space reservation in low
memory we would immediately release it and try again. However, on some
platforms this meant that we would get the same allocation again in the
next iteration (since mmap's `hint` argument is just that, a hint).
Instead we now hold on to low reservations until we have found a
suitable heap reservation.
Fixes #26151.
(cherry picked from commit 0184455728f841a699648f879fdb29128081fc6b)
- - - - -
5667080d by Julian Ospald at 2026-03-03T14:34:14+05:30
ghc-toolchain: Drop `ld.gold` from merge object command
It's deprecated.
Also see #25716
(cherry picked from commit c58f9a615f05e9d43629f6e846ae22cad2a6163d)
- - - - -
72997ed1 by Ben Gamari at 2026-03-03T14:34:14+05:30
gitlab-ci: Make RELEASE_JOB an input
Rather than an undocumented variable.
(cherry picked from commit f9790ca81deb8b14ff2eabf701aecbcfd6501963)
- - - - -
261034be by Cheng Shao at 2026-03-03T14:34:14+05:30
testsuite: fix T3586 for non-SSE3 platforms
`T3586.hs` contains `-fvia-C -optc-msse3` which I think is a
best-effort basis to harvest the C compiler's auto vectorization
optimizations via the C backend back when the test was added. The
`-fvia-C` part is now a deprecated no-op because GHC can't fall back
to the C backend on a non-unregisterised build, and `-optc-msse3`
might actually cause the test to fail on non x86/x64 platforms, e.g.
recent builds of wasi-sdk would report `wasm32-wasi-clang: error:
unsupported option '-msse3' for target 'wasm32-unknown-wasi'`.
So this patch cleans up this historical cruft. `-fvia-C` is removed,
and `-optc-msse3` is only passed when cpuid contains `pni` (which
indicates support of SSE3).
(cherry picked from commit 70ee825a516bcf7aac762bfedb4a017d35f8dcf3)
- - - - -
6e88662b by Julian Ospald at 2026-03-03T14:34:14+05:30
Improve error handling in 'getPackageArchives'
When the library dirs in the package conf files are not set up correctly,
the JS linker will happily ignore such packages and not link against them,
although they're part of the link plan.
Fixes #26383
(cherry picked from commit 91b6be10bd58c2bfc1c7c22e81b06ab3be583228)
- - - - -
f42b5147 by Ben Gamari at 2026-03-03T14:34:35+05:30
rts: Annotate BCOs with their Name
This introduces a new bytecode instruction, `BCO_NAME`, to aid in debugging
bytecode execution. This instruction is injected by `mkProtoBCO` and
captures the Haskell name of the BCO. It is then printed by the
disassembler, allowing ready correlation with STG dumps.
(cherry picked from commit 5192a75fe9b272e8b1ef290fa834714c81bd1f79)
- - - - -
07fb75c7 by sheaf at 2026-03-03T14:34:40+05:30
Bad record update msg: allow out-of-scope datacons
This commit ensures that, when we encounter an invalid record update
(because no constructor exists which contains all of the record fields
mentioned in the record update), we graciously handle the situation in
which the constructors themselves are not in scope. In that case,
instead of looking up the constructors in the GlobalRdrEnv, directly
look up their GREInfo using the lookupGREInfo function.
Fixes #26391
(cherry picked from commit cef8938f3c0d22583f01d5ea29e6109bccd36040)
- - - - -
4ccd32a9 by Cheng Shao at 2026-03-03T14:34:40+05:30
rts: remove obsolete COMPILING_WINDOWS_DLL logic
This patch removes obsolete COMPILING_WINDOWS_DLL logic throughout the
rts. They were once used for compiling to win32 DLLs, but we haven't
been able to compile Haskell units to win32 DLLs for many years now,
due to PE format's restriction of no more than 65536 exported symbols
in a single DLL.
(cherry picked from commit b8cfa8f741729ef123569fb321c4b2ab4a1a941c)
- - - - -
d0d24d38 by Julian Ospald at 2026-03-03T14:34:40+05:30
Skip uniques test if sources are not available
(cherry picked from commit 5dc2e9eaf60fd72771bf2e8112aec182665461a1)
- - - - -
870dfaf4 by Julian Ospald at 2026-03-03T14:34:40+05:30
rts: remove unneccesary cabal flags
We perform those checks via proper autoconf macros
instead that do the right thing and then add those
libs to the rts buildinfo.
(cherry picked from commit 643ce801a8b559071683cad0e5adbc26b9fc8385)
- - - - -
47358676 by Wang Xin at 2026-03-03T14:34:40+05:30
Add -mcmodel=medium moduleflag to generated LLVM IR on LoongArch platform
With the Medium code model, the jump range of the generated jump
instruction is larger than that of the Small code model. It's a
temporary fix of the problem descriped in https://gitlab.haskell
.org/ghc/ghc/-/issues/25495. This commit requires that the LLVM
used contains the code of commit 9dd1d451d9719aa91b3bdd59c0c6679
83e1baf05, i.e., version 8.0 and later. Actually we should not
rely on LLVM, so the only way to solve this problem is to implement
the LoongArch backend.
Add new type for codemodel
(cherry picked from commit e70d41406b5d5638b42c4d8222cd03e76bbfeb86)
- - - - -
0281a324 by Peng Fan at 2026-03-03T14:34:40+05:30
Pass the mcmodel=medium parameter to CC via GHC
Ensure that GHC-driver builds default to mcmodel=medium, so that GHC
passes this default parameter to CC without having to add it to the
compiled project.
Commit e70d41406b5d5638b42c4d8222cd03e76bbfeb86 does not ensure that all
GHC-built object files have a default model of medium, and will raise an
R_LARCH_B26 overflow error.
(cherry picked from commit 1a3f11314cc7b8dbf9af03dd2ae2cb066a998d63)
- - - - -
d7edae1e by Ben Gamari at 2026-03-03T14:34:40+05:30
gitlab-ci: Run ghcup-metadata jobs on OpenCape runners
This significantly reduces our egress traffic
and makes the jobs significantly faster.
(cherry picked from commit ff3f0d09bce1c261638b572af2bac1d87f1f6df7)
- - - - -
b1600913 by Luite Stegeman at 2026-03-03T14:34:40+05:30
rts: fix eager black holes: record mutated closure and fix assertion
This fixes two problems with handling eager black holes, introduced
by a1de535f762bc23d4cf23a5b1853591dda12cdc9.
- the closure mutation must be recorded even for eager black holes,
since the mutator has mutated it before calling threadPaused
- The assertion that an unmarked eager black hole must be owned by
the TSO calling threadPaused is incorrect, since multiple threads
can race to claim the black hole.
fixes #26495
(cherry picked from commit 3ba3d9f9db784c903ebe8fd617447ce62d30b7d3)
- - - - -
d5deb890 by ARATA Mizuki at 2026-03-03T14:34:40+05:30
LLVM backend: Pass the +evex512 attribute to LLVM 18+ if -mavx512f is set
The newer LLVM requires the +evex512 attribute to enable use of ZMM registers.
LLVM exhibits a backward-compatible behavior if the cpu is `x86-64`, but not if `penryn`.
Therefore, on macOS, where the cpu is set to `penryn`, we need to explicitly pass +evex512.
Fixes #26410
(cherry picked from commit b22777d4b7182f40a31eb430fa27f5fb9ef0f292)
- - - - -
4167e8f8 by Matthew Pickering at 2026-03-03T14:34:40+05:30
hadrian: Use a response file to invoke GHC for dep gathering.
In some cases we construct an argument list too long for GHC to
handle directly on windows. This happens when we generate
the dependency file because the command line will contain
references to a large number of .hs files.
To avoid this we now invoke GHC using a response file when
generating dependencies to sidestep length limitations.
Note that we only pass the actual file names in the dependency
file. Why? Because this side-steps #26560
(cherry picked from commit 9d371d23c526fd160d7e99bef2bc7da825cf3c0f)
- - - - -
60ea5d02 by Andreas Klebinger at 2026-03-03T14:34:40+05:30
Add hpc to release script
(cherry picked from commit 64ec82ffa7f48399e18fcec43051d2b7ddcb7cc2)
- - - - -
ea683d49 by Matthew Pickering at 2026-03-03T14:34:40+05:30
rts: Fix a deadlock with eventlog flush interval and RTS shutdown
The ghc_ticker thread attempts to flush at the eventlog tick interval, this requires
waiting to take all capabilities.
At the same time, the main thread is shutting down, the schedule is
stopped and then we wait for the ticker thread to finish.
Therefore we are deadlocked.
The solution is to use `newBoundTask/exitMyTask`, so that flushing can
cooperate with the scheduler shutdown.
Fixes #26573
(cherry picked from commit b7fe744598b4569cd0236268e4f6f5b9d27e12b7)
- - - - -
290925ab by Julian Ospald at 2026-03-03T14:34:40+05:30
rts: Fix object file format detection in loadArchive
Commit 76d1041dfa4b96108cfdd22b07f2b3feb424dcbe seems to
have introduced this bug, ultimately leading to failure of
test T11788. I can only theorize that this test isn't run
in upstream's CI, because they don't build a static GHC.
The culprit is that we go through the thin archive, trying
to follow the members on the filesystem, but don't
re-identify the new object format of the member. This pins
`object_fmt` to `NotObject` from the thin archive.
Thanks to @angerman for spotting this.
(cherry picked from commit fc958fc9eb6f6f4db473cdda23c381da8f32163d)
- - - - -
46edb530 by Simon Peyton Jones at 2026-03-03T14:34:40+05:30
Add missing InVar->OutVar lookup in SetLevels
As #26681 showed, the SetLevels pass was failing to map an InVar to
an OutVar. Very silly! I'm amazed it hasn't broken before now.
I have improved the type singatures (to mention InVar and OutVar)
so it's more obvious what needs to happen.
(cherry picked from commit 52d00c05e1d803b36c93295399fe931c871166bf)
- - - - -
addb45c9 by Cheng Shao at 2026-03-03T14:34:40+05:30
compiler: change sectionProtection to take SectionType argument
This commit changes `sectionProtection` to only take `SectionType`
argument instead of whole `Section`, since it doesn't need the Cmm
section content anyway, and it can then be called in parts of NCG
where we only have a `SectionType` in scope.
(cherry picked from commit 2433e91d41675d56f48f82d22430a8dee915e7a0)
- - - - -
4539ff6b by Cheng Shao at 2026-03-03T14:34:40+05:30
compiler: change isInitOrFiniSection to take SectionType argument
This commit changes `isInitOrFiniSection` to only take `SectionType`
argument instead of whole `Section`, since it doesn't need the Cmm
section content anyway, and it can then be called in parts of NCG
where we only have a `SectionType` in scope. Also marks it as
exported.
(cherry picked from commit e5926fbebf341ee547227d41710d78471eecd09c)
- - - - -
24a20380 by Cheng Shao at 2026-03-03T14:34:40+05:30
compiler: fix split sections on windows
This patch fixes split sections on windows by emitting the right
COMDAT section header in NCG, see added comment for more explanation.
Fix #26696 #26494.
-------------------------
Metric Decrease:
LargeRecord
T9675
size_hello_artifact
size_hello_artifact_gzip
size_hello_unicode
size_hello_unicode_gzip
Metric Increase:
T13035
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 244d57d79a555dcecc7590287bb14976d561291a)
- - - - -
86de7371 by Matthew Pickering at 2026-03-03T14:34:40+05:30
rts: Use INFO_TABLE_CONSTR for stg_dummy_ret_closure
Since the closure type is CONSTR_NOCAF, we need to use INFO_TABLE_CONSTR
to populate the constructor description field (this crashes ghc-debug
when decoding AP_STACK frames sometimes)
Fixes #26745
(cherry picked from commit 322dd6726b11c7101c28ffb8aeb7cb4cee34ab56)
- - - - -
641ad898 by Matthew Pickering at 2026-03-03T14:34:40+05:30
Evaluate backtraces for "error" exceptions at the moment they are thrown
See Note [Capturing the backtrace in throw] and
Note [Hiding precise exception signature in throw] which explain the
implementation.
This commit makes `error` and `throw` behave the same with regard to
backtraces. Previously, exceptions raised by `error` would not contain
useful IPE backtraces.
I did try and implement `error` in terms of `throw` but it started to
involve putting diverging functions into hs-boot files, which seemed to
risky if the compiler wouldn't be able to see if applying a function
would diverge.
CLC proposal: https://github.com/haskell/core-libraries-committee/issues/383
Fixes #26751
(cherry picked from commit 94dcd15e54146abecf9b4f5e47d258ca3cd40f1b)
- - - - -
f70083af by fendor at 2026-03-03T14:34:40+05:30
Remove `traceId` from ghc-pkg executable
(cherry picked from commit d0966e64880e9fa30ce07c0fa5ea28108c6e8ad9)
- - - - -
d4746a27 by sheaf at 2026-03-03T14:34:40+05:30
Don't re-use stack slots for growing registers
This commit avoids re-using a stack slot for a register that has grown
but already had a stack slot.
For example, suppose we have stack slot assigments
%v1 :: FF64 |-> StackSlot 0
%v2 :: FF64 |-> StackSlot 1
Later, we start using %v1 at a larger format (e.g. F64x2) and we need
to spill it again. Then we **must not** use StackSlot 0, as a spill
at format F64x2 would clobber the data in StackSlot 1.
This can cause some fragmentation of the `StackMap`, but that's probably
OK.
Fixes #26668
(cherry picked from commit 023c301c51e7346af3d4d773c448277ad3645ad2)
- - - - -
18e46517 by Cheng Shao at 2026-03-03T14:34:40+05:30
llvm: fix split sections for llvm backend
This patch fixes split sections for llvm backend:
- Pass missing `--data-sections`/`--function-sections` flags to
llc/opt.
- Use `(a)llvm.compiler.used` instead of `(a)llvm.used` to avoid sections
being unnecessarily retained at link-time.
Fixes #26770.
-------------------------
Metric Decrease:
libdir
size_hello_artifact
size_hello_unicode
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit b18b2c42c32488ad6d3480a56a1fcd753cad2023)
- - - - -
904cf121 by Matthew Pickering at 2026-03-03T14:34:40+05:30
Fix ghc-experimental GHC.Exception.Backtrace.Experimental module
This module wasn't added to the cabal file so it was never compiled or
included in the library.
(cherry picked from commit ee937134aa0ddf35c1a9dc7334c0aec0de13b719)
- - - - -
0183ff23 by Sylvain Henry at 2026-03-03T14:34:40+05:30
GC: don't use CAS without PARALLEL_GC on
If we're not using the parallel GC, there is no reason to do a costly
CAS. This was flagged as taking time in a perf profile.
(cherry picked from commit 0491f08a965df0d6448bd9cd940d2b86fca2db5d)
- - - - -
4a8166e3 by Sylvain Henry at 2026-03-03T14:34:40+05:30
GC: suffix parallel GC with "par" instead of "thr"
Avoid some potential confusion (see discussion in !15351).
(cherry picked from commit 211a8f5633f0a5069c0689171f60b57719a242be)
- - - - -
687ae59a by Cheng Shao at 2026-03-03T14:34:40+05:30
testsuite: avoid re.sub in favor of simple string replacements
This patch refactors the testsuite driver and avoids the usage of
re.sub in favor of simple string replacements when possible. The
changes are not comprehensive, and there are still a lot of re.sub
usages lingering around the tree, but this already addresses a major
performance bottleneck in the testsuite driver that might has to do
with quadratic or worse slowdown in cpython's regular expression
engine when handling certain regex patterns with large strings.
Especially on i386, and i386 jobs are the bottlenecks of all full-ci
validate pipelines!
Here are the elapsed times of testing x86_64/i386 with -j48 before
this patch:
x86_64: `Build completed in 6m06s`
i386: `Build completed in 1h36m`
And with this patch:
x86_64: `Build completed in 4m55s`
i386: `Build completed in 4m23s`
Fixes #26786.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit ca79475f6b4dfba991e2c933bac9c22d54a4950d)
- - - - -
f97e959e by Zubin Duggal at 2026-03-03T14:34:40+05:30
hadrian: Add ghc-{experimental,internal}.cabal to the list of dependencies of the doc target
We need these files to detect the version of these libraries
Fixes #26738
(cherry picked from commit 1b490f5a7bbdb1441948241e6089b31efba9db45)
- - - - -
4dcb62d4 by Jessica Clarke at 2026-03-03T14:34:40+05:30
PPC NCG: Use libcall for 64-bit cmpxchg on 32-bit PowerPC
There is no native instruction for this, and even if there were a
register pair version we could use, the implementation here is assuming
the values fit in a single register, and we end up only using / defining
the low halves of the registers.
Fixes: b4d39adbb5 ("PrimOps: Add CAS op for all int sizes")
Fixes: #23969
(cherry picked from commit ce2d62fba69d2ea0c74c46c50628feb8b81719d2)
- - - - -
b088981d by John Paul Adrian Glaubitz at 2026-03-03T14:34:40+05:30
rts: Switch prim to use modern atomic compiler builtins
The __sync_*() atomic compiler builtins have been deprecated in GCC
for a while now and also don't provide variants for 64-bit values
such as __sync_fetch_and_add_8().
Thus, replace them with the modern __atomic_*() compiler builtins and
while we're at it, also drop the helper macro CAS_NAND() which is now
no longer needed since we stopped using the __sync_*() compiler builtins
altogether.
Co-authored-by: Ilias Tsitsimpis <iliastsi(a)debian.org>
Fixes #26729
(cherry picked from commit 7c52c4f9bc8d6ae6404039ec02efe48fbf7a4778)
- - - - -
6b144301 by sterni at 2026-03-03T14:34:40+05:30
users_guide: fix runtime error during build with Sphinx 9.1.0
Appears that pathto is stricter about what it accepts now.
Tested Sphinx 8.2.3 and 9.1.0 on the ghc-9.10 branch.
Resolves #26810.
Co-authored-by: Martin Weinelt <hexa(a)darmstadt.ccc.de>
(cherry picked from commit e8f5a45de561ec80c88cd3da2c66502deb32d4c3)
- - - - -
40163af7 by Michael Karcher at 2026-03-03T14:34:40+05:30
NCG for PPC: add pattern for CmmRegOff to iselExpr64
Closes #26828
(cherry picked from commit 43d977619de65c0cf87695fa5d86f1a3ff3176c3)
- - - - -
e4742ab3 by Matthew Pickering at 2026-03-03T14:34:40+05:30
determinism: Use deterministic map for Strings in TyLitMap
When generating typeable evidence the types we need evidence for all
cached in a TypeMap, the order terms are retrieved from a type map
determines the order the bindings appear in the program.
A TypeMap is quite diligent to use deterministic maps, apart from in the
TyLitMap, which uses a UniqFM for storing strings, whose ordering
depends on the Unique of the FastString.
This can cause non-deterministic .hi and .o files.
An unexpected side-effect is the error message but RecordDotSyntaxFail8
changing. I looked into this with Sam and this change caused the
constraints to be solved in a different order which results in a
slightly different error message. I have accepted the new test, since
the output before was non-deterministic and the new output is consistent
with the other messages in that file.
Fixes #26846
(cherry picked from commit aeeb4a2034e80e26503eb88f5abde85e87a82f7b)
- - - - -
c88e9ef4 by Andrew Lelechenko at 2026-03-03T14:34:40+05:30
Upgrade text submodule to 2.1.4
(cherry picked from commit 9e4d70c2764d117c5cf753127f93056d66e4f0d7)
- - - - -
0f66d7bb by Zubin Duggal at 2026-03-03T14:34:40+05:30
Bump transformers submodule to 0.6.3.0
Fixes #26790
(cherry picked from commit ea0d1317a630799a6b7bea12b24ef7e1ea6ed512)
- - - - -
db406e28 by Matthew Pickering at 2026-03-03T14:34:41+05:30
determinism: Use a stable sort in WithHsDocIdentifiers binary instance
`WithHsDocIdentifiers` is defined as
```
71 data WithHsDocIdentifiers a pass = WithHsDocIdentifiers
72 { hsDocString :: !a
73 , hsDocIdentifiers :: ![Located (IdP pass)]
74 }
```
This list of names is populated from `rnHsDocIdentifiers`, which calls
`lookupGRE`, which calls `lookupOccEnv_AllNameSpaces`, which calls
`nonDetEltsUFM` and returns the results in an order depending on
uniques.
Sorting the list with a stable sort before returning the interface makes
the output deterministic and follows the approach taken by other fields
in `Docs`.
Fixes #26858
(cherry picked from commit 0020e38a021b5f0371c48fe73cddf8987acb1eb1)
- - - - -
fde01119 by Simon Peyton Jones at 2026-03-03T14:34:41+05:30
Fix subtle bug in cast worker/wrapper
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
(cherry picked from commit 99d8c146c12146e1e21b1f2d31809845d4afe9d4)
- - - - -
25c7f544 by Cheng Shao at 2026-03-03T14:34:41+05:30
wasm: use import.meta.main for proper distinction of nodejs main modules
This patch uses `import.meta.main` for proper distinction of nodejs
main modules, especially when the main module might be installed as a
symlink. Fixes #26916.
(cherry picked from commit 039f19778e35b193af0de2a2c6ed89556038627a)
- - - - -
d74bd4da by Simon Peyton Jones at 2026-03-03T14:45:53+05:30
Report solid equality errors before custom errors
This MR fixes #26255 by
* Reporting solid equality errors like
Int ~ Bool
before "custom type errors". See comments in `report1` in
`reportWanteds`
* Suppressing errors that arise from superclasses of
Wanteds. See (SCE1) in Note [Suppressing confusing errors]
More details in #26255.
(cherry picked from commit ba210d981b0812aea604f884d3c0aada4c8ca75c)
- - - - -
ef3b7661 by Simon Peyton Jones at 2026-03-03T14:45:53+05:30
Fix a horrible shadowing bug in implicit parameters
Fixes #26451. The change is in GHC.Tc.Solver.Monad.updInertDicts
where we now do /not/ delete /Wanted/ implicit-parameeter constraints.
This bug has been in GHC since 9.8! But it's quite hard to provoke;
I contructed a tests in T26451, but it was hard to do so.
(cherry picked from commit c052c724d2dfc994994b6548545836969aee8ed8)
- - - - -
388c7e6b by Simon Peyton Jones at 2026-03-03T14:45:53+05:30
Fix subtle bug in GHC.Core.Utils.mkTick
This patch fixes a decade-old bug in `mkTick`, which
could generate type-incorrect code! See the diagnosis
in #26772.
The new code is simpler and easier to understand.
(As #26772 says, I think it could be improved further.)
(cherry picked from commit cbe4300ef586c8bee1800426624db12e0237c6b5)
- - - - -
5c002a1d by Simon Peyton Jones at 2026-03-03T14:45:53+05:30
Fix long-standing interaction between ticks and casts
The code for Note [Eliminate Identity Cases] was simply wrong when
ticks and casts interacted. This patch fixes the interaction.
It was shown up when validating #26772, although it's not the exactly
the bug that's reported by #26772. Nor is it easy to reproduce, hence
no regression test.
(cherry picked from commit b579dfdc614e288b0fd754ac69ae7ff723d808be)
- - - - -
843d1f57 by sheaf at 2026-03-03T14:45:53+05:30
NamedDefaults: require the class to be standard
We now only default type variables if they only appear in constraints
of the form `C v`, where `C` is either a standard class or a class with
an in-scope default declaration.
This rectifies an oversight in the original implementation of the
NamedDefault extensions that was remarked in #25775; that implementation
allowed type variables to appear in unary constraints which had arbitrary
classes at the head.
See the rewritten Note [How type-class constraints are defaulted] for
details of the implementation.
Fixes #25775
Fixes #25778
(cherry picked from commit f1acdd2c2b664ad0bdcaae4064b50e84aa7bc599)
- - - - -
cfc074ea by Rodrigo Mesquita at 2026-03-03T14:45:53+05:30
bytecode: Use 32bits for breakpoint index
Fixes #26325
(cherry picked from commit e368e24779f8a7bf110a025383db23521b313407)
- - - - -
c378a834 by Zubin Duggal at 2026-03-03T14:45:53+05:30
Prepare release 9.12.4
- - - - -
180 changed files:
- .gitlab-ci.yml
- .gitlab/rel_eng/upload_ghc_libs.py
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/Cmm.hs
- compiler/GHC/Cmm/InitFini.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/CmmToAsm/AArch64/Ppr.hs
- compiler/GHC/CmmToAsm/PPC/CodeGen.hs
- compiler/GHC/CmmToAsm/Ppr.hs
- compiler/GHC/CmmToAsm/Reg/Linear.hs
- compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/CmmToLlvm/Data.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Types/DefaultEnv.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Unit/Info.hs
- compiler/ghc.cabal.in
- + docs/users_guide/9.12.4-notes.rst
- docs/users_guide/debugging.rst
- docs/users_guide/release-notes.rst
- docs/users_guide/rtd-theme/layout.html
- hadrian/src/Builder.hs
- hadrian/src/Rules/Documentation.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Settings/Builders/Ghc.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/ghc-experimental/ghc-experimental.cabal.in
- libraries/ghc-experimental/src/GHC/Exception/Backtrace/Experimental.hs
- libraries/ghc-internal/src/GHC/Internal/Err.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- libraries/text
- libraries/transformers
- m4/fp_check_pthreads.m4
- − m4/fp_visibility_hidden.m4
- m4/fptools_set_c_ld_flags.m4
- m4/prep_target_file.m4
- rts/Apply.cmm
- rts/BeginPrivate.h
- rts/Disassembler.c
- rts/EndPrivate.h
- rts/Hash.c
- rts/Interpreter.c
- − rts/RtsDllMain.c
- − rts/RtsDllMain.h
- rts/RtsStartup.c
- rts/RtsSymbols.c
- rts/StgMiscClosures.cmm
- rts/Task.c
- rts/Task.h
- rts/ThreadPaused.c
- rts/configure.ac
- rts/eventlog/EventLog.c
- rts/include/Rts.h
- rts/include/RtsAPI.h
- rts/include/Stg.h
- rts/include/rts/OSThreads.h
- rts/include/rts/Types.h
- rts/include/stg/DLL.h
- rts/linker/LoadArchive.c
- rts/posix/OSMem.c
- rts/posix/OSThreads.c
- rts/prim/atomic.c
- rts/prim/ctz.c
- + rts/rts.buildinfo.in
- rts/rts.cabal
- rts/sm/BlockAlloc.c
- rts/sm/Evac.c
- rts/sm/Evac.h
- rts/sm/Evac_thr.c → rts/sm/Evac_par.c
- rts/sm/GCTDecl.h
- rts/sm/GCThread.h
- rts/sm/Scav_thr.c → rts/sm/Scav_par.c
- rts/sm/Storage.c
- rts/win32/OSThreads.c
- testsuite/driver/cpu_features.py
- testsuite/driver/runtests.py
- testsuite/driver/testlib.py
- testsuite/driver/testutil.py
- + testsuite/tests/bytecode/T26216.hs
- + testsuite/tests/bytecode/T26216.script
- + testsuite/tests/bytecode/T26216.stdout
- + testsuite/tests/bytecode/T26216_aux.hs
- testsuite/tests/bytecode/all.T
- + testsuite/tests/cross/should_run/T26449.hs
- + testsuite/tests/cross/should_run/all.T
- + testsuite/tests/default/T25775.hs
- + testsuite/tests/default/T25775.stderr
- testsuite/tests/default/all.T
- + testsuite/tests/ghc-api/TypeMapStringLiteral.hs
- testsuite/tests/ghc-api/all.T
- + testsuite/tests/ghci-wasm/Makefile
- + testsuite/tests/ghci-wasm/T26430.hs
- + testsuite/tests/ghci-wasm/T26430A.c
- + testsuite/tests/ghci-wasm/T26430B.c
- + testsuite/tests/ghci-wasm/all.T
- testsuite/tests/ghci.debugger/scripts/T8487.stdout
- testsuite/tests/ghci.debugger/scripts/break011.stdout
- testsuite/tests/ghci.debugger/scripts/break017.stdout
- testsuite/tests/ghci.debugger/scripts/break025.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/linters/all.T
- + testsuite/tests/overloadedrecflds/should_fail/T26391.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26391.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/perf/should_run/T3586.hs
- testsuite/tests/perf/should_run/all.T
- − testsuite/tests/process/process010.stdout-i386-unknown-solaris2
- testsuite/tests/rts/all.T
- − testsuite/tests/rts/linker/T11223/T11223_link_order_a_b_2_fail.stderr-ws-32-mingw32
- − testsuite/tests/rts/linker/T11223/T11223_simple_duplicate_lib.stderr-ws-32-mingw32
- − testsuite/tests/rts/outofmem.stderr-i386-apple-darwin
- − testsuite/tests/rts/outofmem.stderr-i386-unknown-mingw32
- − testsuite/tests/rts/outofmem.stderr-powerpc-apple-darwin
- testsuite/tests/showIface/DocsInHiFile1.stdout
- testsuite/tests/showIface/HaddockSpanIssueT24378.stdout
- testsuite/tests/showIface/MagicHashInHaddocks.stdout
- + testsuite/tests/simd/should_run/T26410_ffi.hs
- + testsuite/tests/simd/should_run/T26410_ffi.stdout
- + testsuite/tests/simd/should_run/T26410_ffi_c.c
- + testsuite/tests/simd/should_run/T26410_prim.hs
- + testsuite/tests/simd/should_run/T26410_prim.stdout
- testsuite/tests/simd/should_run/all.T
- + testsuite/tests/simplCore/should_compile/T26681.hs
- + testsuite/tests/simplCore/should_compile/T26903.hs
- + testsuite/tests/simplCore/should_compile/T26903.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/th/T10279.hs
- testsuite/tests/th/T10279.stderr
- + testsuite/tests/typecheck/should_compile/T26277.hs
- + testsuite/tests/typecheck/should_compile/T26451.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_fail/T12921.stderr
- testsuite/tests/typecheck/should_fail/T18851.hs
- + testsuite/tests/typecheck/should_fail/T26255a.hs
- + testsuite/tests/typecheck/should_fail/T26255a.stderr
- + testsuite/tests/typecheck/should_fail/T26255b.hs
- + testsuite/tests/typecheck/should_fail/T26255b.stderr
- + testsuite/tests/typecheck/should_fail/T26255c.hs
- + testsuite/tests/typecheck/should_fail/T26255c.stderr
- testsuite/tests/typecheck/should_fail/UnliftedNewtypesFamilyKindFail2.stderr
- testsuite/tests/typecheck/should_fail/all.T
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/MergeObjs.hs
- utils/jsffi/dyld.mjs
- utils/jsffi/post-link.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/576e550f40cb68c1099628a9558aaa…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/576e550f40cb68c1099628a9558aaa…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fendor/longpath-aware-manifest] Add `-fwin-aware-long-paths` to support ling paths on Windows
by Hannes Siebenhandl (@fendor) 03 Mar '26
by Hannes Siebenhandl (@fendor) 03 Mar '26
03 Mar '26
Hannes Siebenhandl pushed to branch wip/fendor/longpath-aware-manifest at Glasgow Haskell Compiler / GHC
Commits:
115f88e0 by Fendor at 2026-03-03T09:37:32+01:00
Add `-fwin-aware-long-paths` to support ling paths on Windows
While Windows supports file paths longer than the MAX_PATH restriction,
it is opt-in, and not enabled by default.
By declaring the binary to be long path aware in the manifest of the
windows executable, the binary opts-in to the new behaviour.
It is up to the developer to make sure they use UNC paths and Win.h
specific functions for filesystem operations to use long paths in their
application.
See
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-li…
and https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests
for the documentation on the application manifest and long path option.
- - - - -
5 changed files:
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Linker/Windows.hs
- docs/users_guide/phases.rst
Changes:
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -1210,6 +1210,7 @@ defaultFlags settings
= [ Opt_AutoLinkPackages,
Opt_DiagnosticsShowCaret,
Opt_EmbedManifest,
+ Opt_WinLongPathAware,
Opt_FamAppCache,
Opt_GenManifest,
Opt_GhciHistory,
=====================================
compiler/GHC/Driver/Flags.hs
=====================================
@@ -744,6 +744,7 @@ data GeneralFlag
| Opt_PrintBindContents
| Opt_GenManifest
| Opt_EmbedManifest
+ | Opt_WinLongPathAware
| Opt_SharedImplib
| Opt_BuildingCabalPackage
| Opt_IgnoreDotGhci
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -2525,6 +2525,7 @@ fFlagsDeps = [
flagSpec "eager-blackholing" Opt_EagerBlackHoling,
flagSpec "orig-thunk-info" Opt_OrigThunkInfo,
flagSpec "embed-manifest" Opt_EmbedManifest,
+ flagSpec "win-aware-long-paths" Opt_WinLongPathAware,
flagSpec "enable-rewrite-rules" Opt_EnableRewriteRules,
flagSpec "enable-th-splice-warnings" Opt_EnableThSpliceWarnings,
flagSpec "error-spans" Opt_ErrorSpans,
=====================================
compiler/GHC/Linker/Windows.hs
=====================================
@@ -16,6 +16,7 @@ import System.Directory
data ManifestOpts = ManifestOpts
{ manifestEmbed :: !Bool -- ^ Should the manifest be embedded in the binary with Windres
+ , manifestLongPathAware :: !Bool
, manifestTempdir :: TempDir
, manifestWindresConfig :: WindresConfig
, manifestObjectSuf :: String
@@ -24,6 +25,7 @@ data ManifestOpts = ManifestOpts
initManifestOpts :: DynFlags -> ManifestOpts
initManifestOpts dflags = ManifestOpts
{ manifestEmbed = gopt Opt_EmbedManifest dflags
+ , manifestLongPathAware = gopt Opt_WinLongPathAware dflags
, manifestTempdir = tmpDir dflags
, manifestWindresConfig = configureWindres dflags
, manifestObjectSuf = objectSuf dflags
@@ -37,21 +39,7 @@ maybeCreateManifest
-> IO [FilePath] -- ^ extra objects to embed, maybe
maybeCreateManifest logger tmpfs opts exe_filename = do
let manifest_filename = exe_filename <.> "manifest"
- manifest =
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n\
- \ <assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n\
- \ <assemblyIdentity version=\"1.0.0.0\"\n\
- \ processorArchitecture=\"X86\"\n\
- \ name=\"" ++ dropExtension exe_filename ++ "\"\n\
- \ type=\"win32\"/>\n\n\
- \ <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n\
- \ <security>\n\
- \ <requestedPrivileges>\n\
- \ <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n\
- \ </requestedPrivileges>\n\
- \ </security>\n\
- \ </trustInfo>\n\
- \</assembly>\n"
+ manifest = manifestContents (manifestLongPathAware opts) exe_filename
writeFile manifest_filename manifest
@@ -80,3 +68,36 @@ maybeCreateManifest logger tmpfs opts exe_filename = do
removeFile manifest_filename
return [rc_obj_filename]
+
+manifestContents :: Bool -> FilePath -> String
+manifestContents longPathAware exe_filename =
+ unlines $
+ [ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ , " <assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+ , " <assemblyIdentity version=\"1.0.0.0\""
+ , " processorArchitecture=\"X86\""
+ , " name=\"" ++ dropExtension exe_filename ++ "\""
+ , " type=\"win32\"/>"
+ , " <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">"
+ , " <security>"
+ , " <requestedPrivileges>"
+ , " <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>"
+ , " </requestedPrivileges>"
+ , " </security>"
+ , " </trustInfo>"
+ ]
+ ++
+ (
+ if longPathAware
+ then
+ [ " <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">"
+ , " <windowsSettings xmlns:ws2=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">"
+ , " <ws2:longPathAware>true</ws2:longPathAware>"
+ , " </windowsSettings>"
+ , " </application>"
+ ]
+ else
+ []
+ ) ++
+ [ " </assembly>"
+ ]
=====================================
docs/users_guide/phases.rst
=====================================
@@ -1430,6 +1430,32 @@ for example).
See also :ghc-flag:`-pgmwindres ⟨cmd⟩` (:ref:`replacing-phases`) and
:ghc-flag:`-optwindres ⟨option⟩` (:ref:`forcing-options-through`).
+.. ghc-flag:: -fwin-aware-long-paths
+ :shortdesc: Declare the linked binary to be long path aware on Windows.
+ :reverse: -fno-win-aware-long-paths
+ :type: dynamic
+ :category: linking
+
+ :default: on
+
+ :since: 9.14.2
+
+ Declare in the manifest file that GHC generates when linking a binary on Windows
+ to be aware of long paths.
+
+ Windows paths usually have a `MAX_PATH <https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-li…>`__
+ limit of 260 characters.
+ This limitation can be lifted by opting into enabling long paths in various
+ ways, see `Enable long paths in Windows 10 and later`_.
+
+ To invoke the compiled program with long paths, the Windows manifest needs
+ to declare that the program is aware of long paths and can handle them
+ appropriately.
+
+ :ghc-flag:`-fno-embed-manifest` also implies :ghc-flag:`-fno-win-aware-long-paths`.
+
+ .. _Enable long paths in Windows 10 and later: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-li…
+
.. ghc-flag:: -fno-shared-implib
:shortdesc: Don't generate an import library for a DLL (Windows only)
:type: dynamic
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/115f88e097d35fc9cf8d6949c97864e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/115f88e097d35fc9cf8d6949c97864e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/backports-9.12.4] 59 commits: wasm: ensure setKeepCAFs() is called in ghci
by Zubin (@wz1000) 03 Mar '26
by Zubin (@wz1000) 03 Mar '26
03 Mar '26
Zubin pushed to branch wip/backports-9.12.4 at Glasgow Haskell Compiler / GHC
Commits:
2bd17026 by Cheng Shao at 2026-03-03T10:56:44+05:30
wasm: ensure setKeepCAFs() is called in ghci
This patch is a critical bugfix for #26106, see comment and linked
issue for details.
(cherry picked from commit 10f06163d9adcb3b6e6438f1524faaca3bf6c3b2)
- - - - -
3f1ea4c0 by sheaf at 2026-03-03T10:56:44+05:30
Use tcMkScaledFunTys in matchExpectedFunTys
We should use tcMkScaledFunTys rather than mkScaledFunTys in
GHC.Tc.Utils.Unify.matchExpectedFunTys, as the latter crashes
when the kind of the result type is a bare metavariable.
We know the result is always Type-like, so we don't need scaledFunTys
to try to rediscover that from the kind.
Fixes #26277
(cherry picked from commit 624afa4a65caa8ec23f85e70574dfb606f90c173)
- - - - -
8e891e83 by sheaf at 2026-03-03T10:56:44+05:30
Improve Notes about disambiguating record updates
This commit updates the notes [Disambiguating record updates] and
[Type-directed record disambiguation], in particular adding more
information about the deprecation status of type-directed disambiguation
of record updates.
(cherry picked from commit a2d9d7c2073867ee0cabb8d49f93246d95ec0b09)
- - - - -
2688febd by sheaf at 2026-03-03T10:56:44+05:30
Add test for #26216
(cherry picked from commit 2e73f3426ab6e3cf1938b53831005593f3fd351c)
- - - - -
98e197aa by Vladislav Zavialov at 2026-03-03T10:56:44+05:30
Fix PREP_MAYBE_LIBRARY in prep_target_file.m4
This change fixes a configure error introduced in:
commit 8235dd8c4945db9cb03e3be3c388d729d576ed1e
ghc-toolchain: Move UseLibdw to per-Target file
Now the build no longer fails with:
acghc-toolchain: Failed to read a valid Target value from hadrian/cfg/default.target
(cherry picked from commit 1480872af6b80db1b035a44409188416df041048)
- - - - -
59c612a7 by Cheng Shao at 2026-03-03T10:56:44+05:30
rts: remove obsolete CC_SUPPORTS_TLS logic
This patch removes obsolete CC_SUPPORTS_TLS logic throughout the rts,
given __thread is now uniformly supported by C toolchains of all
platforms we currently support.
(cherry picked from commit 0f034942724233e1457549123b46880f7b93e805)
- - - - -
160379e3 by Cheng Shao at 2026-03-03T10:56:44+05:30
rts: remove obsolete HAS_VISIBILITY_HIDDEN logic
This patch removes obsolete HAS_VISIBILITY_HIDDEN logic throughout the
rts, given __attribute__((visibility("hidden"))) is uniformly
supported by C toolchains of all platforms we currently support.
(cherry picked from commit ef7056554df5603ec4d1e33193abe953970e6ab3)
- - - - -
9e0acf07 by Cheng Shao at 2026-03-03T10:56:44+05:30
rts: remove -O3 pragma hack in Hash.c
This patch removes an obsolete gcc pragma to specify -O3 in Hash.c.
Hadrian already passes the right flag.
(cherry picked from commit 9fdc1f7d855cc61f90de909875f6ae0d6798dca7)
- - - - -
7112404c by Cheng Shao at 2026-03-03T10:56:44+05:30
wasm: fix dyld handling for forward declared GOT.func items
This patch fixes wasm shared linker's handling of forward declared
GOT.func items, see linked issue for details. Also adds T26430 test to
witness the fix. Fixes #26430.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 867c26755e8855c6df949e65df0c2aebc9da64c3)
- - - - -
9713682f by Cheng Shao at 2026-03-03T10:56:44+05:30
rts: remove obsolete __GNUC__ related logic
This patch removes obsolete `__GNUC__` related logic, given on any
currently supported platform and toolchain, `__GNUC__ >= 4` is
universally true. Also pulls some other weeds and most notably, use
`__builtin___clear_cache` for clang as well, since clang has supported
this gcc intrinsic since 2014, see
https://github.com/llvm/llvm-project/commit/c491a8d4577052bc6b3b4c72a7db6a7….
(cherry picked from commit 67de53a6ced23caad640d2c7421089242f0dfb76)
- - - - -
d266d4ba by Cheng Shao at 2026-03-03T10:56:44+05:30
hadrian: fix GHC.Platform.Host generation for cross stage1
This patch fixes incorrectly GHC.Platform.Host generation logic for
cross stage1 in hadrian (#26449). Also adds T26449 test case to
witness the fix.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 8cbe006ad09d5a64e4a3cdf4c91a8b81ff1511be)
- - - - -
d7e21dea by Luite Stegeman at 2026-03-03T10:56:44+05:30
rts: Fix lost wakeups in threadPaused for threads blocked on black holes
The lazy blackholing code in threadPaused could overwrite closures
that were already eagerly blackholed, and as such wouldn't have a
marked update frame. If the black hole was overwritten by its
original owner, this would lead to an undetected collision, and
the contents of any existing blocking queue being lost.
This adds a check for eagerly blackholed closures and avoids
overwriting their contents.
Fixes #26324
(cherry picked from commit a1de535f762bc23d4cf23a5b1853591dda12cdc9)
- - - - -
7cc64cb7 by Luite Stegeman at 2026-03-03T10:56:44+05:30
rts: push the correct update frame in stg_AP_STACK
The frame contains an eager black hole (__stg_EAGER_BLACKHOLE_info) so
we should push an stg_bh_upd_frame_info instead of an stg_upd_frame_info.
(cherry picked from commit b7e21e498d39e0ee764e3237544b4c39ddf98467)
- - - - -
3009e8e8 by Cheng Shao at 2026-03-03T10:56:44+05:30
testsuite: remove unused expected output files
This patch removes unused expected output files in the testsuites on
platforms that we no longer support.
(cherry picked from commit 6992ac097b9da989f125f896afe21b75dba8b4c9)
- - - - -
20b65d5b by Ben Gamari at 2026-03-03T10:56:44+05:30
rts/posix: Enforce iteration limit on heap reservation logic
Previously we could loop indefinitely when attempting to get an address
space reservation for our heap. Limit the logic to 8 iterations to
ensure we instead issue a reasonable error message.
Addresses #26151.
(cherry picked from commit ff1650c96c61af02e193854312a9ccd303968e47)
- - - - -
0cb8cba1 by Ben Gamari at 2026-03-03T10:56:45+05:30
rts/posix: Hold on to low reservations when reserving heap
Previously when the OS gave us an address space reservation in low
memory we would immediately release it and try again. However, on some
platforms this meant that we would get the same allocation again in the
next iteration (since mmap's `hint` argument is just that, a hint).
Instead we now hold on to low reservations until we have found a
suitable heap reservation.
Fixes #26151.
(cherry picked from commit 0184455728f841a699648f879fdb29128081fc6b)
- - - - -
06877ae5 by Julian Ospald at 2026-03-03T10:56:45+05:30
ghc-toolchain: Drop `ld.gold` from merge object command
It's deprecated.
Also see #25716
(cherry picked from commit c58f9a615f05e9d43629f6e846ae22cad2a6163d)
- - - - -
4002ea19 by Ben Gamari at 2026-03-03T10:56:45+05:30
gitlab-ci: Make RELEASE_JOB an input
Rather than an undocumented variable.
(cherry picked from commit f9790ca81deb8b14ff2eabf701aecbcfd6501963)
- - - - -
987d29b9 by Cheng Shao at 2026-03-03T10:56:45+05:30
testsuite: fix T3586 for non-SSE3 platforms
`T3586.hs` contains `-fvia-C -optc-msse3` which I think is a
best-effort basis to harvest the C compiler's auto vectorization
optimizations via the C backend back when the test was added. The
`-fvia-C` part is now a deprecated no-op because GHC can't fall back
to the C backend on a non-unregisterised build, and `-optc-msse3`
might actually cause the test to fail on non x86/x64 platforms, e.g.
recent builds of wasi-sdk would report `wasm32-wasi-clang: error:
unsupported option '-msse3' for target 'wasm32-unknown-wasi'`.
So this patch cleans up this historical cruft. `-fvia-C` is removed,
and `-optc-msse3` is only passed when cpuid contains `pni` (which
indicates support of SSE3).
(cherry picked from commit 70ee825a516bcf7aac762bfedb4a017d35f8dcf3)
- - - - -
5c70a9b1 by Julian Ospald at 2026-03-03T10:56:45+05:30
Improve error handling in 'getPackageArchives'
When the library dirs in the package conf files are not set up correctly,
the JS linker will happily ignore such packages and not link against them,
although they're part of the link plan.
Fixes #26383
(cherry picked from commit 91b6be10bd58c2bfc1c7c22e81b06ab3be583228)
- - - - -
26c674fc by Ben Gamari at 2026-03-03T10:56:45+05:30
rts: Annotate BCOs with their Name
This introduces a new bytecode instruction, `BCO_NAME`, to aid in debugging
bytecode execution. This instruction is injected by `mkProtoBCO` and
captures the Haskell name of the BCO. It is then printed by the
disassembler, allowing ready correlation with STG dumps.
(cherry picked from commit 5192a75fe9b272e8b1ef290fa834714c81bd1f79)
- - - - -
16245f7e by sheaf at 2026-03-03T10:56:45+05:30
Bad record update msg: allow out-of-scope datacons
This commit ensures that, when we encounter an invalid record update
(because no constructor exists which contains all of the record fields
mentioned in the record update), we graciously handle the situation in
which the constructors themselves are not in scope. In that case,
instead of looking up the constructors in the GlobalRdrEnv, directly
look up their GREInfo using the lookupGREInfo function.
Fixes #26391
(cherry picked from commit cef8938f3c0d22583f01d5ea29e6109bccd36040)
- - - - -
07634142 by Cheng Shao at 2026-03-03T10:56:45+05:30
rts: remove obsolete COMPILING_WINDOWS_DLL logic
This patch removes obsolete COMPILING_WINDOWS_DLL logic throughout the
rts. They were once used for compiling to win32 DLLs, but we haven't
been able to compile Haskell units to win32 DLLs for many years now,
due to PE format's restriction of no more than 65536 exported symbols
in a single DLL.
(cherry picked from commit b8cfa8f741729ef123569fb321c4b2ab4a1a941c)
- - - - -
73aaff31 by Julian Ospald at 2026-03-03T10:56:45+05:30
Skip uniques test if sources are not available
(cherry picked from commit 5dc2e9eaf60fd72771bf2e8112aec182665461a1)
- - - - -
831ddf7f by Julian Ospald at 2026-03-03T10:56:45+05:30
rts: remove unneccesary cabal flags
We perform those checks via proper autoconf macros
instead that do the right thing and then add those
libs to the rts buildinfo.
(cherry picked from commit 643ce801a8b559071683cad0e5adbc26b9fc8385)
- - - - -
409252c3 by Wang Xin at 2026-03-03T10:56:45+05:30
Add -mcmodel=medium moduleflag to generated LLVM IR on LoongArch platform
With the Medium code model, the jump range of the generated jump
instruction is larger than that of the Small code model. It's a
temporary fix of the problem descriped in https://gitlab.haskell
.org/ghc/ghc/-/issues/25495. This commit requires that the LLVM
used contains the code of commit 9dd1d451d9719aa91b3bdd59c0c6679
83e1baf05, i.e., version 8.0 and later. Actually we should not
rely on LLVM, so the only way to solve this problem is to implement
the LoongArch backend.
Add new type for codemodel
(cherry picked from commit e70d41406b5d5638b42c4d8222cd03e76bbfeb86)
- - - - -
17c3a5d2 by Peng Fan at 2026-03-03T10:56:45+05:30
Pass the mcmodel=medium parameter to CC via GHC
Ensure that GHC-driver builds default to mcmodel=medium, so that GHC
passes this default parameter to CC without having to add it to the
compiled project.
Commit e70d41406b5d5638b42c4d8222cd03e76bbfeb86 does not ensure that all
GHC-built object files have a default model of medium, and will raise an
R_LARCH_B26 overflow error.
(cherry picked from commit 1a3f11314cc7b8dbf9af03dd2ae2cb066a998d63)
- - - - -
01d68aeb by Ben Gamari at 2026-03-03T10:56:45+05:30
gitlab-ci: Run ghcup-metadata jobs on OpenCape runners
This significantly reduces our egress traffic
and makes the jobs significantly faster.
(cherry picked from commit ff3f0d09bce1c261638b572af2bac1d87f1f6df7)
- - - - -
6a4ccf85 by Luite Stegeman at 2026-03-03T10:56:45+05:30
rts: fix eager black holes: record mutated closure and fix assertion
This fixes two problems with handling eager black holes, introduced
by a1de535f762bc23d4cf23a5b1853591dda12cdc9.
- the closure mutation must be recorded even for eager black holes,
since the mutator has mutated it before calling threadPaused
- The assertion that an unmarked eager black hole must be owned by
the TSO calling threadPaused is incorrect, since multiple threads
can race to claim the black hole.
fixes #26495
(cherry picked from commit 3ba3d9f9db784c903ebe8fd617447ce62d30b7d3)
- - - - -
5e3a9c7a by ARATA Mizuki at 2026-03-03T10:56:45+05:30
LLVM backend: Pass the +evex512 attribute to LLVM 18+ if -mavx512f is set
The newer LLVM requires the +evex512 attribute to enable use of ZMM registers.
LLVM exhibits a backward-compatible behavior if the cpu is `x86-64`, but not if `penryn`.
Therefore, on macOS, where the cpu is set to `penryn`, we need to explicitly pass +evex512.
Fixes #26410
(cherry picked from commit b22777d4b7182f40a31eb430fa27f5fb9ef0f292)
- - - - -
ecd145d4 by Matthew Pickering at 2026-03-03T10:56:45+05:30
hadrian: Use a response file to invoke GHC for dep gathering.
In some cases we construct an argument list too long for GHC to
handle directly on windows. This happens when we generate
the dependency file because the command line will contain
references to a large number of .hs files.
To avoid this we now invoke GHC using a response file when
generating dependencies to sidestep length limitations.
Note that we only pass the actual file names in the dependency
file. Why? Because this side-steps #26560
(cherry picked from commit 9d371d23c526fd160d7e99bef2bc7da825cf3c0f)
- - - - -
8252e0be by Andreas Klebinger at 2026-03-03T10:56:45+05:30
Add hpc to release script
(cherry picked from commit 64ec82ffa7f48399e18fcec43051d2b7ddcb7cc2)
- - - - -
638cfe6b by Matthew Pickering at 2026-03-03T10:56:45+05:30
rts: Fix a deadlock with eventlog flush interval and RTS shutdown
The ghc_ticker thread attempts to flush at the eventlog tick interval, this requires
waiting to take all capabilities.
At the same time, the main thread is shutting down, the schedule is
stopped and then we wait for the ticker thread to finish.
Therefore we are deadlocked.
The solution is to use `newBoundTask/exitMyTask`, so that flushing can
cooperate with the scheduler shutdown.
Fixes #26573
(cherry picked from commit b7fe744598b4569cd0236268e4f6f5b9d27e12b7)
- - - - -
b6743dd5 by Julian Ospald at 2026-03-03T10:56:45+05:30
rts: Fix object file format detection in loadArchive
Commit 76d1041dfa4b96108cfdd22b07f2b3feb424dcbe seems to
have introduced this bug, ultimately leading to failure of
test T11788. I can only theorize that this test isn't run
in upstream's CI, because they don't build a static GHC.
The culprit is that we go through the thin archive, trying
to follow the members on the filesystem, but don't
re-identify the new object format of the member. This pins
`object_fmt` to `NotObject` from the thin archive.
Thanks to @angerman for spotting this.
(cherry picked from commit fc958fc9eb6f6f4db473cdda23c381da8f32163d)
- - - - -
75c7592d by Simon Peyton Jones at 2026-03-03T10:56:45+05:30
Add missing InVar->OutVar lookup in SetLevels
As #26681 showed, the SetLevels pass was failing to map an InVar to
an OutVar. Very silly! I'm amazed it hasn't broken before now.
I have improved the type singatures (to mention InVar and OutVar)
so it's more obvious what needs to happen.
(cherry picked from commit 52d00c05e1d803b36c93295399fe931c871166bf)
- - - - -
4d04c098 by Cheng Shao at 2026-03-03T10:56:45+05:30
compiler: change sectionProtection to take SectionType argument
This commit changes `sectionProtection` to only take `SectionType`
argument instead of whole `Section`, since it doesn't need the Cmm
section content anyway, and it can then be called in parts of NCG
where we only have a `SectionType` in scope.
(cherry picked from commit 2433e91d41675d56f48f82d22430a8dee915e7a0)
- - - - -
193fe1bd by Cheng Shao at 2026-03-03T10:56:45+05:30
compiler: change isInitOrFiniSection to take SectionType argument
This commit changes `isInitOrFiniSection` to only take `SectionType`
argument instead of whole `Section`, since it doesn't need the Cmm
section content anyway, and it can then be called in parts of NCG
where we only have a `SectionType` in scope. Also marks it as
exported.
(cherry picked from commit e5926fbebf341ee547227d41710d78471eecd09c)
- - - - -
10282593 by Cheng Shao at 2026-03-03T10:56:45+05:30
compiler: fix split sections on windows
This patch fixes split sections on windows by emitting the right
COMDAT section header in NCG, see added comment for more explanation.
Fix #26696 #26494.
-------------------------
Metric Decrease:
LargeRecord
T9675
size_hello_artifact
size_hello_artifact_gzip
size_hello_unicode
size_hello_unicode_gzip
Metric Increase:
T13035
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit 244d57d79a555dcecc7590287bb14976d561291a)
- - - - -
a4644c5f by Matthew Pickering at 2026-03-03T10:56:45+05:30
rts: Use INFO_TABLE_CONSTR for stg_dummy_ret_closure
Since the closure type is CONSTR_NOCAF, we need to use INFO_TABLE_CONSTR
to populate the constructor description field (this crashes ghc-debug
when decoding AP_STACK frames sometimes)
Fixes #26745
(cherry picked from commit 322dd6726b11c7101c28ffb8aeb7cb4cee34ab56)
- - - - -
cf02c17c by Matthew Pickering at 2026-03-03T10:56:45+05:30
Evaluate backtraces for "error" exceptions at the moment they are thrown
See Note [Capturing the backtrace in throw] and
Note [Hiding precise exception signature in throw] which explain the
implementation.
This commit makes `error` and `throw` behave the same with regard to
backtraces. Previously, exceptions raised by `error` would not contain
useful IPE backtraces.
I did try and implement `error` in terms of `throw` but it started to
involve putting diverging functions into hs-boot files, which seemed to
risky if the compiler wouldn't be able to see if applying a function
would diverge.
CLC proposal: https://github.com/haskell/core-libraries-committee/issues/383
Fixes #26751
(cherry picked from commit 94dcd15e54146abecf9b4f5e47d258ca3cd40f1b)
- - - - -
c1861b28 by fendor at 2026-03-03T10:56:45+05:30
Remove `traceId` from ghc-pkg executable
(cherry picked from commit d0966e64880e9fa30ce07c0fa5ea28108c6e8ad9)
- - - - -
e1252c80 by sheaf at 2026-03-03T10:56:45+05:30
Don't re-use stack slots for growing registers
This commit avoids re-using a stack slot for a register that has grown
but already had a stack slot.
For example, suppose we have stack slot assigments
%v1 :: FF64 |-> StackSlot 0
%v2 :: FF64 |-> StackSlot 1
Later, we start using %v1 at a larger format (e.g. F64x2) and we need
to spill it again. Then we **must not** use StackSlot 0, as a spill
at format F64x2 would clobber the data in StackSlot 1.
This can cause some fragmentation of the `StackMap`, but that's probably
OK.
Fixes #26668
(cherry picked from commit 023c301c51e7346af3d4d773c448277ad3645ad2)
- - - - -
06e89dfc by Cheng Shao at 2026-03-03T10:56:45+05:30
llvm: fix split sections for llvm backend
This patch fixes split sections for llvm backend:
- Pass missing `--data-sections`/`--function-sections` flags to
llc/opt.
- Use `(a)llvm.compiler.used` instead of `(a)llvm.used` to avoid sections
being unnecessarily retained at link-time.
Fixes #26770.
-------------------------
Metric Decrease:
libdir
size_hello_artifact
size_hello_unicode
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit b18b2c42c32488ad6d3480a56a1fcd753cad2023)
- - - - -
b13f3675 by Matthew Pickering at 2026-03-03T10:56:45+05:30
Fix ghc-experimental GHC.Exception.Backtrace.Experimental module
This module wasn't added to the cabal file so it was never compiled or
included in the library.
(cherry picked from commit ee937134aa0ddf35c1a9dc7334c0aec0de13b719)
- - - - -
e4cfc6ec by Sylvain Henry at 2026-03-03T10:56:45+05:30
GC: don't use CAS without PARALLEL_GC on
If we're not using the parallel GC, there is no reason to do a costly
CAS. This was flagged as taking time in a perf profile.
(cherry picked from commit 0491f08a965df0d6448bd9cd940d2b86fca2db5d)
- - - - -
08c10968 by Sylvain Henry at 2026-03-03T10:56:45+05:30
GC: suffix parallel GC with "par" instead of "thr"
Avoid some potential confusion (see discussion in !15351).
(cherry picked from commit 211a8f5633f0a5069c0689171f60b57719a242be)
- - - - -
f26e3be5 by Cheng Shao at 2026-03-03T10:56:45+05:30
testsuite: avoid re.sub in favor of simple string replacements
This patch refactors the testsuite driver and avoids the usage of
re.sub in favor of simple string replacements when possible. The
changes are not comprehensive, and there are still a lot of re.sub
usages lingering around the tree, but this already addresses a major
performance bottleneck in the testsuite driver that might has to do
with quadratic or worse slowdown in cpython's regular expression
engine when handling certain regex patterns with large strings.
Especially on i386, and i386 jobs are the bottlenecks of all full-ci
validate pipelines!
Here are the elapsed times of testing x86_64/i386 with -j48 before
this patch:
x86_64: `Build completed in 6m06s`
i386: `Build completed in 1h36m`
And with this patch:
x86_64: `Build completed in 4m55s`
i386: `Build completed in 4m23s`
Fixes #26786.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit ca79475f6b4dfba991e2c933bac9c22d54a4950d)
- - - - -
3528276b by Zubin Duggal at 2026-03-03T10:56:45+05:30
hadrian: Add ghc-{experimental,internal}.cabal to the list of dependencies of the doc target
We need these files to detect the version of these libraries
Fixes #26738
(cherry picked from commit 1b490f5a7bbdb1441948241e6089b31efba9db45)
- - - - -
b51a3b44 by Jessica Clarke at 2026-03-03T10:56:45+05:30
PPC NCG: Use libcall for 64-bit cmpxchg on 32-bit PowerPC
There is no native instruction for this, and even if there were a
register pair version we could use, the implementation here is assuming
the values fit in a single register, and we end up only using / defining
the low halves of the registers.
Fixes: b4d39adbb5 ("PrimOps: Add CAS op for all int sizes")
Fixes: #23969
(cherry picked from commit ce2d62fba69d2ea0c74c46c50628feb8b81719d2)
- - - - -
55fb8f67 by John Paul Adrian Glaubitz at 2026-03-03T10:56:45+05:30
rts: Switch prim to use modern atomic compiler builtins
The __sync_*() atomic compiler builtins have been deprecated in GCC
for a while now and also don't provide variants for 64-bit values
such as __sync_fetch_and_add_8().
Thus, replace them with the modern __atomic_*() compiler builtins and
while we're at it, also drop the helper macro CAS_NAND() which is now
no longer needed since we stopped using the __sync_*() compiler builtins
altogether.
Co-authored-by: Ilias Tsitsimpis <iliastsi(a)debian.org>
Fixes #26729
(cherry picked from commit 7c52c4f9bc8d6ae6404039ec02efe48fbf7a4778)
- - - - -
d4a72e46 by sterni at 2026-03-03T10:56:46+05:30
users_guide: fix runtime error during build with Sphinx 9.1.0
Appears that pathto is stricter about what it accepts now.
Tested Sphinx 8.2.3 and 9.1.0 on the ghc-9.10 branch.
Resolves #26810.
Co-authored-by: Martin Weinelt <hexa(a)darmstadt.ccc.de>
(cherry picked from commit e8f5a45de561ec80c88cd3da2c66502deb32d4c3)
- - - - -
4d4b3d83 by Michael Karcher at 2026-03-03T10:56:46+05:30
NCG for PPC: add pattern for CmmRegOff to iselExpr64
Closes #26828
(cherry picked from commit 43d977619de65c0cf87695fa5d86f1a3ff3176c3)
- - - - -
e8301ef2 by Matthew Pickering at 2026-03-03T10:56:46+05:30
determinism: Use deterministic map for Strings in TyLitMap
When generating typeable evidence the types we need evidence for all
cached in a TypeMap, the order terms are retrieved from a type map
determines the order the bindings appear in the program.
A TypeMap is quite diligent to use deterministic maps, apart from in the
TyLitMap, which uses a UniqFM for storing strings, whose ordering
depends on the Unique of the FastString.
This can cause non-deterministic .hi and .o files.
An unexpected side-effect is the error message but RecordDotSyntaxFail8
changing. I looked into this with Sam and this change caused the
constraints to be solved in a different order which results in a
slightly different error message. I have accepted the new test, since
the output before was non-deterministic and the new output is consistent
with the other messages in that file.
Fixes #26846
(cherry picked from commit aeeb4a2034e80e26503eb88f5abde85e87a82f7b)
- - - - -
f0705078 by Andrew Lelechenko at 2026-03-03T10:56:46+05:30
Upgrade text submodule to 2.1.4
(cherry picked from commit 9e4d70c2764d117c5cf753127f93056d66e4f0d7)
- - - - -
27a65f5f by Zubin Duggal at 2026-03-03T10:56:46+05:30
Bump transformers submodule to 0.6.3.0
Fixes #26790
(cherry picked from commit ea0d1317a630799a6b7bea12b24ef7e1ea6ed512)
- - - - -
38af2a3d by Matthew Pickering at 2026-03-03T10:56:46+05:30
determinism: Use a stable sort in WithHsDocIdentifiers binary instance
`WithHsDocIdentifiers` is defined as
```
71 data WithHsDocIdentifiers a pass = WithHsDocIdentifiers
72 { hsDocString :: !a
73 , hsDocIdentifiers :: ![Located (IdP pass)]
74 }
```
This list of names is populated from `rnHsDocIdentifiers`, which calls
`lookupGRE`, which calls `lookupOccEnv_AllNameSpaces`, which calls
`nonDetEltsUFM` and returns the results in an order depending on
uniques.
Sorting the list with a stable sort before returning the interface makes
the output deterministic and follows the approach taken by other fields
in `Docs`.
Fixes #26858
(cherry picked from commit 0020e38a021b5f0371c48fe73cddf8987acb1eb1)
- - - - -
ec007e5f by Simon Peyton Jones at 2026-03-03T10:56:46+05:30
Fix subtle bug in cast worker/wrapper
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
(cherry picked from commit 99d8c146c12146e1e21b1f2d31809845d4afe9d4)
- - - - -
f7e2a5e0 by Cheng Shao at 2026-03-03T10:56:46+05:30
wasm: use import.meta.main for proper distinction of nodejs main modules
This patch uses `import.meta.main` for proper distinction of nodejs
main modules, especially when the main module might be installed as a
symlink. Fixes #26916.
(cherry picked from commit 039f19778e35b193af0de2a2c6ed89556038627a)
- - - - -
576e550f by Zubin Duggal at 2026-03-03T10:56:46+05:30
Prepare release 9.12.4
- - - - -
153 changed files:
- .gitlab-ci.yml
- .gitlab/rel_eng/upload_ghc_libs.py
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/Cmm.hs
- compiler/GHC/Cmm/InitFini.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/CmmToAsm/AArch64/Ppr.hs
- compiler/GHC/CmmToAsm/PPC/CodeGen.hs
- compiler/GHC/CmmToAsm/Ppr.hs
- compiler/GHC/CmmToAsm/Reg/Linear.hs
- compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/CmmToLlvm/Data.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Unit/Info.hs
- compiler/ghc.cabal.in
- docs/users_guide/debugging.rst
- docs/users_guide/release-notes.rst
- docs/users_guide/rtd-theme/layout.html
- hadrian/src/Builder.hs
- hadrian/src/Rules/Documentation.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Settings/Builders/Ghc.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/ghc-experimental/ghc-experimental.cabal.in
- libraries/ghc-experimental/src/GHC/Exception/Backtrace/Experimental.hs
- libraries/ghc-internal/src/GHC/Internal/Err.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- libraries/text
- libraries/transformers
- m4/fp_check_pthreads.m4
- − m4/fp_visibility_hidden.m4
- m4/fptools_set_c_ld_flags.m4
- m4/prep_target_file.m4
- rts/Apply.cmm
- rts/BeginPrivate.h
- rts/Disassembler.c
- rts/EndPrivate.h
- rts/Hash.c
- rts/Interpreter.c
- − rts/RtsDllMain.c
- − rts/RtsDllMain.h
- rts/RtsStartup.c
- rts/RtsSymbols.c
- rts/StgMiscClosures.cmm
- rts/Task.c
- rts/Task.h
- rts/ThreadPaused.c
- rts/configure.ac
- rts/eventlog/EventLog.c
- rts/include/Rts.h
- rts/include/RtsAPI.h
- rts/include/Stg.h
- rts/include/rts/OSThreads.h
- rts/include/rts/Types.h
- rts/include/stg/DLL.h
- rts/linker/LoadArchive.c
- rts/posix/OSMem.c
- rts/posix/OSThreads.c
- rts/prim/atomic.c
- rts/prim/ctz.c
- + rts/rts.buildinfo.in
- rts/rts.cabal
- rts/sm/BlockAlloc.c
- rts/sm/Evac.c
- rts/sm/Evac.h
- rts/sm/Evac_thr.c → rts/sm/Evac_par.c
- rts/sm/GCTDecl.h
- rts/sm/GCThread.h
- rts/sm/Scav_thr.c → rts/sm/Scav_par.c
- rts/sm/Storage.c
- rts/win32/OSThreads.c
- testsuite/driver/cpu_features.py
- testsuite/driver/runtests.py
- testsuite/driver/testlib.py
- testsuite/driver/testutil.py
- + testsuite/tests/bytecode/T26216.hs
- + testsuite/tests/bytecode/T26216.script
- + testsuite/tests/bytecode/T26216.stdout
- + testsuite/tests/bytecode/T26216_aux.hs
- testsuite/tests/bytecode/all.T
- + testsuite/tests/cross/should_run/T26449.hs
- + testsuite/tests/cross/should_run/all.T
- + testsuite/tests/ghc-api/TypeMapStringLiteral.hs
- testsuite/tests/ghc-api/all.T
- + testsuite/tests/ghci-wasm/Makefile
- + testsuite/tests/ghci-wasm/T26430.hs
- + testsuite/tests/ghci-wasm/T26430A.c
- + testsuite/tests/ghci-wasm/T26430B.c
- + testsuite/tests/ghci-wasm/all.T
- testsuite/tests/ghci.debugger/scripts/T8487.stdout
- testsuite/tests/ghci.debugger/scripts/break011.stdout
- testsuite/tests/ghci.debugger/scripts/break017.stdout
- testsuite/tests/ghci.debugger/scripts/break025.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/linters/all.T
- + testsuite/tests/overloadedrecflds/should_fail/T26391.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26391.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/perf/should_run/T3586.hs
- testsuite/tests/perf/should_run/all.T
- − testsuite/tests/process/process010.stdout-i386-unknown-solaris2
- testsuite/tests/rts/all.T
- − testsuite/tests/rts/linker/T11223/T11223_link_order_a_b_2_fail.stderr-ws-32-mingw32
- − testsuite/tests/rts/linker/T11223/T11223_simple_duplicate_lib.stderr-ws-32-mingw32
- − testsuite/tests/rts/outofmem.stderr-i386-apple-darwin
- − testsuite/tests/rts/outofmem.stderr-i386-unknown-mingw32
- − testsuite/tests/rts/outofmem.stderr-powerpc-apple-darwin
- testsuite/tests/showIface/DocsInHiFile1.stdout
- testsuite/tests/showIface/HaddockSpanIssueT24378.stdout
- testsuite/tests/showIface/MagicHashInHaddocks.stdout
- + testsuite/tests/simd/should_run/T26410_ffi.hs
- + testsuite/tests/simd/should_run/T26410_ffi.stdout
- + testsuite/tests/simd/should_run/T26410_ffi_c.c
- + testsuite/tests/simd/should_run/T26410_prim.hs
- + testsuite/tests/simd/should_run/T26410_prim.stdout
- testsuite/tests/simd/should_run/all.T
- + testsuite/tests/simplCore/should_compile/T26681.hs
- + testsuite/tests/simplCore/should_compile/T26903.hs
- + testsuite/tests/simplCore/should_compile/T26903.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/th/T10279.hs
- testsuite/tests/th/T10279.stderr
- + testsuite/tests/typecheck/should_compile/T26277.hs
- testsuite/tests/typecheck/should_compile/all.T
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/MergeObjs.hs
- utils/jsffi/dyld.mjs
- utils/jsffi/post-link.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/519601bc63a1b15da28b802bdfe659…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/519601bc63a1b15da28b802bdfe659…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/backports-9.12.4] 20 commits: Evaluate backtraces for "error" exceptions at the moment they are thrown
by Zubin (@wz1000) 03 Mar '26
by Zubin (@wz1000) 03 Mar '26
03 Mar '26
Zubin pushed to branch wip/backports-9.12.4 at Glasgow Haskell Compiler / GHC
Commits:
a3f7ffef by Matthew Pickering at 2026-03-03T10:49:47+05:30
Evaluate backtraces for "error" exceptions at the moment they are thrown
See Note [Capturing the backtrace in throw] and
Note [Hiding precise exception signature in throw] which explain the
implementation.
This commit makes `error` and `throw` behave the same with regard to
backtraces. Previously, exceptions raised by `error` would not contain
useful IPE backtraces.
I did try and implement `error` in terms of `throw` but it started to
involve putting diverging functions into hs-boot files, which seemed to
risky if the compiler wouldn't be able to see if applying a function
would diverge.
CLC proposal: https://github.com/haskell/core-libraries-committee/issues/383
Fixes #26751
(cherry picked from commit 94dcd15e54146abecf9b4f5e47d258ca3cd40f1b)
- - - - -
5839b832 by fendor at 2026-03-03T10:49:47+05:30
Remove `traceId` from ghc-pkg executable
(cherry picked from commit d0966e64880e9fa30ce07c0fa5ea28108c6e8ad9)
- - - - -
79bc27f8 by sheaf at 2026-03-03T10:49:47+05:30
Don't re-use stack slots for growing registers
This commit avoids re-using a stack slot for a register that has grown
but already had a stack slot.
For example, suppose we have stack slot assigments
%v1 :: FF64 |-> StackSlot 0
%v2 :: FF64 |-> StackSlot 1
Later, we start using %v1 at a larger format (e.g. F64x2) and we need
to spill it again. Then we **must not** use StackSlot 0, as a spill
at format F64x2 would clobber the data in StackSlot 1.
This can cause some fragmentation of the `StackMap`, but that's probably
OK.
Fixes #26668
(cherry picked from commit 023c301c51e7346af3d4d773c448277ad3645ad2)
- - - - -
8e964b00 by Cheng Shao at 2026-03-03T10:49:47+05:30
llvm: fix split sections for llvm backend
This patch fixes split sections for llvm backend:
- Pass missing `--data-sections`/`--function-sections` flags to
llc/opt.
- Use `(a)llvm.compiler.used` instead of `(a)llvm.used` to avoid sections
being unnecessarily retained at link-time.
Fixes #26770.
-------------------------
Metric Decrease:
libdir
size_hello_artifact
size_hello_unicode
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit b18b2c42c32488ad6d3480a56a1fcd753cad2023)
- - - - -
e9f0c76e by Matthew Pickering at 2026-03-03T10:49:47+05:30
Fix ghc-experimental GHC.Exception.Backtrace.Experimental module
This module wasn't added to the cabal file so it was never compiled or
included in the library.
(cherry picked from commit ee937134aa0ddf35c1a9dc7334c0aec0de13b719)
- - - - -
43715212 by Sylvain Henry at 2026-03-03T10:49:47+05:30
GC: don't use CAS without PARALLEL_GC on
If we're not using the parallel GC, there is no reason to do a costly
CAS. This was flagged as taking time in a perf profile.
(cherry picked from commit 0491f08a965df0d6448bd9cd940d2b86fca2db5d)
- - - - -
e98afd59 by Sylvain Henry at 2026-03-03T10:49:48+05:30
GC: suffix parallel GC with "par" instead of "thr"
Avoid some potential confusion (see discussion in !15351).
(cherry picked from commit 211a8f5633f0a5069c0689171f60b57719a242be)
- - - - -
8aea6d74 by Cheng Shao at 2026-03-03T10:49:48+05:30
testsuite: avoid re.sub in favor of simple string replacements
This patch refactors the testsuite driver and avoids the usage of
re.sub in favor of simple string replacements when possible. The
changes are not comprehensive, and there are still a lot of re.sub
usages lingering around the tree, but this already addresses a major
performance bottleneck in the testsuite driver that might has to do
with quadratic or worse slowdown in cpython's regular expression
engine when handling certain regex patterns with large strings.
Especially on i386, and i386 jobs are the bottlenecks of all full-ci
validate pipelines!
Here are the elapsed times of testing x86_64/i386 with -j48 before
this patch:
x86_64: `Build completed in 6m06s`
i386: `Build completed in 1h36m`
And with this patch:
x86_64: `Build completed in 4m55s`
i386: `Build completed in 4m23s`
Fixes #26786.
Co-authored-by: Codex <codex(a)openai.com>
(cherry picked from commit ca79475f6b4dfba991e2c933bac9c22d54a4950d)
- - - - -
22e6dda8 by Zubin Duggal at 2026-03-03T10:49:48+05:30
hadrian: Add ghc-{experimental,internal}.cabal to the list of dependencies of the doc target
We need these files to detect the version of these libraries
Fixes #26738
(cherry picked from commit 1b490f5a7bbdb1441948241e6089b31efba9db45)
- - - - -
c2322fcc by Jessica Clarke at 2026-03-03T10:49:48+05:30
PPC NCG: Use libcall for 64-bit cmpxchg on 32-bit PowerPC
There is no native instruction for this, and even if there were a
register pair version we could use, the implementation here is assuming
the values fit in a single register, and we end up only using / defining
the low halves of the registers.
Fixes: b4d39adbb5 ("PrimOps: Add CAS op for all int sizes")
Fixes: #23969
(cherry picked from commit ce2d62fba69d2ea0c74c46c50628feb8b81719d2)
- - - - -
546506f5 by John Paul Adrian Glaubitz at 2026-03-03T10:49:48+05:30
rts: Switch prim to use modern atomic compiler builtins
The __sync_*() atomic compiler builtins have been deprecated in GCC
for a while now and also don't provide variants for 64-bit values
such as __sync_fetch_and_add_8().
Thus, replace them with the modern __atomic_*() compiler builtins and
while we're at it, also drop the helper macro CAS_NAND() which is now
no longer needed since we stopped using the __sync_*() compiler builtins
altogether.
Co-authored-by: Ilias Tsitsimpis <iliastsi(a)debian.org>
Fixes #26729
(cherry picked from commit 7c52c4f9bc8d6ae6404039ec02efe48fbf7a4778)
- - - - -
1b75850a by sterni at 2026-03-03T10:49:48+05:30
users_guide: fix runtime error during build with Sphinx 9.1.0
Appears that pathto is stricter about what it accepts now.
Tested Sphinx 8.2.3 and 9.1.0 on the ghc-9.10 branch.
Resolves #26810.
Co-authored-by: Martin Weinelt <hexa(a)darmstadt.ccc.de>
(cherry picked from commit e8f5a45de561ec80c88cd3da2c66502deb32d4c3)
- - - - -
8103c4f4 by Michael Karcher at 2026-03-03T10:49:48+05:30
NCG for PPC: add pattern for CmmRegOff to iselExpr64
Closes #26828
(cherry picked from commit 43d977619de65c0cf87695fa5d86f1a3ff3176c3)
- - - - -
777a7b5a by Matthew Pickering at 2026-03-03T10:49:48+05:30
determinism: Use deterministic map for Strings in TyLitMap
When generating typeable evidence the types we need evidence for all
cached in a TypeMap, the order terms are retrieved from a type map
determines the order the bindings appear in the program.
A TypeMap is quite diligent to use deterministic maps, apart from in the
TyLitMap, which uses a UniqFM for storing strings, whose ordering
depends on the Unique of the FastString.
This can cause non-deterministic .hi and .o files.
An unexpected side-effect is the error message but RecordDotSyntaxFail8
changing. I looked into this with Sam and this change caused the
constraints to be solved in a different order which results in a
slightly different error message. I have accepted the new test, since
the output before was non-deterministic and the new output is consistent
with the other messages in that file.
Fixes #26846
(cherry picked from commit aeeb4a2034e80e26503eb88f5abde85e87a82f7b)
- - - - -
293ded1d by Andrew Lelechenko at 2026-03-03T10:49:48+05:30
Upgrade text submodule to 2.1.4
(cherry picked from commit 9e4d70c2764d117c5cf753127f93056d66e4f0d7)
- - - - -
bced716b by Zubin Duggal at 2026-03-03T10:49:48+05:30
Bump transformers submodule to 0.6.3.0
Fixes #26790
(cherry picked from commit ea0d1317a630799a6b7bea12b24ef7e1ea6ed512)
- - - - -
5e9a99fb by Matthew Pickering at 2026-03-03T10:49:48+05:30
determinism: Use a stable sort in WithHsDocIdentifiers binary instance
`WithHsDocIdentifiers` is defined as
```
71 data WithHsDocIdentifiers a pass = WithHsDocIdentifiers
72 { hsDocString :: !a
73 , hsDocIdentifiers :: ![Located (IdP pass)]
74 }
```
This list of names is populated from `rnHsDocIdentifiers`, which calls
`lookupGRE`, which calls `lookupOccEnv_AllNameSpaces`, which calls
`nonDetEltsUFM` and returns the results in an order depending on
uniques.
Sorting the list with a stable sort before returning the interface makes
the output deterministic and follows the approach taken by other fields
in `Docs`.
Fixes #26858
(cherry picked from commit 0020e38a021b5f0371c48fe73cddf8987acb1eb1)
- - - - -
f6e481a3 by Simon Peyton Jones at 2026-03-03T10:49:48+05:30
Fix subtle bug in cast worker/wrapper
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
(cherry picked from commit 99d8c146c12146e1e21b1f2d31809845d4afe9d4)
- - - - -
39783f42 by Cheng Shao at 2026-03-03T10:49:48+05:30
wasm: use import.meta.main for proper distinction of nodejs main modules
This patch uses `import.meta.main` for proper distinction of nodejs
main modules, especially when the main module might be installed as a
symlink. Fixes #26916.
(cherry picked from commit 039f19778e35b193af0de2a2c6ed89556038627a)
- - - - -
519601bc by Zubin Duggal at 2026-03-03T10:49:48+05:30
Prepare release 9.12.4
- - - - -
49 changed files:
- compiler/GHC/CmmToAsm/PPC/CodeGen.hs
- compiler/GHC/CmmToAsm/Reg/Linear.hs
- compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Types/Id/Info.hs
- docs/users_guide/release-notes.rst
- docs/users_guide/rtd-theme/layout.html
- hadrian/src/Rules/Documentation.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/ghc-experimental/ghc-experimental.cabal.in
- libraries/ghc-experimental/src/GHC/Exception/Backtrace/Experimental.hs
- libraries/ghc-internal/src/GHC/Internal/Err.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- libraries/text
- libraries/transformers
- rts/prim/atomic.c
- rts/rts.cabal
- rts/sm/Evac.c
- rts/sm/Evac_thr.c → rts/sm/Evac_par.c
- rts/sm/Scav_thr.c → rts/sm/Scav_par.c
- testsuite/driver/runtests.py
- testsuite/driver/testlib.py
- testsuite/driver/testutil.py
- + testsuite/tests/ghc-api/TypeMapStringLiteral.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghci.debugger/scripts/T8487.stdout
- testsuite/tests/ghci.debugger/scripts/break011.stdout
- testsuite/tests/ghci.debugger/scripts/break017.stdout
- testsuite/tests/ghci.debugger/scripts/break025.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/showIface/DocsInHiFile1.stdout
- testsuite/tests/showIface/HaddockSpanIssueT24378.stdout
- testsuite/tests/showIface/MagicHashInHaddocks.stdout
- + testsuite/tests/simplCore/should_compile/T26903.hs
- + testsuite/tests/simplCore/should_compile/T26903.stderr
- testsuite/tests/simplCore/should_compile/all.T
- utils/ghc-pkg/Main.hs
- utils/jsffi/dyld.mjs
- utils/jsffi/post-link.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/45bc79ab3c196a90297cad2368983d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/45bc79ab3c196a90297cad2368983d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/io-manager-deadlock-detection] Deleted 5 commits: Make the IOManager API use CapIOManager rather than Capability
by Duncan Coutts (@dcoutts) 02 Mar '26
by Duncan Coutts (@dcoutts) 02 Mar '26
02 Mar '26
Duncan Coutts pushed to branch wip/io-manager-deadlock-detection at Glasgow Haskell Compiler / GHC
WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below.
Deleted commits:
f340f464 by Duncan Coutts at 2026-02-11T22:48:35+00:00
Make the IOManager API use CapIOManager rather than Capability
This makes the API somewhat more self-contained and more consistent.
Now the IOManager API and each of the backends takes just the I/O
manager structure. Previously we had a bit of a mixture, depending on
whether the function needed access to the Capability or just the
CapIOManager.
We still need access to the cap, so we introduce a back reference to
reach the capability, via iomgr->cap.
Convert all uses in select and poll backends, but not win32 ones.
Convert callers in the scheduler and elsewhere.
Also convert the three CMM primops that call IOManager APIs. They just
need to use Capability_iomgr(MyCapability()).
- - - - -
1136fd5b by Duncan Coutts at 2026-02-16T00:30:48+00:00
Split posix/MIO.c out of posix/Signals.c
The MIO I/O manager was secretly living inside the Signals file.
Now it gets its own file, like any other self-respecting I/O manager.
- - - - -
ec170e68 by Duncan Coutts at 2026-02-16T00:30:50+00:00
Rationalise some scheduler run queue utilities
Move them all to the same place in the file.
Make some static that were used only internally.
Also remove a redundant assignment after calling truncateRunQueue that
is already done within truncateRunQueue.
- - - - -
c4312136 by Duncan Coutts at 2026-02-16T00:30:50+00:00
Rename initIOManager{AfterFork} to {re}startIOManager
These are more accurate names, since these actions happen after
initialisation and are really about starting (or restarting) background
threads.
- - - - -
24a403ed by Duncan Coutts at 2026-02-16T00:30:50+00:00
Add a TODO to the MIO I/O manager
The direction of travel is to make I/O managers per-capability and have
all their state live in the struct CapIOManager. The MIO I/O manager
however still has a number of global variables.
It's not obvious how handle these globals however.
- - - - -
20 changed files:
- rts/Capability.c
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/PrimOps.cmm
- rts/RaiseAsync.c
- rts/RtsStartup.c
- rts/Schedule.c
- rts/Schedule.h
- + rts/posix/MIO.c
- + rts/posix/MIO.h
- rts/posix/Poll.c
- rts/posix/Poll.h
- rts/posix/Select.c
- rts/posix/Select.h
- rts/posix/Signals.c
- rts/posix/Signals.h
- rts/posix/Timeout.c
- rts/posix/Timeout.h
- rts/rts.cabal
Changes:
=====================================
rts/Capability.c
=====================================
@@ -286,7 +286,8 @@ initCapability (Capability *cap, uint32_t i)
#endif
cap->total_allocated = 0;
- initCapabilityIOManager(cap); /* initialises cap->iomgr */
+ cap->iomgr = allocCapabilityIOManager(cap);
+ initCapabilityIOManager(cap->iomgr);
cap->f.stgEagerBlackholeInfo = (W_)&__stg_EAGER_BLACKHOLE_info;
cap->f.stgGCEnter1 = (StgFunPtr)__stg_gc_enter_1;
@@ -1344,7 +1345,7 @@ markCapability (evac_fn evac, void *user, Capability *cap,
}
#endif
- markCapabilityIOManager(evac, user, cap);
+ markCapabilityIOManager(evac, user, cap->iomgr);
// Free STM structures for this Capability
stmPreGCHook(cap);
=====================================
rts/IOManager.c
=====================================
@@ -39,7 +39,7 @@
#endif
#if defined(IOMGR_ENABLED_MIO_POSIX)
-#include "posix/Signals.h"
+#include "posix/MIO.h"
#include "Prelude.h"
#endif
@@ -316,22 +316,29 @@ char * showIOManager(void)
}
}
+/* Allocate a CapIOManager for a given Capability. Having this helps us keep
+ * struct CapIOManager opaque from most of the rest of the RTS.
+ */
+CapIOManager *allocCapabilityIOManager(Capability *cap)
+{
+ CapIOManager *iomgr = stgMallocBytes(sizeof(CapIOManager),
+ "allocCapabilityIOManager");
+ iomgr->cap = cap; /* link back */
+ return iomgr;
+}
+
-/* Allocate and initialise the per-capability CapIOManager that lives in each
- * Capability. Called from initCapability(), which is done in the RTS startup
- * in initCapabilities(), and later at runtime via setNumCapabilities().
+/* Initialise the per-capability CapIOManager that lives in each Capability.
+ * Called from initCapability(), which is done in the RTS startup in
+ * initCapabilities(), and later at runtime via setNumCapabilities().
*
* Note that during RTS startup this is called _before_ the storage manager
* is initialised, so this is not allowed to allocate on the GC heap.
*/
-void initCapabilityIOManager(Capability *cap)
+void initCapabilityIOManager(CapIOManager *iomgr)
{
debugTrace(DEBUG_iomanager, "initialising I/O manager %s for cap %d",
- showIOManager(), cap->no);
-
- CapIOManager *iomgr =
- (CapIOManager *) stgMallocBytes(sizeof(CapIOManager),
- "initCapabilityIOManager");
+ showIOManager(), iomgr->cap->no);
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
@@ -363,16 +370,14 @@ void initCapabilityIOManager(Capability *cap)
default:
break;
}
-
- cap->iomgr = iomgr;
}
/* Called late in the RTS initialisation
*/
-void initIOManager(void)
+void startIOManager(void)
{
- debugTrace(DEBUG_iomanager, "initialising %s I/O manager", showIOManager());
+ debugTrace(DEBUG_iomanager, "starting %s I/O manager", showIOManager());
switch (iomgr_type) {
@@ -436,7 +441,7 @@ void initIOManager(void)
/* Called from forkProcess in the child process on the surviving capability.
*/
void
-initIOManagerAfterFork(Capability **pcap)
+restartIOManager(CapIOManager *iomgr, Capability **pcap)
{
switch (iomgr_type) {
@@ -467,7 +472,7 @@ initIOManagerAfterFork(Capability **pcap)
/* Called from setNumCapabilities.
*/
-void notifyIOManagerCapabilitiesChanged(Capability **pcap)
+void notifyIOManagerCapabilitiesChanged(CapIOManager *iomgr, Capability **pcap)
{
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_MIO_POSIX)
@@ -572,38 +577,29 @@ void wakeupIOManager(void)
}
}
-void markCapabilityIOManager(evac_fn evac, void *user, Capability *cap)
+void markCapabilityIOManager(evac_fn evac, void *user, CapIOManager *iomgr)
{
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
case IO_MANAGER_SELECT:
- {
- CapIOManager *iomgr = cap->iomgr;
evac(user, (StgClosure **)(void *)&iomgr->blocked_queue_hd);
evac(user, (StgClosure **)(void *)&iomgr->blocked_queue_tl);
evac(user, (StgClosure **)(void *)&iomgr->sleeping_queue);
break;
- }
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- {
- CapIOManager *iomgr = cap->iomgr;
markClosureTable(evac, user, &iomgr->aiop_table);
evac(user, (StgClosure **)(void *)&iomgr->timeout_queue);
break;
- }
#endif
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
- {
- CapIOManager *iomgr = cap->iomgr;
evac(user, (StgClosure **)(void *)&iomgr->blocked_queue_hd);
evac(user, (StgClosure **)(void *)&iomgr->blocked_queue_tl);
break;
- }
#endif
default:
break;
@@ -665,29 +661,23 @@ setIOManagerControlFd(uint32_t cap_no, int fd) {
#endif
-bool anyPendingTimeoutsOrIO(Capability *cap)
+bool anyPendingTimeoutsOrIO(CapIOManager *iomgr)
{
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
case IO_MANAGER_SELECT:
- {
- CapIOManager *iomgr = cap->iomgr;
return (iomgr->blocked_queue_hd != END_TSO_QUEUE)
|| (iomgr->sleeping_queue != END_TSO_QUEUE);
- }
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- return anyPendingTimeoutsOrIOPoll(cap->iomgr);
+ return anyPendingTimeoutsOrIOPoll(iomgr);
#endif
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
- {
- CapIOManager *iomgr = cap->iomgr;
return (iomgr->blocked_queue_hd != END_TSO_QUEUE);
- }
#endif
/* For the purpose of the scheduler, the threaded I/O managers never have
@@ -729,19 +719,19 @@ bool anyPendingTimeoutsOrIO(Capability *cap)
}
-void pollCompletedTimeoutsOrIO(Capability *cap)
+void pollCompletedTimeoutsOrIO(CapIOManager *iomgr)
{
debugTrace(DEBUG_iomanager, "polling for completed IO or timeouts");
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
case IO_MANAGER_SELECT:
- awaitCompletedTimeoutsOrIOSelect(cap, false);
+ awaitCompletedTimeoutsOrIOSelect(iomgr, false);
break;
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- pollCompletedTimeoutsOrIOPoll(cap);
+ pollCompletedTimeoutsOrIOPoll(iomgr);
break;
#endif
@@ -753,7 +743,7 @@ void pollCompletedTimeoutsOrIO(Capability *cap)
#if defined(IOMGR_ENABLED_WINIO)
case IO_MANAGER_WINIO:
#endif
- awaitCompletedTimeoutsOrIOWin32(cap, false);
+ awaitCompletedTimeoutsOrIOWin32(iomgr->cap, false);
break;
#endif
default:
@@ -762,19 +752,19 @@ void pollCompletedTimeoutsOrIO(Capability *cap)
}
-void awaitCompletedTimeoutsOrIO(Capability *cap)
+void awaitCompletedTimeoutsOrIO(CapIOManager *iomgr)
{
debugTrace(DEBUG_iomanager, "waiting for completed IO or timeouts");
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
case IO_MANAGER_SELECT:
- awaitCompletedTimeoutsOrIOSelect(cap, true);
+ awaitCompletedTimeoutsOrIOSelect(iomgr, true);
break;
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- awaitCompletedTimeoutsOrIOPoll(cap);
+ awaitCompletedTimeoutsOrIOPoll(iomgr);
break;
#endif
@@ -786,17 +776,18 @@ void awaitCompletedTimeoutsOrIO(Capability *cap)
#if defined(IOMGR_ENABLED_WINIO)
case IO_MANAGER_WINIO:
#endif
- awaitCompletedTimeoutsOrIOWin32(cap, true);
+ awaitCompletedTimeoutsOrIOWin32(iomgr->cap, true);
break;
#endif
default:
barf("pollCompletedTimeoutsOrIO not implemented");
}
- ASSERT(!emptyRunQueue(cap) || getSchedState() != SCHED_RUNNING);
+ ASSERT(!emptyRunQueue(iomgr->cap) || getSchedState() != SCHED_RUNNING);
}
-bool syncIOWaitReady(Capability *cap,
+/* CMM primop. Result is true on success, or false on allocation failure. */
+bool syncIOWaitReady(CapIOManager *iomgr,
StgTSO *tso,
IOReadOrWrite rw,
HsInt fd)
@@ -812,14 +803,14 @@ bool syncIOWaitReady(Capability *cap,
StgWord why_blocked = rw == IORead ? BlockedOnRead : BlockedOnWrite;
tso->block_info.fd = fd;
RELEASE_STORE(&tso->why_blocked, why_blocked);
- appendToIOBlockedQueue(cap, tso);
+ appendToIOBlockedQueue(iomgr, tso);
return true;
}
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
ASSERT(tso->why_blocked == NotBlocked);
- return syncIOWaitReadyPoll(cap, tso, rw, fd);
+ return syncIOWaitReadyPoll(iomgr, tso, rw, fd);
#endif
default:
barf("waitRead# / waitWrite# not available for current I/O manager");
@@ -827,25 +818,29 @@ bool syncIOWaitReady(Capability *cap,
}
-void syncIOCancel(Capability *cap, StgTSO *tso)
+void syncIOCancel(CapIOManager *iomgr, StgTSO *tso)
{
debugTrace(DEBUG_iomanager, "cancelling I/O for thread %ld", (long) tso->id);
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
case IO_MANAGER_SELECT:
- removeThreadFromDeQueue(cap, &cap->iomgr->blocked_queue_hd,
- &cap->iomgr->blocked_queue_tl, tso);
+ removeThreadFromDeQueue(iomgr->cap,
+ &iomgr->blocked_queue_hd,
+ &iomgr->blocked_queue_tl,
+ tso);
break;
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- syncIOCancelPoll(cap, tso);
+ syncIOCancelPoll(iomgr, tso);
break;
#endif
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
- removeThreadFromDeQueue(cap, &cap->iomgr->blocked_queue_hd,
- &cap->iomgr->blocked_queue_tl, tso);
+ removeThreadFromDeQueue(iomgr->cap,
+ &iomgr->blocked_queue_hd,
+ &iomgr->blocked_queue_tl,
+ tso);
abandonWorkRequest(tso->block_info.async_result->reqID);
break;
#endif
@@ -856,11 +851,12 @@ void syncIOCancel(Capability *cap, StgTSO *tso)
#if defined(IOMGR_ENABLED_SELECT)
-static void insertIntoSleepingQueue(Capability *cap, StgTSO *tso, LowResTime target);
+static void insertIntoSleepingQueue(CapIOManager *iomgr, StgTSO *tso, LowResTime target);
#endif
-bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
+/* CMM primop. Result is true on success, or false on allocation failure. */
+bool syncDelay(CapIOManager *iomgr, StgTSO *tso, HsInt us_delay)
{
debugTrace(DEBUG_iomanager, "thread %ld waiting for %lld us", tso->id, us_delay);
ASSERT(tso->why_blocked == NotBlocked);
@@ -871,13 +867,13 @@ bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
LowResTime target = getDelayTarget(us_delay);
tso->block_info.target = target;
RELEASE_STORE(&tso->why_blocked, BlockedOnDelay);
- insertIntoSleepingQueue(cap, tso, target);
+ insertIntoSleepingQueue(iomgr, tso, target);
return true;
}
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- return syncDelayTimeout(cap, tso, us_delay);
+ return syncDelayTimeout(iomgr, tso, us_delay);
#endif
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
@@ -897,7 +893,7 @@ bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
* delayed thread on the blocked_queue.
*/
RELEASE_STORE(&tso->why_blocked, BlockedOnDoProc);
- appendToIOBlockedQueue(cap, tso);
+ appendToIOBlockedQueue(iomgr, tso);
return true;
}
#endif
@@ -907,18 +903,18 @@ bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
}
-void syncDelayCancel(Capability *cap, StgTSO *tso)
+void syncDelayCancel(CapIOManager *iomgr, StgTSO *tso)
{
debugTrace(DEBUG_iomanager, "cancelling delay for thread %ld", (long) tso->id);
switch (iomgr_type) {
#if defined(IOMGR_ENABLED_SELECT)
case IO_MANAGER_SELECT:
- removeThreadFromQueue(cap, &cap->iomgr->sleeping_queue, tso);
+ removeThreadFromQueue(iomgr->cap, &iomgr->sleeping_queue, tso);
break;
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- syncDelayCancelTimeout(cap, tso);
+ syncDelayCancelTimeout(iomgr, tso);
break;
#endif
/* Note: no case for IO_MANAGER_WIN32_LEGACY despite it having a case
@@ -935,14 +931,13 @@ void syncDelayCancel(Capability *cap, StgTSO *tso)
#if defined(IOMGR_ENABLED_SELECT) || defined(IOMGR_ENABLED_WIN32_LEGACY)
-void appendToIOBlockedQueue(Capability *cap, StgTSO *tso)
+void appendToIOBlockedQueue(CapIOManager *iomgr, StgTSO *tso)
{
- CapIOManager *iomgr = cap->iomgr;
ASSERT(tso->_link == END_TSO_QUEUE);
if (iomgr->blocked_queue_hd == END_TSO_QUEUE) {
iomgr->blocked_queue_hd = tso;
} else {
- setTSOLink(cap, iomgr->blocked_queue_tl, tso);
+ setTSOLink(iomgr->cap, iomgr->blocked_queue_tl, tso);
}
iomgr->blocked_queue_tl = tso;
}
@@ -957,9 +952,8 @@ void appendToIOBlockedQueue(Capability *cap, StgTSO *tso)
* used. This is a wart that should be excised.
*/
// TODO: move to Select.c and rename
-static void insertIntoSleepingQueue(Capability *cap, StgTSO *tso, LowResTime target)
+static void insertIntoSleepingQueue(CapIOManager *iomgr, StgTSO *tso, LowResTime target)
{
- CapIOManager *iomgr = cap->iomgr;
StgTSO *prev = NULL;
StgTSO *t = iomgr->sleeping_queue;
while (t != END_TSO_QUEUE && t->block_info.target < target) {
@@ -971,7 +965,7 @@ static void insertIntoSleepingQueue(Capability *cap, StgTSO *tso, LowResTime tar
if (prev == NULL) {
iomgr->sleeping_queue = tso;
} else {
- setTSOLink(cap, prev, tso);
+ setTSOLink(iomgr->cap, prev, tso);
}
}
#endif
=====================================
rts/IOManager.h
=====================================
@@ -19,6 +19,7 @@
#pragma once
+#include "Capability.h"
#include "sm/GC.h" // for evac_fn
#include "BeginPrivate.h"
@@ -227,26 +228,35 @@ enum IOOpOutcome {
void selectIOManager(void);
-/* Allocate and initialise the per-capability CapIOManager that lives in each
- * Capability. Called from initCapability(), which is done in the RTS startup
- * in initCapabilities(), and later at runtime via setNumCapabilities().
+/* Allocate a CapIOManager for a given Capability. Having this helps us keep
+ * struct CapIOManager opaque from most of the rest of the RTS.
*/
-void initCapabilityIOManager(Capability *cap);
+CapIOManager *allocCapabilityIOManager(Capability *cap);
+
+/* Initialise the per-capability CapIOManager that lives in each Capability.
+ * Called from initCapability(), which is done in the RTS startup in
+ * initCapabilities(), and later at runtime via setNumCapabilities().
+ *
+ * This is separate from allocCapabilityIOManager so that we can re-initialise
+ * I/O managers after forkProcess.
+ */
+void initCapabilityIOManager(CapIOManager *iomgr);
/* Init hook: called from hs_init_ghc, very late in the startup after almost
* everything else is done.
*/
-void initIOManager(void);
+void startIOManager(void);
/* Init hook: called from forkProcess in the child process on the surviving
* capability.
*
- * Note that this is synchronous and can run Haskell code, so can change the
- * given cap.
+ * This is synchronous and can run Haskell code, so can change the given cap.
+ * TODO: it would make for a cleaner API here if this were made asynchronous.
*/
-void initIOManagerAfterFork(/* inout */ Capability **pcap);
+void restartIOManager(CapIOManager *iomgr,
+ /* inout */ Capability **pcap);
/* TODO: rationalise initIOManager and initIOManagerAfterFork into a single
per-capability init function.
@@ -254,8 +264,12 @@ void initIOManagerAfterFork(/* inout */ Capability **pcap);
/* Called from setNumCapabilities.
+ *
+ * This is synchronous and can run Haskell code, so can change the given cap.
+ * TODO: it would make for a cleaner API here if this were made asynchronous.
*/
-void notifyIOManagerCapabilitiesChanged(Capability **pcap);
+void notifyIOManagerCapabilitiesChanged(CapIOManager *iomgr,
+ /* inout */ Capability **pcap);
/* Shutdown hooks: called from hs_exit_ before and after the scheduler exits.
@@ -288,7 +302,7 @@ void wakeupIOManager(void);
/* GC hook: mark any per-capability GC roots the I/O manager uses.
*/
-void markCapabilityIOManager(evac_fn evac, void *user, Capability *cap);
+void markCapabilityIOManager(evac_fn evac, void *user, CapIOManager *iomgr);
/* GC hook: scavenge I/O related tso->block_info. Used by scavengeTSO.
@@ -305,21 +319,20 @@ typedef enum { IORead, IOWrite } IOReadOrWrite;
* necessarily operate on threads. The thread is suspended until the operation
* completes.
*
- * These are called from CMM primops. The ones returing int can perform heap
- * allocation, which might fail. They return 0 on success, or n > 0 on heap
- * allocation failure, needing n words. The CMM primops should invoke the
- * GC to free up at least n words and then retry the operation.
+ * Some of these are called from CMM primops. The primops returing bool can
+ * perform heap allocation, which might fail. They return true on success, or
+ * false on heap allocation failure.
*/
-/* Result is true on success, or false on allocation failure. */
-bool syncIOWaitReady(Capability *cap, StgTSO *tso, IOReadOrWrite rw, HsInt fd);
+/* Called from CMM primop */
+bool syncIOWaitReady(CapIOManager *iomgr, StgTSO *tso, IOReadOrWrite rw, HsInt fd);
-void syncIOCancel(Capability *cap, StgTSO *tso);
+void syncIOCancel(CapIOManager *iomgr, StgTSO *tso);
-/* Result is true on success, or false on allocation failure. */
-bool syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay);
+/* Called from CMM primop */
+bool syncDelay(CapIOManager *iomgr, StgTSO *tso, HsInt us_delay);
-void syncDelayCancel(Capability *cap, StgTSO *tso);
+void syncDelayCancel(CapIOManager *iomgr, StgTSO *tso);
#if defined(IOMGR_ENABLED_SELECT) || defined(IOMGR_ENABLED_WIN32_LEGACY)
/* Add a thread to the end of the queue of threads blocked on I/O.
@@ -327,7 +340,7 @@ void syncDelayCancel(Capability *cap, StgTSO *tso);
* This is used by the select() and the Windows MIO non-threaded I/O manager
* implementation. Called from CMM code.
*/
-void appendToIOBlockedQueue(Capability *cap, StgTSO *tso);
+void appendToIOBlockedQueue(CapIOManager *iomgr, StgTSO *tso);
#endif
/* Check to see if there are any pending timeouts or I/O operations
@@ -336,7 +349,7 @@ void appendToIOBlockedQueue(Capability *cap, StgTSO *tso);
* This is used by the scheduler as part of deadlock-detection, and the
* "context switch as often as possible" test.
*/
-bool anyPendingTimeoutsOrIO(Capability *cap);
+bool anyPendingTimeoutsOrIO(CapIOManager *iomgr);
/* If there are any completed I/O operations or expired timers, process the
* completions as appropriate (which will typically unblock some waiting
@@ -344,7 +357,7 @@ bool anyPendingTimeoutsOrIO(Capability *cap);
*
* Called from schedule() both *before* and *after* scheduleDetectDeadlock().
*/
-void pollCompletedTimeoutsOrIO(Capability *cap);
+void pollCompletedTimeoutsOrIO(CapIOManager *iomgr);
/* If there are any completed I/O operations or expired timers, process the
* completions as appropriate. If there are none, wait until I/O or a timer
@@ -360,6 +373,6 @@ void pollCompletedTimeoutsOrIO(Capability *cap);
*
* Called from schedule() both *before* and *after* scheduleDetectDeadlock().
*/
-void awaitCompletedTimeoutsOrIO(Capability *cap);
+void awaitCompletedTimeoutsOrIO(CapIOManager *iomgr);
#include "EndPrivate.h"
=====================================
rts/IOManagerInternals.h
=====================================
@@ -24,7 +24,8 @@
/* The per-capability data structures belonging to the I/O manager.
*
- * It can be accessed as cap->iomgr.
+ * It can be accessed as cap->iomgr. Or given just the iomgr, you can access
+ * the owning cap as iomgr->cap.
*
* The content of the structure is defined conditionally so it is different for
* each I/O manager implementation.
@@ -33,6 +34,9 @@
*/
struct _CapIOManager {
+ /* Back reference to the containing capability */
+ Capability *cap;
+
#if defined(IOMGR_ENABLED_SELECT)
/* Thread queue for threads blocked on I/O completion. */
StgTSO *blocked_queue_hd;
=====================================
rts/PrimOps.cmm
=====================================
@@ -2279,7 +2279,8 @@ stg_waitReadzh ( W_ fd )
{
CBool ok; /* Ok, or heap alloc failure. */
- (ok) = ccall syncIOWaitReady(MyCapability() "ptr", CurrentTSO "ptr",
+ (ok) = ccall syncIOWaitReady(Capability_iomgr(MyCapability()) "ptr",
+ CurrentTSO "ptr",
/* IORead */ 0::I32, fd);
if (ok != 0::CBool) (likely: True) {
jump stg_block_noregs();
@@ -2292,7 +2293,8 @@ stg_waitWritezh ( W_ fd )
{
CBool ok; /* Ok, or heap alloc failure. */
- (ok) = ccall syncIOWaitReady(MyCapability() "ptr", CurrentTSO "ptr",
+ (ok) = ccall syncIOWaitReady(Capability_iomgr(MyCapability()) "ptr",
+ CurrentTSO "ptr",
/* IOWrite */ 1::I32, fd);
if (ok != 0::CBool) (likely: True) {
jump stg_block_noregs();
@@ -2305,7 +2307,8 @@ stg_delayzh ( W_ us_delay )
{
CBool ok; /* Ok, or heap alloc failure. */
- (ok) = ccall syncDelay(MyCapability() "ptr", CurrentTSO "ptr", us_delay);
+ (ok) = ccall syncDelay(Capability_iomgr(MyCapability()) "ptr",
+ CurrentTSO "ptr", us_delay);
if (ok != 0::CBool) (likely: True) {
/* Annoyingly, we cannot be consistent with how we wait and resume the
=====================================
rts/RaiseAsync.c
=====================================
@@ -708,12 +708,12 @@ removeFromQueues(Capability *cap, StgTSO *tso)
case BlockedOnWrite:
case BlockedOnDoProc:
// These blocking reasons are only used by some I/O managers
- syncIOCancel(cap, tso);
+ syncIOCancel(cap->iomgr, tso);
goto done;
case BlockedOnDelay:
// This blocking reasons is only used by some I/O managers
- syncDelayCancel(cap, tso);
+ syncDelayCancel(cap->iomgr, tso);
goto done;
default:
=====================================
rts/RtsStartup.c
=====================================
@@ -427,7 +427,7 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config)
}
#endif
- initIOManager();
+ startIOManager();
x86_init_fpu();
=====================================
rts/Schedule.c
=====================================
@@ -174,6 +174,11 @@ static void deleteAllThreads (void);
static void deleteThread_(StgTSO *tso);
#endif
+#if defined(FORKPROCESS_PRIMOP_SUPPORTED)
+static void truncateRunQueue(Capability *cap);
+#endif
+static StgTSO *popRunQueue (Capability *cap);
+
/* ---------------------------------------------------------------------------
Main scheduling loop.
@@ -409,7 +414,7 @@ schedule (Capability *initialCapability, Task *task)
*/
if (RtsFlags.ConcFlags.ctxtSwitchTicks == 0 &&
(!emptyRunQueue(cap) ||
- anyPendingTimeoutsOrIO(cap))) {
+ anyPendingTimeoutsOrIO(cap->iomgr))) {
RELAXED_STORE(&cap->context_switch, 1);
}
@@ -591,38 +596,6 @@ run_thread:
} /* end of while() */
}
-/* -----------------------------------------------------------------------------
- * Run queue operations
- * -------------------------------------------------------------------------- */
-
-static void
-removeFromRunQueue (Capability *cap, StgTSO *tso)
-{
- if (tso->block_info.prev == END_TSO_QUEUE) {
- ASSERT(cap->run_queue_hd == tso);
- cap->run_queue_hd = tso->_link;
- } else {
- setTSOLink(cap, tso->block_info.prev, tso->_link);
- }
- if (tso->_link == END_TSO_QUEUE) {
- ASSERT(cap->run_queue_tl == tso);
- cap->run_queue_tl = tso->block_info.prev;
- } else {
- setTSOPrev(cap, tso->_link, tso->block_info.prev);
- }
- tso->_link = tso->block_info.prev = END_TSO_QUEUE;
- cap->n_run_queue--;
-
- IF_DEBUG(sanity, checkRunQueue(cap));
-}
-
-void
-promoteInRunQueue (Capability *cap, StgTSO *tso)
-{
- removeFromRunQueue(cap, tso);
- pushOnRunQueue(cap, tso);
-}
-
/* -----------------------------------------------------------------------------
* scheduleFindWork()
*
@@ -923,14 +896,14 @@ scheduleCheckBlockedThreads(Capability *cap USED_IF_NOT_THREADS)
* awaitCompletedTimeoutsOrIO below for the case of !defined(THREADED_RTS)
* && defined(mingw32_HOST_OS).
*/
- if (anyPendingTimeoutsOrIO(cap))
+ if (anyPendingTimeoutsOrIO(cap->iomgr))
{
if (emptyRunQueue(cap)) {
// block and wait
- awaitCompletedTimeoutsOrIO(cap);
+ awaitCompletedTimeoutsOrIO(cap->iomgr);
} else {
// poll but do not wait
- pollCompletedTimeoutsOrIO(cap);
+ pollCompletedTimeoutsOrIO(cap->iomgr);
}
}
#endif
@@ -950,7 +923,7 @@ scheduleDetectDeadlock (Capability **pcap, Task *task)
* other tasks are waiting for work, we must have a deadlock of
* some description.
*/
- if ( emptyRunQueue(cap) && !anyPendingTimeoutsOrIO(cap) )
+ if ( emptyRunQueue(cap) && !anyPendingTimeoutsOrIO(cap->iomgr) )
{
#if defined(THREADED_RTS)
/*
@@ -2191,7 +2164,6 @@ forkProcess(HsStablePtr *entry
// bound threads for which the corresponding Task does not
// exist.
truncateRunQueue(cap);
- cap->n_run_queue = 0;
// Any suspended C-calling Tasks are no more, their OS threads
// don't exist now:
@@ -2208,7 +2180,7 @@ forkProcess(HsStablePtr *entry
cap->n_returning_tasks = 0;
#endif
- // Release all caps except 0, we'll use that for starting
+ // Release all caps except 0, we'll use that for restarting
// the IO manager and running the client action below.
if (cap->no != 0) {
task->cap = cap;
@@ -2232,7 +2204,7 @@ forkProcess(HsStablePtr *entry
// like startup event, capabilities, process info etc
traceTaskCreate(task, cap);
- initIOManagerAfterFork(&cap);
+ restartIOManager(cap->iomgr, &cap);
// start timer after the IOManager is initialized
// (the idle GC may wake up the IOManager)
@@ -2392,7 +2364,7 @@ setNumCapabilities (uint32_t new_n_capabilities USED_IF_THREADS)
}
// Notify IO manager that the number of capabilities has changed.
- notifyIOManagerCapabilitiesChanged(&cap);
+ notifyIOManagerCapabilitiesChanged(cap->iomgr, &cap);
startTimer();
@@ -2997,7 +2969,7 @@ pushOnRunQueue (Capability *cap, StgTSO *tso)
cap->n_run_queue++;
}
-StgTSO *popRunQueue (Capability *cap)
+static StgTSO *popRunQueue (Capability *cap)
{
ASSERT(cap->n_run_queue > 0);
StgTSO *t = cap->run_queue_hd;
@@ -3017,6 +2989,45 @@ StgTSO *popRunQueue (Capability *cap)
return t;
}
+#if defined(FORKPROCESS_PRIMOP_SUPPORTED)
+static void truncateRunQueue(Capability *cap)
+{
+ // Can only be called by the task owning the capability.
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_hd, "truncateRunQueue");
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_tl, "truncateRunQueue");
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->n_run_queue, "truncateRunQueue");
+ cap->run_queue_hd = END_TSO_QUEUE;
+ cap->run_queue_tl = END_TSO_QUEUE;
+ cap->n_run_queue = 0;
+}
+#endif
+
+static void removeFromRunQueue (Capability *cap, StgTSO *tso)
+{
+ if (tso->block_info.prev == END_TSO_QUEUE) {
+ ASSERT(cap->run_queue_hd == tso);
+ cap->run_queue_hd = tso->_link;
+ } else {
+ setTSOLink(cap, tso->block_info.prev, tso->_link);
+ }
+ if (tso->_link == END_TSO_QUEUE) {
+ ASSERT(cap->run_queue_tl == tso);
+ cap->run_queue_tl = tso->block_info.prev;
+ } else {
+ setTSOPrev(cap, tso->_link, tso->block_info.prev);
+ }
+ tso->_link = tso->block_info.prev = END_TSO_QUEUE;
+ cap->n_run_queue--;
+
+ IF_DEBUG(sanity, checkRunQueue(cap));
+}
+
+void promoteInRunQueue (Capability *cap, StgTSO *tso)
+{
+ removeFromRunQueue(cap, tso);
+ pushOnRunQueue(cap, tso);
+}
+
/* -----------------------------------------------------------------------------
raiseExceptionHelper
=====================================
rts/Schedule.h
=====================================
@@ -164,10 +164,6 @@ void appendToRunQueue (Capability *cap, StgTSO *tso);
*/
void pushOnRunQueue (Capability *cap, StgTSO *tso);
-/* Pop the first thread off the runnable queue.
- */
-StgTSO *popRunQueue (Capability *cap);
-
INLINE_HEADER StgTSO *
peekRunQueue (Capability *cap)
{
@@ -184,18 +180,6 @@ emptyRunQueue(Capability *cap)
return cap->n_run_queue == 0;
}
-INLINE_HEADER void
-truncateRunQueue(Capability *cap)
-{
- // Can only be called by the task owning the capability.
- TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_hd, "truncateRunQueue");
- TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_tl, "truncateRunQueue");
- TSAN_ANNOTATE_BENIGN_RACE(&cap->n_run_queue, "truncateRunQueue");
- cap->run_queue_hd = END_TSO_QUEUE;
- cap->run_queue_tl = END_TSO_QUEUE;
- cap->n_run_queue = 0;
-}
-
#endif /* !IN_STG_CODE */
#include "EndPrivate.h"
=====================================
rts/posix/MIO.c
=====================================
@@ -0,0 +1,163 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 1998-2005
+ *
+ * Signal processing / handling.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "rts/PosixSource.h"
+#include "Rts.h"
+
+#include "Schedule.h"
+#include "RtsUtils.h"
+#include "Prelude.h"
+#include "ThreadLabels.h"
+
+#include "MIO.h"
+#include "IOManager.h"
+#include "IOManagerInternals.h"
+
+#if defined(HAVE_ERRNO_H)
+# include <errno.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+
+// Here's the pipe into which we will send our signals
+static int io_manager_wakeup_fd = -1;
+static int timer_manager_control_wr_fd = -1;
+// TODO: Eliminate these globals. Put then into the CapIOManager, but the
+// problem is these are shared across all caps, not per cap.
+
+#define IO_MANAGER_WAKEUP 0xff
+#define IO_MANAGER_DIE 0xfe
+#define IO_MANAGER_SYNC 0xfd
+
+void setTimerManagerControlFd(int fd) {
+ RELAXED_STORE(&timer_manager_control_wr_fd, fd);
+}
+
+void
+setIOManagerWakeupFd (int fd)
+{
+ // only called when THREADED_RTS, but unconditionally
+ // compiled here because GHC.Event.Control depends on it.
+ SEQ_CST_STORE(&io_manager_wakeup_fd, fd);
+}
+
+#if defined(THREADED_RTS)
+void timerManagerNotifySignal(int sig, siginfo_t *info)
+{
+ StgWord8 buf[sizeof(siginfo_t) + 1];
+ int r;
+
+ buf[0] = sig;
+ if (info == NULL) {
+ // info may be NULL on Solaris (see #3790)
+ memset(buf+1, 0, sizeof(siginfo_t));
+ } else {
+ memcpy(buf+1, info, sizeof(siginfo_t));
+ }
+
+ int timer_control_fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
+ if (0 <= timer_control_fd)
+ {
+ r = write(timer_control_fd, buf, sizeof(siginfo_t)+1);
+ if (r == -1 && errno == EAGAIN) {
+ errorBelch("lost signal due to full pipe: %d\n", sig);
+ }
+ }
+
+ // If the IO manager hasn't told us what the FD of the write end
+ // of its pipe is, there's not much we can do here, so just ignore
+ // the signal..
+}
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * Wake up at least one IO or timer manager HS thread.
+ * -------------------------------------------------------------------------- */
+void
+ioManagerWakeup (void)
+{
+ int r;
+ const int wakeup_fd = SEQ_CST_LOAD(&io_manager_wakeup_fd);
+ // Wake up the IO Manager thread by sending a byte down its pipe
+ if (wakeup_fd >= 0) {
+#if defined(HAVE_EVENTFD)
+ StgWord64 n = (StgWord64)IO_MANAGER_WAKEUP;
+ r = write(wakeup_fd, (char *) &n, 8);
+#else
+ StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
+ r = write(wakeup_fd, &byte, 1);
+#endif
+ /* N.B. If the TimerManager is shutting down as we run this
+ * then there is a possibility that our first read of
+ * io_manager_wakeup_fd is non-negative, but before we get to the
+ * write the file is closed. If this occurs, io_manager_wakeup_fd
+ * will be written into with -1 (GHC.Event.Control does this prior
+ * to closing), so checking this allows us to distinguish this case.
+ * To ensure we observe the correct ordering, we declare the
+ * io_manager_wakeup_fd as volatile.
+ * Since this is not an error condition, we do not print the error
+ * message in this case.
+ */
+ if (r == -1 && SEQ_CST_LOAD(&io_manager_wakeup_fd) >= 0) {
+ sysErrorBelch("ioManagerWakeup: write");
+ }
+ }
+}
+
+#if defined(THREADED_RTS)
+void
+ioManagerDie (void)
+{
+ StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
+ uint32_t i;
+ int r;
+
+ {
+ // Shut down timer manager
+ const int fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
+ if (0 <= fd) {
+ r = write(fd, &byte, 1);
+ if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
+ RELAXED_STORE(&timer_manager_control_wr_fd, -1);
+ }
+ }
+
+ {
+ // Shut down IO managers
+ for (i=0; i < getNumCapabilities(); i++) {
+ const int fd = RELAXED_LOAD(&getCapability(i)->iomgr->control_fd);
+ if (0 <= fd) {
+ r = write(fd, &byte, 1);
+ if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
+ RELAXED_STORE(&getCapability(i)->iomgr->control_fd, -1);
+ }
+ }
+ }
+}
+
+void
+ioManagerStartCap (Capability **cap)
+{
+ rts_evalIO(cap,ensureIOManagerIsRunning_closure,NULL);
+}
+
+void
+ioManagerStart (void)
+{
+ // Make sure the IO manager thread is running
+ Capability *cap;
+ if (SEQ_CST_LOAD(&timer_manager_control_wr_fd) < 0 || SEQ_CST_LOAD(&io_manager_wakeup_fd) < 0) {
+ cap = rts_lock();
+ ioManagerStartCap(&cap);
+ rts_unlock(cap);
+ }
+}
+#endif
+
=====================================
rts/posix/MIO.h
=====================================
@@ -0,0 +1,30 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 1998-2005
+ *
+ * Signal processing / handling.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "IOManager.h"
+
+#if defined(HAVE_SIGNAL_H)
+# include <signal.h>
+#endif
+
+#include "BeginPrivate.h"
+
+/* Communicating with the IO manager thread (see GHC.Conc).
+ */
+void ioManagerWakeup (void);
+#if defined(THREADED_RTS)
+void ioManagerDie (void);
+void ioManagerStart (void);
+void ioManagerStartCap (/* inout */ Capability **cap);
+
+void timerManagerNotifySignal(int sig, siginfo_t *info);
+#endif
+
+#include "EndPrivate.h"
=====================================
rts/posix/Poll.c
=====================================
@@ -120,9 +120,9 @@ also allows the signal mask to be adjusted, but we do not make use of this.
******************************************************************************/
/* Forward declarations */
-static bool enlargeTables(Capability *cap, CapIOManager *iomgr);
-static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop);
-static void ioCancel(Capability *cap, StgAsyncIOOp *aiop);
+static bool enlargeTables(CapIOManager *iomgr);
+static void notifyIOCompletion(CapIOManager *iomgr, StgAsyncIOOp *aiop);
+static void ioCancel(CapIOManager *iomgr, StgAsyncIOOp *aiop);
static void reportPollError(int res, nfds_t nfds) STG_NORETURN;
@@ -136,32 +136,31 @@ void initCapabilityIOManagerPoll(CapIOManager *iomgr)
/* Used to implement syncIOWaitReady.
* Result is true on success, or false on allocation failure. */
-bool syncIOWaitReadyPoll(Capability *cap, StgTSO *tso,
+bool syncIOWaitReadyPoll(CapIOManager *iomgr, StgTSO *tso,
IOReadOrWrite rw, HsInt fd)
{
StgAsyncIOOp *aiop;
- aiop = (StgAsyncIOOp *)allocateMightFail(cap, sizeofW(StgAsyncIOOp));
+ aiop = (StgAsyncIOOp *)allocateMightFail(iomgr->cap, sizeofW(StgAsyncIOOp));
if (RTS_UNLIKELY(aiop == NULL)) return false;
- SET_HDR(aiop, &stg_ASYNCIOOP_info, cap->r.rCCCS);
+ SET_HDR(aiop, &stg_ASYNCIOOP_info, iomgr->cap->r.rCCCS);
aiop->notify.tso = tso;
aiop->notify_type = NotifyTSO;
aiop->live = &stg_ASYNCIO_LIVE0_closure;
tso->why_blocked = rw == IORead ? BlockedOnRead : BlockedOnWrite;
tso->block_info.aiop = aiop;
- return asyncIOWaitReadyPoll(cap, aiop, rw, fd);
+ return asyncIOWaitReadyPoll(iomgr, aiop, rw, fd);
}
/* Result is true on success, or false on allocation failure. */
-bool asyncIOWaitReadyPoll(Capability *cap, StgAsyncIOOp *aiop,
+bool asyncIOWaitReadyPoll(CapIOManager *iomgr, StgAsyncIOOp *aiop,
IOReadOrWrite rw, int fd)
{
- CapIOManager *iomgr = cap->iomgr;
if (RTS_UNLIKELY(isFullClosureTable(&iomgr->aiop_table))) {
- bool ok = enlargeTables(cap, iomgr);
+ bool ok = enlargeTables(iomgr);
if (RTS_UNLIKELY(!ok)) return false;
}
- int ix = insertClosureTable(cap, &iomgr->aiop_table, aiop);
+ int ix = insertClosureTable(iomgr->cap, &iomgr->aiop_table, aiop);
/* We use the aiop_table and aiop_poll_table densely. */
ASSERT(ix == sizeClosureTable(&iomgr->aiop_table) - 1);
@@ -169,7 +168,7 @@ bool asyncIOWaitReadyPoll(Capability *cap, StgAsyncIOOp *aiop,
/* The syncIO wrapper or CMM primop filled in the notify and live fields,
* we fill the rest.
*/
- aiop->capno = cap->no;
+ aiop->capno = iomgr->cap->no;
aiop->index = ix;
aiop->outcome = IOOpOutcomeInFlight;
@@ -183,12 +182,12 @@ bool asyncIOWaitReadyPoll(Capability *cap, StgAsyncIOOp *aiop,
}
-void syncIOCancelPoll(Capability *cap, StgTSO *tso)
+void syncIOCancelPoll(CapIOManager *iomgr, StgTSO *tso)
{
StgAsyncIOOp *aiop = tso->block_info.aiop;
ASSERT(aiop->notify_type == NotifyTSO);
- ASSERT(indexClosureTable(&cap->iomgr->aiop_table, aiop->index) == aiop);
- ioCancel(cap, aiop);
+ ASSERT(indexClosureTable(&iomgr->aiop_table, aiop->index) == aiop);
+ ioCancel(iomgr, aiop);
/* We cannot use the normal notifyIOCompletion here. We are in the context
* of throwTo, interrupting a thread blocked on IO via an async exception.
* We don't put the TSO back on the run queue or change the why_blocked
@@ -198,7 +197,7 @@ void syncIOCancelPoll(Capability *cap, StgTSO *tso)
}
-void asyncIOCancelPoll(Capability *cap, StgAsyncIOOp *aiop)
+void asyncIOCancelPoll(CapIOManager *iomgr, StgAsyncIOOp *aiop)
{
/* We can reliably determine if the aiop is still in progress by checking
* if the aiop_table still points to this aiop object. This is reliable
@@ -206,20 +205,18 @@ void asyncIOCancelPoll(Capability *cap, StgAsyncIOOp *aiop)
* is no longer retained by the application.
*/
ASSERT(aiop->notify_type != NotifyTSO);
- if (indexClosureTable(&cap->iomgr->aiop_table, aiop->index) == aiop) {
- ioCancel(cap, aiop);
- notifyIOCompletion(cap, aiop);
+ if (indexClosureTable(&iomgr->aiop_table, aiop->index) == aiop) {
+ ioCancel(iomgr, aiop);
+ notifyIOCompletion(iomgr, aiop);
}
}
-static void ioCancel(Capability *cap, StgAsyncIOOp *aiop)
+static void ioCancel(CapIOManager *iomgr, StgAsyncIOOp *aiop)
{
- CapIOManager *iomgr = cap->iomgr;
-
int ix = aiop->index;
int ix_from; int ix_to;
- removeCompactClosureTable(cap, &iomgr->aiop_table, ix,
+ removeCompactClosureTable(iomgr->cap, &iomgr->aiop_table, ix,
&ix_from, &ix_to);
if (ix_to != ix_from) {
StgAsyncIOOp *aiop_to = indexClosureTable(&iomgr->aiop_table, ix_to);
@@ -237,7 +234,7 @@ bool anyPendingTimeoutsOrIOPoll(CapIOManager *iomgr)
}
-static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop)
+static void notifyIOCompletion(CapIOManager *iomgr, StgAsyncIOOp *aiop)
{
ASSERT(aiop->outcome != IOOpOutcomeInFlight);
switch (aiop->notify_type) {
@@ -251,7 +248,8 @@ static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop)
debugTrace(DEBUG_iomanager,
"Raising exception in thread %" FMT_StgThreadID
" blocked on an invalid fd", tso->id);
- raiseAsync(cap, tso, (StgClosure *)blockedOnBadFD_closure,
+ raiseAsync(iomgr->cap, tso,
+ (StgClosure *)blockedOnBadFD_closure,
false, NULL);
break;
} else {
@@ -262,7 +260,7 @@ static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop)
StgTSO *tso = aiop->notify.tso;
tso->why_blocked = NotBlocked;
tso->_link = END_TSO_QUEUE;
- pushOnRunQueue(cap, tso);
+ pushOnRunQueue(iomgr->cap, tso);
}
break;
}
@@ -277,8 +275,7 @@ static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop)
}
-static void processIOCompletions(Capability *cap, CapIOManager *iomgr,
- int ncompletions)
+static void processIOCompletions(CapIOManager *iomgr, int ncompletions)
{
/* The scheme we use with poll is that we have a dense poll table, and a
* corresponding table that maps to the closure table index. The poll
@@ -320,7 +317,7 @@ static void processIOCompletions(Capability *cap, CapIOManager *iomgr,
* apply the same compacting to the aiop_poll_table.
*/
int ix_from; int ix_to;
- removeCompactClosureTable(cap, &iomgr->aiop_table, i,
+ removeCompactClosureTable(iomgr->cap, &iomgr->aiop_table, i,
&ix_from, &ix_to);
if (ix_to != ix_from) {
StgAsyncIOOp *aiop_to;
@@ -329,7 +326,7 @@ static void processIOCompletions(Capability *cap, CapIOManager *iomgr,
aiop_poll_table[ix_to] = aiop_poll_table[ix_from];
}
- notifyIOCompletion(cap, aiop);
+ notifyIOCompletion(iomgr, aiop);
n--;
} else {
/* You'd expect incrementing the poll table index to be
@@ -343,13 +340,11 @@ static void processIOCompletions(Capability *cap, CapIOManager *iomgr,
}
-void pollCompletedTimeoutsOrIOPoll(Capability *cap)
+void pollCompletedTimeoutsOrIOPoll(CapIOManager *iomgr)
{
- CapIOManager *iomgr = cap->iomgr;
-
if (!isEmptyTimeoutQueue(iomgr->timeout_queue)) {
Time now = getProcessElapsedTime();
- processTimeoutCompletions(cap, now);
+ processTimeoutCompletions(iomgr, now);
}
if (!isEmptyClosureTable(&iomgr->aiop_table)) {
@@ -379,7 +374,7 @@ void pollCompletedTimeoutsOrIOPoll(Capability *cap)
} else if (res > 0) {
int ncompletions = res;
ASSERT(ncompletions <= (int)nfds);
- processIOCompletions(cap, iomgr, ncompletions);
+ processIOCompletions(iomgr, ncompletions);
} else if (errno == EINTR) {
/* We got interrupted by a signal. This is unlikely since we asked
@@ -393,10 +388,8 @@ void pollCompletedTimeoutsOrIOPoll(Capability *cap)
}
-void awaitCompletedTimeoutsOrIOPoll(Capability *cap)
+void awaitCompletedTimeoutsOrIOPoll(CapIOManager *iomgr)
{
- CapIOManager *iomgr = cap->iomgr;
-
/* Loop until we've woken up some threads. This loop is needed because the
* poll() timing isn't accurate, we sometimes sleep for a while but not
* long enough to wake up a thread in a threadDelay. Or we may need to
@@ -409,14 +402,14 @@ void awaitCompletedTimeoutsOrIOPoll(Capability *cap)
!isEmptyClosureTable(&iomgr->aiop_table));
Time now = getProcessElapsedTime();
- processTimeoutCompletions(cap, now);
+ processTimeoutCompletions(iomgr, now);
/* If we didn't wake any threads due to expiring timeouts, then we need
* to wait on I/O. Or to put it another way, even if we did wake some
* threads, we'll still poll (but not wait) for I/O. This is to ensure
* we avoid starving threads blocked on I/O.
*/
- bool wait = emptyRunQueue(cap);
+ bool wait = emptyRunQueue(iomgr->cap);
/* Decide if we are going to wait if no I/O is ready, either:
* poll only, wait indefinitely, or wait until a timeout.
@@ -461,7 +454,7 @@ void awaitCompletedTimeoutsOrIOPoll(Capability *cap)
} else if (res > 0) {
int ncompletions = res;
ASSERT(ncompletions <= (int)nfds);
- processIOCompletions(cap, iomgr, ncompletions);
+ processIOCompletions(iomgr, ncompletions);
} else if (errno == EINTR) {
/* We got interrupted by a signal. In the non-threaded RTS, if the
@@ -471,7 +464,7 @@ void awaitCompletedTimeoutsOrIOPoll(Capability *cap)
* signal is serviced.
*/
#if defined(RTS_USER_SIGNALS)
- if (startPendingSignalHandlers(cap)) break;
+ if (startPendingSignalHandlers(iomgr->cap)) break;
#endif
/* We can also be interrupted by the shutdown signal handler, which
@@ -485,7 +478,7 @@ void awaitCompletedTimeoutsOrIOPoll(Capability *cap)
reportPollError(res, nfds);
}
- } while (emptyRunQueue(cap)
+ } while (emptyRunQueue(iomgr->cap)
&& (getSchedState() == SCHED_RUNNING));
}
@@ -507,12 +500,12 @@ static void reportPollError(int res, nfds_t nfds)
/* Helper function to double the size of the aiop_table and aiop_poll_table.
*/
-static bool enlargeTables(Capability *cap, CapIOManager *iomgr)
+static bool enlargeTables(CapIOManager *iomgr)
{
int oldcapacity = capacityClosureTable(&iomgr->aiop_table);
int newcapacity = (oldcapacity == 0) ? 1 : (oldcapacity * 2);
- bool ok = enlargeClosureTable(cap, &iomgr->aiop_table, newcapacity);
+ bool ok = enlargeClosureTable(iomgr->cap, &iomgr->aiop_table, newcapacity);
if (RTS_UNLIKELY(!ok)) return false;
/* Update the auxiliary aiop_poll_table to match */
=====================================
rts/posix/Poll.h
=====================================
@@ -19,19 +19,19 @@
void initCapabilityIOManagerPoll(CapIOManager *iomgr);
/* Synchronous I/O and timer operations */
-bool syncIOWaitReadyPoll(Capability *cap, StgTSO *tso,
+bool syncIOWaitReadyPoll(CapIOManager *iomgr, StgTSO *tso,
IOReadOrWrite rw, HsInt fd);
-void syncIOCancelPoll(Capability *cap, StgTSO *tso);
+void syncIOCancelPoll(CapIOManager *iomgr, StgTSO *tso);
/* Asynchronous operations */
-bool asyncIOWaitReadyPoll(Capability *cap, StgAsyncIOOp *aiop,
+bool asyncIOWaitReadyPoll(CapIOManager *iomgr, StgAsyncIOOp *aiop,
IOReadOrWrite rw, int fd);
-void asyncIOCancelPoll(Capability *cap, StgAsyncIOOp *aiop);
+void asyncIOCancelPoll(CapIOManager *iomgr, StgAsyncIOOp *aiop);
/* Scheduler operations */
bool anyPendingTimeoutsOrIOPoll(CapIOManager *iomgr);
-void pollCompletedTimeoutsOrIOPoll(Capability *cap);
-void awaitCompletedTimeoutsOrIOPoll(Capability *cap);
+void pollCompletedTimeoutsOrIOPoll(CapIOManager *iomgr);
+void awaitCompletedTimeoutsOrIOPoll(CapIOManager *iomgr);
#endif /* IOMGR_ENABLED_POLL */
=====================================
rts/posix/Select.c
=====================================
@@ -93,9 +93,8 @@ LowResTime getDelayTarget (HsInt us)
* if this is true, then our time has expired.
* (idea due to Andy Gill).
*/
-static bool wakeUpSleepingThreads (Capability *cap, LowResTime now)
+static bool wakeUpSleepingThreads (CapIOManager *iomgr, LowResTime now)
{
- CapIOManager *iomgr = cap->iomgr;
StgTSO *tso;
bool flag = false;
@@ -109,7 +108,7 @@ static bool wakeUpSleepingThreads (Capability *cap, LowResTime now)
tso->_link = END_TSO_QUEUE;
IF_DEBUG(scheduler, debugBelch("Waking up sleeping thread %"
FMT_StgThreadID "\n", tso->id));
- pushOnRunQueue(cap,tso);
+ pushOnRunQueue(iomgr->cap,tso);
flag = true;
}
return flag;
@@ -217,9 +216,8 @@ static enum FdState fdPollWriteState (int fd)
*
*/
void
-awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
+awaitCompletedTimeoutsOrIOSelect(CapIOManager *iomgr, bool wait)
{
- CapIOManager *iomgr = cap->iomgr;
StgTSO *tso, *prev, *next;
fd_set rfd,wfd;
int numFound;
@@ -244,7 +242,7 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
do {
now = getLowResTimeOfDay();
- if (wakeUpSleepingThreads(cap, now)) {
+ if (wakeUpSleepingThreads(iomgr, now)) {
return;
}
@@ -355,7 +353,7 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
*/
#if defined(RTS_USER_SIGNALS)
if (RtsFlags.MiscFlags.install_signal_handlers && signals_pending()) {
- startSignalHandlers(cap);
+ startSignalHandlers(iomgr->cap);
return; /* still hold the lock */
}
#endif
@@ -368,12 +366,12 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
/* check for threads that need waking up
*/
- wakeUpSleepingThreads(cap, getLowResTimeOfDay());
+ wakeUpSleepingThreads(iomgr, getLowResTimeOfDay());
/* If new runnable threads have arrived, stop waiting for
* I/O and run them.
*/
- if (!emptyRunQueue(cap)) {
+ if (!emptyRunQueue(iomgr->cap)) {
return; /* still hold the lock */
}
}
@@ -429,7 +427,7 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
IF_DEBUG(scheduler,
debugBelch("Killing blocked thread %" FMT_StgThreadID
" on bad fd=%i\n", tso->id, fd));
- raiseAsync(cap, tso,
+ raiseAsync(iomgr->cap, tso,
(StgClosure *)blockedOnBadFD_closure, false, NULL);
break;
case RTS_FD_IS_READY:
@@ -438,13 +436,13 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
tso->id));
tso->why_blocked = NotBlocked;
tso->_link = END_TSO_QUEUE;
- pushOnRunQueue(cap,tso);
+ pushOnRunQueue(iomgr->cap,tso);
break;
case RTS_FD_IS_BLOCKING:
if (prev == NULL)
iomgr->blocked_queue_hd = tso;
else
- setTSOLink(cap, prev, tso);
+ setTSOLink(iomgr->cap, prev, tso);
prev = tso;
break;
}
@@ -460,7 +458,7 @@ awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait)
}
} while (wait && getSchedState() == SCHED_RUNNING
- && emptyRunQueue(cap));
+ && emptyRunQueue(iomgr->cap));
}
#endif /* IOMGR_ENABLED_SELECT */
=====================================
rts/posix/Select.h
=====================================
@@ -15,7 +15,7 @@ typedef StgWord LowResTime;
LowResTime getDelayTarget (HsInt us);
-void awaitCompletedTimeoutsOrIOSelect(Capability *cap, bool wait);
+void awaitCompletedTimeoutsOrIOSelect(CapIOManager *iomgr, bool wait);
#include "EndPrivate.h"
=====================================
rts/posix/Signals.c
=====================================
@@ -9,21 +9,12 @@
#include "rts/PosixSource.h"
#include "Rts.h"
-#include "Schedule.h"
#include "RtsSignals.h"
-#include "Signals.h"
-#include "IOManager.h"
#include "RtsUtils.h"
+#include "Schedule.h"
#include "Prelude.h"
-#include "Ticker.h"
#include "ThreadLabels.h"
-#include "Libdw.h"
-
-/* TODO: eliminate this include. This file should be about signals, not be
- * part of an I/O manager implementation. The code here that are really part
- * of an I/O manager should be moved into an appropriate I/O manager impl.
- */
-#include "IOManagerInternals.h"
+#include "MIO.h"
#if defined(alpha_HOST_ARCH)
# if defined(linux_HOST_OS)
@@ -45,10 +36,6 @@
# include <errno.h>
#endif
-#if defined(HAVE_EVENTFD_H)
-# include <sys/eventfd.h>
-#endif
-
#if defined(HAVE_TERMIOS_H)
#include <termios.h>
#endif
@@ -134,110 +121,6 @@ more_handlers(int sig)
nHandlers = sig + 1;
}
-// Here's the pipe into which we will send our signals
-static int io_manager_wakeup_fd = -1;
-static int timer_manager_control_wr_fd = -1;
-
-#define IO_MANAGER_WAKEUP 0xff
-#define IO_MANAGER_DIE 0xfe
-#define IO_MANAGER_SYNC 0xfd
-
-void setTimerManagerControlFd(int fd) {
- RELAXED_STORE(&timer_manager_control_wr_fd, fd);
-}
-
-void
-setIOManagerWakeupFd (int fd)
-{
- // only called when THREADED_RTS, but unconditionally
- // compiled here because GHC.Event.Control depends on it.
- SEQ_CST_STORE(&io_manager_wakeup_fd, fd);
-}
-
-/* -----------------------------------------------------------------------------
- * Wake up at least one IO or timer manager HS thread.
- * -------------------------------------------------------------------------- */
-void
-ioManagerWakeup (void)
-{
- int r;
- const int wakeup_fd = SEQ_CST_LOAD(&io_manager_wakeup_fd);
- // Wake up the IO Manager thread by sending a byte down its pipe
- if (wakeup_fd >= 0) {
-#if defined(HAVE_EVENTFD)
- StgWord64 n = (StgWord64)IO_MANAGER_WAKEUP;
- r = write(wakeup_fd, (char *) &n, 8);
-#else
- StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
- r = write(wakeup_fd, &byte, 1);
-#endif
- /* N.B. If the TimerManager is shutting down as we run this
- * then there is a possibility that our first read of
- * io_manager_wakeup_fd is non-negative, but before we get to the
- * write the file is closed. If this occurs, io_manager_wakeup_fd
- * will be written into with -1 (GHC.Event.Control does this prior
- * to closing), so checking this allows us to distinguish this case.
- * To ensure we observe the correct ordering, we declare the
- * io_manager_wakeup_fd as volatile.
- * Since this is not an error condition, we do not print the error
- * message in this case.
- */
- if (r == -1 && SEQ_CST_LOAD(&io_manager_wakeup_fd) >= 0) {
- sysErrorBelch("ioManagerWakeup: write");
- }
- }
-}
-
-#if defined(THREADED_RTS)
-void
-ioManagerDie (void)
-{
- StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
- uint32_t i;
- int r;
-
- {
- // Shut down timer manager
- const int fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
- if (0 <= fd) {
- r = write(fd, &byte, 1);
- if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
- RELAXED_STORE(&timer_manager_control_wr_fd, -1);
- }
- }
-
- {
- // Shut down IO managers
- for (i=0; i < getNumCapabilities(); i++) {
- const int fd = RELAXED_LOAD(&getCapability(i)->iomgr->control_fd);
- if (0 <= fd) {
- r = write(fd, &byte, 1);
- if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
- RELAXED_STORE(&getCapability(i)->iomgr->control_fd, -1);
- }
- }
- }
-}
-
-void
-ioManagerStartCap (Capability **cap)
-{
- rts_evalIO(cap,ensureIOManagerIsRunning_closure,NULL);
-}
-
-void
-ioManagerStart (void)
-{
- // Make sure the IO manager thread is running
- Capability *cap;
- if (SEQ_CST_LOAD(&timer_manager_control_wr_fd) < 0 || SEQ_CST_LOAD(&io_manager_wakeup_fd) < 0) {
- cap = rts_lock();
- ioManagerStartCap(&cap);
- rts_unlock(cap);
- }
-}
-#endif
-
#if !defined(THREADED_RTS)
#define N_PENDING_HANDLERS 16
@@ -260,31 +143,9 @@ generic_handler(int sig USED_IF_THREADS,
void *p STG_UNUSED)
{
#if defined(THREADED_RTS)
-
- StgWord8 buf[sizeof(siginfo_t) + 1];
- int r;
-
- buf[0] = sig;
- if (info == NULL) {
- // info may be NULL on Solaris (see #3790)
- memset(buf+1, 0, sizeof(siginfo_t));
- } else {
- memcpy(buf+1, info, sizeof(siginfo_t));
- }
-
- int timer_control_fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
- if (0 <= timer_control_fd)
- {
- r = write(timer_control_fd, buf, sizeof(siginfo_t)+1);
- if (r == -1 && errno == EAGAIN) {
- errorBelch("lost signal due to full pipe: %d\n", sig);
- }
- }
-
- // If the IO manager hasn't told us what the FD of the write end
- // of its pipe is, there's not much we can do here, so just ignore
- // the signal..
-
+ //TODO: This calls MIO directly. We should go via IOManager API.
+ // The IOManager API should be extended to cover signals.
+ timerManagerNotifySignal(sig, info);
#else /* not THREADED_RTS */
/* Can't call allocate from here. Probably can't call malloc
=====================================
rts/posix/Signals.h
=====================================
@@ -27,18 +27,6 @@ void startSignalHandlers(Capability *cap);
void install_vtalrm_handler(int sig, TickProc handle_tick);
-/* Communicating with the IO manager thread (see GHC.Conc).
- *
- * TODO: these I/O manager things are not related to signals and ought to live
- * elsewhere, e.g. in a module specifically for the I/O manager.
- */
-void ioManagerWakeup (void);
-#if defined(THREADED_RTS)
-void ioManagerDie (void);
-void ioManagerStart (void);
-void ioManagerStartCap (/* inout */ Capability **cap);
-#endif
-
extern StgInt *signal_handlers;
#include "EndPrivate.h"
=====================================
rts/posix/Timeout.c
=====================================
@@ -26,7 +26,7 @@
*/
#if defined(IOMGR_ENABLED_POLL)
-bool syncDelayTimeout(Capability *cap, StgTSO *tso, HsInt us_delay)
+bool syncDelayTimeout(CapIOManager *iomgr, StgTSO *tso, HsInt us_delay)
{
Time now = getProcessElapsedTime();
Time target;
@@ -42,16 +42,16 @@ bool syncDelayTimeout(Capability *cap, StgTSO *tso, HsInt us_delay)
/* fill in a new timeout queue entry */
StgTimeout *timeout;
- timeout = (StgTimeout *)allocateMightFail(cap, sizeofW(StgTimeout));
+ timeout = (StgTimeout *)allocateMightFail(iomgr->cap, sizeofW(StgTimeout));
if (RTS_UNLIKELY(timeout == NULL)) { return false; }
union NotifyCompletion notify = { .tso = tso };
- initElemTimeoutQueue(timeout, notify, NotifyTSO, cap->r.rCCCS);
+ initElemTimeoutQueue(timeout, notify, NotifyTSO, iomgr->cap->r.rCCCS);
ASSERT(tso->why_blocked == NotBlocked);
tso->why_blocked = BlockedOnDelay;
tso->block_info.timeout = timeout;
- insertTimeoutQueue(&cap->iomgr->timeout_queue, timeout, target);
+ insertTimeoutQueue(&iomgr->timeout_queue, timeout, target);
debugTrace(DEBUG_iomanager,
"timer for delay of %lld usec installed at time %lld ns",
@@ -60,18 +60,18 @@ bool syncDelayTimeout(Capability *cap, StgTSO *tso, HsInt us_delay)
}
-void syncDelayCancelTimeout(Capability *cap, StgTSO *tso)
+void syncDelayCancelTimeout(CapIOManager *iomgr, StgTSO *tso)
{
ASSERT(tso->why_blocked == BlockedOnDelay);
StgTimeoutQueue *timeout = tso->block_info.timeout;
- deleteTimeoutQueue(&cap->iomgr->timeout_queue, timeout);
+ deleteTimeoutQueue(&iomgr->timeout_queue, timeout);
tso->block_info.closure = (StgClosure *)END_TSO_QUEUE;
/* the timeout is no longer accessible from anywhere (except here) */
IF_NONMOVING_WRITE_BARRIER_ENABLED {
- updateRemembSetPushClosure(cap, (StgClosure *)timeout);
+ updateRemembSetPushClosure(iomgr->cap, (StgClosure *)timeout);
}
/* We don't put the TSO back on the run queue or change the why_blocked
@@ -79,7 +79,7 @@ void syncDelayCancelTimeout(Capability *cap, StgTSO *tso)
*/
}
-static void notifyTimeoutCompletion(Capability *cap, StgTimeout *timeout);
+static void notifyTimeoutCompletion(CapIOManager *iomgr, StgTimeout *timeout);
/* We use the 64bit Time type from rts/Time.h so our max time (in nanosecond
* precision) is over 290 years from the epoch of the monotonic clock.
@@ -90,10 +90,8 @@ static void notifyTimeoutCompletion(Capability *cap, StgTimeout *timeout);
* With 64bit Time we do not need to worry about clock wraparound and can just
* use the simple formula.
*/
-void processTimeoutCompletions(Capability *cap, Time now)
+void processTimeoutCompletions(CapIOManager *iomgr, Time now)
{
- CapIOManager *iomgr = cap->iomgr;
-
/* Pop entries from the front of the sleeping queue that are past their
* wake time, and unblock the corresponding MVars.
*/
@@ -105,17 +103,17 @@ void processTimeoutCompletions(Capability *cap, Time now)
debugTrace(DEBUG_iomanager,"timer expired at %lld ns", waketime);
StgTimeout *timeout;
deleteMinTimeoutQueue(&iomgr->timeout_queue, &timeout);
- notifyTimeoutCompletion(cap, timeout);
+ notifyTimeoutCompletion(iomgr, timeout);
/* the timeout is no longer accessible from anywhere (except here) */
IF_NONMOVING_WRITE_BARRIER_ENABLED {
- updateRemembSetPushClosure(cap, (StgClosure *)timeout);
+ updateRemembSetPushClosure(iomgr->cap, (StgClosure *)timeout);
}
}
}
-static void notifyTimeoutCompletion(Capability *cap, StgTimeout *timeout)
+static void notifyTimeoutCompletion(CapIOManager *iomgr, StgTimeout *timeout)
{
switch (timeout->notify_type) {
case NotifyTSO:
@@ -123,11 +121,11 @@ static void notifyTimeoutCompletion(Capability *cap, StgTimeout *timeout)
StgTSO *tso = timeout->notify.tso;
tso->why_blocked = NotBlocked;
tso->_link = END_TSO_QUEUE;
- pushOnRunQueue(cap, tso);
+ pushOnRunQueue(iomgr->cap, tso);
break;
}
case NotifyMVar:
- performTryPutMVar(cap, timeout->notify.mvar, Unit_closure);
+ performTryPutMVar(iomgr->cap, timeout->notify.mvar, Unit_closure);
break;
case NotifyTVar:
=====================================
rts/posix/Timeout.h
=====================================
@@ -12,9 +12,9 @@
#include "BeginPrivate.h"
-bool syncDelayTimeout(Capability *cap, StgTSO *tso, HsInt us_delay);
+bool syncDelayTimeout(CapIOManager *iomgr, StgTSO *tso, HsInt us_delay);
-void syncDelayCancelTimeout(Capability *cap, StgTSO *tso);
+void syncDelayCancelTimeout(CapIOManager *iomgr, StgTSO *tso);
/* Process the completion of any timeouts that have expired: this means
* notifying whatever is waiting on the timeout, a thread, an MVar or TVar.
@@ -24,7 +24,7 @@ void syncDelayCancelTimeout(Capability *cap, StgTSO *tso);
* No result is returned: callers can check if there are now any runnable
* threads by consulting the scheduler's run queue.
*/
-void processTimeoutCompletions(Capability *cap, Time now);
+void processTimeoutCompletions(CapIOManager *iomgr, Time now);
/* Utility to compute the timeout wait time (in milliseconds) between now and
* the next timer expiry (if any), or no waiting (if !wait).
=====================================
rts/rts.cabal
=====================================
@@ -581,6 +581,7 @@ library
posix/Ticker.c
posix/OSMem.c
posix/OSThreads.c
+ posix/MIO.c
posix/Poll.c
posix/Select.c
posix/Signals.c
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/694defb0348b886d4733d663a6f96b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/694defb0348b886d4733d663a6f96b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/int-index/tyop] Infix holes in types (#11107)
by Vladislav Zavialov (@int-index) 02 Mar '26
by Vladislav Zavialov (@int-index) 02 Mar '26
02 Mar '26
Vladislav Zavialov pushed to branch wip/int-index/tyop at Glasgow Haskell Compiler / GHC
Commits:
ae3491b0 by Vladislav Zavialov at 2026-03-03T02:12:25+03:00
Infix holes in types (#11107)
This patch introduces several improvements that follow naturally from
refactoring HsOpTy to represent the operator as an HsType, aligning it
with the approach taken by OpApp and HsExpr.
User-facing changes:
1. Infix holes (t1 `_` t2) are now permitted in types, following the
precedent set by term-level expressions.
Test case: T11107
2. Error messages for illegal promotion ticks are now reported at more
precise source locations.
Test case: T17865
Internal changes:
* The definition of HsOpTy now mirrors that of OpApp:
| HsOpTy (XOpTy p) (LHsType p) (LHsType p) (LHsType p)
| OpApp (XOpApp p) (LHsExpr p) (LHsExpr p) (LHsExpr p)
This moves us one step closer to unifying HsType and HsExpr.
* Ignoring locations,
the old pattern match (HsOpTy x prom lhs op rhs)
is now written as (HsOpTy x lhs (HsTyVar x' prom op) rhs)
but we also handle (HsOpTy x lhs (HsWildCardTy x') rhs)
Constructors other than HsTyVar and HsWildCardTy never appear
in the operator position.
* The various definitions across the compiler have been updated to work
with the new representation, drawing inspiration from the term-level
pipeline where appropriate. For example,
ppr_infix_ty <=> ppr_infix_expr
get_tyop <=> get_op
lookupTypeFixityRn <=> lookupExprFixityRn
(the latter is factored out from rnExpr)
Test cases: T11107 T17865
- - - - -
30 changed files:
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Fixity.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/ThToHs.hs
- compiler/Language/Haskell/Syntax/Type.hs
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_fail/T17865.stderr
- + testsuite/tests/partial-sigs/should_compile/T11107.hs
- + testsuite/tests/partial-sigs/should_compile/T11107.stderr
- testsuite/tests/partial-sigs/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
Changes:
=====================================
compiler/GHC/Hs/Type.hs
=====================================
@@ -684,11 +684,12 @@ ignoreParens ty = ty
mkAnonWildCardTy :: EpToken "_" -> HsType GhcPs
mkAnonWildCardTy tok = HsWildCardTy tok
-mkHsOpTy :: (Anno (IdOccGhcP p) ~ SrcSpanAnnN)
+mkHsOpTy :: (Anno (IdOccGhcP p) ~ EpAnn a)
=> PromotionFlag
- -> LHsType (GhcPass p) -> LocatedN (IdOccP (GhcPass p))
+ -> LHsType (GhcPass p) -> LIdOccP (GhcPass p)
-> LHsType (GhcPass p) -> HsType (GhcPass p)
-mkHsOpTy prom ty1 op ty2 = HsOpTy noExtField prom ty1 op ty2
+mkHsOpTy prom ty1 op ty2 = HsOpTy noExtField ty1 tyop ty2
+ where tyop = L (l2l op) $ HsTyVar noAnn prom op
mkHsAppTy :: LHsType (GhcPass p) -> LHsType (GhcPass p) -> LHsType (GhcPass p)
mkHsAppTy t1 t2 = addCLocA t1 t2 (HsAppTy noExtField t1 t2)
@@ -746,7 +747,7 @@ hsTyGetAppHead_maybe = go
go (L _ (HsTyVar _ _ ln)) = Just ln
go (L _ (HsAppTy _ l _)) = go l
go (L _ (HsAppKindTy _ t _)) = go t
- go (L _ (HsOpTy _ _ _ ln _)) = Just ln
+ go (L _ (HsOpTy _ _ op _)) = go op
go (L _ (HsParTy _ t)) = go t
go (L _ (HsKindSig _ t _)) = go t
go _ = Nothing
@@ -1458,9 +1459,14 @@ ppr_mono_ty (HsAppTy _ fun_ty arg_ty)
= hsep [ppr_mono_lty fun_ty, ppr_mono_lty arg_ty]
ppr_mono_ty (HsAppKindTy _ ty k)
= ppr_mono_lty ty <+> char '@' <> ppr_mono_lty k
-ppr_mono_ty (HsOpTy _ prom ty1 (L _ op) ty2)
- = sep [ ppr_mono_lty ty1
- , sep [pprOccWithTick Infix prom op, ppr_mono_lty ty2 ] ]
+ppr_mono_ty (HsOpTy _ ty1 tyop ty2)
+ | Just pp_op <- ppr_infix_ty tyop
+ = sep [pp_ty1, sep [pp_op, pp_ty2]]
+ | otherwise
+ = hang (ppr tyop) 2 (sep [pp_ty1, pp_ty2])
+ where
+ pp_ty1 = ppr_mono_lty ty1
+ pp_ty2 = ppr_mono_lty ty2
ppr_mono_ty (HsParTy _ ty)
= parens (ppr_mono_lty ty)
-- Put the parens in where the user did
@@ -1477,6 +1483,11 @@ ppr_mono_ty (XHsType t) = case ghcPass @p of
HsRecTy _ flds -> pprHsConDeclRecFields flds
GhcRn -> ppr t
+ppr_infix_ty :: (OutputableBndrId p) => LHsType (GhcPass p) -> Maybe SDoc
+ppr_infix_ty (L _ (HsTyVar _ prom (L _ op))) = Just (pprOccWithTick Infix prom op)
+ppr_infix_ty (L _ (HsWildCardTy _)) = Just (text "`_`")
+ppr_infix_ty _ = Nothing
+
--------------------------
ppr_fun_ty :: (OutputableBndrId p)
=> HsMultAnn (GhcPass p) -> LHsType (GhcPass p) -> LHsType (GhcPass p) -> SDoc
=====================================
compiler/GHC/Hs/Utils.hs
=====================================
@@ -632,7 +632,7 @@ nlHsTyConApp :: forall p a. IsSrcSpanAnn p a
nlHsTyConApp prom fixity tycon tys
| Infix <- fixity
, HsValArg _ ty1 : HsValArg _ ty2 : rest <- tys
- = foldl' mk_app (noLocA $ HsOpTy noExtField prom ty1 (noLocA tycon) ty2) rest
+ = foldl' mk_app (noLocA $ mkHsOpTy prom ty1 (noLocA tycon) ty2) rest
| otherwise
= foldl' mk_app (nlHsTyVar prom $ forgetUserRdr @p tycon) tys
where
=====================================
compiler/GHC/HsToCore/Quote.hs
=====================================
@@ -1473,8 +1473,7 @@ repTy (HsTupleTy _ _ tys) = do tys1 <- repLTys tys
repTy (HsSumTy _ tys) = do tys1 <- repLTys tys
tcon <- repUnboxedSumTyCon (length tys)
repTapps tcon tys1
-repTy (HsOpTy _ prom ty1 n ty2) = repLTy ((nlHsTyVar prom (getName n) `nlHsAppTy` ty1)
- `nlHsAppTy` ty2)
+repTy (HsOpTy _ ty1 op ty2) = repLTy ((op `nlHsAppTy` ty1) `nlHsAppTy` ty2)
repTy (HsParTy _ t) = repLTy t
repTy (HsStarTy _ _) = repTStar
repTy (HsKindSig _ t k) = do
=====================================
compiler/GHC/Iface/Ext/Ast.hs
=====================================
@@ -1921,9 +1921,9 @@ instance ToHie (LocatedA (HsType GhcRn)) where
HsSumTy _ tys ->
[ toHie tys
]
- HsOpTy _ _prom a op b ->
+ HsOpTy _ a op b ->
[ toHie a
- , toHie $ C Use op
+ , toHie op
, toHie b
]
HsParTy _ a ->
=====================================
compiler/GHC/Parser.y
=====================================
@@ -2316,15 +2316,14 @@ infixtype :: { forall b. DisambTD b => PV (LocatedA b) }
: ftype %shift { $1 }
| ftype tyop infixtype { $1 >>= \ $1 ->
$3 >>= \ $3 ->
- do { let (op, prom) = $2
- ; when (looksLikeMult $1 op $3) $ hintLinear (getLocA op)
- ; mkHsOpTyPV prom $1 op $3 } }
+ do { when (looksLikeMult $1 $2 $3) $ hintLinear (getLocA $2)
+ ; mkHsOpTyPV $1 $2 $3 } }
| unpackedness infixtype { $2 >>= \ $2 ->
mkUnpackednessPV $1 $2 }
ftype :: { forall b. DisambTD b => PV (LocatedA b) }
: atype { mkHsAppTyHeadPV $1 }
- | tyop { failOpFewArgs (fst $1) }
+ | tyop { failOpFewArgs $1 }
| ftype tyarg { $1 >>= \ $1 ->
mkHsAppTyPV $1 $2 }
| ftype PREFIX_AT atype { $1 >>= \ $1 ->
@@ -2334,15 +2333,12 @@ tyarg :: { LHsType GhcPs }
: atype { $1 }
| unpackedness atype {% addUnpackednessP $1 $2 }
-tyop :: { (LocatedN RdrName, PromotionFlag) }
- : qtyconop { ($1, NotPromoted) }
- | tyvarop { ($1, NotPromoted) }
- | SIMPLEQUOTE qconop {% do { op <- amsr (sLL $1 $> (unLoc $2))
- (NameAnnQuote (epTok $1) (gl $2) [])
- ; return (op, IsPromoted) } }
- | SIMPLEQUOTE varop {% do { op <- amsr (sLL $1 $> (unLoc $2))
- (NameAnnQuote (epTok $1) (gl $2) [])
- ; return (op, IsPromoted) } }
+tyop :: { LHsType GhcPs }
+ : qtyconop { sL1a $1 (HsTyVar noAnn NotPromoted $1) }
+ | tyvarop { sL1a $1 (HsTyVar noAnn NotPromoted $1) }
+ | SIMPLEQUOTE qconop { sLLa $1 $> (HsTyVar (epTok $1) IsPromoted $2) }
+ | SIMPLEQUOTE varop { sLLa $1 $> (HsTyVar (epTok $1) IsPromoted $2) }
+ | '`' '_' '`' { sLLa $1 $> (mkAnonWildCardTy (epTok $2)) } -- TODO (int-index): NameBackquotes; reuse hole_op
atype :: { LHsType GhcPs }
: ntgtycon {% amsA' (sL1 $1 (HsTyVar noAnn NotPromoted $1)) } -- Not including unit tuples
@@ -4464,12 +4460,12 @@ hintLinear span = do
unless linearEnabled $ addError $ mkPlainErrorMsgEnvelope span $ PsErrLinearFunction
-- Does this look like (a %m)?
-looksLikeMult :: LHsType GhcPs -> LocatedN RdrName -> LHsType GhcPs -> Bool
-looksLikeMult ty1 l_op ty2
- | Unqual op_name <- unLoc l_op
+looksLikeMult :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs -> Bool
+looksLikeMult ty1 tyop ty2
+ | HsTyVar _ _ (L _ (Unqual op_name)) <- unLoc tyop
, occNameFS op_name == fsLit "%"
, Strict.Just ty1_pos <- getBufSpan (getLocA ty1)
- , Strict.Just pct_pos <- getBufSpan (getLocA l_op)
+ , Strict.Just pct_pos <- getBufSpan (getLocA tyop)
, Strict.Just ty2_pos <- getBufSpan (getLocA ty2)
, bufSpanEnd ty1_pos /= bufSpanStart pct_pos
, bufSpanEnd pct_pos == bufSpanStart ty2_pos
=====================================
compiler/GHC/Parser/PostProcess.hs
=====================================
@@ -1137,8 +1137,8 @@ checkTyClHdr is_cls ty
go cs l (HsTyVar _ _ ltc@(L _ tc)) acc ops cps fix
| isRdrTc tc = return (ltc, acc, fix, (reverse ops), cps, cs Semi.<> comments l)
- go cs l (HsOpTy _ _ t1 ltc@(L _ tc) t2) acc ops cps _fix
- | isRdrTc tc = return (ltc, lhs:rhs:acc, Infix, (reverse ops), cps, cs Semi.<> comments l)
+ go cs l (HsOpTy _ t1 tyop t2) acc ops cps _fix
+ = goL (cs Semi.<> comments l) tyop (lhs:rhs:acc) ops cps Infix
where lhs = HsValArg noExtField t1
rhs = HsValArg noExtField t2
go cs l (HsParTy (o,c) ty) acc ops cps fix = goL (cs Semi.<> comments l) ty acc (o:ops) (c:cps) fix
@@ -2401,7 +2401,7 @@ class DisambTD b where
-- | Disambiguate @f \@t@ (visible kind application)
mkHsAppKindTyPV :: LocatedA b -> EpToken "@" -> LHsType GhcPs -> PV (LocatedA b)
-- | Disambiguate @f \# x@ (infix operator)
- mkHsOpTyPV :: PromotionFlag -> LHsType GhcPs -> LocatedN RdrName -> LHsType GhcPs -> PV (LocatedA b)
+ mkHsOpTyPV :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs -> PV (LocatedA b)
-- | Disambiguate @{-\# UNPACK \#-} t@ (unpack/nounpack pragma)
mkUnpackednessPV :: Located UnpackednessPragma -> LocatedA b -> PV (LocatedA b)
@@ -2409,8 +2409,8 @@ instance DisambTD (HsType GhcPs) where
mkHsAppTyHeadPV = return
mkHsAppTyPV t1 t2 = return (mkHsAppTy t1 t2)
mkHsAppKindTyPV t at ki = return (mkHsAppKindTy at t ki)
- mkHsOpTyPV prom t1 op t2 = do
- let (L l ty) = mkLHsOpTy prom t1 op t2
+ mkHsOpTyPV t1 tyop t2 = do
+ let (L l ty) = mkLHsOpTy t1 tyop t2
!cs <- getCommentsFor (locA l)
return (L (addCommentsToEpAnn l cs) ty)
mkUnpackednessPV = addUnpackednessP
@@ -2452,11 +2452,11 @@ instance DisambTD DataConBuilder where
addFatalError $ mkPlainErrorMsgEnvelope (getEpTokenSrcSpan at) $
(PsErrUnexpectedKindAppInDataCon (unLoc lhs) (unLoc ki))
- mkHsOpTyPV prom lhs tc rhs = do
+ mkHsOpTyPV lhs op@(L _ (HsTyVar _ prom tc)) rhs = do
check_no_ops (unLoc rhs) -- check the RHS because parsing type operators is right-associative
data_con <- eitherToP $ tyConToDataCon tc
!cs <- getCommentsFor (locA l)
- checkNotPromotedDataCon prom data_con
+ checkNotPromotedDataCon (getLocA op) prom data_con
return $ L (addCommentsToEpAnn l cs) (InfixDataConBuilder lhs data_con rhs)
where
l = combineLocsA lhs rhs
@@ -2465,6 +2465,9 @@ instance DisambTD DataConBuilder where
addError $ mkPlainErrorMsgEnvelope (locA l) $
(PsErrInvalidInfixDataCon (unLoc lhs) (unLoc tc) (unLoc rhs))
check_no_ops _ = return ()
+ mkHsOpTyPV _ (L l (HsWildCardTy _)) _ =
+ addFatalError $ mkPlainErrorMsgEnvelope (getHasLoc l) $ PsErrInvalidInfixHole
+ mkHsOpTyPV _ op _ = pprPanic "mkHsOpTyPV: impossible type operator" (ppr op)
mkUnpackednessPV unpk constr_stuff
| L _ (InfixDataConBuilder lhs data_con rhs) <- constr_stuff
@@ -2480,7 +2483,7 @@ instance DisambTD DataConBuilder where
tyToDataConBuilder :: LHsType GhcPs -> PV (LocatedA DataConBuilder)
tyToDataConBuilder (L l (HsTyVar _ prom v)) = do
data_con <- eitherToP $ tyConToDataCon v
- checkNotPromotedDataCon prom data_con
+ checkNotPromotedDataCon (locA l) prom data_con
return $ L l (PrefixDataConBuilder nilOL data_con)
tyToDataConBuilder (L l (HsTupleTy _ HsBoxedOrConstraintTuple ts)) = do
let data_con = L (l2l l) (getRdrName (tupleDataCon Boxed (length ts)))
@@ -2493,10 +2496,10 @@ tyToDataConBuilder t =
(PsErrInvalidDataCon (unLoc t))
-- | Rejects declarations such as @data T = 'MkT@ (note the leading tick).
-checkNotPromotedDataCon :: PromotionFlag -> LocatedN RdrName -> PV ()
-checkNotPromotedDataCon NotPromoted _ = return ()
-checkNotPromotedDataCon IsPromoted (L l name) =
- addError $ mkPlainErrorMsgEnvelope (locA l) $
+checkNotPromotedDataCon :: SrcSpan -> PromotionFlag -> LocatedN RdrName -> PV ()
+checkNotPromotedDataCon _ NotPromoted _ = return ()
+checkNotPromotedDataCon loc IsPromoted (L _ name) =
+ addError $ mkPlainErrorMsgEnvelope loc $
PsErrIllegalPromotionQuoteDataCon name
mkUnboxedSumCon :: LHsType GhcPs -> ConTag -> Arity -> (LocatedN RdrName, HsConDeclH98Details GhcPs)
@@ -3452,12 +3455,15 @@ failSpliceOrQuoteTwice lvl =
warnStarIsType :: SrcSpan -> P ()
warnStarIsType span = addPsMessage span PsWarnStarIsType
-failOpFewArgs :: MonadP m => LocatedN RdrName -> m a
-failOpFewArgs (L loc op) =
+failOpFewArgs :: MonadP m => LHsType GhcPs -> m a
+failOpFewArgs (L _ (HsTyVar _ _ (L loc op))) =
do { star_is_type <- getBit StarIsTypeBit
; let is_star_type = if star_is_type then StarIsType else StarIsNotType
; addFatalError $ mkPlainErrorMsgEnvelope (locA loc) $
(PsErrOpFewArgs is_star_type op) }
+failOpFewArgs (L l (HsWildCardTy _)) =
+ addFatalError $ mkPlainErrorMsgEnvelope (getHasLoc l) $ PsErrInvalidInfixHole
+failOpFewArgs op = pprPanic "failOpFewArgs: impossible type operator" (ppr op)
requireExplicitNamespaces :: MonadP m => ExplicitNamespaceKeyword -> m ()
requireExplicitNamespaces kw = do
@@ -3693,10 +3699,10 @@ mkSumOrTuplePat l Boxed a@Sum{} _ =
addFatalError $
mkPlainErrorMsgEnvelope (locA l) $ PsErrUnsupportedBoxedSumPat a
-mkLHsOpTy :: PromotionFlag -> LHsType GhcPs -> LocatedN RdrName -> LHsType GhcPs -> LHsType GhcPs
-mkLHsOpTy prom x op y =
+mkLHsOpTy :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs
+mkLHsOpTy x op y =
let loc = locA x `combineSrcSpans` locA op `combineSrcSpans` locA y
- in L (noAnnSrcSpan loc) (mkHsOpTy prom x op y)
+ in L (noAnnSrcSpan loc) (HsOpTy noExtField x op y)
mkMultExpr :: EpToken "%" -> LHsExpr GhcPs -> TokRarrow -> HsMultAnnOf (LHsExpr GhcPs) GhcPs
mkMultExpr pct t@(L _ (HsOverLit _ (OverLit _ (HsIntegral (IL (SourceText (unpackFS -> "1")) _ 1))))) arr
=====================================
compiler/GHC/Rename/Expr.hs
=====================================
@@ -50,7 +50,6 @@ import GHC.Unit.Module ( isInteractiveModule )
import GHC.Types.Basic (TypeOrKind (TypeLevel))
import GHC.Types.FieldLabel
-import GHC.Types.Fixity
import GHC.Types.Id.Make
import GHC.Types.Name
import GHC.Types.Name.Set
@@ -401,12 +400,7 @@ rnExpr (OpApp _ e1 op e2)
-- we used to avoid fixity stuff, but we can't easily tell any
-- more, so I've removed the test. Adding HsPars in GHC.Tc.Deriv.Generate
-- should prevent bad things happening.
- ; fixity <- case op' of
- L _ (HsVar _ (L _ (WithUserRdr _ n))) -> lookupFixityRn n
- L _ (XExpr (HsRecSelRn f)) -> lookupFieldFixityRn f
- _ -> return (Fixity minPrecedence InfixL)
- -- c.f. lookupFixity for unbound
-
+ ; fixity <- lookupExprFixityRn op'
; lexical_negation <- xoptM LangExt.LexicalNegation
; let negation_handling | lexical_negation = KeepNegationIntact
| otherwise = ReassociateNegation
=====================================
compiler/GHC/Rename/Fixity.hs
=====================================
@@ -11,7 +11,8 @@ module GHC.Rename.Fixity
, lookupFixityRn
, lookupFixityRn_help
, lookupFieldFixityRn
- , lookupTyFixityRn
+ , lookupExprFixityRn
+ , lookupTypeFixityRn
) where
import GHC.Prelude
@@ -26,6 +27,7 @@ import GHC.Unit.Module.ModIface
import GHC.Types.Fixity.Env
import GHC.Types.Name
import GHC.Types.Name.Env
+import GHC.Types.Name.Reader
import GHC.Types.Fixity
import GHC.Types.SrcLoc
@@ -198,8 +200,19 @@ lookupFixityRn_help name
doc = text "Checking fixity for" <+> ppr name
---------------
-lookupTyFixityRn :: LocatedN Name -> RnM Fixity
-lookupTyFixityRn = lookupFixityRn . unLoc
-
lookupFieldFixityRn :: FieldOcc GhcRn -> RnM Fixity
lookupFieldFixityRn (FieldOcc _ n) = lookupFixityRn (unLoc n)
+
+lookupExprFixityRn :: LHsExpr GhcRn -> RnM Fixity
+lookupExprFixityRn e =
+ case e of
+ L _ (HsVar _ op) -> lookupFixityRn (unLocWithUserRdr op)
+ L _ (XExpr (HsRecSelRn f)) -> lookupFieldFixityRn f
+ _ -> return (Fixity minPrecedence InfixL)
+ -- c.f. lookupFixity for unbound
+
+lookupTypeFixityRn :: LHsType GhcRn -> RnM Fixity
+lookupTypeFixityRn t =
+ case t of
+ L _ (HsTyVar _ _ op) -> lookupFixityRn (unLocWithUserRdr op)
+ _ -> return (Fixity minPrecedence InfixL)
=====================================
compiler/GHC/Rename/HsType.hs
=====================================
@@ -54,7 +54,7 @@ import GHC.Rename.Utils ( mapFvRn, bindLocalNamesFV
, typeAppErr, newLocalBndrRn, checkDupRdrNames
, checkShadowedRdrNames )
import GHC.Rename.Fixity ( lookupFieldFixityRn, lookupFixityRn
- , lookupTyFixityRn )
+ , lookupTypeFixityRn )
import GHC.Rename.Unbound ( notInScopeErr, WhereLooking(WL_LocalOnly) )
import GHC.Tc.Errors.Types
import GHC.Tc.Errors.Ppr ( pprHsDocContext )
@@ -67,7 +67,6 @@ import GHC.Types.Name
import GHC.Types.SrcLoc
import GHC.Types.Name.Set
import GHC.Types.FieldLabel
-import GHC.Types.Error
import GHC.Utils.Misc
import GHC.Types.Fixity ( compareFixity, negateFixity )
@@ -551,16 +550,13 @@ rnHsTyKi env tv@(HsTyVar _ ip (L loc rdr_name))
; checkPromotedDataConName env tv Prefix ip name
; return (HsTyVar noAnn ip loc_name_with_rdr, unitFV name) }
-rnHsTyKi env ty@(HsOpTy _ prom ty1 l_op ty2)
- = setSrcSpan (getLocA l_op) $
- do { let op_rdr = unLoc l_op
- ; (l_op', fvs1) <- rnHsTyOp env (ppr ty) l_op
- ; let op_name = unLoc l_op'
- ; fix <- lookupTyFixityRn l_op'
+rnHsTyKi env ty@(HsOpTy _ ty1 tyop ty2)
+ = setSrcSpan (getLocA tyop) $
+ do { (tyop', fvs1) <- rnHsTyOp env ty tyop
+ ; fix <- lookupTypeFixityRn tyop'
; (ty1', fvs2) <- rnLHsTyKi env ty1
; (ty2', fvs3) <- rnLHsTyKi env ty2
- ; res_ty <- mkHsOpTyRn prom (fmap (WithUserRdr op_rdr) l_op') fix ty1' ty2'
- ; checkPromotedDataConName env ty Infix prom op_name
+ ; res_ty <- mkHsOpTyRn tyop' fix ty1' ty2'
; return (res_ty, plusFVs [fvs1, fvs2, fvs3]) }
rnHsTyKi env (HsParTy _ ty)
@@ -770,15 +766,20 @@ rnLTyVar (L loc rdr_name)
; return (L loc tyvar) }
--------------
-rnHsTyOp :: RnTyKiEnv -> SDoc -> LocatedN RdrName
- -> RnM (LocatedN Name, FreeVars)
-rnHsTyOp env overall_ty (L loc op)
+rnHsTyOp :: RnTyKiEnv -> HsType GhcPs -> LHsType GhcPs
+ -> RnM (LHsType GhcRn, FreeVars)
+rnHsTyOp env overall_ty tyop
+ | L l (HsTyVar ann prom (L loc op)) <- tyop
= do { op' <- rnTyVar env op
; unlessXOptM LangExt.TypeOperators $
if (op' `hasKey` eqTyConKey) -- See [eqTyCon (~) compatibility fallback] in GHC.Rename.Env
then addDiagnostic TcRnTypeEqualityRequiresOperators
- else addErr $ TcRnIllegalTypeOperator overall_ty op
- ; return (L loc op', unitFV op') }
+ else addErr $ TcRnIllegalTypeOperator (ppr overall_ty) op
+ ; checkPromotedDataConName env overall_ty Infix prom op'
+ ; let tyop' = L l (HsTyVar ann prom (L loc (WithUserRdr op op')))
+ ; return (tyop', unitFV op') }
+ | otherwise
+ = rnLHsTyKi env tyop
--------------
checkWildCard :: RnTyKiEnv
@@ -1400,33 +1401,33 @@ precedence and does not require rearrangement.
---------------
-- Building (ty1 `op1` (ty2a `op2` ty2b))
-mkHsOpTyRn :: PromotionFlag
- -> LocatedN (WithUserRdr Name) -> Fixity -> LHsType GhcRn -> LHsType GhcRn
+mkHsOpTyRn :: LHsType GhcRn
+ -> Fixity -> LHsType GhcRn -> LHsType GhcRn
-> RnM (HsType GhcRn)
-mkHsOpTyRn prom1 op1 fix1 ty1 (L loc2 (HsOpTy _ prom2 ty2a op2 ty2b))
- = do { fix2 <- lookupTyFixityRn (fmap getName op2)
- ; mk_hs_op_ty prom1 op1 fix1 ty1 prom2 op2 fix2 ty2a ty2b loc2 }
+mkHsOpTyRn tyop1 fix1 ty1 (L loc2 (HsOpTy _ ty2a tyop2 ty2b))
+ = do { fix2 <- lookupTypeFixityRn tyop2
+ ; mk_hs_op_ty tyop1 fix1 ty1 tyop2 fix2 ty2a ty2b loc2 }
-mkHsOpTyRn prom1 op1 _ ty1 ty2 -- Default case, no rearrangement
- = return (HsOpTy noExtField prom1 ty1 op1 ty2)
+mkHsOpTyRn tyop _ ty1 ty2 -- Default case, no rearrangement
+ = return (HsOpTy noExtField ty1 tyop ty2)
---------------
-mk_hs_op_ty :: PromotionFlag -> LocatedN (WithUserRdr Name) -> Fixity -> LHsType GhcRn
- -> PromotionFlag -> LocatedN (WithUserRdr Name) -> Fixity -> LHsType GhcRn
+mk_hs_op_ty :: LHsType GhcRn -> Fixity -> LHsType GhcRn
+ -> LHsType GhcRn -> Fixity -> LHsType GhcRn
-> LHsType GhcRn -> SrcSpanAnnA
-> RnM (HsType GhcRn)
-mk_hs_op_ty prom1 op1 fix1 ty1 prom2 op2 fix2 ty2a ty2b loc2
- | nofix_error = do { precParseErr (NormalOp (unLoc op1),fix1)
- (NormalOp (unLoc op2),fix2)
+mk_hs_op_ty tyop1 fix1 ty1 tyop2 fix2 ty2a ty2b loc2
+ | nofix_error = do { precParseErr (get_tyop tyop1,fix1)
+ (get_tyop tyop2,fix2)
; return (ty1 `op1ty` (L loc2 (ty2a `op2ty` ty2b))) }
| associate_right = return (ty1 `op1ty` (L loc2 (ty2a `op2ty` ty2b)))
| otherwise = do { -- Rearrange to ((ty1 `op1` ty2a) `op2` ty2b)
- new_ty <- mkHsOpTyRn prom1 op1 fix1 ty1 ty2a
+ new_ty <- mkHsOpTyRn tyop1 fix1 ty1 ty2a
; return (noLocA new_ty `op2ty` ty2b) }
where
- lhs `op1ty` rhs = HsOpTy noExtField prom1 lhs op1 rhs
- lhs `op2ty` rhs = HsOpTy noExtField prom2 lhs op2 rhs
+ lhs `op1ty` rhs = HsOpTy noExtField lhs tyop1 rhs
+ lhs `op2ty` rhs = HsOpTy noExtField lhs tyop2 rhs
(nofix_error, associate_right) = compareFixity fix1 fix2
@@ -1493,6 +1494,11 @@ get_op (L _ (HsHole (HoleVar (L _ uv)))) = UnboundOp uv
get_op (L _ (XExpr (HsRecSelRn fld))) = RecFldOp fld
get_op other = pprPanic "get_op" (ppr other)
+get_tyop :: LHsType GhcRn -> OpName
+get_tyop (L _ (HsTyVar _ _ n)) = NormalOp (unLoc n)
+get_tyop (L _ (HsWildCardTy _)) = UnboundOp (Unqual (mkVarOcc "_"))
+get_tyop other = pprPanic "get_tyop" (ppr other)
+
-- Parser left-associates everything, but
-- derived instances may have correctly-associated things to
-- in the right operand. So we just check that the right operand is OK
@@ -2119,8 +2125,8 @@ extract_lty (L _ ty) acc
extract_hs_mult_ann m $ -- See Note [Ordering of implicit variables]
extract_lty ty2 acc
HsIParamTy _ _ ty -> extract_lty ty acc
- HsOpTy _ _ ty1 tv ty2 -> extract_lty ty1 $
- extract_tv tv $
+ HsOpTy _ ty1 op ty2 -> extract_lty ty1 $
+ extract_lty op $
extract_lty ty2 acc
HsParTy _ ty -> extract_lty ty acc
HsSpliceTy {} -> acc -- Type splices mention no tvs
=====================================
compiler/GHC/Rename/Pat.hs
=====================================
@@ -1314,6 +1314,16 @@ rn_ty_pat_var lrdr@(L l rdr) = do
name <- lookupTypeOccTPRnM rdr
pure (L l $ WithUserRdr rdr name)
+rn_tyop_pat :: LHsType GhcPs -> TPRnM (LHsType GhcRn)
+rn_tyop_pat tyop
+ | L l (HsTyVar ann prom l_op) <- tyop
+ = do l_op' <- rn_ty_pat_var l_op
+ let op_name = getName l_op'
+ when (isDataConName op_name && not (isPromoted prom)) $
+ liftRn $ addDiagnostic (TcRnUntickedPromotedThing $ UntickedConstructor Infix op_name)
+ return (L l $ HsTyVar ann prom l_op')
+ | otherwise = rn_lty_pat tyop
+
-- | Rename type patterns
--
-- For the difference between `rn_ty_pat` and `rnHsTyKi` see Note [CpsRn monad]
@@ -1373,15 +1383,13 @@ rn_ty_pat (HsSumTy an tys) = do
tys' <- mapM rn_lty_pat tys
pure (HsSumTy an tys')
-rn_ty_pat (HsOpTy _ prom ty1 l_op ty2) = do
+rn_ty_pat (HsOpTy _ ty1 tyop ty2) = do
ty1' <- rn_lty_pat ty1
- l_op' <- rn_ty_pat_var l_op
+ tyop' <- rn_tyop_pat tyop
ty2' <- rn_lty_pat ty2
- fix <- liftRn $ lookupTyFixityRn $ fmap getName l_op'
- let op_name = getName l_op'
- when (isDataConName op_name && not (isPromoted prom)) $
- liftRn $ addDiagnostic (TcRnUntickedPromotedThing $ UntickedConstructor Infix op_name)
- liftRn $ mkHsOpTyRn prom l_op' fix ty1' ty2'
+ liftRn $ do
+ fix <- lookupTypeFixityRn tyop'
+ mkHsOpTyRn tyop' fix ty1' ty2'
rn_ty_pat (HsParTy an ty) = do
ty' <- rn_lty_pat ty
=====================================
compiler/GHC/Tc/Gen/App.hs
=====================================
@@ -1136,15 +1136,11 @@ expr_to_type earg =
do { lhs' <- go lhs
; rhs' <- unwrap_wc rhs
; return (L l (HsAppKindTy noExtField lhs' rhs')) }
- go (L l e@(OpApp _ lhs op rhs)) =
+ go (L l (OpApp _ lhs op rhs)) =
do { lhs' <- go lhs
; op' <- go op
; rhs' <- go rhs
- ; op_id <- unwrap_op_tv op'
- ; return (L l (HsOpTy noExtField NotPromoted lhs' op_id rhs')) }
- where
- unwrap_op_tv (L _ (HsTyVar _ _ op_id)) = return op_id
- unwrap_op_tv _ = failWith $ TcRnIllformedTypeArgument (L l e)
+ ; return (L l (HsOpTy noExtField lhs' op' rhs')) }
go (L l (HsOverLit _ ol))
= do { let lit = tyLitFromOverloadedLit (ol_val ol)
; return (L l (HsTyLit noExtField lit)) }
=====================================
compiler/GHC/Tc/Gen/HsType.hs
=====================================
@@ -103,7 +103,7 @@ import GHC.Core.TyCo.Ppr
import GHC.Builtin.Types.Prim
import GHC.Types.Error
import GHC.Types.Name.Env
-import GHC.Types.Name.Reader( WithUserRdr(..), lookupLocalRdrOcc )
+import GHC.Types.Name.Reader
import GHC.Types.Var
import GHC.Types.Var.Set
import GHC.Core.TyCon
@@ -1146,8 +1146,9 @@ tcHsType _ (HsSpliceTy (HsUntypedSpliceNested n) s) _ = pprPanic "tcHsType: inva
tcHsType mode (HsFunTy _ mult ty1 ty2) exp_kind
= tc_fun_type mode mult ty1 ty2 exp_kind
-tcHsType mode (HsOpTy _ _ ty1 (L _ (WithUserRdr _ op)) ty2) exp_kind
- | op `hasKey` unrestrictedFunTyConKey
+tcHsType mode (HsOpTy _ ty1 tyop ty2) exp_kind
+ | L _ (HsTyVar _ _ op) <- tyop
+ , unLocWithUserRdr op `hasKey` unrestrictedFunTyConKey
= tc_fun_type mode (HsUnannotated noExtField) ty1 ty2 exp_kind
--------- Foralls
@@ -1531,12 +1532,15 @@ splitHsAppTys_maybe hs_ty
is_app :: HsType GhcRn -> Bool
is_app (HsAppKindTy {}) = True
is_app (HsAppTy {}) = True
- is_app (HsOpTy _ _ _ (L _ (WithUserRdr _ op)) _)
- = not (op `hasKey` unrestrictedFunTyConKey)
+ is_app (HsOpTy _ _ tyop _)
+ | L _ (HsTyVar _ _ op) <- tyop
+ , unLocWithUserRdr op `hasKey` unrestrictedFunTyConKey
-- I'm not sure why this funTyConKey test is necessary
-- Can it even happen? Perhaps for t1 `(->)` t2
-- but then maybe it's ok to treat that like a normal
-- application rather than using the special rule for HsFunTy
+ = False
+ is_app (HsOpTy {}) = True
is_app (HsTyVar {}) = True
is_app (HsParTy _ (L _ ty)) = is_app ty
is_app _ = False
@@ -1552,9 +1556,8 @@ splitHsAppTys hs_ty = go (noLocA hs_ty) []
go (L _ (HsAppTy _ f a)) as = go f (HsValArg noExtField a : as)
go (L _ (HsAppKindTy _ ty k)) as = go ty (HsTypeArg noExtField k : as)
go (L sp (HsParTy _ f)) as = go f (HsArgPar (locA sp) : as)
- go (L _ (HsOpTy _ prom l op@(L sp _) r)) as
- = ( L (l2l sp) (HsTyVar noAnn prom op)
- , HsValArg noExtField l : HsValArg noExtField r : as )
+ go (L _ (HsOpTy _ l tyop r)) as =
+ (tyop, HsValArg noExtField l : HsValArg noExtField r : as)
go f as = (f, as)
---------------------------
=====================================
compiler/GHC/Tc/Gen/Pat.hs
=====================================
@@ -549,7 +549,7 @@ pat_to_type (NPat _ (L _ ol) _ _)
pat_to_type (ConPat _ lname (InfixCon left right))
= do { lty <- pat_to_type (unLoc left)
; rty <- pat_to_type (unLoc right)
- ; let { t = noLocA (HsOpTy noExtField NotPromoted lty lname rty)}
+ ; let { t = noLocA (mkHsOpTy NotPromoted lty lname rty)}
; pure t }
pat_to_type (ConPat _ lname (PrefixCon args))
= do { let { appHead = noLocA (HsTyVar noAnn NotPromoted lname) }
=====================================
compiler/GHC/Tc/Gen/Sig.hs
=====================================
@@ -292,7 +292,7 @@ no_anon_wc_ty lty = go lty
HsListTy _ ty -> go ty
HsTupleTy _ _ tys -> gos tys
HsSumTy _ tys -> gos tys
- HsOpTy _ _ ty1 _ ty2 -> go ty1 && go ty2
+ HsOpTy _ ty1 tyop ty2 -> go tyop && go ty1 && go ty2
HsParTy _ ty -> go ty
HsIParamTy _ _ ty -> go ty
HsKindSig _ ty kind -> go ty && go kind
=====================================
compiler/GHC/ThToHs.hs
=====================================
@@ -1870,7 +1870,7 @@ cvtTypeKind typeOrKind ty
let px = parenthesizeHsType opPrec x'
py = parenthesizeHsType opPrec y'
in do { eq_tc <- returnLA eqTyCon_RDR
- ; returnLA (HsOpTy noExtField NotPromoted px eq_tc py) }
+ ; returnLA (mkHsOpTy NotPromoted px eq_tc py) }
-- The long-term goal is to remove the above case entirely and
-- subsume it under the case for InfixT. See #15815, comment:6,
-- for more details.
=====================================
compiler/Language/Haskell/Syntax/Type.hs
=====================================
@@ -838,9 +838,9 @@ data HsType pass
[LHsType pass] -- Element types (length gives arity)
| HsOpTy (XOpTy pass)
- PromotionFlag -- Whether explicitly promoted,
- -- for the pretty printer
- (LHsType pass) (LIdOccP pass) (LHsType pass)
+ (LHsType pass)
+ (LHsType pass)
+ (LHsType pass)
| HsParTy (XParTy pass)
(LHsType pass) -- See Note [Parens in HsSyn] in GHC.Hs.Expr
=====================================
testsuite/tests/parser/should_compile/DumpParsedAst.stderr
=====================================
@@ -388,7 +388,6 @@
[]))
(HsOpTy
(NoExtField)
- (NotPromoted)
(L
(EpAnn
(EpaSpan { DumpParsedAst.hs:11:11 })
@@ -411,12 +410,22 @@
(L
(EpAnn
(EpaSpan { DumpParsedAst.hs:11:13 })
- (NameAnnTrailing
+ (AnnListItem
[])
(EpaComments
[]))
- (Exact
- {Name: :}))
+ (HsTyVar
+ (NoEpTok)
+ (NotPromoted)
+ (L
+ (EpAnn
+ (EpaSpan { DumpParsedAst.hs:11:13 })
+ (NameAnnTrailing
+ [])
+ (EpaComments
+ []))
+ (Exact
+ {Name: :}))))
(L
(EpAnn
(EpaSpan { DumpParsedAst.hs:11:15-16 })
=====================================
testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
=====================================
@@ -335,7 +335,6 @@
[]))
(HsOpTy
(NoExtField)
- (NotPromoted)
(L
(EpAnn
(EpaSpan { DumpRenamedAst.hs:13:11 })
@@ -360,14 +359,24 @@
(L
(EpAnn
(EpaSpan { DumpRenamedAst.hs:13:13 })
- (NameAnnTrailing
+ (AnnListItem
[])
(EpaComments
[]))
- (WithUserRdr
- (Exact
- {Name: :})
- {Name: :}))
+ (HsTyVar
+ (NoEpTok)
+ (NotPromoted)
+ (L
+ (EpAnn
+ (EpaSpan { DumpRenamedAst.hs:13:13 })
+ (NameAnnTrailing
+ [])
+ (EpaComments
+ []))
+ (WithUserRdr
+ (Exact
+ {Name: :})
+ {Name: :}))))
(L
(EpAnn
(EpaSpan { DumpRenamedAst.hs:13:15-16 })
=====================================
testsuite/tests/parser/should_fail/T17865.stderr
=====================================
@@ -1,9 +1,8 @@
-
-T17865.hs:3:11: error: [GHC-80236]
+T17865.hs:3:10: error: [GHC-80236]
Illegal promotion quote mark in the declaration of
data/newtype constructor MkT
-T17865.hs:5:13: error: [GHC-80236]
+T17865.hs:5:11: error: [GHC-80236]
Illegal promotion quote mark in the declaration of
data/newtype constructor MkT'
@@ -14,3 +13,4 @@ T17865.hs:7:16: error: [GHC-80236]
T17865.hs:9:17: error: [GHC-80236]
Illegal promotion quote mark in the declaration of
data/newtype constructor (:>$)
+
=====================================
testsuite/tests/partial-sigs/should_compile/T11107.hs
=====================================
@@ -0,0 +1,5 @@
+{-# LANGUAGE PartialTypeSignatures #-}
+module T11107 where
+
+e :: Int `_` Bool
+e = Left 0
\ No newline at end of file
=====================================
testsuite/tests/partial-sigs/should_compile/T11107.stderr
=====================================
@@ -0,0 +1,4 @@
+T11107.hs:4:10: warning: [GHC-88464] [-Wpartial-type-signatures (in -Wdefault)]
+ • Found type wildcard ‘_’ standing for ‘Either :: * -> * -> *’
+ • In the type signature: e :: Int `_` Bool
+
=====================================
testsuite/tests/partial-sigs/should_compile/all.T
=====================================
@@ -109,3 +109,4 @@ test('T22065', normal, compile, [''])
test('T16152', normal, compile, [''])
test('T20076', expect_broken(20076), compile, [''])
test('T26256', normal, compile, [''])
+test('T11107', normal, compile, [''])
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -3965,11 +3965,11 @@ instance ExactPrint (HsType GhcPs) where
tys' <- markAnnotated tys
an1 <- markClosingParen an0
return (HsSumTy an1 tys')
- exact (HsOpTy x promoted t1 lo t2) = do
+ exact (HsOpTy x t1 lo t2) = do
t1' <- markAnnotated t1
lo' <- markAnnotated lo
t2' <- markAnnotated t2
- return (HsOpTy x promoted t1' lo' t2')
+ return (HsOpTy x t1' lo' t2')
exact (HsParTy (o,c) ty) = do
o' <- markEpToken o
ty' <- markAnnotated ty
=====================================
utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
=====================================
@@ -102,7 +102,7 @@ dropHsDocTy = drop_sig_ty
drop_ty (HsFunTy x w a b) = HsFunTy x w (drop_lty a) (drop_lty b)
drop_ty (HsListTy x a) = HsListTy x (drop_lty a)
drop_ty (HsTupleTy x a b) = HsTupleTy x a (map drop_lty b)
- drop_ty (HsOpTy x p a b c) = HsOpTy x p (drop_lty a) b (drop_lty c)
+ drop_ty (HsOpTy x a b c) = HsOpTy x (drop_lty a) (drop_lty b) (drop_lty c)
drop_ty (HsParTy x a) = HsParTy x (drop_lty a)
drop_ty (HsKindSig x a b) = HsKindSig x (drop_lty a) b
drop_ty (HsDocTy _ a _) = drop_ty $ unL a
=====================================
utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
=====================================
@@ -1345,17 +1345,15 @@ ppr_mono_ty (HsAppTy _ fun_ty arg_ty) unicode =
hsep [ppr_mono_lty fun_ty unicode, ppr_mono_lty arg_ty unicode]
ppr_mono_ty (HsAppKindTy _ fun_ty arg_ki) unicode =
hsep [ppr_mono_lty fun_ty unicode, atSign <> ppr_mono_lty arg_ki unicode]
-ppr_mono_ty (HsOpTy _ prom ty1 op ty2) unicode =
- ppr_mono_lty ty1 unicode <+> ppr_op_prom <+> ppr_mono_lty ty2 unicode
+ppr_mono_ty (HsOpTy _ ty1 tyop ty2) unicode
+ | Just pp_op <- ppr_infix_ty tyop
+ = pp_ty1 <+> pp_op <+> pp_ty2
+ | otherwise
+ = let pp_op = ppr_mono_lty tyop unicode
+ in hsep [hsep [pp_op, pp_ty1], pp_ty2]
where
- ppr_op_prom
- | isPromoted prom =
- char '\'' <> ppr_op
- | otherwise =
- ppr_op
- ppr_op
- | isSymOcc (getOccName op) = ppLDocName op
- | otherwise = char '`' <> ppLDocName op <> char '`'
+ pp_ty1 = ppr_mono_lty ty1 unicode
+ pp_ty2 = ppr_mono_lty ty2 unicode
ppr_mono_ty (HsParTy _ ty) unicode =
parens (ppr_mono_lty ty unicode)
-- = ppr_mono_lty ty unicode
@@ -1367,6 +1365,18 @@ ppr_mono_ty (HsTyLit _ t) u = ppr_tylit t u
ppr_mono_ty (HsStarTy _ isUni) unicode = starSymbol (isUni || unicode)
ppr_mono_ty (XHsType HsRedacted{}) _ = error "ppr_mono_ty: HsRedacted can't be used here"
+ppr_infix_ty :: LHsType DocNameI -> Maybe LaTeX
+ppr_infix_ty (L _ (HsTyVar _ prom op)) = Just pp_op_prom
+ where
+ pp_op_prom
+ | isPromoted prom = char '\'' <> pp_op
+ | otherwise = pp_op
+ pp_op
+ | isSymOcc (getOccName op) = ppLDocName op
+ | otherwise = char '`' <> ppLDocName op <> char '`'
+ppr_infix_ty (L _ (HsWildCardTy _)) = Just (text "`_`")
+ppr_infix_ty _ = Nothing
+
ppr_tylit :: HsLit DocNameI -> Bool -> LaTeX
ppr_tylit (HsNatural _ n) _ = integer (il_value n)
ppr_tylit (HsString _ s) _ = text (show s)
=====================================
utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
=====================================
@@ -1863,15 +1863,15 @@ ppr_mono_ty (HsAppKindTy _ fun_ty arg_ki) unicode qual _ =
[ ppr_mono_lty fun_ty unicode qual HideEmptyContexts
, atSign <> ppr_mono_lty arg_ki unicode qual HideEmptyContexts
]
-ppr_mono_ty (HsOpTy _ prom ty1 op ty2) unicode qual _ =
- ppr_mono_lty ty1 unicode qual HideEmptyContexts <+> ppr_op_prom <+> ppr_mono_lty ty2 unicode qual HideEmptyContexts
+ppr_mono_ty (HsOpTy _ ty1 tyop ty2) unicode qual _
+ | Just pp_op <- ppr_infix_ty tyop qual
+ = pp_ty1 <+> pp_op <+> pp_ty2
+ | otherwise
+ = let pp_op = ppr_mono_lty tyop unicode qual HideEmptyContexts
+ in hsep [hsep [pp_op, pp_ty1], pp_ty2]
where
- ppr_op_prom
- | isPromoted prom =
- promoQuote ppr_op
- | otherwise =
- ppr_op
- ppr_op = ppLDocName qual Infix op
+ pp_ty1 = ppr_mono_lty ty1 unicode qual HideEmptyContexts
+ pp_ty2 = ppr_mono_lty ty2 unicode qual HideEmptyContexts
ppr_mono_ty (HsParTy _ ty) unicode qual emptyCtxts =
parens (ppr_mono_lty ty unicode qual emptyCtxts)
-- = parens (ppr_mono_lty ctxt_prec ty unicode qual emptyCtxts)
@@ -1882,6 +1882,16 @@ ppr_mono_ty (HsWildCardTy _) _ _ _ = char '_'
ppr_mono_ty (HsTyLit _ n) _ _ _ = ppr_tylit n
ppr_mono_ty (XHsType HsRedacted{}) _ _ _ = error "ppr_mono_ty: HsRedacted can't be used here"
+ppr_infix_ty :: LHsType DocNameI -> Qualification -> Maybe Html
+ppr_infix_ty (L _ (HsTyVar _ prom op)) qual = Just pp_op_prom
+ where
+ pp_op_prom
+ | isPromoted prom = promoQuote pp_op
+ | otherwise = pp_op
+ pp_op = ppLDocName qual Infix op
+ppr_infix_ty (L _ (HsWildCardTy _)) _ = Just (toHtml ("`_`" :: LText))
+ppr_infix_ty _ _ = Nothing
+
ppr_tylit :: HsLit DocNameI -> Html
ppr_tylit (HsNatural _ n) = toHtml (show (il_value n))
ppr_tylit (HsString _ s) = toHtml (show s)
=====================================
utils/haddock/haddock-api/src/Haddock/Convert.hs
=====================================
@@ -842,7 +842,8 @@ synifyType _ boundTvs (TyConApp tc tys) =
| L _ (HsExplicitListTy _ IsPromoted tTy') <- stripKindSig tTy ->
noLocA $ HsExplicitListTy noExtField IsPromoted (hTy : tTy')
| otherwise ->
- noLocA $ HsOpTy noExtField IsPromoted hTy (noLocA $ noUserRdr $ getName tc) tTy
+ let tyop = noLocA $ HsTyVar noAnn IsPromoted (noLocA $ noUserRdr $ getName tc)
+ in noLocA $ HsOpTy noExtField hTy tyop tTy
-- ditto for implicit parameter tycons
| tc `hasKey` ipClassKey
, [name, ty] <- tys
@@ -854,9 +855,8 @@ synifyType _ boundTvs (TyConApp tc tys) =
noLocA $
HsOpTy
noExtField
- NotPromoted
(synifyType WithinType boundTvs ty1)
- (noLocA $ noUserRdr eqTyConName)
+ (noLocA $ HsTyVar noAnn NotPromoted (noLocA $ noUserRdr eqTyConName))
(synifyType WithinType boundTvs ty2)
-- and infix type operators
| isSymOcc (nameOccName (getName tc))
@@ -864,9 +864,8 @@ synifyType _ boundTvs (TyConApp tc tys) =
mk_app_tys
( HsOpTy
noExtField
- prom
(synifyType WithinType boundTvs ty1)
- (noLocA $ noUserRdr $ getName tc)
+ (noLocA $ HsTyVar noAnn prom (noLocA $ noUserRdr $ getName tc))
(synifyType WithinType boundTvs ty2)
)
tys_rest
=====================================
utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
=====================================
@@ -465,8 +465,8 @@ reparenTypePrec = go
paren p PREC_CON $ HsAppTy x (goL PREC_FUN fun_ty) (goL PREC_CON arg_ty)
go p (HsAppKindTy x fun_ty arg_ki) =
paren p PREC_CON $ HsAppKindTy x (goL PREC_FUN fun_ty) (goL PREC_CON arg_ki)
- go p (HsOpTy x prom ty1 op ty2) =
- paren p PREC_FUN $ HsOpTy x prom (goL PREC_OP ty1) op (goL PREC_OP ty2)
+ go p (HsOpTy x ty1 op ty2) =
+ paren p PREC_FUN $ HsOpTy x (goL PREC_OP ty1) op (goL PREC_OP ty2)
go p (HsParTy _ t) = unXRec @a $ goL p t -- pretend the paren doesn't exist - it will be added back if needed
go _ t@HsTyVar{} = t
go _ t@HsStarTy{} = t
=====================================
utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
=====================================
@@ -399,11 +399,11 @@ renameType t = case t of
return (HsAppTy noAnn lhs rhs)
HsTupleTy _ b ts -> return . HsTupleTy noAnn b =<< mapM renameLType ts
HsSumTy _ ts -> HsSumTy noAnn <$> mapM renameLType ts
- HsOpTy _ prom a (L loc op) b -> do
- op' <- renameName (getName op)
+ HsOpTy _ a op b -> do
+ op' <- renameLType op
a' <- renameLType a
b' <- renameLType b
- return (HsOpTy noAnn prom a' (L loc op') b')
+ return (HsOpTy noAnn a' op' b')
HsParTy _ ty -> return . (HsParTy noAnn) =<< renameLType ty
HsKindSig _ ty k -> do
ty' <- renameLType ty
=====================================
utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
=====================================
@@ -104,8 +104,8 @@ renameType (HsFunTy x w la lr) = HsFunTy x <$> renameHsMultAnn w <*> renameLType
renameType (HsListTy x lt) = HsListTy x <$> renameLType lt
renameType (HsTupleTy x srt lt) = HsTupleTy x srt <$> mapM renameLType lt
renameType (HsSumTy x lt) = HsSumTy x <$> mapM renameLType lt
-renameType (HsOpTy x f la lop lb) =
- HsOpTy x <$> pure f <*> renameLType la <*> renameLNameOcc lop <*> renameLType lb
+renameType (HsOpTy x la lop lb) =
+ HsOpTy x <$> renameLType la <*> renameLType lop <*> renameLType lb
renameType (HsParTy x lt) = HsParTy x <$> renameLType lt
renameType (HsIParamTy x ip lt) = HsIParamTy x ip <$> renameLType lt
renameType (HsKindSig x lt lk) = HsKindSig x <$> renameLType lt <*> pure lk
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ae3491b07fddfb6a8331679d4a6f4fb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ae3491b07fddfb6a8331679d4a6f4fb…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/floatout-verbosity-check] compiler: avoid unneeded traversals in GHC.Unit.State
by Cheng Shao (@TerrorJack) 02 Mar '26
by Cheng Shao (@TerrorJack) 02 Mar '26
02 Mar '26
Cheng Shao pushed to branch wip/floatout-verbosity-check at Glasgow Haskell Compiler / GHC
Commits:
8da5121c by Cheng Shao at 2026-03-02T21:42:28+00:00
compiler: avoid unneeded traversals in GHC.Unit.State
Following !15591, this patch avoids unneeded traversals in
`reportCycles`/`reportUnusable` when log verbosity is below given
threshold. Also applies `logVerbAtLeast` when appropriate.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
2 changed files:
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Error.hs
Changes:
=====================================
compiler/GHC/Unit/State.hs
=====================================
@@ -1279,7 +1279,7 @@ pprReason pref reason = case reason of
nest 2 (hsep (map ppr deps))
reportCycles :: Logger -> [SCC UnitInfo] -> IO ()
-reportCycles logger sccs = mapM_ report sccs
+reportCycles logger sccs = when (logVerbAtLeast logger 2) $ mapM_ report sccs
where
report (AcyclicSCC _) = return ()
report (CyclicSCC vs) =
@@ -1288,7 +1288,7 @@ reportCycles logger sccs = mapM_ report sccs
nest 2 (hsep (map (ppr . unitId) vs))
reportUnusable :: Logger -> UnusableUnits -> IO ()
-reportUnusable logger pkgs = mapM_ report (nonDetUniqMapToList pkgs)
+reportUnusable logger pkgs = when (logVerbAtLeast logger 2) $ mapM_ report (nonDetUniqMapToList pkgs)
where
report (ipid, (_, reason)) =
debugTraceMsg logger 2 $
@@ -1389,7 +1389,7 @@ mergeDatabases logger = foldM merge (emptyUniqMap, emptyUniqMap) . zip [1..]
merge (pkg_map, prec_map) (i, UnitDatabase db_path db) = do
debugTraceMsg logger 2 $
text "loading package database" <+> ppr db_path
- when (log_verbosity (logFlags logger) >= 2) $
+ when (logVerbAtLeast logger 2) $
forM_ (Set.toList override_set) $ \pkg ->
debugTraceMsg logger 2 $
text "package" <+> ppr pkg <+>
=====================================
compiler/GHC/Utils/Error.hs
=====================================
@@ -463,7 +463,7 @@ withTiming' logger what force_result prtimings action
debugTraceMsg :: Logger -> Int -> SDoc -> IO ()
debugTraceMsg logger val msg =
- when (log_verbosity (logFlags logger) >= val) $
+ when (logVerbAtLeast logger val) $
logInfo logger (withPprStyle defaultDumpStyle msg)
{-# INLINE debugTraceMsg #-} -- see Note [INLINE conditional tracing utilities]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8da5121cf870d86854281e69c430847…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8da5121cf870d86854281e69c430847…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 5 commits: Clean up join points, casts & ticks
by Marge Bot (@marge-bot) 02 Mar '26
by Marge Bot (@marge-bot) 02 Mar '26
02 Mar '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
08bc245b by sheaf at 2026-03-01T11:11:54-05:00
Clean up join points, casts & ticks
This commit shores up the logic dealing with casts and ticks occurring
in between a join point binding and a jump.
Fixes #26642 #26929 #26693
Makes progress on #14610 #26157 #26422
Changes:
- Remove 'GHC.Types.Tickish.TickishScoping' in favour of simpler
predicates 'tickishHasNoScope'/'tickishHasSoftScope', as things were
before commit 993975d3. This makes the code easier to read and
document (fewer indirections).
- Introduce 'canCollectArgsThroughTick' for consistent handling of
ticks around PrimOps and other 'Id's that cannot be eta-reduced.
See overhauled Note [Ticks and mandatory eta expansion].
- New Note [JoinId vs TailCallInfo] in GHC.Core.SimpleOpt that explains
robustness of JoinId vs fragility of TailCallInfo.
- Allow casts/non-soft-scoped ticks to occur in between a join point
binder and a jump, but only in Core Prep.
See Note [Join points, casts, and ticks] and
Note [Join points, casts, and ticks... in Core Prep]
in GHC.Core.Opt.Simplify.Iteration.
Also update Core Lint to account for this.
See Note [Linting join points with casts or ticks] in GHC.Core.Lint.
- Update 'GHC.Core.Utils.mergeCaseAlts' to avoid pushing a cast in
between a join point binding and its jumps. This fixes #26642.
See the new (MC5) and (MC6) in Note [Merge Nested Cases].
- Update float out to properly handle source note ticks. They are now
properly floated out instead of being discarded.
This increases the number of ticks in certain tests with -g.
Test cases: T26642 and TrickyJoins.
Metric increase due to more source note ticks with -g:
-------------------------
Metric Increase:
libdir
size_hello_artifact
size_hello_unicode
-------------------------
- - - - -
476c4cdf by Sean D. Gillespie at 2026-03-02T10:14:37-05:00
Add SIMD absolute value on x86 and LLVM
On x86, absolute value of 32 bits or less is implemented with
PABSB/PABSW/PABSD if SSSE3 is available. Otherwise, there is a fallback
for SSE2. For 64 bit integers it uses VPABSQ, required by AVX-512VL,
with fallbacks for SSE4.2 and SSE2.
There is no dedicated instruction for floating point absolute value on
x86, so it is simulated using bitwise AND.
Absolute value for signed integers and floats are implemented by the
"llvm.abs/llvm.fabs" standard library intrinsics. This implementation
uses MachOps constructors, unlike non-vector floating point absolute
value, which uses CallishMachOps.
- - - - -
709448c0 by Sean D. Gillespie at 2026-03-02T10:14:46-05:00
Add SIMD floating point square root
On x86, this is implemented with the SQRTPS and SQRTPD instructions. On
LLVM, it uses the sqrt library intrinstic.
- - - - -
0deadf66 by Sean D. Gillespie at 2026-03-02T10:14:47-05:00
Improve error message for SIMD on aarch64
When encountering vector literals on aarch64, previously it would
throw:
<no location info>: error:
panic! (the 'impossible' happened)
GHC version 9.15.20251219:
getRegister' (CmmLit:CmmVec):
Now it is more consistent with the other vector operations:
<no location info>: error:
sorry! (unimplemented feature or known bug)
GHC version 9.15.20251219:
SIMD operations on AArch64 currently require the LLVM backend
- - - - -
a1280207 by Vladislav Zavialov at 2026-03-02T16:07:36-05:00
Replace maybeAddSpace with spaceIfSingleQuote
Simplify pretty-printing of HsTypes by using spaceIfSingleQuote.
This allows us to drop the unwieldy lhsTypeHasLeadingPromotionQuote
helper function.
Follow-up to 178c1fd830c78377ef5d338406a41e1d8eb5f0da
- - - - -
63 changed files:
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/Cmm/MachOp.hs
- compiler/GHC/Cmm/Node.hs
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/FloatIn.hs
- compiler/GHC/Core/Opt/FloatOut.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/StgToCmm/Expr.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/Prim.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Tickish.hs
- libraries/base/src/GHC/Base.hs
- libraries/base/src/GHC/Exts.hs
- libraries/ghc-experimental/CHANGELOG.md
- testsuite/tests/codeGen/should_compile/debug.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/simd/should_run/doublex2_arith.hs
- testsuite/tests/simd/should_run/doublex2_arith.stdout
- testsuite/tests/simd/should_run/doublex2_arith_baseline.hs
- testsuite/tests/simd/should_run/doublex2_arith_baseline.stdout
- testsuite/tests/simd/should_run/floatx4_arith.hs
- testsuite/tests/simd/should_run/floatx4_arith.stdout
- testsuite/tests/simd/should_run/floatx4_arith_baseline.hs
- testsuite/tests/simd/should_run/floatx4_arith_baseline.stdout
- testsuite/tests/simd/should_run/int16x8_arith.hs
- testsuite/tests/simd/should_run/int16x8_arith.stdout
- testsuite/tests/simd/should_run/int16x8_arith_baseline.hs
- testsuite/tests/simd/should_run/int16x8_arith_baseline.stdout
- testsuite/tests/simd/should_run/int32x4_arith.hs
- testsuite/tests/simd/should_run/int32x4_arith.stdout
- testsuite/tests/simd/should_run/int32x4_arith_baseline.hs
- testsuite/tests/simd/should_run/int32x4_arith_baseline.stdout
- testsuite/tests/simd/should_run/int64x2_arith.hs
- testsuite/tests/simd/should_run/int64x2_arith.stdout
- testsuite/tests/simd/should_run/int64x2_arith_baseline.hs
- testsuite/tests/simd/should_run/int64x2_arith_baseline.stdout
- testsuite/tests/simd/should_run/int8x16_arith.hs
- testsuite/tests/simd/should_run/int8x16_arith.stdout
- testsuite/tests/simd/should_run/int8x16_arith_baseline.hs
- testsuite/tests/simd/should_run/int8x16_arith_baseline.stdout
- + testsuite/tests/simplCore/should_compile/T26642.hs
- + testsuite/tests/simplCore/should_compile/TrickyJoins.hs
- testsuite/tests/simplCore/should_compile/all.T
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/77b48b37fa767a00d747419c0483af…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/77b48b37fa767a00d747419c0483af…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fendor/longpath-aware-manifest] Add `-fwin-aware-long-paths` to support ling paths on Windows
by Hannes Siebenhandl (@fendor) 02 Mar '26
by Hannes Siebenhandl (@fendor) 02 Mar '26
02 Mar '26
Hannes Siebenhandl pushed to branch wip/fendor/longpath-aware-manifest at Glasgow Haskell Compiler / GHC
Commits:
e23169ef by Fendor at 2026-03-02T21:37:51+01:00
Add `-fwin-aware-long-paths` to support ling paths on Windows
While Windows supports file paths longer than the MAX_PATH restriction,
it is opt-in, and not enabled by default.
By declaring the binary to be long path aware in the manifest of the
windows executable, the binary opts-in to the new behaviour.
It is up to the developer to make sure they use UNC paths and Win.h
specific functions for filesystem operations to use long paths in their
application.
See
https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-li…
and https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests
for the documentation on the application manifest and long path option.
- - - - -
5 changed files:
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Linker/Windows.hs
- docs/users_guide/phases.rst
Changes:
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -1210,6 +1210,7 @@ defaultFlags settings
= [ Opt_AutoLinkPackages,
Opt_DiagnosticsShowCaret,
Opt_EmbedManifest,
+ Opt_WinLongPathAware,
Opt_FamAppCache,
Opt_GenManifest,
Opt_GhciHistory,
=====================================
compiler/GHC/Driver/Flags.hs
=====================================
@@ -744,6 +744,7 @@ data GeneralFlag
| Opt_PrintBindContents
| Opt_GenManifest
| Opt_EmbedManifest
+ | Opt_WinLongPathAware
| Opt_SharedImplib
| Opt_BuildingCabalPackage
| Opt_IgnoreDotGhci
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -2525,6 +2525,7 @@ fFlagsDeps = [
flagSpec "eager-blackholing" Opt_EagerBlackHoling,
flagSpec "orig-thunk-info" Opt_OrigThunkInfo,
flagSpec "embed-manifest" Opt_EmbedManifest,
+ flagSpec "win-aware-long-paths" Opt_WinLongPathAware,
flagSpec "enable-rewrite-rules" Opt_EnableRewriteRules,
flagSpec "enable-th-splice-warnings" Opt_EnableThSpliceWarnings,
flagSpec "error-spans" Opt_ErrorSpans,
=====================================
compiler/GHC/Linker/Windows.hs
=====================================
@@ -16,6 +16,7 @@ import System.Directory
data ManifestOpts = ManifestOpts
{ manifestEmbed :: !Bool -- ^ Should the manifest be embedded in the binary with Windres
+ , manifestLongPathAware :: !Bool
, manifestTempdir :: TempDir
, manifestWindresConfig :: WindresConfig
, manifestObjectSuf :: String
@@ -24,6 +25,7 @@ data ManifestOpts = ManifestOpts
initManifestOpts :: DynFlags -> ManifestOpts
initManifestOpts dflags = ManifestOpts
{ manifestEmbed = gopt Opt_EmbedManifest dflags
+ , manifestLongPathAware = gopt Opt_WinLongPathAware dflags
, manifestTempdir = tmpDir dflags
, manifestWindresConfig = configureWindres dflags
, manifestObjectSuf = objectSuf dflags
@@ -37,21 +39,7 @@ maybeCreateManifest
-> IO [FilePath] -- ^ extra objects to embed, maybe
maybeCreateManifest logger tmpfs opts exe_filename = do
let manifest_filename = exe_filename <.> "manifest"
- manifest =
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n\
- \ <assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n\
- \ <assemblyIdentity version=\"1.0.0.0\"\n\
- \ processorArchitecture=\"X86\"\n\
- \ name=\"" ++ dropExtension exe_filename ++ "\"\n\
- \ type=\"win32\"/>\n\n\
- \ <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n\
- \ <security>\n\
- \ <requestedPrivileges>\n\
- \ <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>\n\
- \ </requestedPrivileges>\n\
- \ </security>\n\
- \ </trustInfo>\n\
- \</assembly>\n"
+ manifest = manifestContents (manifestLongPathAware opts) exe_filename
writeFile manifest_filename manifest
@@ -80,3 +68,36 @@ maybeCreateManifest logger tmpfs opts exe_filename = do
removeFile manifest_filename
return [rc_obj_filename]
+
+manifestContents :: Bool -> FilePath -> String
+manifestContents longPathAware exe_filename =
+ unlines $
+ [ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ , " <assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+ , " <assemblyIdentity version=\"1.0.0.0\""
+ , " processorArchitecture=\"X86\""
+ , " name=\"" ++ dropExtension exe_filename ++ "\""
+ , " type=\"win32\"/>"
+ , " <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">"
+ , " <security>"
+ , " <requestedPrivileges>"
+ , " <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\"/>"
+ , " </requestedPrivileges>"
+ , " </security>"
+ , " </trustInfo>"
+ ]
+ ++
+ (
+ if longPathAware
+ then
+ [ " <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">"
+ , " <windowsSettings xmlns:ws2=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">"
+ , " <ws2:longPathAware>true</ws2:longPathAware>"
+ , " </windowsSettings>"
+ , " </application>"
+ ]
+ else
+ []
+ ) ++
+ [ " </assembly>"
+ ]
=====================================
docs/users_guide/phases.rst
=====================================
@@ -1430,6 +1430,29 @@ for example).
See also :ghc-flag:`-pgmwindres ⟨cmd⟩` (:ref:`replacing-phases`) and
:ghc-flag:`-optwindres ⟨option⟩` (:ref:`forcing-options-through`).
+.. ghc-flag:: -fwin-aware-long-paths
+ :shortdesc: Declare the linked binary to be long path aware on Windows.
+ :reverse: -fno-win-aware-long-paths
+ :type: dynamic
+ :category: linking
+ :since: 9.14.2
+
+ Declare in the manifest file that GHC generates when linking a binary on Windows
+ to be aware of long paths.
+
+ Windows paths usually have a `MAX_PATH <https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-li…>`__
+ limit of 260 characters.
+ This limitation can be lifted by opting into enabling long paths in various
+ ways, see `Enable long paths in Windows 10 and later`_.
+
+ To invoke the compiled program with long paths, the Windows manifest needs
+ to declare that the program is aware of long paths and can handle them
+ appropriately.
+
+ :ghc-flag:`-fno-embed-manifest` also implies :ghc-flag:`-fno-win-aware-long-paths`.
+
+ _Enable long paths in Windows 10 and later: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-li…
+
.. ghc-flag:: -fno-shared-implib
:shortdesc: Don't generate an import library for a DLL (Windows only)
:type: dynamic
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e23169efcda88936d05b0660b066645…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e23169efcda88936d05b0660b066645…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/floatout-verbosity-check
by Cheng Shao (@TerrorJack) 02 Mar '26
by Cheng Shao (@TerrorJack) 02 Mar '26
02 Mar '26
Cheng Shao pushed new branch wip/floatout-verbosity-check at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/floatout-verbosity-check
You're receiving this email because of your account on gitlab.haskell.org.
1
0