10 Mar '26
Simon Peyton Jones pushed to branch wip/T26868 at Glasgow Haskell Compiler / GHC
Commits:
e1e28cd0 by Simon Peyton Jones at 2026-03-10T10:56:15+00:00
Comments only [skip ci]
- - - - -
1 changed file:
- compiler/GHC/Core/TyCo/FVs.hs
Changes:
=====================================
compiler/GHC/Core/TyCo/FVs.hs
=====================================
@@ -129,6 +129,10 @@ But we must take care (see #14880):
free variables. This is plain wrong. We must instead compute that b is free
and then conclude that b's kind is free.
+ BUT: there is no worry here any more because of Invariant (NoTypeShadowing).
+ in GHC.Core. In the example, the `forall k` shadows the `k` in
+ b's kind, which is now illegal and checked by Lint.
+
An obvious first approach is to compute the /shallow/ free variables of the type,
and /then/ close over kinds. But that turns out not to be very efficient.
Fortunately, there is a simpler way, which works with the accumulating
@@ -139,18 +143,20 @@ GHC.Types.Var.FV. At an occurrence of a variable (a::k)
* Check if `a` is already in the accumulator; if so, ignore it because we have
deal with its kind already. Also pre-checking set membership before inserting
- ends up not only being faster,
+ allocates less than just inserting, because the no-op case of insertion does
+ allocation.
* Otherwise add `a` to the accumulator,
AND add on the free vars of its kind `k`.
BUT in this latter step, start with an empty BoundVars set.
-This twist is implemented in `deepUnitFV`
-
-So now consider:
+The "start with an empty BoundVars set" is implemented in `deepUnitFV`. It's
+not /necessary/ to zap the BoundVars set, because of Invariant (NoTypeShadowing).
+But it's a tiny bit more efficient because the BoundVars set is smaller.
+Side note: the free-variable binder would still work even without (NoTypeShadowing).
+Consider:
forall k. b -> k
-
where b :: k->Type is free; but of course, it's a different k! When looking at
b -> k we'll have k in the bound-var set. So we'll ignore the k. But suppose
this is our first encounter with b; we want the free vars of its kind. But we
@@ -537,8 +543,6 @@ deepDetCoVarFolder = TyCoFolder { tcf_view = noView
* *
********************************************************************* -}
-------------- Closing over kinds -----------------
-
closeOverKinds :: TyCoVarSet -> TyCoVarSet
-- For each element of the input set,
-- add the deep free variables of its kind
@@ -553,60 +557,6 @@ closeOverKindsDSet vs = nonDetStrictFoldDVarSet do_one vs vs
where
do_one v = runFVAcc (deepDetTypeFV (varType v))
-{- --------------- Alternative version 1 (using FV) ------------
-closeOverKinds = fvVarSet . closeOverKindsFV . nonDetEltsUniqSet
--}
-
-{- ---------------- Alternative version 2 -------------
-
--- | Add the kind variables free in the kinds of the tyvars in the given set.
--- Returns a non-deterministic set.
-closeOverKinds :: TyCoVarSet -> TyCoVarSet
-closeOverKinds vs
- = go vs vs
- where
- go :: VarSet -- Work list
- -> VarSet -- Accumulator, always a superset of wl
- -> VarSet
- go wl acc
- | isEmptyVarSet wl = acc
- | otherwise = go wl_kvs (acc `unionVarSet` wl_kvs)
- where
- k v inner_acc = ty_co_vars_of_type (varType v) acc inner_acc
- wl_kvs = nonDetFoldVarSet k emptyVarSet wl
- -- wl_kvs = union of shallow free vars of the kinds of wl
- -- but don't bother to collect vars in acc
-
--}
-
-{- ---------------- Alternative version 3 -------------
--- | Add the kind variables free in the kinds of the tyvars in the given set.
--- Returns a non-deterministic set.
-closeOverKinds :: TyVarSet -> TyVarSet
-closeOverKinds vs = close_over_kinds vs emptyVarSet
-
-
-close_over_kinds :: TyVarSet -- Work list
- -> TyVarSet -- Accumulator
- -> TyVarSet
--- Precondition: in any call (close_over_kinds wl acc)
--- for every tv in acc, the shallow kind-vars of tv
--- are either in the work list wl, or in acc
--- Postcondition: result is the deep free vars of (wl `union` acc)
-close_over_kinds wl acc
- = nonDetFoldVarSet do_one acc wl
- where
- do_one :: Var -> TyVarSet -> TyVarSet
- -- (do_one v acc) adds v and its deep free-vars to acc
- do_one v acc | v `elemVarSet` acc
- = acc
- | otherwise
- = close_over_kinds (shallowTyCoVarsOfType (varType v)) $
- acc `extendVarSet` v
--}
-
-
-
{-
%************************************************************************
@@ -614,7 +564,6 @@ close_over_kinds wl acc
almostDevoidCoVarOfCo
%* *
%************************************************************************
-
-}
----- Whether a covar is /Almost Devoid/ in a type or coercion ----
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e1e28cd0ef9baf22e4631d476d970b8…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e1e28cd0ef9baf22e4631d476d970b8…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][ghc-9.12] 90 commits: wasm: prevent bundlers from resolving import("node:timers")
by Zubin (@wz1000) 10 Mar '26
by Zubin (@wz1000) 10 Mar '26
10 Mar '26
Zubin pushed to branch ghc-9.12 at Glasgow Haskell Compiler / GHC
Commits:
bac63be0 by amesgen at 2026-02-02T15:09:23+01:00
wasm: prevent bundlers from resolving import("node:timers")
This fixes the following esbuild error:
✘ [ERROR] Could not resolve "node:timers"
www/ghc_wasm_jsffi.js:66:25:
66 │ return (await import("node:timers")).setImmediate;
╵ ~~~~~~~~~~~~~
The package "node:timers" wasn't found on the file system but is built into node. Are you trying
to bundle for node? You can use "--platform=node" to do that, which will remove this error.
Previously (i.e. after !13503), one had to work around this by passing
`--external:node:timers`.
(cherry picked from commit f6493dbccc7bf95dcdf946b978e262f739e3e15a)
- - - - -
4a1e98c9 by Simon Peyton Jones at 2026-02-02T15:09:23+01:00
Fix in-scope set for CSE
Ticket #25468 showed an assertion failure in CSE because a top-level
Id was being used before it was defined. Reason: Note [Glomming] in
GHC.Core.Opt.OccurAnal.
Solution (used in many places): just put all the top-level bindings in
scope at the beginning of CSE.
Compile-time allocation wobbles up and down a tiny bit; geo mean is
zero. But MultiLayerModulesTH_OneShot and hard_hole_fits increase (on
some architectures only) by a bit oever 2% . I think these are just a
random fluctuations.
Metric Increase:
MultiLayerModulesTH_OneShot
hard_hole_fits
(cherry picked from commit c02b1e4620493eee1f6d6d71bead4af9d7246845)
- - - - -
cf8f041a by Sven Tennie at 2026-02-02T15:09:23+01:00
Add reproducer for dealloc instructions in switch table jump expressions (#25733)
Measures taken to make the test stable:
- Use 'a' as variable prefix, because X86 32bit stumbled over the
variable name 'i386'
- Flush stdout to make test output deterministic
- Use type annotations to support 32bit archs
(cherry picked from commit 39e51ddbc03afda71608bcef75c64f57c6175183)
- - - - -
5404575e by Matthew Pickering at 2026-02-02T15:09:23+01:00
testsuite: Add test for :steplocal performance
This adds a simple test which exercises #25779
(cherry picked from commit 7f358f25ad5604c6e6053f880ca7057690ebd864)
- - - - -
bccd7a3e by Andreas Klebinger at 2026-03-03T21:22:01+05:30
Interpreter: Add limited support for direct primop evaluation.
This commit adds support for a number of primops directly
to the interpreter. This avoids the indirection of going
through the primop wrapper for those primops speeding interpretation
of optimized code up massively.
Code involving IntSet runs about 25% faster with optimized core and these
changes. For core without breakpoints it's even more pronouced and I
saw reductions in runtime by up to 50%.
Running GHC itself in the interpreter was sped up by ~15% through this
change.
Additionally this comment does a few other related changes:
testsuite:
* Run foundation test in ghci and ghci-opt ways to test these
primops.
* Vastly expand the foundation test to cover all basic primops
by comparing result with the result of calling the wrapper.
Interpreter:
* When pushing arguments for interpreted primops extend each argument to
at least word with when pushing. This avoids some issues with big
endian. We can revisit this if it causes performance issues.
* Restructure the stack chunk check logic. There are now macros for
read accesses which might cross stack chunk boundries and macros which
omit the checks which are used when we statically know we access an
address in the current stack chunk.
(cherry picked from commit 202b201c968de68f864f4c8abbfec713f8ffd323)
- - - - -
63f04c09 by Ben Gamari at 2026-03-03T21:22:01+05:30
base: Expose Backtraces constructor and fields
This was specified in the proposal (CLC #199) yet somehow didn't make it
into the implementation.
Fixes #26049.
(cherry picked from commit 17db44c5b32fff82ea988fa4f1a233d1a27bdf57)
- - - - -
bf460d1f by Mario Blažević at 2026-03-03T21:22:01+05:30
Introduce parenBreakableList and use it in ppHsContext
(cherry picked from commit 7b64697c12fb3054067c98c41d6d26441cfa20e5)
- - - - -
4ce3a7fb by fendor at 2026-03-03T21:22:01+05:30
Bump GHC on darwin CI to 9.10.1
(cherry picked from commit 358bc4fc8324a0685f336142d0d608cbd51d54f9)
- - - - -
36516e6c by Simon Peyton Jones at 2026-03-03T21:22:02+05:30
Take more care in zonkEqTypes on AppTy/AppTy
This patch fixes #26256.
See Note [zonkEqTypes and the PKTI] in GHC.Tc.Solver.Equality
(cherry picked from commit 18036d5205ac648bb245217519fed2fd931a9982)
- - - - -
ead68b1d by fendor at 2026-03-03T21:22:02+05:30
Store `StackTrace` and `StackSnapshot` in `Backtraces`
Instead of decoding the stack traces when collecting the `Backtraces`,
defer this decoding until actually showing the `Backtraces`.
This allows users to customise how `Backtraces` are displayed by
using a custom implementation of `displayExceptionWithInfo`, overwriting
the default implementation for `Backtraces` (`displayBacktraces`).
(cherry picked from commit c91e26500ab0e1b8b67c1d374f657523c7c15f55)
- - - - -
230f93b6 by fendor at 2026-03-03T21:22:02+05:30
Allow users to customise the collection of exception annotations
Add a global `CollectExceptionAnnotationMechanism` which determines how
`ExceptionAnnotation`s are collected upon throwing an `Exception`.
This API is exposed via `ghc-experimental`.
By overriding how we collect `Backtraces`, we can control how the
`Backtraces` are displayed to the user by newtyping `Backtraces` and
giving a different instance for `ExceptionAnnotation`.
A concrete use-case for this feature is allowing us to experiment with
alternative stack decoders, without having to modify `base`, which take
additional information from the stack frames.
This commit does not modify how `Backtraces` are currently
collected or displayed.
(cherry picked from commit dee28cdd794652a3ebc271184e2ab3c866b5e219)
- - - - -
e829a12f by fendor at 2026-03-03T21:22:02+05:30
Expose Backtraces internals from ghc-experimental
Additionally, expose the same API `base:Control.Exception.Backtrace`
to make it easier to use as a drop-in replacement.
(cherry picked from commit 6602472273e1cdffcdb7753c9133047e571896bd)
- - - - -
b8c936fd by Zubin Duggal at 2026-03-03T21:22:02+05:30
testsuite: Be more permissive when filtering out GNU_PROPERTY_TYPE linker warnings
The warning text is slightly different with ld.bfd.
Fixes #26249
(cherry picked from commit 51c701fef034e2062809eed5de3a51bb0a4243ba)
- - - - -
08fdd10d by Cheng Shao at 2026-03-03T21:22:02+05:30
hadrian: enforce have_llvm=False for wasm32/js
This patch fixes hadrian to always pass have_llvm=False to the
testsuite driver for wasm32/js targets. These targets don't really
support the LLVM backend, and the optllvm test way doesn't work. We
used to special-case wasm32/js to avoid auto-adding optllvm way in
testsuite/config/ghc, but this is still problematic if someone writes
a new LLVM-related test and uses something like when(have_llvm(),
extra_ways(["optllvm"])). So better just enforce have_llvm=False for
these targets here.
(cherry picked from commit 1cdc6f46c4168dd92a8f5ea0c398b67fc59449a9)
- - - - -
e5e992aa by Cheng Shao at 2026-03-03T21:22:02+05:30
libffi: update to 3.5.2
Bumps libffi submodule.
(cherry picked from commit 45dbfa23f508f221b6aeb667783a928511a7654e)
- - - - -
6c53d508 by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
71074efc by sheaf at 2026-03-03T21:22:02+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)
- - - - -
9adfadee by sheaf at 2026-03-03T21:22:02+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)
- - - - -
618d313d by sheaf at 2026-03-03T21:22:02+05:30
Add test for #26216
(cherry picked from commit 2e73f3426ab6e3cf1938b53831005593f3fd351c)
- - - - -
6daa51da by Vladislav Zavialov at 2026-03-03T21:22:02+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)
- - - - -
be85e2f2 by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
8d60d8cb by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
00ff6203 by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
a932ffce by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
792c400d by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
05a2ea3a by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
b1b86f5e by Luite Stegeman at 2026-03-03T21:22:02+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)
- - - - -
ce70dd20 by Luite Stegeman at 2026-03-03T21:22:02+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)
- - - - -
49280208 by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
728e0f04 by Ben Gamari at 2026-03-03T21:22:02+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)
- - - - -
ad59d234 by Ben Gamari at 2026-03-03T21:22:02+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)
- - - - -
57b614ec by Julian Ospald at 2026-03-03T21:22:02+05:30
ghc-toolchain: Drop `ld.gold` from merge object command
It's deprecated.
Also see #25716
(cherry picked from commit c58f9a615f05e9d43629f6e846ae22cad2a6163d)
- - - - -
80e12dcc by Ben Gamari at 2026-03-03T21:22:02+05:30
gitlab-ci: Make RELEASE_JOB an input
Rather than an undocumented variable.
(cherry picked from commit f9790ca81deb8b14ff2eabf701aecbcfd6501963)
- - - - -
cc5186b0 by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
f24ff1de by Julian Ospald at 2026-03-03T21:22:02+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)
- - - - -
139ccc08 by Ben Gamari at 2026-03-03T21:22:02+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)
- - - - -
17275b20 by sheaf at 2026-03-03T21:22:02+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)
- - - - -
992ee39a by Cheng Shao at 2026-03-03T21:22:02+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)
- - - - -
ba0ec0e8 by Julian Ospald at 2026-03-03T21:22:02+05:30
Skip uniques test if sources are not available
(cherry picked from commit 5dc2e9eaf60fd72771bf2e8112aec182665461a1)
- - - - -
edf8a6b0 by Julian Ospald at 2026-03-03T21:22:02+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)
- - - - -
b2b97d29 by Wang Xin at 2026-03-03T21:22:02+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)
- - - - -
092a603d by Peng Fan at 2026-03-03T21:22:02+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)
- - - - -
e18faa95 by Ben Gamari at 2026-03-03T21:22:02+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)
- - - - -
f162eb8f by Luite Stegeman at 2026-03-03T21:22:02+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)
- - - - -
1b5d5d6e by ARATA Mizuki at 2026-03-03T21:22:03+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)
- - - - -
2220a9b7 by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
cb56617c by Andreas Klebinger at 2026-03-03T21:22:03+05:30
Add hpc to release script
(cherry picked from commit 64ec82ffa7f48399e18fcec43051d2b7ddcb7cc2)
- - - - -
17dd9b2b by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
85ffa1a5 by Julian Ospald at 2026-03-03T21:22:03+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)
- - - - -
e26515de by Simon Peyton Jones at 2026-03-03T21:22:03+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)
- - - - -
dcf082dd by Cheng Shao at 2026-03-03T21:22:03+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)
- - - - -
19b88fab by Cheng Shao at 2026-03-03T21:22:03+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)
- - - - -
b492c847 by Cheng Shao at 2026-03-03T21:22:03+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)
- - - - -
133b829f by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
055db6f2 by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
bdeb6030 by fendor at 2026-03-03T21:22:03+05:30
Remove `traceId` from ghc-pkg executable
(cherry picked from commit d0966e64880e9fa30ce07c0fa5ea28108c6e8ad9)
- - - - -
59cc8e68 by sheaf at 2026-03-03T21:22:03+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)
- - - - -
c75b616e by Cheng Shao at 2026-03-03T21:22:03+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)
- - - - -
c7f7e692 by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
c16b52c5 by Sylvain Henry at 2026-03-03T21:22:03+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)
- - - - -
03a8a5f9 by Sylvain Henry at 2026-03-03T21:22:03+05:30
GC: suffix parallel GC with "par" instead of "thr"
Avoid some potential confusion (see discussion in !15351).
(cherry picked from commit 211a8f5633f0a5069c0689171f60b57719a242be)
- - - - -
cd6a8dae by Cheng Shao at 2026-03-03T21:22:03+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)
- - - - -
8f1dcca2 by Zubin Duggal at 2026-03-03T21:22:03+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)
- - - - -
1b6763b1 by Jessica Clarke at 2026-03-03T21:22:03+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)
- - - - -
dd0e0021 by John Paul Adrian Glaubitz at 2026-03-03T21:22:03+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)
- - - - -
1d0e18e6 by sterni at 2026-03-03T21:22:03+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)
- - - - -
ef151f0d by Michael Karcher at 2026-03-03T21:22:03+05:30
NCG for PPC: add pattern for CmmRegOff to iselExpr64
Closes #26828
(cherry picked from commit 43d977619de65c0cf87695fa5d86f1a3ff3176c3)
- - - - -
50c6836b by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
0a356c08 by Andrew Lelechenko at 2026-03-03T21:22:03+05:30
Upgrade text submodule to 2.1.4
(cherry picked from commit 9e4d70c2764d117c5cf753127f93056d66e4f0d7)
- - - - -
9d4e88a2 by Zubin Duggal at 2026-03-03T21:22:03+05:30
Bump transformers submodule to 0.6.3.0
Fixes #26790
(cherry picked from commit ea0d1317a630799a6b7bea12b24ef7e1ea6ed512)
- - - - -
bd510e4d by Matthew Pickering at 2026-03-03T21:22:03+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)
- - - - -
03eb3918 by Simon Peyton Jones at 2026-03-03T21:22:03+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)
- - - - -
c74d75f4 by Cheng Shao at 2026-03-03T21:22:03+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)
- - - - -
451c6a43 by Simon Peyton Jones at 2026-03-04T12:15:09+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)
- - - - -
85b0aae2 by Simon Peyton Jones at 2026-03-04T12:15:09+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)
- - - - -
55885e4b by Simon Peyton Jones at 2026-03-04T12:15:09+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)
- - - - -
4fdab7ca by sheaf at 2026-03-04T12:15:09+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)
- - - - -
cfbec95d by Rodrigo Mesquita at 2026-03-04T12:15:09+05:30
bytecode: Use 32bits for breakpoint index
Fixes #26325
(cherry picked from commit e368e24779f8a7bf110a025383db23521b313407)
- - - - -
2ee8a948 by Zubin Duggal at 2026-03-05T10:59:34+05:30
Bump Win32 submodule to 2.14.2.1.
- - - - -
928c81aa by Zubin Duggal at 2026-03-05T10:59:35+05:30
Bump directory submodule to 1.3.10.1.
- - - - -
7630ef4e by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump exceptions submodule to 0.10.12.
- - - - -
06f47576 by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump file-io submodule to 0.1.6.
- - - - -
8f6f0053 by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump filepath submodule to 1.5.5.0.
- - - - -
2129f6f1 by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump haskeline submodule to 0.8.4.1.
- - - - -
995cb006 by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump mtl submodule to 2.3.2.
- - - - -
4e021a4b by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump os-string submodule to 2.0.10.
- - - - -
58d74a0c by Zubin Duggal at 2026-03-05T11:56:26+05:30
Bump unix submodule to 2.8.8.0.
- - - - -
4d81dd7f by sheaf at 2026-03-06T11:21:09+05:30
Mark T26410_ffi as fragile on Windows
As seen in #26595, this test intermittently fails on Windows.
This commit marks it as fragile, until we get around to fixing it.
(cherry picked from commit 6b42232c34273137b194c41b3c968be4a377a68f)
- - - - -
309889a5 by Zubin Duggal at 2026-03-06T11:21:09+05:30
Prepare release 9.12.4
- - - - -
1070cf05 by Zubin Duggal at 2026-03-10T13:02:18+05:30
Fix warning for Werror due to mismatched pragma pop
- - - - -
250 changed files:
- .gitlab-ci.yml
- .gitlab/darwin/toolchain.nix
- .gitlab/rel_eng/upload_ghc_libs.py
- compiler/GHC/Builtin/primops.txt.pp
- 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/Lint.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/CSE.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/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/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/Instance/Class.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Types/Evidence.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
- configure.ac
- + 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
- hadrian/src/Settings/Builders/RunTest.hs
- libffi-tarballs
- libraries/Win32
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Control/Exception/Backtrace.hs
- libraries/directory
- libraries/exceptions
- libraries/file-io
- libraries/filepath
- 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/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs-boot
- + libraries/ghc-internal/tests/Makefile
- + libraries/ghc-internal/tests/all.T
- + libraries/ghc-internal/tests/backtraces/Makefile
- + libraries/ghc-internal/tests/backtraces/T14532a.hs
- + libraries/ghc-internal/tests/backtraces/T14532a.stdout
- + libraries/ghc-internal/tests/backtraces/T14532b.hs
- + libraries/ghc-internal/tests/backtraces/T14532b.stdout
- + libraries/ghc-internal/tests/backtraces/all.T
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- libraries/haskeline
- libraries/mtl
- libraries/os-string
- libraries/text
- libraries/transformers
- libraries/unix
- 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/Bytecodes.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/config/ghc
- testsuite/driver/cpu_features.py
- testsuite/driver/runtests.py
- testsuite/driver/testlib.py
- testsuite/driver/testutil.py
- testsuite/tests/arrows/should_compile/T21301.stderr
- + 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/cmm/should_run/JumpTableNoStackDealloc.hs
- + testsuite/tests/cmm/should_run/JumpTableNoStackDealloc.stdout
- + testsuite/tests/cmm/should_run/JumpTableNoStackDeallocGen.hs
- + testsuite/tests/cmm/should_run/JumpTableNoStackDealloc_cmm.cmm
- testsuite/tests/cmm/should_run/all.T
- testsuite/tests/codeGen/should_run/all.T
- + testsuite/tests/cross/should_run/T26449.hs
- + testsuite/tests/cross/should_run/all.T
- testsuite/tests/deSugar/should_fail/DsStrictFail.stderr
- testsuite/tests/deSugar/should_run/T20024.stderr
- testsuite/tests/deSugar/should_run/dsrun005.stderr
- testsuite/tests/deSugar/should_run/dsrun007.stderr
- testsuite/tests/deSugar/should_run/dsrun008.stderr
- + testsuite/tests/default/T25775.hs
- + testsuite/tests/default/T25775.stderr
- testsuite/tests/default/all.T
- testsuite/tests/deriving/should_run/T9576.stderr
- + testsuite/tests/ghc-api/TypeMapStringLiteral.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-e/should_fail/T9930fail.stderr
- + 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/ghci/all.T
- + testsuite/tests/ghci/ghci-mem-primops.hs
- + testsuite/tests/ghci/ghci-mem-primops.script
- + testsuite/tests/ghci/ghci-mem-primops.stdout
- testsuite/tests/ghci/scripts/Defer02.stderr
- testsuite/tests/ghci/scripts/T15325.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/linters/all.T
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/numeric/should_run/foundation.stdout
- + testsuite/tests/overloadedrecflds/should_fail/T26391.hs
- + testsuite/tests/overloadedrecflds/should_fail/T26391.stderr
- testsuite/tests/overloadedrecflds/should_fail/all.T
- testsuite/tests/patsyn/should_run/ghci.stderr
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/perf/compiler/interpreter_steplocal.hs
- + testsuite/tests/perf/compiler/interpreter_steplocal.script
- + testsuite/tests/perf/compiler/interpreter_steplocal.stdout
- 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/safeHaskell/safeLanguage/SafeLang15.stderr
- 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/type-data/should_run/T22332a.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_run/T10284.stderr
- testsuite/tests/typecheck/should_run/T13838.stderr
- testsuite/tests/typecheck/should_run/T9497a-run.stderr
- testsuite/tests/typecheck/should_run/T9497b-run.stderr
- testsuite/tests/typecheck/should_run/T9497c-run.stderr
- testsuite/tests/unsatisfiable/T23816.stderr
- testsuite/tests/unsatisfiable/UnsatDefer.stderr
- utils/genprimopcode/Main.hs
- utils/genprimopcode/Syntax.hs
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/MergeObjs.hs
- utils/haddock/haddock-api/resources/html/Linuwial.std-theme/linuwial.css
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Utils.hs
- utils/haddock/html-test/ref/Bug1004.html
- utils/haddock/html-test/ref/Bug548.html
- utils/haddock/html-test/ref/Bug973.html
- utils/haddock/html-test/ref/Hash.html
- utils/haddock/html-test/ref/ImplicitParams.html
- utils/haddock/html-test/ref/Instances.html
- utils/haddock/html-test/ref/TypeOperators.html
- utils/jsffi/dyld.mjs
- utils/jsffi/post-link.mjs
- utils/jsffi/prelude.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/65370007e2d9f1976fbcfbb514917f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/65370007e2d9f1976fbcfbb514917f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/io-manager-deadlock-detection] 2 commits: Move THREADED_RTS-conditional struct members to end of Capability
by Duncan Coutts (@dcoutts) 10 Mar '26
by Duncan Coutts (@dcoutts) 10 Mar '26
10 Mar '26
Duncan Coutts pushed to branch wip/io-manager-deadlock-detection at Glasgow Haskell Compiler / GHC
Commits:
bb63cf06 by Duncan Coutts at 2026-03-10T10:09:52+00:00
Move THREADED_RTS-conditional struct members to end of Capability
Accessing members of the Capability struct from CMM code rely on
accessor macros. (The macros are generated by deriveConstants).
These macros have a single definition. This means that the offsets of
all struct members must *not* vary based on THREADED_RTS vs
!THREADED_RTS. This requires that any struct members that are
conditional on THREADED_RTS must occur after the unconditional struct
members. Hence we move all the ones that are conditional on
THREADED_RTS to the end.
Add a deriveConstants entry for the iomgr member of the Capability
struct, which was the motivation for this change.
Add warning messages to help our future selves. Debugging this took me
a couple hours in gdb!
It is unclear why reordering the capability struct should make the
hello world program bigger, but perhaps it was just on the edge of the
+5% and this changed the size slightly. A last straw if you like.
-------------------------
Metric Increase:
size_hello_artifact
-------------------------
- - - - -
97cb8f22 by Duncan Coutts at 2026-03-10T10:11:14+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()).
- - - - -
15 changed files:
- rts/Capability.c
- rts/Capability.h
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/PrimOps.cmm
- rts/RaiseAsync.c
- rts/Schedule.c
- rts/posix/Poll.c
- rts/posix/Poll.h
- rts/posix/Select.c
- rts/posix/Select.h
- rts/posix/Timeout.c
- rts/posix/Timeout.h
- utils/deriveConstants/Main.hs
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/Capability.h
=====================================
@@ -139,6 +139,19 @@ struct Capability_ {
// See Note [allocation accounting] in Storage.c
uint64_t total_allocated;
+ // I/O manager data structures for this capability
+ CapIOManager *iomgr;
+
+ // Per-capability STM-related data
+ StgTVarWatchQueue *free_tvar_watch_queues;
+ StgTRecChunk *free_trec_chunks;
+ StgTRecHeader *free_trec_headers;
+ uint32_t transaction_tokens;
+
+ // WARNING: unconditional struct members must come before ones
+ // conditional on THREADED_RTS. Otherwise the CMM Capability_*
+ // accessor macros would have the wrong offsets.
+
#if defined(THREADED_RTS)
// Worker Tasks waiting in the wings. Singly-linked.
Task *spare_workers;
@@ -175,14 +188,9 @@ struct Capability_ {
SparkCounters spark_stats;
#endif
- // I/O manager data structures for this capability
- CapIOManager *iomgr;
+ // WARNING: No more unconditional struct members here, or they will
+ // have inconsistent CMM offset macros.
- // Per-capability STM-related data
- StgTVarWatchQueue *free_tvar_watch_queues;
- StgTRecChunk *free_trec_chunks;
- StgTRecHeader *free_trec_headers;
- uint32_t transaction_tokens;
} // typedef Capability is defined in RtsAPI.h
ATTRIBUTE_ALIGNED(CAPABILITY_ALIGNMENT)
;
=====================================
rts/IOManager.c
=====================================
@@ -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,8 +370,6 @@ void initCapabilityIOManager(Capability *cap)
default:
break;
}
-
- cap->iomgr = iomgr;
}
@@ -436,7 +441,7 @@ void initIOManager(void)
/* Called from forkProcess in the child process on the surviving capability.
*/
void
-initIOManagerAfterFork(Capability **pcap)
+initIOManagerAfterFork(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,11 +228,19 @@ 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
@@ -243,10 +252,11 @@ void initIOManager(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 initIOManagerAfterFork(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
@@ -2348,7 +2351,8 @@ stg_asyncReadzh ( W_ fd, W_ is_sock, W_ len, W_ buf )
ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32);
%release StgTSO_why_blocked(CurrentTSO) = BlockedOnRead::I32;
- ccall appendToIOBlockedQueue(MyCapability() "ptr", CurrentTSO "ptr");
+ ccall appendToIOBlockedQueue(Capability_iomgr(MyCapability()) "ptr",
+ CurrentTSO "ptr");
jump stg_block_async();
#endif
}
@@ -2374,7 +2378,8 @@ stg_asyncWritezh ( W_ fd, W_ is_sock, W_ len, W_ buf )
ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32);
%release StgTSO_why_blocked(CurrentTSO) = BlockedOnWrite::I32;
- ccall appendToIOBlockedQueue(MyCapability() "ptr", CurrentTSO "ptr");
+ ccall appendToIOBlockedQueue(Capability_iomgr(MyCapability()) "ptr",
+ CurrentTSO "ptr");
jump stg_block_async();
#endif
}
@@ -2400,7 +2405,8 @@ stg_asyncDoProczh ( W_ proc, W_ param )
ASSERT(StgTSO_why_blocked(CurrentTSO) == NotBlocked::I32);
%release StgTSO_why_blocked(CurrentTSO) = BlockedOnDoProc::I32;
- ccall appendToIOBlockedQueue(MyCapability() "ptr", CurrentTSO "ptr");
+ ccall appendToIOBlockedQueue(Capability_iomgr(MyCapability()) "ptr",
+ CurrentTSO "ptr");
jump stg_block_async();
#endif
}
=====================================
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/Schedule.c
=====================================
@@ -326,7 +326,7 @@ schedule (Capability *initialCapability, Task *task)
/* TODO: see if we can rationalise these two awaitCompletedTimeoutsOrIO
* calls before and after scheduleDetectDeadlock().
*/
- awaitCompletedTimeoutsOrIO(cap);
+ awaitCompletedTimeoutsOrIO(cap->iomgr);
#else
ASSERT(getSchedState() >= SCHED_INTERRUPTING);
#endif
@@ -409,7 +409,7 @@ schedule (Capability *initialCapability, Task *task)
*/
if (RtsFlags.ConcFlags.ctxtSwitchTicks == 0 &&
(!emptyRunQueue(cap) ||
- anyPendingTimeoutsOrIO(cap))) {
+ anyPendingTimeoutsOrIO(cap->iomgr))) {
RELAXED_STORE(&cap->context_switch, 1);
}
@@ -923,14 +923,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 +950,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)
/*
@@ -2232,7 +2232,7 @@ forkProcess(HsStablePtr *entry
// like startup event, capabilities, process info etc
traceTaskCreate(task, cap);
- initIOManagerAfterFork(&cap);
+ initIOManagerAfterFork(cap->iomgr, &cap);
// start timer after the IOManager is initialized
// (the idle GC may wake up the IOManager)
@@ -2392,7 +2392,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();
=====================================
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/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).
=====================================
utils/deriveConstants/Main.hs
=====================================
@@ -414,6 +414,7 @@ wanteds os = concat
,structField C "Capability" "weak_ptr_list_tl"
,structField C "Capability" "n_run_queue"
,structField C "Capability" "pinned_object_block"
+ ,structField C "Capability" "iomgr"
,structField Both "bdescr" "start"
,structField Both "bdescr" "free"
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ac79161475ca41f462e6b1ff66e641…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ac79161475ca41f462e6b1ff66e641…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/backports-9.12.4] Fix warning for Werror due to mismatched pragma pop
by Zubin (@wz1000) 10 Mar '26
by Zubin (@wz1000) 10 Mar '26
10 Mar '26
Zubin pushed to branch wip/backports-9.12.4 at Glasgow Haskell Compiler / GHC
Commits:
1070cf05 by Zubin Duggal at 2026-03-10T13:02:18+05:30
Fix warning for Werror due to mismatched pragma pop
- - - - -
1 changed file:
- rts/prim/atomic.c
Changes:
=====================================
rts/prim/atomic.c
=====================================
@@ -96,8 +96,6 @@ StgWord64 hs_atomic_nand64(StgWord x, StgWord64 val)
return __atomic_fetch_nand((volatile StgWord64 *) x, val, __ATOMIC_SEQ_CST);
}
-#pragma GCC diagnostic pop
-
// FetchOrByteArrayOp_Int
StgWord hs_atomic_or8(StgWord x, StgWord val)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1070cf051bc110175dd29bc142d4fe3…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1070cf051bc110175dd29bc142d4fe3…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 2 commits: chore: Merge GHC.Internal.TH.Quote into GHC.Internal.TH.Monad
by Marge Bot (@marge-bot) 10 Mar '26
by Marge Bot (@marge-bot) 10 Mar '26
10 Mar '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
05f905f2 by Rajkumar Natarajan at 2026-03-10T00:20:29-04:00
chore: Merge GHC.Internal.TH.Quote into GHC.Internal.TH.Monad
Move the QuasiQuoter datatype from GHC.Internal.TH.Quote to
GHC.Internal.TH.Monad and delete the Quote module.
Update submodule template-haskell-quasiquoter to use the merged
upstream version that imports from the correct module.
Co-authored-by: Cursor <cursoragent(a)cursor.com>
- - - - -
95f76326 by Simon Jakobi at 2026-03-10T00:20:30-04:00
Add regression test for #16122
- - - - -
13 changed files:
- compiler/GHC/Builtin/Names/TH.hs
- libraries/ghc-boot-th/GHC/Boot/TH/Quote.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- − libraries/ghc-internal/src/GHC/Internal/TH/Quote.hs
- libraries/template-haskell-quasiquoter
- testsuite/tests/linters/Makefile
- testsuite/tests/plugins/plugins10.stdout
- testsuite/tests/quotes/QQError.stderr
- + testsuite/tests/simplCore/should_compile/T16122.hs
- + testsuite/tests/simplCore/should_compile/T16122.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/th/QQTopError.stderr
Changes:
=====================================
compiler/GHC/Builtin/Names/TH.hs
=====================================
@@ -185,7 +185,7 @@ thSyn, thMonad, thLib, qqLib, liftLib :: Module
thSyn = mkTHModule (fsLit "GHC.Internal.TH.Syntax")
thMonad = mkTHModule (fsLit "GHC.Internal.TH.Monad")
thLib = mkTHModule (fsLit "GHC.Internal.TH.Lib")
-qqLib = mkTHModule (fsLit "GHC.Internal.TH.Quote")
+qqLib = mkTHModule (fsLit "GHC.Internal.TH.Monad")
liftLib = mkTHModule (fsLit "GHC.Internal.TH.Lift")
=====================================
libraries/ghc-boot-th/GHC/Boot/TH/Quote.hs
=====================================
@@ -1,5 +1,5 @@
{-# OPTIONS_HADDOCK not-home #-}
module GHC.Boot.TH.Quote
- (module GHC.Internal.TH.Quote) where
+ (QuasiQuoter(..)) where
-import GHC.Internal.TH.Quote
+import GHC.Internal.TH.Monad (QuasiQuoter(..))
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -306,7 +306,6 @@ Library
GHC.Internal.TH.Syntax
GHC.Internal.TH.Lib
GHC.Internal.TH.Lift
- GHC.Internal.TH.Quote
GHC.Internal.TH.Monad
GHC.Internal.TopHandler
GHC.Internal.TypeError
=====================================
libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
=====================================
@@ -20,6 +20,7 @@
-- Import "Language.Haskell.TH" or "Language.Haskell.TH.Syntax" instead!
module GHC.Internal.TH.Monad
( module GHC.Internal.TH.Monad
+ , QuasiQuoter(..)
) where
#ifdef BOOTSTRAP_TH
@@ -313,6 +314,33 @@ class Monad m => Quote m where
instance Quote Q where
newName s = Q (qNewName s)
+-----------------------------------------------------
+--
+-- The QuasiQuoter type
+--
+-----------------------------------------------------
+
+-- | The 'QuasiQuoter' type, a value @q@ of this type can be used
+-- in the syntax @[q| ... string to parse ...|]@. In fact, for
+-- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters
+-- to be used in different splice contexts. In the usual case of a
+-- @QuasiQuoter@ that is only intended to be used in certain splice
+-- contexts, the unused fields should just 'fail'. This is most easily
+-- accomplished using 'namedefaultQuasiQuoter' or 'defaultQuasiQuoter'.
+--
+-- This is exposed both from the @template-haskell-quasiquoter@ and @template-haskell@ packages.
+-- Consider importing it from the more stable @template-haskell-quasiquoter@ if you don't need the full breadth of the @template-haskell@ interface.
+data QuasiQuoter = QuasiQuoter {
+ -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
+ quoteExp :: String -> Q Exp,
+ -- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
+ quotePat :: String -> Q Pat,
+ -- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
+ quoteType :: String -> Q Type,
+ -- | Quasi-quoter for declarations, invoked by top-level quotes
+ quoteDec :: String -> Q [Dec]
+ }
+
-----------------------------------------------------
--
-- The TExp type
=====================================
libraries/ghc-internal/src/GHC/Internal/TH/Quote.hs deleted
=====================================
@@ -1,46 +0,0 @@
-{-# LANGUAGE CPP, RankNTypes, ScopedTypeVariables, Trustworthy #-}
-{- |
-Module : GHC.Internal.TH.Quote
-Description : Quasi-quoting support for Template Haskell
-
-Template Haskell supports quasiquoting, which permits users to construct
-program fragments by directly writing concrete syntax. A quasiquoter is
-essentially a function with takes a string to a Template Haskell AST.
-This module defines the 'QuasiQuoter' datatype, which specifies a
-quasiquoter @q@ which can be invoked using the syntax
-@[q| ... string to parse ... |]@ when the @QuasiQuotes@ language
-extension is enabled, and some utility functions for manipulating
-quasiquoters. Nota bene: this package does not define any parsers,
-that is up to you.
-
-This is an internal module. Please import 'Language.Haskell.TH.Quote' instead.
--}
-module GHC.Internal.TH.Quote(
- QuasiQuoter(..),
- ) where
-
-import GHC.Internal.TH.Syntax
-import GHC.Internal.TH.Monad
-import GHC.Internal.Base hiding (Type)
-
-
--- | The 'QuasiQuoter' type, a value @q@ of this type can be used
--- in the syntax @[q| ... string to parse ...|]@. In fact, for
--- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters
--- to be used in different splice contexts. In the usual case of a
--- @QuasiQuoter@ that is only intended to be used in certain splice
--- contexts, the unused fields should just 'fail'. This is most easily
--- accomplished using 'namedefaultQuasiQuoter' or 'defaultQuasiQuoter'.
---
--- This is exposed both from the @template-haskell-quasiquoter@ and @template-haskell@ packages.
--- Consider importing it from the more stable @template-haskell-quasiquoter@ if you don't need the full breadth of the @template-haskell@ interface.
-data QuasiQuoter = QuasiQuoter {
- -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
- quoteExp :: String -> Q Exp,
- -- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
- quotePat :: String -> Q Pat,
- -- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
- quoteType :: String -> Q Type,
- -- | Quasi-quoter for declarations, invoked by top-level quotes
- quoteDec :: String -> Q [Dec]
- }
=====================================
libraries/template-haskell-quasiquoter
=====================================
@@ -1 +1 @@
-Subproject commit a47506eca032b139d9779fb8210d408c81d3fbd6
+Subproject commit e7c7af444a467fb8d56483583987002b43317576
=====================================
testsuite/tests/linters/Makefile
=====================================
@@ -81,7 +81,6 @@ whitespace:
libraries/base/include/HsEvent.h\
libraries/base/include/md5.h\
libraries/ghc-prim/GHC/Tuple.hs\
- libraries/template-haskell/Language/Haskell/TH/Quote.hs\
rts/STM.h\
rts/Sparks.h\
rts/Threads.h\
=====================================
testsuite/tests/plugins/plugins10.stdout
=====================================
@@ -6,10 +6,9 @@ interfacePlugin: GHC.Internal.Base
interfacePlugin: GHC.Internal.Data.NonEmpty
interfacePlugin: GHC.Internal.Float
interfacePlugin: GHC.Internal.Prim.Ext
-interfacePlugin: GHC.Internal.TH.Quote
+interfacePlugin: GHC.Internal.TH.Monad
interfacePlugin: GHC.Internal.TH.Syntax
typeCheckPlugin (rn)
-interfacePlugin: GHC.Internal.TH.Monad
interfacePlugin: GHC.Internal.Stack.Types
interfacePlugin: GHC.Internal.Exception.Context
typeCheckPlugin (tc)
=====================================
testsuite/tests/quotes/QQError.stderr
=====================================
@@ -1,5 +1,5 @@
QQError.hs:5:12: error: [GHC-83865]
- • Couldn't match expected type ‘GHC.Internal.TH.Quote.QuasiQuoter’
+ • Couldn't match expected type ‘GHC.Internal.TH.Monad.QuasiQuoter’
with actual type ‘a1 -> a1’
• Probable cause: ‘id’ is applied to too few arguments
In the expression: [| [id|hello|] |]
@@ -9,7 +9,7 @@ QQError.hs:5:12: error: [GHC-83865]
| ^^
QQError.hs:7:13: error: [GHC-83865]
- • Couldn't match expected type ‘GHC.Internal.TH.Quote.QuasiQuoter’
+ • Couldn't match expected type ‘GHC.Internal.TH.Monad.QuasiQuoter’
with actual type ‘a0 -> a0’
• Probable cause: ‘id’ is applied to too few arguments
In the expression: [| [id|hello|] |]
=====================================
testsuite/tests/simplCore/should_compile/T16122.hs
=====================================
@@ -0,0 +1,12 @@
+{-# LANGUAGE TypeApplications #-}
+-- Test that the Core for f isn't "worse" than g's.
+-- The optimized Core for f used to involve dictionary-passing. See #16122.
+module T16122 (f, g) where
+
+import Data.Int (Int64)
+
+f :: Double -> Int64
+f = round
+
+g :: Double -> Int64
+g = fromIntegral @Int @Int64 . round
=====================================
testsuite/tests/simplCore/should_compile/T16122.stderr
=====================================
@@ -0,0 +1,26 @@
+f = \ x ->
+ I64#
+ (case x of { D# ds1 ->
+ case {__ffi_static_ccall_unsafe ghc-internal:rintDouble :: Double#
+ -> State# RealWorld
+ -> (# State# RealWorld, Double# #)}
+ ds1 realWorld#
+ of
+ { (# _, ds3 #) ->
+ intToInt64# (double2Int# ds3)
+ }
+ })
+
+g = \ x ->
+ I64#
+ (case x of { D# ds1 ->
+ case {__ffi_static_ccall_unsafe ghc-internal:rintDouble :: Double#
+ -> State# RealWorld
+ -> (# State# RealWorld, Double# #)}
+ ds1 realWorld#
+ of
+ { (# _, ds3 #) ->
+ intToInt64# (double2Int# ds3)
+ }
+ })
+
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -295,6 +295,10 @@ test('T15631',
normal,
makefile_test, ['T15631'])
test('T15673', normal, compile, ['-O'])
+test('T16122', [when(wordsize(32), skip)],
+ multimod_compile_filter,
+ ['T16122', '-O -ddump-simpl -dsuppress-all -dsuppress-uniques -dno-typeable-binds',
+ "sed -n '/^f = /,/^$/p;/^g = /,/^$/p'"])
test('T16288', normal, multimod_compile, ['T16288B', '-O -dcore-lint -v0'])
test('T16348', normal, compile, ['-O'])
test('T16918', normal, compile, ['-O'])
=====================================
testsuite/tests/th/QQTopError.stderr
=====================================
@@ -1,10 +1,10 @@
QQTopError.hs:4:9: error: [GHC-83865]
- • Couldn't match expected type ‘GHC.Internal.TH.Quote.QuasiQuoter’
+ • Couldn't match expected type ‘GHC.Internal.TH.Monad.QuasiQuoter’
with actual type ‘a0 -> a0’
• Probable cause: ‘id’ is applied to too few arguments
- In the first argument of ‘GHC.Internal.TH.Quote.quoteExp’, namely
+ In the first argument of ‘GHC.Internal.TH.Monad.quoteExp’, namely
‘id’
- In the expression: GHC.Internal.TH.Quote.quoteExp id "hello"
+ In the expression: GHC.Internal.TH.Monad.quoteExp id "hello"
In the quasi-quotation: [id|hello|]
|
4 | main = [id|hello|]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ab85b3dad8a97925eab89f10f8b9b7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ab85b3dad8a97925eab89f10f8b9b7…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/ani/kill-SrcCodeOrigin] add zonking for PatSigErrCtxt, fix err string for pprExpectedFunTyCtxt
by Apoorv Ingle (@ani) 10 Mar '26
by Apoorv Ingle (@ani) 10 Mar '26
10 Mar '26
Apoorv Ingle pushed to branch wip/ani/kill-SrcCodeOrigin at Glasgow Haskell Compiler / GHC
Commits:
d0f2dc6f by Apoorv Ingle at 2026-03-09T22:17:16-05:00
add zonking for PatSigErrCtxt, fix err string for pprExpectedFunTyCtxt
- - - - -
3 changed files:
- compiler/GHC/Tc/Gen/Do.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Zonk/TcType.hs
Changes:
=====================================
compiler/GHC/Tc/Gen/Do.hs
=====================================
@@ -106,7 +106,7 @@ expand_do_stmts doFlavour (stmt@(L loc (BindStmt xbsrn pat e)): lstmts)
-- -------------------------------------------------------
-- pat <- e ; stmts ~~> (>>=) e f
= do expand_stmts_expr <- expand_do_stmts doFlavour lstmts
- failable_expr <- mk_failable_expr doFlavour pat stmt expand_stmts_expr fail_op
+ failable_expr <- mk_failable_expr doFlavour pat expand_stmts_expr fail_op
let expansion = genHsExpApps bind_op -- (>>=)
[ e
, failable_expr ]
@@ -177,9 +177,9 @@ expand_do_stmts doFlavour
expand_do_stmts _ stmts = pprPanic "expand_do_stmts: impossible happened" $ (ppr stmts)
-- checks the pattern `pat` for irrefutability which decides if we need to wrap it with a fail block
-mk_failable_expr :: HsDoFlavour -> LPat GhcRn -> ExprLStmt GhcRn -> LHsExpr GhcRn
+mk_failable_expr :: HsDoFlavour -> LPat GhcRn -> LHsExpr GhcRn
-> FailOperator GhcRn -> TcM (LHsExpr GhcRn)
-mk_failable_expr doFlav lpat stmt expr fail_op =
+mk_failable_expr doFlav lpat expr fail_op =
do { is_strict <- xoptM LangExt.Strict
; hscEnv <- getTopEnv
; rdrEnv <- getGlobalRdrEnv
@@ -191,16 +191,16 @@ mk_failable_expr doFlav lpat stmt expr fail_op =
; if irrf_pat -- don't wrap with fail block if
-- the pattern is irrefutable
then return $ genHsLamDoExp doFlav [lpat] expr
- else wrapGenSpan <$> mk_fail_block doFlav lpat stmt expr fail_op
+ else wrapGenSpan <$> mk_fail_block doFlav lpat expr fail_op
}
-- | Makes the fail block with a given fail_op
-- mk_fail_block pat rhs fail builds
-- \x. case x of {pat -> rhs; _ -> fail "Pattern match failure..."}
mk_fail_block :: HsDoFlavour
- -> LPat GhcRn -> ExprLStmt GhcRn
+ -> LPat GhcRn
-> LHsExpr GhcRn -> FailOperator GhcRn -> TcM (HsExpr GhcRn)
-mk_fail_block doFlav pat stmt e (Just (SyntaxExprRn fail_op)) =
+mk_fail_block doFlav pat e (Just (SyntaxExprRn fail_op)) =
do dflags <- getDynFlags
return $ HsLam noAnn LamCases $ mkMatchGroup (doExpansionOrigin doFlav) -- \
(wrapGenSpan [ genHsCaseAltDoExp doFlav pat e -- pat -> expr
@@ -218,10 +218,10 @@ mk_fail_block doFlav pat stmt e (Just (SyntaxExprRn fail_op)) =
mk_fail_msg_expr :: DynFlags -> LPat GhcRn -> LHsExpr GhcRn
mk_fail_msg_expr dflags pat
= nlHsLit $ mkHsString $ showPpr dflags $
- text "Pattern match failure in" <+> pprHsDoFlavour (DoExpr Nothing)
+ text "Pattern match failure in" <+> pprHsDoFlavour doFlav
<+> text "at" <+> ppr (getLocA pat)
-mk_fail_block _ _ _ _ _ = pprPanic "mk_fail_block: impossible happened" empty
+mk_fail_block _ _ _ _ = pprPanic "mk_fail_block: impossible happened" empty
{- Note [Expanding HsDo with XXExprGhcRn]
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -1484,7 +1484,7 @@ pprExpectedFunTyCtxt funTy_origin i =
case funTy_origin of
ExpectedFunTySyntaxOp orig op ->
vcat [ sep [ the_arg_of
- , text "The rebindable syntax operator"
+ , text "the rebindable syntax operator"
, quotes (ppr op) ]
, nest 2 (ppr orig) ]
ExpectedTySyntax orig arg ->
=====================================
compiler/GHC/Tc/Zonk/TcType.hs
=====================================
@@ -91,12 +91,14 @@ import GHC.Core.Predicate
import GHC.Utils.Constants
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Misc
-import GHC.Utils.Monad ( mapAccumLM )
+import GHC.Utils.Monad ( mapAccumLM, liftIO )
import GHC.Utils.Panic
import GHC.Data.Bag
import GHC.Data.Pair
+import GHC.IORef (readIORef)
+
import Data.Semigroup
import Data.Maybe
@@ -795,11 +797,6 @@ tidyEvVar env var = updateIdTypeAndMult (tidyType env) var
-- No need for tidyOpenType because all the free tyvars are already tidied
-
-{-
-Zonk ErrCtxtMsg
--}
-
zonkTidyErrCtxtMsg :: TidyEnv -> ErrCtxtMsg -> ZonkM (TidyEnv, ErrCtxtMsg)
zonkTidyErrCtxtMsg env e@(ExprCtxt{}) = return (env, e)
zonkTidyErrCtxtMsg env (ThetaCtxt ctxt theta_ty) = do
@@ -823,7 +820,15 @@ zonkTidyErrCtxtMsg env (FunResCtxt e i1 ty1 ty2 i2 i3) = do
(env', ty1') <- zonkTidyTcType env ty1
(env', ty2') <- zonkTidyTcType env' ty2
return $ (env', FunResCtxt e i1 ty1' ty2' i2 i3)
--- zonkTidyErrCtxtMsg env (PatSigErrCtxt sig_ty res_ty) = do
--- (env', sig_ty) <- zonkTidyTcType env sig_ty
--- (env', res_ty) <- zonkZidy
+zonkTidyErrCtxtMsg env (PatSigErrCtxt sig_ty res_ty) = do
+ (env', sig_ty') <- zonkTidyTcType env sig_ty
+ (env', res_ty') <-
+ case res_ty of
+ Check ty -> zonkTidyTcType env' ty
+ Infer (IR {ir_ref = ref}) -> do -- inlining readExpTyp_maybe to avoid module dep loops
+ mb_ty <- liftIO $ readIORef ref
+ case mb_ty of
+ Nothing -> error "zonkTidyErrCtxtMsg PatSigErrCtxt"
+ Just ty -> zonkTidyTcType env' ty
+ return (env', PatSigErrCtxt sig_ty' (Check res_ty'))
zonkTidyErrCtxtMsg env p = return (env, p)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d0f2dc6f165950916dffea8aa0adc3d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d0f2dc6f165950916dffea8aa0adc3d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/spj-reinstallable-base
by Simon Peyton Jones (@simonpj) 10 Mar '26
by Simon Peyton Jones (@simonpj) 10 Mar '26
10 Mar '26
Simon Peyton Jones pushed new branch wip/spj-reinstallable-base at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/spj-reinstallable-base
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 2 commits: chore: Merge GHC.Internal.TH.Quote into GHC.Internal.TH.Monad
by Marge Bot (@marge-bot) 10 Mar '26
by Marge Bot (@marge-bot) 10 Mar '26
10 Mar '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
0fda1313 by Rajkumar Natarajan at 2026-03-09T20:19:44-04:00
chore: Merge GHC.Internal.TH.Quote into GHC.Internal.TH.Monad
Move the QuasiQuoter datatype from GHC.Internal.TH.Quote to
GHC.Internal.TH.Monad and delete the Quote module.
Update submodule template-haskell-quasiquoter to use the merged
upstream version that imports from the correct module.
Co-authored-by: Cursor <cursoragent(a)cursor.com>
- - - - -
ab85b3da by Simon Jakobi at 2026-03-09T20:19:45-04:00
Add regression test for #16122
- - - - -
13 changed files:
- compiler/GHC/Builtin/Names/TH.hs
- libraries/ghc-boot-th/GHC/Boot/TH/Quote.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- − libraries/ghc-internal/src/GHC/Internal/TH/Quote.hs
- libraries/template-haskell-quasiquoter
- testsuite/tests/linters/Makefile
- testsuite/tests/plugins/plugins10.stdout
- testsuite/tests/quotes/QQError.stderr
- + testsuite/tests/simplCore/should_compile/T16122.hs
- + testsuite/tests/simplCore/should_compile/T16122.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/th/QQTopError.stderr
Changes:
=====================================
compiler/GHC/Builtin/Names/TH.hs
=====================================
@@ -185,7 +185,7 @@ thSyn, thMonad, thLib, qqLib, liftLib :: Module
thSyn = mkTHModule (fsLit "GHC.Internal.TH.Syntax")
thMonad = mkTHModule (fsLit "GHC.Internal.TH.Monad")
thLib = mkTHModule (fsLit "GHC.Internal.TH.Lib")
-qqLib = mkTHModule (fsLit "GHC.Internal.TH.Quote")
+qqLib = mkTHModule (fsLit "GHC.Internal.TH.Monad")
liftLib = mkTHModule (fsLit "GHC.Internal.TH.Lift")
=====================================
libraries/ghc-boot-th/GHC/Boot/TH/Quote.hs
=====================================
@@ -1,5 +1,5 @@
{-# OPTIONS_HADDOCK not-home #-}
module GHC.Boot.TH.Quote
- (module GHC.Internal.TH.Quote) where
+ (QuasiQuoter(..)) where
-import GHC.Internal.TH.Quote
+import GHC.Internal.TH.Monad (QuasiQuoter(..))
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -306,7 +306,6 @@ Library
GHC.Internal.TH.Syntax
GHC.Internal.TH.Lib
GHC.Internal.TH.Lift
- GHC.Internal.TH.Quote
GHC.Internal.TH.Monad
GHC.Internal.TopHandler
GHC.Internal.TypeError
=====================================
libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
=====================================
@@ -20,6 +20,7 @@
-- Import "Language.Haskell.TH" or "Language.Haskell.TH.Syntax" instead!
module GHC.Internal.TH.Monad
( module GHC.Internal.TH.Monad
+ , QuasiQuoter(..)
) where
#ifdef BOOTSTRAP_TH
@@ -313,6 +314,33 @@ class Monad m => Quote m where
instance Quote Q where
newName s = Q (qNewName s)
+-----------------------------------------------------
+--
+-- The QuasiQuoter type
+--
+-----------------------------------------------------
+
+-- | The 'QuasiQuoter' type, a value @q@ of this type can be used
+-- in the syntax @[q| ... string to parse ...|]@. In fact, for
+-- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters
+-- to be used in different splice contexts. In the usual case of a
+-- @QuasiQuoter@ that is only intended to be used in certain splice
+-- contexts, the unused fields should just 'fail'. This is most easily
+-- accomplished using 'namedefaultQuasiQuoter' or 'defaultQuasiQuoter'.
+--
+-- This is exposed both from the @template-haskell-quasiquoter@ and @template-haskell@ packages.
+-- Consider importing it from the more stable @template-haskell-quasiquoter@ if you don't need the full breadth of the @template-haskell@ interface.
+data QuasiQuoter = QuasiQuoter {
+ -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
+ quoteExp :: String -> Q Exp,
+ -- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
+ quotePat :: String -> Q Pat,
+ -- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
+ quoteType :: String -> Q Type,
+ -- | Quasi-quoter for declarations, invoked by top-level quotes
+ quoteDec :: String -> Q [Dec]
+ }
+
-----------------------------------------------------
--
-- The TExp type
=====================================
libraries/ghc-internal/src/GHC/Internal/TH/Quote.hs deleted
=====================================
@@ -1,46 +0,0 @@
-{-# LANGUAGE CPP, RankNTypes, ScopedTypeVariables, Trustworthy #-}
-{- |
-Module : GHC.Internal.TH.Quote
-Description : Quasi-quoting support for Template Haskell
-
-Template Haskell supports quasiquoting, which permits users to construct
-program fragments by directly writing concrete syntax. A quasiquoter is
-essentially a function with takes a string to a Template Haskell AST.
-This module defines the 'QuasiQuoter' datatype, which specifies a
-quasiquoter @q@ which can be invoked using the syntax
-@[q| ... string to parse ... |]@ when the @QuasiQuotes@ language
-extension is enabled, and some utility functions for manipulating
-quasiquoters. Nota bene: this package does not define any parsers,
-that is up to you.
-
-This is an internal module. Please import 'Language.Haskell.TH.Quote' instead.
--}
-module GHC.Internal.TH.Quote(
- QuasiQuoter(..),
- ) where
-
-import GHC.Internal.TH.Syntax
-import GHC.Internal.TH.Monad
-import GHC.Internal.Base hiding (Type)
-
-
--- | The 'QuasiQuoter' type, a value @q@ of this type can be used
--- in the syntax @[q| ... string to parse ...|]@. In fact, for
--- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters
--- to be used in different splice contexts. In the usual case of a
--- @QuasiQuoter@ that is only intended to be used in certain splice
--- contexts, the unused fields should just 'fail'. This is most easily
--- accomplished using 'namedefaultQuasiQuoter' or 'defaultQuasiQuoter'.
---
--- This is exposed both from the @template-haskell-quasiquoter@ and @template-haskell@ packages.
--- Consider importing it from the more stable @template-haskell-quasiquoter@ if you don't need the full breadth of the @template-haskell@ interface.
-data QuasiQuoter = QuasiQuoter {
- -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
- quoteExp :: String -> Q Exp,
- -- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
- quotePat :: String -> Q Pat,
- -- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
- quoteType :: String -> Q Type,
- -- | Quasi-quoter for declarations, invoked by top-level quotes
- quoteDec :: String -> Q [Dec]
- }
=====================================
libraries/template-haskell-quasiquoter
=====================================
@@ -1 +1 @@
-Subproject commit a47506eca032b139d9779fb8210d408c81d3fbd6
+Subproject commit e7c7af444a467fb8d56483583987002b43317576
=====================================
testsuite/tests/linters/Makefile
=====================================
@@ -81,7 +81,6 @@ whitespace:
libraries/base/include/HsEvent.h\
libraries/base/include/md5.h\
libraries/ghc-prim/GHC/Tuple.hs\
- libraries/template-haskell/Language/Haskell/TH/Quote.hs\
rts/STM.h\
rts/Sparks.h\
rts/Threads.h\
=====================================
testsuite/tests/plugins/plugins10.stdout
=====================================
@@ -6,10 +6,9 @@ interfacePlugin: GHC.Internal.Base
interfacePlugin: GHC.Internal.Data.NonEmpty
interfacePlugin: GHC.Internal.Float
interfacePlugin: GHC.Internal.Prim.Ext
-interfacePlugin: GHC.Internal.TH.Quote
+interfacePlugin: GHC.Internal.TH.Monad
interfacePlugin: GHC.Internal.TH.Syntax
typeCheckPlugin (rn)
-interfacePlugin: GHC.Internal.TH.Monad
interfacePlugin: GHC.Internal.Stack.Types
interfacePlugin: GHC.Internal.Exception.Context
typeCheckPlugin (tc)
=====================================
testsuite/tests/quotes/QQError.stderr
=====================================
@@ -1,5 +1,5 @@
QQError.hs:5:12: error: [GHC-83865]
- • Couldn't match expected type ‘GHC.Internal.TH.Quote.QuasiQuoter’
+ • Couldn't match expected type ‘GHC.Internal.TH.Monad.QuasiQuoter’
with actual type ‘a1 -> a1’
• Probable cause: ‘id’ is applied to too few arguments
In the expression: [| [id|hello|] |]
@@ -9,7 +9,7 @@ QQError.hs:5:12: error: [GHC-83865]
| ^^
QQError.hs:7:13: error: [GHC-83865]
- • Couldn't match expected type ‘GHC.Internal.TH.Quote.QuasiQuoter’
+ • Couldn't match expected type ‘GHC.Internal.TH.Monad.QuasiQuoter’
with actual type ‘a0 -> a0’
• Probable cause: ‘id’ is applied to too few arguments
In the expression: [| [id|hello|] |]
=====================================
testsuite/tests/simplCore/should_compile/T16122.hs
=====================================
@@ -0,0 +1,12 @@
+{-# LANGUAGE TypeApplications #-}
+-- Test that the Core for f isn't "worse" than g's.
+-- The optimized Core for f used to involve dictionary-passing. See #16122.
+module T16122 (f, g) where
+
+import Data.Int (Int64)
+
+f :: Double -> Int64
+f = round
+
+g :: Double -> Int64
+g = fromIntegral @Int @Int64 . round
=====================================
testsuite/tests/simplCore/should_compile/T16122.stderr
=====================================
@@ -0,0 +1,26 @@
+f = \ x ->
+ I64#
+ (case x of { D# ds1 ->
+ case {__ffi_static_ccall_unsafe ghc-internal:rintDouble :: Double#
+ -> State# RealWorld
+ -> (# State# RealWorld, Double# #)}
+ ds1 realWorld#
+ of
+ { (# _, ds3 #) ->
+ intToInt64# (double2Int# ds3)
+ }
+ })
+
+g = \ x ->
+ I64#
+ (case x of { D# ds1 ->
+ case {__ffi_static_ccall_unsafe ghc-internal:rintDouble :: Double#
+ -> State# RealWorld
+ -> (# State# RealWorld, Double# #)}
+ ds1 realWorld#
+ of
+ { (# _, ds3 #) ->
+ intToInt64# (double2Int# ds3)
+ }
+ })
+
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -295,6 +295,10 @@ test('T15631',
normal,
makefile_test, ['T15631'])
test('T15673', normal, compile, ['-O'])
+test('T16122', [when(wordsize(32), skip)],
+ multimod_compile_filter,
+ ['T16122', '-O -ddump-simpl -dsuppress-all -dsuppress-uniques -dno-typeable-binds',
+ "sed -n '/^f = /,/^$/p;/^g = /,/^$/p'"])
test('T16288', normal, multimod_compile, ['T16288B', '-O -dcore-lint -v0'])
test('T16348', normal, compile, ['-O'])
test('T16918', normal, compile, ['-O'])
=====================================
testsuite/tests/th/QQTopError.stderr
=====================================
@@ -1,10 +1,10 @@
QQTopError.hs:4:9: error: [GHC-83865]
- • Couldn't match expected type ‘GHC.Internal.TH.Quote.QuasiQuoter’
+ • Couldn't match expected type ‘GHC.Internal.TH.Monad.QuasiQuoter’
with actual type ‘a0 -> a0’
• Probable cause: ‘id’ is applied to too few arguments
- In the first argument of ‘GHC.Internal.TH.Quote.quoteExp’, namely
+ In the first argument of ‘GHC.Internal.TH.Monad.quoteExp’, namely
‘id’
- In the expression: GHC.Internal.TH.Quote.quoteExp id "hello"
+ In the expression: GHC.Internal.TH.Monad.quoteExp id "hello"
In the quasi-quotation: [id|hello|]
|
4 | main = [id|hello|]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/87ad1dd89d7380e229ac00e71c465a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/87ad1dd89d7380e229ac00e71c465a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/ani/kill-SrcCodeOrigin] fixes for error message diffs for RepPolyBinds etc.
by Apoorv Ingle (@ani) 10 Mar '26
by Apoorv Ingle (@ani) 10 Mar '26
10 Mar '26
Apoorv Ingle pushed to branch wip/ani/kill-SrcCodeOrigin at Glasgow Haskell Compiler / GHC
Commits:
c6f2ab89 by Apoorv Ingle at 2026-03-09T19:16:59-05:00
fixes for error message diffs for RepPolyBinds etc.
- - - - -
7 changed files:
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/Do.hs
- compiler/GHC/Tc/Types/ErrCtxt.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Zonk/TcType.hs
Changes:
=====================================
compiler/GHC/Hs/Expr.hs
=====================================
@@ -1064,7 +1064,7 @@ instance Outputable XXExprGhcRn where
pprCtxt (ExprCtxt e) = ppr_builder "<OrigExpr>:" (ppr e)
pprCtxt (StmtErrCtxt _ stmt) = ppr_builder "<OrigStmt>:" (ppr stmt)
pprCtxt (DoStmtErrCtxt _ stmt) = ppr_builder "<OrigStmt>:" (ppr stmt)
- pprCtxt (StmtErrCtxtPat _ _ pat) = ppr_builder "<OrigPat>:" (ppr pat)
+ pprCtxt (StmtErrCtxtPat pat) = ppr_builder "<OrigPat>:" (ppr pat)
pprCtxt (FunAppCtxt (FunAppCtxtExpr _ e) _) = ppr_builder "<FunAppCtxt>:" (ppr e)
pprCtxt _ = ppr_builder "<MiscErrCtxtMsg>:" empty
@@ -1081,7 +1081,7 @@ instance Outputable XXExprGhcTc where
pprCtxt (ExprCtxt e) = ppr_builder "<OrigExpr>:" (ppr e)
pprCtxt (StmtErrCtxt _ stmt) = ppr_builder "<OrigStmt>:" (ppr stmt)
pprCtxt (DoStmtErrCtxt _ stmt) = ppr_builder "<OrigStmt>:" (ppr stmt)
- pprCtxt (StmtErrCtxtPat _ _ pat) = ppr_builder "<OrigPat>:" (ppr pat)
+ pprCtxt (StmtErrCtxtPat pat) = ppr_builder "<OrigPat>:" (ppr pat)
pprCtxt (FunAppCtxt (FunAppCtxtExpr _ e) _) = ppr_builder "<FunAppCtxt>:" (ppr e)
pprCtxt _ = ppr_builder "<MiscErrCtxtMsg>:" empty
=====================================
compiler/GHC/HsToCore/Ticks.hs
=====================================
@@ -416,6 +416,8 @@ addTickLHsExpr e@(L pos e0) = do
case d of
TickForBreakPoints | isGoodBreakExpr e0 -> tick_it
TickForCoverage | XExpr (ExpandedThingTc StmtErrCtxt{} _) <- e0 -- expansion ticks are handled separately
+ -> dont_tick_it
+ | XExpr (ExpandedThingTc DoStmtErrCtxt{} _) <- e0 -- expansion ticks are handled separately
-> dont_tick_it
| otherwise -> tick_it
TickCallSites | isCallSite e0 -> tick_it
@@ -485,6 +487,7 @@ addTickLHsExprNever (L pos e0) = do
-- values) are good break points.
isGoodBreakExpr :: HsExpr GhcTc -> Bool
isGoodBreakExpr (XExpr (ExpandedThingTc (StmtErrCtxt{}) _)) = False
+isGoodBreakExpr (XExpr (ExpandedThingTc (DoStmtErrCtxt{}) _)) = False
isGoodBreakExpr e = isCallSite e
isCallSite :: HsExpr GhcTc -> Bool
=====================================
compiler/GHC/Tc/Errors/Ppr.hs
=====================================
@@ -7884,8 +7884,7 @@ pprErrCtxtMsg = \case
-> hang (text "In a stmt of" <+> pprAStmtContext ctxt <> colon)
2 (ppr_stmt (unLoc stmt))
- StmtErrCtxtPat _ _ pat ->
- hang (text "In the pattern:") 2 (ppr pat)
+ StmtErrCtxtPat{} -> empty
DerivInstCtxt pred ->
text "When deriving the instance for" <+> parens (ppr pred)
=====================================
compiler/GHC/Tc/Gen/Do.hs
=====================================
@@ -213,7 +213,7 @@ mk_fail_block doFlav pat stmt e (Just (SyntaxExprRn fail_op)) =
fail_op_expr :: DynFlags -> LPat GhcRn -> HsExpr GhcRn -> LHsExpr GhcRn
fail_op_expr dflags pat@(L pat_lspan _) fail_op
- = L pat_lspan $ mkExpandedPatRn doFlav pat stmt $ genHsApp fail_op (mk_fail_msg_expr dflags pat)
+ = L pat_lspan $ mkExpandedPatRn pat $ genHsApp fail_op (mk_fail_msg_expr dflags pat)
mk_fail_msg_expr :: DynFlags -> LPat GhcRn -> LHsExpr GhcRn
mk_fail_msg_expr dflags pat
@@ -481,7 +481,7 @@ It stores the original statement (with location) and the expanded expression
-}
-mkExpandedPatRn :: HsDoFlavour -> LPat GhcRn -> ExprLStmt GhcRn -> HsExpr GhcRn -> HsExpr GhcRn
-mkExpandedPatRn flav pat stmt e = XExpr $ ExpandedThingRn
- { xrn_orig = StmtErrCtxtPat (HsDoStmt flav) stmt pat
+mkExpandedPatRn :: LPat GhcRn -> HsExpr GhcRn -> HsExpr GhcRn
+mkExpandedPatRn pat e = XExpr $ ExpandedThingRn
+ { xrn_orig = StmtErrCtxtPat pat
, xrn_expanded = e}
=====================================
compiler/GHC/Tc/Types/ErrCtxt.hs
=====================================
@@ -340,7 +340,7 @@ data ErrCtxtMsg
| DoStmtErrCtxt !HsStmtContextRn !(ExprLStmt GhcRn)
-- | In patten of the do statement. (c.f. MonadFailErrors)
- | StmtErrCtxtPat !HsStmtContextRn !(ExprLStmt GhcRn) (LPat GhcRn)
+ | StmtErrCtxtPat (LPat GhcRn)
-- | In an rebindable syntax expression.
| SyntaxNameCtxt !(HsExpr GhcRn) !CtOrigin !TcType !SrcSpan
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -638,7 +638,7 @@ errCtxtCtOrigin (ExprCtxt e) = exprCtOrigin e
errCtxtCtOrigin (FunAppCtxt (FunAppCtxtExpr _ e) _) = exprCtOrigin e
errCtxtCtOrigin (StmtErrCtxt{}) = DoStmtOrigin
errCtxtCtOrigin (DoStmtErrCtxt{}) = DoStmtOrigin
-errCtxtCtOrigin (StmtErrCtxtPat _ _ p) = DoPatOrigin p
+errCtxtCtOrigin (StmtErrCtxtPat p) = DoPatOrigin p
errCtxtCtOrigin (RecordUpdCtxt{}) = RecordUpdOrigin
errCtxtCtOrigin _ = Shouldn'tHappenOrigin "errCtxtCtOrigin"
@@ -1484,11 +1484,11 @@ pprExpectedFunTyCtxt funTy_origin i =
case funTy_origin of
ExpectedFunTySyntaxOp orig op ->
vcat [ sep [ the_arg_of
- , text "the rebindable syntax operator"
+ , text "The rebindable syntax operator"
, quotes (ppr op) ]
, nest 2 (ppr orig) ]
ExpectedTySyntax orig arg ->
- vcat [ text "the expression" <+> quotes (ppr arg)
+ vcat [ text "The expression" <+> quotes (ppr arg)
, nest 2 (ppr orig) ]
ExpectedFunTyViewPat expr ->
vcat [ the_arg_of <+> text "the view pattern"
=====================================
compiler/GHC/Tc/Zonk/TcType.hs
=====================================
@@ -805,9 +805,6 @@ zonkTidyErrCtxtMsg env e@(ExprCtxt{}) = return (env, e)
zonkTidyErrCtxtMsg env (ThetaCtxt ctxt theta_ty) = do
(env', theta_ty') <- zonkTidyTcTypes env theta_ty
return $ (env', ThetaCtxt ctxt theta_ty')
--- zonkTidyErrCtxtMsg env (QuantifiedCtCtxt ty) = do
--- (env', ty') <- zonkTidyTcTypes env ty
--- return $ QuantifiedCtCtxt ty'
zonkTidyErrCtxtMsg env (InferredTypeCtxt n ty) = do
(env', ty') <- zonkTidyTcType env ty
return $ (env', InferredTypeCtxt n ty')
@@ -826,4 +823,7 @@ zonkTidyErrCtxtMsg env (FunResCtxt e i1 ty1 ty2 i2 i3) = do
(env', ty1') <- zonkTidyTcType env ty1
(env', ty2') <- zonkTidyTcType env' ty2
return $ (env', FunResCtxt e i1 ty1' ty2' i2 i3)
+-- zonkTidyErrCtxtMsg env (PatSigErrCtxt sig_ty res_ty) = do
+-- (env', sig_ty) <- zonkTidyTcType env sig_ty
+-- (env', res_ty) <- zonkZidy
zonkTidyErrCtxtMsg env p = return (env, p)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c6f2ab89a300c9756352e360bb8f361…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c6f2ab89a300c9756352e360bb8f361…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Simon Peyton Jones pushed new branch wip/T13867 at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/T13867
You're receiving this email because of your account on gitlab.haskell.org.
1
0