Rodrigo Mesquita pushed to branch wip/romes/25636 at Glasgow Haskell Compiler / GHC
Commits:
5a089abc by Rodrigo Mesquita at 2025-12-19T18:01:51+00:00
101%
- - - - -
3 changed files:
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/Cmm/Liveness.hs
- libraries/ghci/GHCi/CreateBCO.hs
Changes:
=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -3948,7 +3948,7 @@ primop NewBCOOp "newBCO#" GenPrimOp
out_of_line = True
primop NewConAppObjOp "newConAppObj#" GenPrimOp
- Addr# -> ByteArray# -> Array# a -> Word# -> State# s -> (# State# s, a #)
+ Addr# -> ByteArray# -> Array# a -> Word# -> State# s -> (# State# s, b #)
{ @'newConAppObj#' datacon_itbl lits ptrs arity@ creates a new constructor
application object on the heap from the info table pointer of the data
constructor and the data arguments given in @ptrs@ and @lits@. The
=====================================
compiler/GHC/Cmm/Liveness.hs
=====================================
@@ -65,7 +65,7 @@ cmmGlobalLiveness platform graph =
-- | On entry to the procedure, there had better not be any LocalReg's live-in.
-- If you see this error it most likely means you are trying to use a variable
--- without it being defined in the given scope.
+-- without it being defined, or initialized, in the given scope.
noLiveOnEntry :: BlockId -> CmmLive LocalReg -> a -> a
noLiveOnEntry bid in_fact x =
if nullRegSet in_fact then x
=====================================
libraries/ghci/GHCi/CreateBCO.hs
=====================================
@@ -20,7 +20,6 @@ import Prelude -- See note [Why do we import Prelude here?]
import GHCi.ResolvedBCO
import GHCi.RemoteTypes
import GHCi.BreakArray
-import GHCi.InfoTable
import GHC.Data.SizedSeq
import System.IO (fixIO)
@@ -33,8 +32,6 @@ import GHC.Exts hiding ( BCO, mkApUpd0#, newBCO# )
import GHC.Internal.Base ( BCO, mkApUpd0#, newBCO# )
import GHC.IO
import Control.Exception ( ErrorCall(..) )
-import Data.Kind
-import Data.Maybe
createBCOs :: [ResolvedBCO] -> IO [HValueRef]
createBCOs bcos = do
@@ -54,7 +51,7 @@ createBCO _ obj | resolvedBCOIsLE obj /= isLittleEndian
createBCO arr bco
= do linked_thing <- linkBCO' arr bco
case linked_thing of
- Left linked_bco -> do
+ LinkedBCO bco_arity linked_bco -> do
-- Note [Updatable CAF BCOs]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~
-- Why do we need mkApUpd0 here? Otherwise top-level
@@ -70,14 +67,18 @@ createBCO arr bco
-- non-zero arity BCOs in an AP thunk.
--
-- See #17424.
- if (resolvedBCOArity bco > 0)
+ if (bco_arity > 0)
then return (HValue (unsafeCoerce linked_bco))
else case mkApUpd0# linked_bco of { (# final_bco #) ->
return (HValue final_bco) }
- Right linked_static_con -> do
+ LinkedStaticCon linked_static_con -> do
return linked_static_con
-linkBCO' :: Array Int HValue -> ResolvedBCO -> IO (Either BCO HValue)
+data LinkedBCO
+ = LinkedBCO !Int{-BCO arity-} BCO
+ | LinkedStaticCon HValue
+
+linkBCO' :: Array Int HValue -> ResolvedBCO -> IO LinkedBCO
linkBCO' arr resolved_obj =
case resolved_obj of
ResolvedBCO{..} -> do
@@ -94,7 +95,8 @@ linkBCO' arr resolved_obj =
PtrsArr marr <- mkPtrsArray arr n_ptrs ptrs
IO $ \s ->
case unsafeFreezeArray# marr s of { (# s, arr #) ->
- case Left <$> newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->
+ case LinkedBCO resolvedBCOArity <$>
+ newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->
io s
}}
ResolvedStaticCon{..} -> do
@@ -114,7 +116,7 @@ linkBCO' arr resolved_obj =
IO $ \s ->
case unsafeFreezeArray# marr s of { (# s, arr #) ->
case newConAppObj# itbl_ptr# literals_barr arr data_size# s of
- (# s, hval #) -> (# s, Right (HValue hval) #)
+ (# s, hval #) -> (# s, LinkedStaticCon (HValue hval) #)
}
where
!(EmptyArr empty#) = emptyArr -- See Note [BCO empty array]
@@ -141,9 +143,9 @@ mkPtrsArray arr n_ptrs ptrs = do
fill (ResolvedBCOPtrBCO bco) i = do
obj <- linkBCO' arr bco
case obj of
- Left bco ->
+ LinkedBCO _ bco ->
writePtrsArrayBCO i bco marr
- Right !linked_static_con ->
+ LinkedStaticCon !linked_static_con ->
writePtrsArrayHValue i linked_static_con marr
fill (ResolvedBCOPtrBreakArray r) i = do
BA mba <- localRef r
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5a089abcf76f3724da794eaa4a79b2b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5a089abcf76f3724da794eaa4a79b2b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Rodrigo Mesquita pushed to branch wip/romes/25636 at Glasgow Haskell Compiler / GHC
Commits:
0018ec46 by Rodrigo Mesquita at 2025-12-19T18:00:31+00:00
101%
- - - - -
3 changed files:
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/Cmm/Liveness.hs
- libraries/ghci/GHCi/CreateBCO.hs
Changes:
=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -3948,7 +3948,7 @@ primop NewBCOOp "newBCO#" GenPrimOp
out_of_line = True
primop NewConAppObjOp "newConAppObj#" GenPrimOp
- Addr# -> ByteArray# -> Array# a -> Word# -> State# s -> (# State# s, a #)
+ Addr# -> ByteArray# -> Array# a -> Word# -> State# s -> (# State# s, b #)
{ @'newConAppObj#' datacon_itbl lits ptrs arity@ creates a new constructor
application object on the heap from the info table pointer of the data
constructor and the data arguments given in @ptrs@ and @lits@. The
=====================================
compiler/GHC/Cmm/Liveness.hs
=====================================
@@ -65,7 +65,7 @@ cmmGlobalLiveness platform graph =
-- | On entry to the procedure, there had better not be any LocalReg's live-in.
-- If you see this error it most likely means you are trying to use a variable
--- without it being defined in the given scope.
+-- without it being defined, or initialized, in the given scope.
noLiveOnEntry :: BlockId -> CmmLive LocalReg -> a -> a
noLiveOnEntry bid in_fact x =
if nullRegSet in_fact then x
=====================================
libraries/ghci/GHCi/CreateBCO.hs
=====================================
@@ -20,7 +20,6 @@ import Prelude -- See note [Why do we import Prelude here?]
import GHCi.ResolvedBCO
import GHCi.RemoteTypes
import GHCi.BreakArray
-import GHCi.InfoTable
import GHC.Data.SizedSeq
import System.IO (fixIO)
@@ -33,8 +32,6 @@ import GHC.Exts hiding ( BCO, mkApUpd0#, newBCO# )
import GHC.Internal.Base ( BCO, mkApUpd0#, newBCO# )
import GHC.IO
import Control.Exception ( ErrorCall(..) )
-import Data.Kind
-import Data.Maybe
createBCOs :: [ResolvedBCO] -> IO [HValueRef]
createBCOs bcos = do
@@ -54,7 +51,7 @@ createBCO _ obj | resolvedBCOIsLE obj /= isLittleEndian
createBCO arr bco
= do linked_thing <- linkBCO' arr bco
case linked_thing of
- Left linked_bco -> do
+ LinkedBCO bco_arity linked_bco -> do
-- Note [Updatable CAF BCOs]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~
-- Why do we need mkApUpd0 here? Otherwise top-level
@@ -70,14 +67,18 @@ createBCO arr bco
-- non-zero arity BCOs in an AP thunk.
--
-- See #17424.
- if (resolvedBCOArity bco > 0)
+ if (bco_arity > 0)
then return (HValue (unsafeCoerce linked_bco))
else case mkApUpd0# linked_bco of { (# final_bco #) ->
return (HValue final_bco) }
- Right linked_static_con -> do
+ LinkedStaticCon linked_static_con -> do
return linked_static_con
-linkBCO' :: Array Int HValue -> ResolvedBCO -> IO (Either BCO HValue)
+data LinkedBCO
+ = LinkedBCO !Int{-BCO arity-} BCO
+ | LinkedStaticCon HValue
+
+linkBCO' :: Array Int HValue -> ResolvedBCO -> IO LinkedBCO
linkBCO' arr resolved_obj =
case resolved_obj of
ResolvedBCO{..} -> do
@@ -94,7 +95,8 @@ linkBCO' arr resolved_obj =
PtrsArr marr <- mkPtrsArray arr n_ptrs ptrs
IO $ \s ->
case unsafeFreezeArray# marr s of { (# s, arr #) ->
- case Left <$> newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->
+ case LinkedBCO resolvedBCOArity <$>
+ newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->
io s
}}
ResolvedStaticCon{..} -> do
@@ -114,7 +116,7 @@ linkBCO' arr resolved_obj =
IO $ \s ->
case unsafeFreezeArray# marr s of { (# s, arr #) ->
case newConAppObj# itbl_ptr# literals_barr arr data_size# s of
- (# s, hval #) -> (# s, Right (HValue hval) #)
+ (# s, hval #) -> (# s, LinkedStaticCon (HValue hval) #)
}
where
!(EmptyArr empty#) = emptyArr -- See Note [BCO empty array]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0018ec46e901cdbc381196bca5b946e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0018ec46e901cdbc381196bca5b946e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/25636] 67 commits: Build external interpreter program on demand (#24731)
by Rodrigo Mesquita (@alt-romes) 19 Dec '25
by Rodrigo Mesquita (@alt-romes) 19 Dec '25
19 Dec '25
Rodrigo Mesquita pushed to branch wip/romes/25636 at Glasgow Haskell Compiler / GHC
Commits:
55eab80d by Sylvain Henry at 2025-11-20T17:33:13-05:00
Build external interpreter program on demand (#24731)
This patch teaches GHC how to build the external interpreter program
when it is missing. As long as we have the `ghci` library, doing this is
trivial so most of this patch is refactoring for doing it sanely.
- - - - -
08bbc028 by Rodrigo Mesquita at 2025-11-20T17:33:54-05:00
Add tests for #23973 and #26565
These were fixed by 4af4f0f070f83f948e49ad5d7835fd91b8d3f0e6 in !10417
- - - - -
6b42232c by sheaf at 2025-11-20T17:34:35-05:00
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.
- - - - -
b7b7c049 by Andrew Lelechenko at 2025-11-21T21:04:01+00:00
Add nubOrd / nubOrdBy to Data.List and Data.List.NonEmpty
As per https://github.com/haskell/core-libraries-committee/issues/336
- - - - -
352d5462 by Marc Scholten at 2025-11-22T10:33:03-05:00
Fix haddock test runner to handle UTF-8 output
xhtml 3000.4.0.0 now produces UTF-8 output instead of escaping non-ASCII characters.
When using --test-accept it previously wrote files in the wrong encoding
because they have not been decoded properly when reading the files.
- - - - -
48a3ed57 by Simon Peyton Jones at 2025-11-25T15:33:54+00:00
Add a fast-path for args=[] to occAnalApp
In the common case of having not arguments, occAnalApp
was doing redundant work.
- - - - -
951e5ed9 by Simon Peyton Jones at 2025-11-25T15:33:54+00:00
Fix a performance hole in the occurrence analyser
As #26425 showed, the clever stuff in
Note [Occurrence analysis for join points]
does a lot of duplication of usage details. This patch
improved matters with a little fancy footwork. It is
described in the new (W4) of the same Note.
Compile-time allocations go down slightly. Here are the changes
of +/- 0.5% or more:
T13253(normal) 329,369,244 326,395,544 -0.9%
T13253-spj(normal) 66,410,496 66,095,864 -0.5%
T15630(normal) 129,797,200 128,663,136 -0.9%
T15630a(normal) 129,212,408 128,027,560 -0.9%
T16577(normal) 6,756,706,896 6,723,028,512 -0.5%
T18282(normal) 128,462,070 125,808,584 -2.1% GOOD
T18698a(normal) 208,418,305 202,037,336 -3.1% GOOD
T18730(optasm) 136,981,756 136,208,136 -0.6%
T18923(normal) 58,103,088 57,745,840 -0.6%
T19695(normal) 1,386,306,272 1,365,609,416 -1.5%
T26425(normal) 3,344,402,957 2,457,811,664 -26.5% GOOD
T6048(optasm) 79,763,816 79,212,760 -0.7%
T9020(optasm) 225,278,408 223,682,440 -0.7%
T9961(normal) 303,810,717 300,729,168 -1.0% GOOD
geo. mean -0.5%
minimum -26.5%
maximum +0.4%
Metric Decrease:
T18282
T18698a
T26425
T9961
- - - - -
f1959dfc by Simon Peyton Jones at 2025-11-26T11:58:07+00:00
Remove a quadratic-cost assertion check in mkCoreApp
See the new Note [Assertion checking in mkCoreApp]
- - - - -
98fa0d36 by Simon Hengel at 2025-11-27T17:54:57-05:00
Fix typo in docs/users_guide/exts/type_families.rst
- - - - -
5b97e5ce by Simon Hengel at 2025-11-27T17:55:37-05:00
Fix broken RankNTypes example in user's guide
- - - - -
fa2aaa00 by Simon Peyton Jones at 2025-11-27T17:56:18-05:00
Switch off specialisation in ExactPrint
In !15057 (where we re-introduced -fpolymoprhic-specialisation) we found
that ExactPrint's compile time blew up by a factor of 5. It turned out
to be caused by bazillions of specialisations of `markAnnotated`.
Since ExactPrint isn't perf-critical, it does not seem worth taking
the performance hit, so this patch switches off specialisation in
this one module.
- - - - -
1fd25987 by Simon Peyton Jones at 2025-11-27T17:56:18-05:00
Switch -fpolymorphic-specialisation on by default
This patch addresses #23559.
Now that !10479 has landed and #26329 is fixed, we can switch on
polymorphic specialisation by default, addressing a bunch of other
tickets listed in #23559.
Metric changes:
* CoOpt_Singleton: +4% compiler allocations: we just get more
specialisations
* info_table_map_perf: -20% decrease in compiler allocations.
This is caused by using -fno-specialise in ExactPrint.hs
Without that change we get a 4x blow-up in compile time;
see !15058 for details
Metric Decrease:
info_table_map_perf
Metric Increase:
CoOpt_Singletons
- - - - -
b7fe7445 by Matthew Pickering at 2025-11-27T17:56:59-05:00
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
- - - - -
1d4a1229 by sheaf at 2025-11-27T17:58:02-05:00
SimpleOpt: don't subst in pushCoercionIntoLambda
It was noticed in #26589 that the change in 15b311be was incorrect:
the simple optimiser carries two different substitution-like pieces of
information: 'soe_subst' (from InVar to OutExpr) and 'soe_inl'
(from InId to InExpr). It is thus incorrect to have 'pushCoercionIntoLambda'
apply the substitution from 'soe_subst' while discarding 'soe_inl'
entirely, which is what was done in 15b311be.
Instead, we change back pushCoercionIntoLambda to take an InScopeSet,
and optimise the lambda before calling 'pushCoercionIntoLambda' to avoid
mixing InExpr with OutExpr, or mixing two InExpr with different
environments. We can then call 'soeZapSubst' without problems.
Fixes #26588 #26589
- - - - -
84a087d5 by Sylvain Henry at 2025-11-28T17:35:28-05:00
Fix PIC jump tables on Windows (#24016)
Avoid overflows in jump tables by using a base label closer to the jump
targets. See added Note [Jump tables]
- - - - -
82db7042 by Zubin Duggal at 2025-11-28T17:36:10-05:00
rts/linker/PEi386: Copy strings before they are inserted into LoadedDllCache. The original strings are temporary and might be freed at an arbitrary point.
Fixes #26613
- - - - -
ff3f0d09 by Ben Gamari at 2025-11-29T18:34:28-05:00
gitlab-ci: Run ghcup-metadata jobs on OpenCape runners
This significantly reduces our egress traffic
and makes the jobs significantly faster.
- - - - -
ef0dc33b by Matthew Pickering at 2025-11-29T18:35:10-05:00
Use 'OsPath' in getModificationTimeIfExists
This part of the compiler is quite hot during recompilation checking in
particular since the filepaths will be translated to a string. It is
better to use the 'OsPath' native function, which turns out to be easy
to do.
- - - - -
fa3bd0a6 by Georgios Karachalias at 2025-11-29T18:36:05-05:00
Use OsPath in PkgDbRef and UnitDatabase, not FilePath
- - - - -
0d7c05ec by Ben Gamari at 2025-12-01T03:13:46-05:00
hadrian: Place user options after package arguments
This makes it easier for the user to override the default package
arguments with `UserSettings.hs`.
Fixes #25821.
-------------------------
Metric Decrease:
T14697
-------------------------
- - - - -
3b2c4598 by Vladislav Zavialov at 2025-12-01T03:14:29-05:00
Namespace-specified wildcards in import/export lists (#25901)
This change adds support for top-level namespace-specified wildcards
`type ..` and `data ..` to import and export lists.
Examples:
import M (type ..) -- imports all type and class constructors from M
import M (data ..) -- imports all data constructors and terms from M
module M (type .., f) where
-- exports all type and class constructors defined in M,
-- plus the function 'f'
The primary intended usage of this feature is in combination with module
aliases, allowing namespace disambiguation:
import Data.Proxy as T (type ..) -- T.Proxy is unambiguously the type constructor
import Data.Proxy as D (data ..) -- D.Proxy is unambiguously the data constructor
The patch accounts for the interactions of wildcards with:
* Imports with `hiding` clauses
* Import warnings -Wunused-imports, -Wdodgy-imports
* Export warnings -Wduplicate-exports, -Wdodgy-exports
Summary of the changes:
1. Move the NamespaceSpecifier type from GHC.Hs.Binds to GHC.Hs.Basic,
making it possible to use it in more places in the AST.
2. Extend the AST (type: IE) with a representation of `..`, `type ..`,
and `data ..` (constructor: IEWholeNamespace). Per the proposal, the
plain `..` is always rejected with a dedicated error message.
3. Extend the grammar in Parser.y with productions for `..`, `type ..`,
and `data ..` in both import and export lists.
4. Implement wildcard imports by updating the `filterImports` function
in GHC.Rename.Names; the logic for IEWholeNamespace is roughly
modeled after the Nothing (no explicit import list) case.
5. Implement wildcard exports by updating the `exports_from_avail`
function in GHC.Tc.Gen.Export; the logic for IEWholeNamespace is
closely modeled after the IEModuleContents case.
6. Refactor and extend diagnostics to report the new warnings and
errors. See PsErrPlainWildcardImport, DodgyImportsWildcard,
PsErrPlainWildcardExport, DodgyExportsWildcard,
TcRnDupeWildcardExport.
Note that this patch is specifically about top-level import/export
items. Subordinate import/export items are left unchanged.
- - - - -
c71faa76 by Luite Stegeman at 2025-12-01T03:16:05-05:00
rts: Handle overflow of ELF section header string table
If the section header string table is stored in a section greater
than or equal to SHN_LORESERVE (0xff00), the 16-bit field e_shstrndx
in the ELF header does not contain the section number, but rather
an overflow value SHN_XINDEX (0xffff) indicating that we need to look
elsewhere.
This fixes the linker by not using e_shstrndx directly but calling
elf_shstrndx, which correctly handles the SHN_XINDEX value.
Fixes #26603
- - - - -
ab20eb54 by Mike Pilgrem at 2025-12-01T22:46:55+00:00
Re CLC issue 292 Warn GHC.Internal.List.{init,last} are partial
Also corrects the warning for `tail` to refer to `Data.List.uncons` (like the existing warning for `head`).
In module `Settings.Warnings`, applies `-Wno-x-partial` to the `filepath`, and `parsec` packages (outside GHC's repository).
Also bumps submodules.
- - - - -
fc1d7f79 by Jade Lovelace at 2025-12-02T11:04:09-05:00
docs: fix StandaloneKindSignatures in DataKinds docs
These should be `type` as otherwise GHC reports a duplicate definition
error.
- - - - -
beae879b by Rodrigo Mesquita at 2025-12-03T15:42:37+01:00
task: Substitute some datatypes for newtypes
* Substitutes some data type declarations for newtype declarations
* Adds comment to `LlvmConfigCache`, which must decidedly not be a
newtype.
Fixes #23555
- - - - -
3bd7dd44 by mangoiv at 2025-12-04T04:36:45-05:00
Renamer: reinstate the template haskell level check in notFound
Out-of-scope names might be caused by a staging error, as is explained by
Note [Out of scope might be a staging error] in GHC.Tc.Utils.Env.hs.
This logic was assumed to be dead code after 217caad1 and has thus been
removed. This commit reintroduces it and thus fixes issue #26099.
- - - - -
0318010b by Zubin Duggal at 2025-12-04T04:37:27-05:00
testlib: Optionally include the way name in the expected output file
This allows us to have different outputs for different ways.
- - - - -
6d945fdd by Zubin Duggal at 2025-12-04T04:37:27-05:00
testsuite: Accept output of tests failing in ext-interp way due to differing compilation requirements
Fixes #26552
- - - - -
0ffc5243 by Cheng Shao at 2025-12-04T04:38:09-05:00
devx: minor fixes for compile_flags.txt
This patch includes minor fixes for compile_flags.txt to improve
developer experience when using clangd as language server to hack on
RTS C sources:
- Ensure `-fPIC` is passed and `__PIC__` is defined, to be coherent
with `-DDYNAMIC` and ensure the `__PIC__` guarded code paths are
indexed
- Add the missing `-DRtsWay` definition, otherwise a few source files
like `RtsUtils.c` and `Trace.c` would produce clangd errors
- - - - -
e36a5fcb by Matthew Pickering at 2025-12-05T16:25:57-05:00
Add support for building bytecode libraries
A bytecode library is a collection of bytecode files (.gbc) and a
library which combines together additional object files.
A bytecode library is created by invoking GHC with the `-bytecodelib`
flag.
A library can be created from in-memory `ModuleByteCode` linkables or
by passing `.gbc` files as arguments on the command line.
Fixes #26298
- - - - -
8f9ae339 by Matthew Pickering at 2025-12-05T16:25:57-05:00
Load bytecode libraries to satisfy package dependencies
This commit allows you to use a bytecode library to satisfy a package
dependency when using the interpreter.
If a user enables `-fprefer-byte-code`, then if a package provides a
bytecode library, that will be loaded and used to satisfy the
dependency.
The main change is to separate the relevant parts of the `LoaderState`
into external and home package byte code. Bytecode is loaded into either
the home package or external part (similar to HPT/EPS split), HPT
bytecode can be unloaded. External bytecode is never unloaded.
The unload function has also only been called with an empty list of
"stable linkables" for a long time. It has been modified to directly
implement a complete unloading of the home package bytecode linkables.
At the moment, the bytecode libraries are found in the "library-dirs"
field from the package description. In the future when `Cabal`
implements support for "bytecode-library-dirs" field, we can read the
bytecode libraries from there. No changes to the Cabal submodule are
necessary at the moment.
Four new tests are added in testsuite/tests/cabal, which generate fake
package descriptions and test loading the libraries into GHCi.
Fixes #26298
- - - - -
54458ce4 by mangoiv at 2025-12-05T16:26:50-05:00
ExplicitLevelImports: improve documentation of the code
- more explicit names for variable names like `flg` or `topLevel`
- don't pass the same value twice to functions
- some explanations of interesting but undocumented code paths
- adjust comment to not mention non-existent error message
- - - - -
c7061392 by mangoiv at 2025-12-05T16:27:42-05:00
driver: don't expect nodes to exist when checking paths between them
In `mgQueryZero`, previously node lookups were expected to never fail,
i.e. it was expected that when calculating the path between two nodes in
a zero level import graph, both nodes would always exist. This is not
the case, e.g. in some situations involving exact names (see the
test-case). The fix is to first check whether the node is present in the
graph at all, instead of panicking, just to report that there is no
path.
Closes #26568
- - - - -
d6cf8463 by Peng Fan at 2025-12-06T11:06:28-05:00
NCG/LA64: Simplify genCCall into two parts
genCCall is too long, so it's been simplified into two parts:
genPrim and genLibCCall.
Suggested by Andreas Klebinger
- - - - -
9d371d23 by Matthew Pickering at 2025-12-06T11:07:09-05:00
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
- - - - -
0043bfb0 by Marc Scholten at 2025-12-06T11:08:03-05:00
update xhtml to 3000.4.0.0
haddock-api: bump xhtml bounds
haddock-api: use lazy text instead of string to support xhtml 3000.4.0.0
Bumping submodule xhtml to 3000.4.0.0
add xhtml to stage0Packages
remove unused import of writeUtf8File
Remove redundant import
Update haddock golden files for xhtml 3000.4.0.0
Metric Decrease:
haddock.Cabal
haddock.base
- - - - -
fc958fc9 by Julian Ospald at 2025-12-06T11:08:53-05:00
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.
- - - - -
0f297f6e by mangoiv at 2025-12-06T11:09:44-05:00
users' guide: don't use f strings in the python script to ensure compatibility with python 3.5
- - - - -
3bfe7aa2 by Matthew Pickering at 2025-12-07T12:18:57-05:00
ci: Try using multi repl in ghc-in-ghci test
This should be quite a bit faster than the ./hadrian/ghci command as it
doesn't properly build all the dependencies.
- - - - -
2ef1601a by Rodrigo Mesquita at 2025-12-07T12:19:38-05:00
Stack.Decode: Don't error on bitmap size 0
A RET_BCO may have a bitmap with no payload.
In that case, the bitmap = 0.
One can observe this by using -ddump-bcos and interpreting
```
main = pure ()
```
Observe, for instance, that the BCO for this main function has size 0:
```
ProtoBCO Main.main#0:
\u []
break<main:Main,0>() GHC.Internal.Base.pure
GHC.Internal.Base.$fApplicativeIO GHC.Internal.Tuple.()
bitmap: 0 []
BRK_FUN <breakarray> main:Main 0 <cc>
PACK () 0
PUSH_G GHC.Internal.Base.$fApplicativeIO
PUSH_APPLY_PP
PUSH_G GHC.Internal.Base.pure
ENTER
```
Perhaps we never tried to decode a stack in which a BCO like this was
present. However, for the debugger, we want to decode stacks of threads
stopped at breakpoints, and these kind of BCOs do get on a stack under
e.g. `stg_apply_interp_info` frames.
See the accompanying test in the next commit for an example to trigger
the bug this commit fixes.
Fixes #26640
- - - - -
747153d2 by Rodrigo Mesquita at 2025-12-07T12:19:38-05:00
Add test for #26640
- - - - -
d4b1e353 by Simon Hengel at 2025-12-10T00:00:02-05:00
Fix syntax error in gadt_syntax.rst
- - - - -
91cc8be6 by Cheng Shao at 2025-12-10T00:00:43-05:00
ci: fix "ci.sh clean" to address frequent out of space error on windows runners
This patch fixes the `ci.sh clean` logic to address frequent out of
space error on windows runners; previously it didn't clean up the
inplace mingw blobs, which is the largest source of space leak on
windows runners. See added comment for detailed explanation.
- - - - -
fe2b79f4 by Recursion Ninja at 2025-12-10T08:34:18-05:00
Narrow before optimising MUL/DIV/REM into shifts
The MUL/DIV/REM operations can be optimised into shifts when one of the
operands is a constant power of 2. However, as literals in Cmm are
stored as 'Integer', for this to be correct we first need to narrow the
literal to the appropriate width before checking whether the literal is
a power of 2.
Fixes #25664
- - - - -
06c2349c by Recursion Ninja at 2025-12-10T08:34:58-05:00
Decouple 'Language.Haskell.Syntax.Type' from 'GHC.Utils.Panic'
- Remove the *original* defintion of 'hsQTvExplicit' defined within 'Language.Haskell.Syntax.Type'
- Redefine 'hsQTvExplicit' as 'hsq_explicit' specialized to 'GhcPass' exported by 'GHC.Utils.Panic'
- Define 'hsQTvExplicitBinders' as 'hsq_explicit' specialized to 'DocNameI' exported by 'Haddock.GhcUtils'.
- Replace all call sites of the original 'hsQTvExplicit' definition with either:
1. 'hsQTvExplicit' updated definition
2. 'hsQTvExplicitBinders'
All call sites never entered the 'XLHsQTyVars' constructor branch, but a call to 'panic' existed on this code path because the type system was not strong enought to guarantee that the 'XLHsQTyVars' construction was impossible.
These two specialized functions provide the type system with enough information to make that guarantee, and hence the dependancy on 'panic' can be removed.
- - - - -
ac0815d5 by sheaf at 2025-12-10T23:39:57-05:00
Quantify arg before mult in function arrows
As noted in #23764, we expect quantification order to be left-to-right,
so that in a type such as
a %m -> b
the inferred quantification order should be [a, m, b] and not [m, a, b].
This was addressed in commit d31fbf6c, but that commit failed to update
some other functions such as GHC.Core.TyCo.FVs.tyCoFVsOfType.
This affects Haddock, as whether we print an explicit forall or not
depends on whether the inferred quantification order matches the actual
quantification order.
- - - - -
2caf796e by sheaf at 2025-12-10T23:39:57-05:00
Haddock: improvements to ty-var quantification
This commit makes several improvements to how Haddock deals with the
quantification of type variables:
1. In pattern synonyms, Haddock used to jumble up universal and
existential quantification. That is now fixed, fixing #26252.
Tested in the 'PatternSyns2' haddock-html test.
2. The logic for computing whether to use an explicit kind annotation
for a type variable quantified in a forall was not even wrong.
This commit improves the heuristic, but it will always remain an
imperfect heuristic (lest we actually run kind inference again).
In the future (#26271), we hope to avoid reliance on this heuristic.
- - - - -
b14bdd59 by Teo Camarasu at 2025-12-10T23:40:38-05:00
Add explicit export list to GHC.Num
Let's make clear what this module exports to allow us to easily deprecate and remove some of these in the future. Resolves https://gitlab.haskell.org/ghc/ghc/-/issues/26625
- - - - -
d99f8326 by Cheng Shao at 2025-12-11T19:14:18-05:00
compiler: remove unused CPP code in foreign stub
This patch removes unused CPP code in the generated foreign stub:
- `#define IN_STG_CODE 0` is not needed, since `Rts.h` already
includes this definition
- The `if defined(__cplusplus)` code paths are not needed in the `.c`
file, since we don't generate C++ stubs and don't include C++
headers in our stubs. But it still needs to be present in the `.h`
header since it might be later included into C++ source files.
- - - - -
46c9746f by Cheng Shao at 2025-12-11T19:14:57-05:00
configure: bump LlvmMaxVersion to 22
This commit bumps LlvmMaxVersion to 22; 21.x releases have been
available since Aug 26th, 2025 and there's no regressions with 21.x so
far. This bump is also required for updating fedora image to 43.
- - - - -
96fce8d0 by Cheng Shao at 2025-12-12T01:17:51+01:00
hadrian: add support for building with UndefinedBehaviorSanitizer
This patch adds a +ubsan flavour transformer to hadrian to build all
stage1+ C/C++ code with UndefinedBehaviorSanitizer. This is
particularly useful to catch potential undefined behavior in the RTS
codebase.
- - - - -
f7a06d8c by Cheng Shao at 2025-12-12T01:17:51+01:00
ci: update alpine/fedora & add ubsan job
This patch updates alpine image to 3.23, fedora image to 43, and adds
a `x86_64-linux-fedora43-validate+debug_info+ubsan` job that's run in
validate/nightly pipelines to catch undefined behavior in the RTS
codebase.
- - - - -
2ccd11ca by Cheng Shao at 2025-12-12T01:17:51+01:00
rts: fix zero-length VLA undefined behavior in interpretBCO
This commit fixes a zero-length VLA undefined behavior in interpretBCO, caught by UBSan:
```
+rts/Interpreter.c:3133:19: runtime variable length array bound evaluates to non-positive value 0
```
- - - - -
4156ed19 by Cheng Shao at 2025-12-12T01:17:51+01:00
rts: fix unaligned ReadSpB in interpretBCO
This commit fixes unaligned ReadSpB in interpretBCO, caught by UBSan:
```
+rts/Interpreter.c:2174:64: runtime load of misaligned address 0x004202059dd1 for type 'StgWord', which requires 8 byte alignment
```
To perform proper unaligned read, we define StgUnalignedWord as a type
alias of StgWord with aligned(1) attribute, and load StgUnalignedWord
instead of StgWord in ReadSpB, so the C compiler is aware that we're
not loading with natural alignment.
- - - - -
fef89fb9 by Cheng Shao at 2025-12-12T01:17:51+01:00
rts: fix signed integer overflow in subword arithmetic in interpretBCO
This commit fixes signed integer overflow in subword arithmetic in
interpretBCO, see added note for detailed explanation.
- - - - -
3c001377 by Cheng Shao at 2025-12-13T05:03:15-05:00
ci: use treeless fetch for perf notes
This patch improves the ci logic for fetching perf notes by using
treeless fetch
(https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-…)
to avoid downloading all blobs of the perf notes repo at once, and
only fetch the actually required blobs on-demand when needed. This
makes the initial `test-metrics.sh pull` operation much faster, and
also more robust, since we are seeing an increasing rate of 504 errors
in CI when fetching all perf notes at once, which is a major source of
CI flakiness at this point.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
123a8d77 by Peter Trommler at 2025-12-13T05:03:57-05:00
Cmm: remove restriction in MachOp folding
- - - - -
0b54b5fd by Andreas Klebinger at 2025-12-13T05:04:38-05:00
Remove explicit Typeable deriviations.
- - - - -
08b13f7b by Cheng Shao at 2025-12-13T05:05:18-05:00
ci: set gc.auto=0 during setup stage
This patch sets `gc.auto=0` during `setup` stage of CI, see added
comment for detailed explanation.
- - - - -
3b5aecb5 by Ben Gamari at 2025-12-13T23:43:10+01:00
Bump exceptions submodule to 0.10.11
- - - - -
c32de3b0 by Johan Förberg at 2025-12-15T02:36:03-05:00
base: Define Semigroup and Monoid instances for lazy ST
CLC proposal:
https://github.com/haskell/core-libraries-committee/issues/374
Fixes #26581
- - - - -
4f8b660c by mangoiv at 2025-12-15T02:37:05-05:00
ci: do not require nightly cabal-reinstall job to succeed
- - - - -
c7cdf15c by Rodrigo Mesquita at 2025-12-19T14:42:02+00:00
Add test for #25636
The existing test behaviour of "T23146_liftedeq" changed because the
simplifier now does a bit more inlining. We can restore the previous bad
behavior by using an OPAQUE pragma.
This test doubles as a test for #25636 when run in ghci, so we add it as
such.
- - - - -
8a2cd31f by Rodrigo Mesquita at 2025-12-19T14:42:02+00:00
refactor: protoBCOName is always a Name
Simplifies the code by removing the unnecessary type argument to
ProtoBCO which was always 'Name'
- - - - -
561abc86 by Rodrigo Mesquita at 2025-12-19T14:44:05+00:00
90%
+5%
No such StaticConObj needed
X
- - - - -
0edbe9de by Rodrigo Mesquita at 2025-12-19T15:03:56+00:00
X
- - - - -
c3f6b435 by Rodrigo Mesquita at 2025-12-19T17:47:46+00:00
100% compiled; now the running...
- - - - -
354 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .gitlab/rel_eng/fetch-gitlab-artifacts/fetch_gitlab.py
- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- .gitlab/test-metrics.sh
- compile_flags.txt
- compiler/GHC.hs
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Cmm/Opt.hs
- compiler/GHC/CmmToAsm/AArch64/RegInfo.hs
- compiler/GHC/CmmToAsm/LA64/CodeGen.hs
- compiler/GHC/CmmToAsm/PPC/RegInfo.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/Data/OsPath.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/CodeOutput.hs
- + compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/Config/Linker.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/LlvmConfigCache.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Phases.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/Hs/Basic.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/Iface/Ext/Ast.hs
- + compiler/GHC/Linker/ByteCode.hs
- compiler/GHC/Linker/Config.hs
- compiler/GHC/Linker/Dynamic.hs
- + compiler/GHC/Linker/Executable.hs
- − compiler/GHC/Linker/ExtraObj.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/MacOS.hs
- compiler/GHC/Linker/Static.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Linker/Windows.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Prelude/Basic.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Runtime/Debugger.hs
- compiler/GHC/Runtime/Eval.hs
- + compiler/GHC/Runtime/Interpreter/C.hs
- + compiler/GHC/Runtime/Interpreter/Init.hs
- compiler/GHC/Settings.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/Prim.hs
- compiler/GHC/SysTools/Tasks.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Unique/Set.hs
- compiler/GHC/Types/Var/Env.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Home/PackageTable.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Misc.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- configure.ac
- docs/users_guide/9.16.1-notes.rst
- docs/users_guide/conf.py
- docs/users_guide/exts/data_kinds.rst
- docs/users_guide/exts/explicit_namespaces.rst
- docs/users_guide/exts/gadt_syntax.rst
- docs/users_guide/exts/rank_polymorphism.rst
- docs/users_guide/exts/type_families.rst
- docs/users_guide/phases.rst
- docs/users_guide/using-optimisation.rst
- ghc/GHCi/UI.hs
- ghc/Main.hs
- hadrian/doc/flavours.md
- hadrian/src/Builder.hs
- hadrian/src/Flavour.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Hadrian/Haskell/Hash.hs
- hadrian/src/Hadrian/Oracles/ArgsHash.hs
- hadrian/src/Hadrian/Oracles/Cabal/Type.hs
- hadrian/src/Hadrian/Oracles/DirectoryContents.hs
- hadrian/src/Hadrian/Oracles/Path.hs
- hadrian/src/Hadrian/Oracles/TextFile.hs
- hadrian/src/Hadrian/Utilities.hs
- hadrian/src/Oracles/Flavour.hs
- hadrian/src/Oracles/ModuleFiles.hs
- hadrian/src/Rules/ToolArgs.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/Ghc.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Warnings.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NonEmpty.hs
- + libraries/base/src/Data/List/NubOrdSet.hs
- libraries/base/src/GHC/Num.hs
- libraries/exceptions
- libraries/ghc-boot-th/GHC/Boot/TH/Ppr.hs
- libraries/ghc-boot/GHC/Unit/Database.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- libraries/ghc-internal/src/GHC/Internal/List.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- libraries/ghc-internal/src/GHC/Internal/System/IO.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Syntax.hs
- libraries/ghci/GHCi/CreateBCO.hs
- libraries/ghci/GHCi/ResolvedBCO.hs
- libraries/template-haskell/vendored-filepath/System/FilePath/Posix.hs
- libraries/template-haskell/vendored-filepath/System/FilePath/Windows.hs
- libraries/xhtml
- + rts/.ubsan-suppressions
- rts/Interpreter.c
- rts/PrimOps.cmm
- rts/RtsSymbols.c
- rts/eventlog/EventLog.c
- rts/include/stg/MiscClosures.h
- rts/include/stg/Types.h
- rts/linker/Elf.c
- rts/linker/LoadArchive.c
- rts/linker/PEi386.c
- rts/rts.cabal
- testsuite/config/ghc
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- testsuite/mk/boilerplate.mk
- + testsuite/tests/bytecode/T23973.hs
- + testsuite/tests/bytecode/T23973.script
- + testsuite/tests/bytecode/T23973.stdout
- + testsuite/tests/bytecode/T26565.hs
- + testsuite/tests/bytecode/T26565.script
- + testsuite/tests/bytecode/T26565.stdout
- + testsuite/tests/bytecode/T26640.hs
- + testsuite/tests/bytecode/T26640.script
- + testsuite/tests/bytecode/T26640.stdout
- testsuite/tests/bytecode/all.T
- + testsuite/tests/cabal/Bytecode.hs
- + testsuite/tests/cabal/BytecodeForeign.c
- + testsuite/tests/cabal/BytecodeForeign.hs
- testsuite/tests/cabal/Makefile
- testsuite/tests/cabal/all.T
- + testsuite/tests/cabal/bytecode.pkg
- + testsuite/tests/cabal/bytecode.script
- + testsuite/tests/cabal/bytecode_foreign.pkg
- + testsuite/tests/cabal/bytecode_foreign.script
- testsuite/tests/cabal/ghcpkg03.stderr
- testsuite/tests/cabal/ghcpkg03.stderr-mingw32
- testsuite/tests/cabal/ghcpkg05.stderr
- testsuite/tests/cabal/ghcpkg05.stderr-mingw32
- + testsuite/tests/cabal/pkg_bytecode.stderr
- + testsuite/tests/cabal/pkg_bytecode.stdout
- + testsuite/tests/cabal/pkg_bytecode_foreign.stderr
- + testsuite/tests/cabal/pkg_bytecode_foreign.stdout
- + testsuite/tests/cabal/pkg_bytecode_with_gbc.stderr
- + testsuite/tests/cabal/pkg_bytecode_with_gbc.stdout
- + testsuite/tests/cabal/pkg_bytecode_with_o.stderr
- + testsuite/tests/cabal/pkg_bytecode_with_o.stdout
- + testsuite/tests/cmm/opt/T25664.hs
- + testsuite/tests/cmm/opt/T25664.stdout
- testsuite/tests/cmm/opt/all.T
- testsuite/tests/codeGen/should_run/T23146/T23146_liftedeq.hs
- + testsuite/tests/codeGen/should_run/T23146/T25636.script
- testsuite/tests/codeGen/should_run/T23146/all.T
- + testsuite/tests/codeGen/should_run/T24016.hs
- + testsuite/tests/codeGen/should_run/T24016.stdout
- testsuite/tests/codeGen/should_run/all.T
- + testsuite/tests/driver/T20696/T20696.stderr-ext-interp
- testsuite/tests/driver/T20696/all.T
- + testsuite/tests/driver/T24731.hs
- testsuite/tests/driver/all.T
- testsuite/tests/driver/bytecode-object/Makefile
- testsuite/tests/driver/bytecode-object/all.T
- testsuite/tests/driver/bytecode-object/bytecode_object19.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object20.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object21.stderr
- + testsuite/tests/driver/bytecode-object/bytecode_object21.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object23.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object24.stdout
- testsuite/tests/driver/fat-iface/all.T
- + testsuite/tests/driver/fat-iface/fat012.stderr-ext-interp
- + testsuite/tests/driver/fat-iface/fat015.stderr-ext-interp
- testsuite/tests/driver/j-space/jspace.hs
- 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/module/T25901_exp_plain_wc.hs
- + testsuite/tests/module/T25901_exp_plain_wc.stderr
- + testsuite/tests/module/T25901_imp_plain_wc.hs
- + testsuite/tests/module/T25901_imp_plain_wc.stderr
- testsuite/tests/module/all.T
- + testsuite/tests/rename/should_compile/T25901_exp_1.hs
- + testsuite/tests/rename/should_compile/T25901_exp_1_helper.hs
- + testsuite/tests/rename/should_compile/T25901_exp_2.hs
- + testsuite/tests/rename/should_compile/T25901_exp_2_helper.hs
- + testsuite/tests/rename/should_compile/T25901_imp_hq.hs
- + testsuite/tests/rename/should_compile/T25901_imp_hu.hs
- + testsuite/tests/rename/should_compile/T25901_imp_sq.hs
- + testsuite/tests/rename/should_compile/T25901_imp_su.hs
- testsuite/tests/rename/should_compile/all.T
- + testsuite/tests/rename/should_fail/T25901_exp_fail_1.hs
- + testsuite/tests/rename/should_fail/T25901_exp_fail_1.stderr
- + testsuite/tests/rename/should_fail/T25901_exp_fail_1_helper.hs
- + testsuite/tests/rename/should_fail/T25901_exp_fail_2.hs
- + testsuite/tests/rename/should_fail/T25901_exp_fail_2.stderr
- + testsuite/tests/rename/should_fail/T25901_exp_fail_2_helper.hs
- + testsuite/tests/rename/should_fail/T25901_imp_hq_fail_5.hs
- + testsuite/tests/rename/should_fail/T25901_imp_hq_fail_5.stderr
- + testsuite/tests/rename/should_fail/T25901_imp_hq_fail_6.hs
- + testsuite/tests/rename/should_fail/T25901_imp_hq_fail_6.stderr
- + testsuite/tests/rename/should_fail/T25901_imp_hu_fail_4.hs
- + testsuite/tests/rename/should_fail/T25901_imp_hu_fail_4.stderr
- + testsuite/tests/rename/should_fail/T25901_imp_sq_fail_2.hs
- + testsuite/tests/rename/should_fail/T25901_imp_sq_fail_2.stderr
- + testsuite/tests/rename/should_fail/T25901_imp_sq_fail_3.hs
- + testsuite/tests/rename/should_fail/T25901_imp_sq_fail_3.stderr
- + testsuite/tests/rename/should_fail/T25901_imp_su_fail_1.hs
- + testsuite/tests/rename/should_fail/T25901_imp_su_fail_1.stderr
- testsuite/tests/rename/should_fail/all.T
- testsuite/tests/rts/KeepCafsBase.hs
- testsuite/tests/rts/all.T
- testsuite/tests/simd/should_run/all.T
- + testsuite/tests/simplCore/should_compile/T26588.hs
- + testsuite/tests/simplCore/should_compile/T26589.hs
- testsuite/tests/simplCore/should_compile/T8331.stderr
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/splice-imports/SI07.stderr-ext-interp
- testsuite/tests/splice-imports/all.T
- + testsuite/tests/th/T26099.hs
- + testsuite/tests/th/T26099.stderr
- + testsuite/tests/th/T26568.hs
- + testsuite/tests/th/T26568.stderr
- testsuite/tests/th/all.T
- testsuite/tests/unboxedsums/UbxSumUnpackedSize.hs
- + testsuite/tests/warnings/should_compile/T25901_exp_dodgy.hs
- + testsuite/tests/warnings/should_compile/T25901_exp_dodgy.stderr
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_1.hs
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_1.stderr
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_2.hs
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_2.stderr
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_3.hs
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_3.stderr
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_4.hs
- + testsuite/tests/warnings/should_compile/T25901_exp_dup_wc_4.stderr
- + testsuite/tests/warnings/should_compile/T25901_helper_1.hs
- + testsuite/tests/warnings/should_compile/T25901_helper_2.hs
- + testsuite/tests/warnings/should_compile/T25901_helper_3.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_dodgy_1.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_dodgy_1.stderr
- + testsuite/tests/warnings/should_compile/T25901_imp_dodgy_2.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_dodgy_2.stderr
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_1.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_1.stderr
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_2.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_2.stderr
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_3.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_3.stderr
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_4.hs
- + testsuite/tests/warnings/should_compile/T25901_imp_unused_4.stderr
- testsuite/tests/warnings/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/deriveConstants/Main.hs
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Utils.hs
- utils/haddock/cabal.project
- utils/haddock/haddock-api/haddock-api.cabal
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Renderer.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Names.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Themes.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Utils.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Doc.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Utils.hs
- utils/haddock/haddock-library/src/Documentation/Haddock/Parser.hs
- utils/haddock/haddock-test/src/Test/Haddock.hs
- utils/haddock/html-test/ref/Bug1050.html
- utils/haddock/html-test/ref/Bug26.html
- utils/haddock/html-test/ref/Bug298.html
- utils/haddock/html-test/ref/Bug458.html
- utils/haddock/html-test/ref/LinearTypes.html
- utils/haddock/html-test/ref/Nesting.html
- utils/haddock/html-test/ref/PatternSyns.html
- + utils/haddock/html-test/ref/PatternSyns2.html
- utils/haddock/html-test/ref/TitledPicture.html
- utils/haddock/html-test/ref/TypeOperators.html
- utils/haddock/html-test/ref/Unicode.html
- utils/haddock/html-test/ref/Unicode2.html
- + utils/haddock/html-test/src/PatternSyns2.hs
- utils/haddock/latex-test/ref/LinearTypes/LinearTypes.tex
- utils/hpc
- utils/hsc2hs
- utils/iserv/iserv.cabal.in
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e8aeb770b7e2e0ff91e89aba17eb34…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e8aeb770b7e2e0ff91e89aba17eb34…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
19 Dec '25
Simon Peyton Jones pushed to branch wip/T26681 at Glasgow Haskell Compiler / GHC
Commits:
459bd467 by Simon Peyton Jones at 2025-12-19T17:38:29+00:00
Refactor SetLevels [skip ci]
- - - - -
2 changed files:
- compiler/GHC/Core.hs
- compiler/GHC/Core/Opt/SetLevels.hs
Changes:
=====================================
compiler/GHC/Core.hs
=====================================
@@ -10,7 +10,8 @@ module GHC.Core (
-- * Main data types
Expr(..), Alt(..), Bind(..), AltCon(..), Arg,
CoreProgram, CoreExpr, CoreAlt, CoreBind, CoreArg, CoreBndr,
- TaggedExpr, TaggedAlt, TaggedBind, TaggedArg, TaggedBndr(..), deTagExpr,
+ TaggedExpr, TaggedAlt, TaggedBind, TaggedArg, TaggedBndr(..),
+ deTagExpr, taggedBndrBndr,
-- * In/Out type synonyms
InId, InBind, InExpr, InAlt, InArg, InType, InKind,
@@ -1931,6 +1932,9 @@ type TaggedAlt t = Alt (TaggedBndr t)
instance Outputable b => Outputable (TaggedBndr b) where
ppr (TB b l) = char '<' <> ppr b <> comma <> ppr l <> char '>'
+taggedBndrBndr :: TaggedBndr t -> CoreBndr
+taggedBndrBndr (TB b _) = b
+
deTagExpr :: TaggedExpr t -> CoreExpr
deTagExpr (Var v) = Var v
deTagExpr (Lit l) = Lit l
=====================================
compiler/GHC/Core/Opt/SetLevels.hs
=====================================
@@ -111,12 +111,13 @@ import GHC.Types.Demand ( DmdSig, prependArgsDmdSig )
import GHC.Types.Cpr ( CprSig, prependArgsCprSig )
import GHC.Types.Name ( getOccName, mkSystemVarName )
import GHC.Types.Name.Occurrence ( occNameFS )
-import GHC.Types.Unique ( hasKey )
+import GHC.Types.Unique ( Unique, hasKey )
import GHC.Types.Tickish ( tickishIsCode )
import GHC.Types.Unique.Supply
import GHC.Types.Unique.DFM
import GHC.Types.Basic ( Arity, RecFlag(..), isRec )
+import GHC.Data.Maybe ( orElse )
import GHC.Builtin.Types
import GHC.Builtin.Names ( runRWKey )
@@ -290,7 +291,7 @@ lvl_top env is_rec bndr rhs
= do { rhs' <- lvlRhs env is_rec (isDeadEndId bndr)
NotJoinPoint
(freeVars rhs)
- ; return (stayPut tOP_LEVEL bndr, rhs') }
+ ; return (TB bndr (StayPut tOP_LEVEL), rhs') }
{-
************************************************************************
@@ -363,8 +364,8 @@ lvlExpr env expr@(_, AnnLam {})
; return (mkLams new_bndrs new_body) }
where
(bndrs, body) = collectAnnBndrs expr
- (env1, bndrs1) = substBndrsSL NonRecursive env bndrs
- (new_env, new_bndrs) = lvlLamBndrs env1 (le_ctxt_lvl env) bndrs1
+ bndr_lvl = lamBndrLevel (le_ctxt_lvl env) bndrs
+ (new_env, new_bndrs) = substAndLvlBndrs env NonRecursive bndr_lvl bndrs
-- At one time we called a special version of collectBinders,
-- which ignored coercions, because we don't want to split
-- a lambda like this (\x -> coerce t (\s -> ...))
@@ -455,11 +456,11 @@ lvlCase env scrut_fvs scrut' case_bndr ty alts
do { (env1, (case_bndr' : bs')) <- cloneCaseBndrs env dest_lvl (case_bndr : bs)
; let rhs_env = extendCaseBndrEnv env1 case_bndr scrut'
; body' <- lvlMFE rhs_env True body
- ; let alt' = Alt con (map (stayPut dest_lvl) bs') body'
- ; return (Case scrut' (TB case_bndr' (FloatMe dest_lvl)) ty' [alt']) }
+ ; let alt' = Alt con bs' body'
+ ; return (Case scrut' case_bndr' ty' [alt']) }
| otherwise -- Stays put
- = do { let (alts_env1, [case_bndr']) = substAndLvlBndrs NonRecursive env incd_lvl [case_bndr]
+ = do { let (alts_env1, [case_bndr']) = substAndLvlBndrs env NonRecursive incd_lvl [case_bndr]
alts_env = extendCaseBndrEnv alts_env1 case_bndr scrut'
; alts' <- mapM (lvl_alt alts_env) alts
; return (Case scrut' case_bndr' ty' alts') }
@@ -474,7 +475,7 @@ lvlCase env scrut_fvs scrut' case_bndr ty alts
= do { rhs' <- lvlMFE new_env True rhs
; return (Alt con bs' rhs') }
where
- (new_env, bs') = substAndLvlBndrs NonRecursive alts_env incd_lvl bs
+ (new_env, bs') = substAndLvlBndrs alts_env NonRecursive incd_lvl bs
{- Note [Floating single-alternative cases]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -631,13 +632,14 @@ lvlMFE env strict_ctxt ann_expr
| float_is_new_lam || exprIsTopLevelBindable expr expr_ty
-- No wrapping needed if the type is lifted, or is a literal string
-- or if we are wrapping it in one or more value lambdas
- = do { expr1 <- lvlFloatRhs abs_vars dest_lvl rhs_env NonRecursive
- is_bot_lam NotJoinPoint ann_expr
+ = do { rhs' <- lvlFloatRhs env dest_lvl abs_vars NonRecursive
+ is_bot_lam NotJoinPoint ann_expr
-- Treat the expr just like a right-hand side
- ; var <- newLvlVar expr1 NotJoinPoint is_mk_static
- ; let var2 = annotateBotStr var float_n_lams mb_bot_str
- ; return (Let (NonRec (TB var2 (FloatMe dest_lvl)) expr1)
- (mkVarApps (Var var2) abs_vars)) }
+ ; var <- newLvlVar rhs' NotJoinPoint is_mk_static
+ ; let lb = TB (FloatMe dest_lvl) var
+ lb' = annotateBotStr lb float_n_lams mb_bot_str
+ ; return (Let (NonRec lb' rhs')
+ (mkVarApps (Var var abs_vars))) }
-- OK, so the float has an unlifted type (not top-level bindable)
-- and no new value lambdas (float_is_new_lam is False)
@@ -649,14 +651,15 @@ lvlMFE env strict_ctxt ann_expr
, BI_Box { bi_data_con = box_dc, bi_inst_con = boxing_expr
, bi_boxed_type = box_ty } <- boxingDataCon expr_ty
, let [bx_bndr, ubx_bndr] = mkTemplateLocals [box_ty, expr_ty]
- = do { expr1 <- lvlExpr rhs_env ann_expr
- ; let l1r = incMinorLvlFrom rhs_env
- float_rhs = mkLams abs_vars_w_lvls $
+ = do { let bndr_lvl = lamBndrLevel dest_lvl abs_vars
+ ; expr1 <- lvlExpr (env `setCtxtLevel` bndr_lvl) ann_expr
+ ; let l1r = incMinorLvl bndr_lvl
+ float_rhs = mkLams (stayPut bndr_lvl abs_vars) $
Case expr1 (stayPut l1r ubx_bndr) box_ty
[Alt DEFAULT [] (App boxing_expr (Var ubx_bndr))]
; var <- newLvlVar float_rhs NotJoinPoint is_mk_static
- ; let l1u = incMinorLvlFrom env
+ ; let l1u = incMinorLvl (ctxtLevel env)
use_expr = Case (mkVarApps (Var var) abs_vars)
(stayPut l1u bx_bndr) expr_ty
[Alt (DataAlt box_dc) [stayPut l1u ubx_bndr] (Var ubx_bndr)]
@@ -690,8 +693,6 @@ lvlMFE env strict_ctxt ann_expr
float_is_new_lam = float_n_lams > 0
float_n_lams = count isId abs_vars
- (rhs_env, abs_vars_w_lvls) = lvlLamBndrs env dest_lvl abs_vars
-
is_mk_static = isJust (collectMakeStaticArgs expr)
-- Yuk: See Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable
@@ -706,7 +707,7 @@ lvlMFE env strict_ctxt ann_expr
saves_work = escapes_value_lam -- (a)
&& not is_hnf -- (b)
&& not float_is_new_lam -- (c)
- escapes_value_lam = dest_lvl `ltMajLvl` (le_ctxt_lvl env)
+ escapes_value_lam = dest_lvl `ltMajLvl` (ctxtLevel env)
-- See Note [Saving allocation] and Note [Floating to the top]
saves_alloc = isTopLvl dest_lvl
@@ -720,8 +721,9 @@ hasFreeJoin :: LevelEnv -> DVarSet -> Bool
-- (In the latter case it won't be a join point any more.)
-- Not treating top-level ones specially had a massive effect
-- on nofib/minimax/Prog.prog
-hasFreeJoin env fvs
- = not (maxFvLevel isJoinId env fvs == tOP_LEVEL)
+hasFreeJoin env fvs = anyDVarSet bad_join fvs
+ where
+ bad_join v = isJoinId v && lookupLevel env v == tOP_LEVEL
{- Note [Saving work]
~~~~~~~~~~~~~~~~~~~~~
@@ -1117,18 +1119,20 @@ artificial benchmarks (e.g. integer, queens), but there is no perfect
answer.
-}
-annotateBotStr :: Id -> Arity -> Maybe (Arity, DmdSig, CprSig) -> Id
+annotateBotStr :: LevelledBndr -> Arity -> Maybe (Arity, DmdSig, CprSig) -> LevelledBndr
-- See Note [Bottoming floats] for why we want to add
-- bottoming information right now
--
-- n_extra are the number of extra value arguments added during floating
-annotateBotStr id n_extra mb_bot_str
- | Just (arity, str_sig, cpr_sig) <- mb_bot_str
- = id `setIdArity` (arity + n_extra)
- `setIdDmdSig` prependArgsDmdSig n_extra str_sig
- `setIdCprSig` prependArgsCprSig n_extra cpr_sig
- | otherwise
- = id
+annotateBotStr lb@(TB lvl id) n_extra mb_bot_str
+ = case mb_bot_str of
+ Nothing -> lb
+ Just (arity, str_sig, cpr_sig)
+ -> TB lvl id'
+ where
+ id' = id `setIdArity` (arity + n_extra)
+ `setIdDmdSig` prependArgsDmdSig n_extra str_sig
+ `setIdCprSig` prependArgsCprSig n_extra cpr_sig
notWorthFloating :: CoreExpr -> [Var] -> Bool
-- See Note [notWorthFloating]
@@ -1269,26 +1273,26 @@ lvlBind env (AnnNonRec bndr rhs)
|| not (wantToFloat env NonRecursive dest_lvl is_join is_top_bindable)
= -- No float
do { rhs' <- lvlRhs env NonRecursive is_bot_lam mb_join_arity rhs
- ; let bind_lvl = incMinorLvl (le_ctxt_lvl env)
- (env', [bndr']) = substAndLvlBndrs NonRecursive env bind_lvl [bndr]
+ ; let bind_lvl = incMinorLvl (ctxtLevel env)
+ (env', [bndr']) = substAndLvlBndrs env NonRecursive bind_lvl [bndr]
; return (NonRec bndr' rhs', env') }
-- Otherwise we are going to float
| null abs_vars
= do { -- No type abstraction; clone existing binder
- rhs' <- lvlFloatRhs [] dest_lvl env NonRecursive
+ rhs' <- lvlFloatRhs env dest_lvl [] NonRecursive
is_bot_lam NotJoinPoint rhs
- ; (env', [bndr']) <- cloneLetVars NonRecursive env dest_lvl [bndr]
- ; let bndr2 = annotateBotStr bndr' 0 mb_bot_str
- ; return (NonRec (TB bndr2 (FloatMe dest_lvl)) rhs', env') }
+ ; (env', [lbndr]) <- cloneLetVars NonRecursive env dest_lvl [bndr]
+ ; let lbndr' = annotateBotStr lbndr 0 mb_bot_str
+ ; return (NonRec lbndr' rhs', env') }
| otherwise
= do { -- Yes, type abstraction; create a new binder, extend substitution, etc
- rhs' <- lvlFloatRhs abs_vars dest_lvl env NonRecursive
+ rhs' <- lvlFloatRhs env dest_lvl abs_vars NonRecursive
is_bot_lam NotJoinPoint rhs
- ; (env', [bndr']) <- newPolyBndrs dest_lvl env abs_vars [bndr]
- ; let bndr2 = annotateBotStr bndr' n_extra mb_bot_str
- ; return (NonRec (TB bndr2 (FloatMe dest_lvl)) rhs', env') }
+ ; (env', [lbndr]) <- newPolyBndrs env dest_lvl abs_vars [bndr]
+ ; let lbndr' = annotateBotStr lbndr n_extra mb_bot_str
+ ; return (NonRec lbndr' rhs', env') }
where
bndr_ty = idType bndr
@@ -1314,8 +1318,8 @@ lvlBind env (AnnNonRec bndr rhs)
lvlBind env (AnnRec pairs)
| not (wantToFloat env Recursive dest_lvl is_join is_top_bindable)
= -- No float
- do { let bind_lvl = incMinorLvl (le_ctxt_lvl env)
- (env', bndrs') = substAndLvlBndrs Recursive env bind_lvl bndrs
+ do { let bind_lvl = incMinorLvl (ctxtLevel env)
+ (env', bndrs') = substAndLvlBndrs env Recursive bind_lvl bndrs
lvl_rhs (b,r) = lvlRhs env' Recursive is_bot (idJoinPointHood b) r
; rhss' <- mapM lvl_rhs pairs
; return (Rec (bndrs' `zip` rhss'), env') }
@@ -1331,7 +1335,7 @@ lvlBind env (AnnRec pairs)
-- I think we want to stop doing this
| [(bndr,rhs)] <- pairs
, count isId abs_vars > 1
- = do -- Special case for self recursion where there are
+ = -- Special case for self recursion where there are
-- several variables carried around: build a local loop:
-- poly_f = \abs_vars. \lam_vars . letrec f = \lam_vars. rhs in f lam_vars
-- This just makes the closures a bit smaller. If we don't do
@@ -1341,26 +1345,25 @@ lvlBind env (AnnRec pairs)
-- mutually recursive functions, but it's quite a bit more complicated
--
-- This all seems a bit ad hoc -- sigh
- let (rhs_env, abs_vars_w_lvls) = lvlLamBndrs env dest_lvl abs_vars
- rhs_lvl = le_ctxt_lvl rhs_env
-
- (rhs_env', [new_bndr]) <- cloneLetVars Recursive rhs_env rhs_lvl [bndr]
- let
- (lam_bndrs, rhs_body) = collectAnnBndrs rhs
- (body_env1, lam_bndrs1) = substBndrsSL NonRecursive rhs_env' lam_bndrs
- (body_env2, lam_bndrs2) = lvlLamBndrs body_env1 rhs_lvl lam_bndrs1
- new_rhs_body <- lvlRhs body_env2 Recursive is_bot NotJoinPoint rhs_body
- (poly_env, [poly_bndr]) <- newPolyBndrs dest_lvl env abs_vars [bndr]
- return (Rec [(TB poly_bndr (FloatMe dest_lvl)
- , mkLams abs_vars_w_lvls $
- mkLams lam_bndrs2 $
- Let (Rec [( TB new_bndr (StayPut rhs_lvl)
- , mkLams lam_bndrs2 new_rhs_body)])
- (mkVarApps (Var new_bndr) lam_bndrs1))]
- , poly_env)
+ do { let (lam_bndrs, body) = collectAnnBndrs rhs
+ bndr_lvl = lamBndrLevel dest_lvl (abs_vars ++ lam_bndrs)
+ abs_lbs = stayPut bndr_lvl abs_vars
+ (body_env1, lam_lbs) = substAndLvlBndrs env NonRecursive bndr_lvl lam_bndrs
+
+ ; (body_env2, [new_bndr]) <- cloneLetVars Recursive body_env1 (ctxtLevel body_env1) [bndr]
+ ; new_body <- lvlRhs body_env2 Recursive is_bot NotJoinPoint body
+ ; (poly_env, [poly_bndr]) <- newPolyBndrs dest_lvl env abs_vars [bndr]
+
+ ; let rec_rhs = mkLams lam_lbs new_body
+ new_rhs = mkLams abs_lbs $
+ mkLams lam_lbs $
+ Let (Rec [( new_bndr, rec_rhs )]) $
+ mkVarApps (Var new_bndr) (map taggedBndrBndr lam_lbs)
+ ; return ( Rec [(poly_bndr, new_rhs)]
+ , poly_env) }
| otherwise -- Non-null abs_vars
- = do { (new_env, new_bndrs) <- newPolyBndrs dest_lvl env abs_vars bndrs
+ = do { (new_env, new_bndrs) <- newPolyBndrs env dest_lvl abs_vars bndrs
; new_rhss <- mapM (do_rhs new_env) pairs
; return ( Rec ([TB b (FloatMe dest_lvl) | b <- new_bndrs] `zip` new_rhss)
, new_env) }
@@ -1375,7 +1378,7 @@ lvlBind env (AnnRec pairs)
-- function in a Rec, and we don't much care what
-- happens to it. False is simple!
- do_rhs env (_,rhs) = lvlFloatRhs abs_vars dest_lvl env Recursive
+ do_rhs env (_,rhs) = lvlFloatRhs env dest_lvl abs_vars Recursive
is_bot NotJoinPoint
rhs
@@ -1425,7 +1428,7 @@ wantToFloat env is_rec dest_lvl is_join is_top_bindable
profitableFloat :: LevelEnv -> Level -> Bool
profitableFloat env dest_lvl
- = (dest_lvl `ltMajLvl` le_ctxt_lvl env) -- Escapes a value lambda
+ = (dest_lvl `ltMajLvl` ctxtLevel env) -- Escapes a value lambda
|| (isTopLvl dest_lvl && floatConsts env) -- Going all the way to top level
@@ -1439,33 +1442,31 @@ lvlRhs :: LevelEnv
-> CoreExprWithFVs
-> LvlM LevelledExpr
lvlRhs env rec_flag is_bot mb_join_arity expr
- = lvlFloatRhs [] (le_ctxt_lvl env) env
+ = lvlFloatRhs env (ctxtLevel env) []
rec_flag is_bot mb_join_arity expr
-lvlFloatRhs :: [OutVar] -> Level -> LevelEnv -> RecFlag
+lvlFloatRhs :: LevelEnv -> Level -> [OutVar] -> RecFlag
-> Bool -- Binding is for a bottoming function
-> JoinPointHood
-> CoreExprWithFVs
-> LvlM (Expr LevelledBndr)
-- Ignores the le_ctxt_lvl in env; treats dest_lvl as the baseline
-lvlFloatRhs abs_vars dest_lvl env rec is_bot mb_join_arity rhs
+lvlFloatRhs env dest_lvl abs_vars rec_flag is_bot mb_join_arity rhs
= do { body' <- if not is_bot -- See Note [Floating from a RHS]
&& any isId bndrs
then lvlMFE body_env True body
else lvlExpr body_env body
- ; return (mkLams bndrs' body') }
+ ; return (mkLams (abs_bndrs ++ bndrs') body') }
where
- (bndrs, body) | JoinPoint join_arity <- mb_join_arity
- = collectNAnnBndrs join_arity rhs
- | otherwise
- = collectAnnBndrs rhs
- (env1, bndrs1) = substBndrsSL NonRecursive env bndrs
- all_bndrs = abs_vars ++ bndrs1
- (body_env, bndrs') | JoinPoint {} <- mb_join_arity
- = lvlJoinBndrs env1 dest_lvl rec all_bndrs
- | otherwise
- = lvlLamBndrs env1 dest_lvl all_bndrs
- -- The important thing here is that we call lvlLamBndrs on
+ (bndrs, body) = collectAnnBndrs rhs
+ bndr_lvl = case mb_join_arity of
+ JoinPoint ja -> assertPpr (null abs_vars) (ppr abs_vars) $
+ joinLamBndrLevel dest_lvl rec_flag ja bndrs
+ NotJoinPoint -> lamBndrLevel dest_lvl (abs_bndrs ++ bndrs)
+
+ abs_bndrs = stayPut bndr_lvl abs_vars
+ (body_env, bndrs') = substAndLvlBndrs env NonRecursive bndr_lvl bndrs
+ -- The important thing here is that we call `lamBndrLevel` on
-- all these binders at once (abs_vars and bndrs), so they
-- all get the same major level. Otherwise we create stupid
-- let-bindings inside, joyfully thinking they can float; but
@@ -1522,31 +1523,32 @@ Use lvlExpr otherwise. A little subtle, and I got it wrong at least twice
************************************************************************
-}
-substAndLvlBndrs :: RecFlag -> LevelEnv -> Level -> [InVar] -> (LevelEnv, [LevelledBndr])
-substAndLvlBndrs is_rec env lvl bndrs
- = lvlBndrs subst_env lvl subst_bndrs
+setCtxtLevel :: LevelEnv -> Level -> LevelEnv
+setCtxtLevel env lvl = env { le_ctxt_lvl = lvl }
+
+substAndLvlBndrs :: LevelEnv -> RecFlag -> Level -> [InVar] -> (LevelEnv, [LevelledBndr])
+-- New env has
+-- * Updated context level
+-- * Updated le_lvl_env for the InVars
+-- * Updated le_subst and le_env for cloning
+substAndLvlBndrs env@(LE { le_subst = subst, le_env = id_env, le_lvl_env = lvl_env })
+ is_rec bndr_lvl in_bndrs
+ = ( env { le_ctxt_lvl = bndr_lvl
+ , le_lvl_env = addLvls bndr_lvl lvl_env in_bndrs
+ , le_subst = subst'
+ , le_env = foldl' add_id id_env (in_bndrs `zip` lvld_bndrs) }
+ , lvld_bndrs)
where
- (subst_env, subst_bndrs) = substBndrsSL is_rec env bndrs
-
-substBndrsSL :: RecFlag -> LevelEnv -> [InVar] -> (LevelEnv, [OutVar])
--- So named only to avoid the name clash with GHC.Core.Subst.substBndrs
-substBndrsSL is_rec env@(LE { le_subst = subst, le_env = id_env }) bndrs
- = ( env { le_subst = subst'
- , le_env = foldl' add_id id_env (bndrs `zip` bndrs') }
- , bndrs')
+ lvld_bndrs = stayPut bndr_lvl out_bndrs
+ (subst', out_bndrs) = case is_rec of
+ NonRecursive -> substBndrs subst in_bndrs
+ Recursive -> substRecBndrs subst in_bndrs
+
+lamBndrLevel :: Level -> [InVar] -> Level
+lamBndrLevel ctxt_lvl bndrs
+ | any is_major bndrs = incMajorLvl ctxt_lvl
+ | otherwise = incMinorLvl ctxt_lvl
where
- (subst', bndrs') = case is_rec of
- NonRecursive -> substBndrs subst bndrs
- Recursive -> substRecBndrs subst bndrs
-
-lvlLamBndrs :: LevelEnv -> Level -> [OutVar] -> (LevelEnv, [LevelledBndr])
--- Compute the levels for the binders of a lambda group
-lvlLamBndrs env lvl bndrs
- = lvlBndrs env new_lvl bndrs
- where
- new_lvl | any is_major bndrs = incMajorLvl lvl
- | otherwise = incMinorLvl lvl
-
is_major bndr = not (isOneShotBndr bndr)
-- Only non-one-shot lambdas bump a major level, which in
-- turn triggers floating. NB: isOneShotBndr is always
@@ -1554,14 +1556,10 @@ lvlLamBndrs env lvl bndrs
-- out of a big lambda.
-- See Note [Computing one-shot info] in GHC.Types.Demand
-lvlJoinBndrs :: LevelEnv -> Level -> RecFlag -> [OutVar]
- -> (LevelEnv, [LevelledBndr])
-lvlJoinBndrs env lvl rec bndrs
- = lvlBndrs env new_lvl bndrs
- where
- new_lvl | isRec rec = incMajorLvl lvl
- | otherwise = incMinorLvl lvl
- -- Non-recursive join points are one-shot; recursive ones are not
+joinLamBndrLevel :: Level -> RecFlag -> JoinArity -> [InVar] -> Level
+joinLamBndrLevel ctxt_lvl rec_flag join_arity bndrs
+ | isRec rec_flag = lamBndrLevel ctxt_lvl bndrs
+ | otherwise = lamBndrLevel ctxt_lvl (drop join_arity bndrs)
lvlBndrs :: LevelEnv -> Level -> [CoreBndr] -> (LevelEnv, [LevelledBndr])
-- The binders returned are exactly the same as the ones passed,
@@ -1576,10 +1574,10 @@ lvlBndrs :: LevelEnv -> Level -> [CoreBndr] -> (LevelEnv, [LevelledBndr])
lvlBndrs env@(LE { le_lvl_env = lvl_env }) new_lvl bndrs
= ( env { le_ctxt_lvl = new_lvl
, le_lvl_env = addLvls new_lvl lvl_env bndrs }
- , map (stayPut new_lvl) bndrs)
+ , stayPut new_lvl bndrs)
-stayPut :: Level -> OutVar -> LevelledBndr
-stayPut new_lvl bndr = TB bndr (StayPut new_lvl)
+stayPut :: Level -> [OutVar] -> [LevelledBndr]
+stayPut new_lvl bndrs = [ TB bndr (StayPut new_lvl) | bndr <- bndrs ]
-- Destination level is the max Id level of the expression
-- (We'll abstract the type variables, if any.)
@@ -1677,14 +1675,15 @@ countFreeIds = nonDetStrictFoldUDFM add 0 . getUniqDSet
data LevelEnv
= LE { le_switches :: FloatOutSwitches
, le_ctxt_lvl :: Level -- The current level
- , le_lvl_env :: VarEnv Level -- Domain is *post-cloned* TyVars and Ids
+ , le_lvl_env :: VarEnv Level -- Domain is *pre-cloned* InVars
-- See Note [le_subst and le_env]
- , le_subst :: Subst -- Domain is pre-cloned TyVars and Ids
- -- The Id -> CoreExpr in the Subst is ignored
- -- (since we want to substitute a LevelledExpr for
- -- an Id via le_env) but we do use the Co/TyVar substs
- , le_env :: IdEnv ([OutVar], LevelledExpr) -- Domain is pre-cloned Ids
+ , le_subst :: Subst -- Domain is pre-cloned TyVars and Ids
+ -- The Id -> CoreExpr in the Subst is ignored
+ -- (since we want to substitute a LevelledExpr for
+ -- an Id via le_env) but we do use the Co/TyVar substs
+ , le_env :: IdEnv ([LevelledBndr], LevelledExpr) -- Domain is pre-cloned Ids
+ -- The LevelledBndrs are the free vars of LevelledExpr
}
{- Note [le_subst and le_env]
@@ -1733,10 +1732,13 @@ initialEnv float_lams binds
-- to a later one. So here we put all the top-level binders in scope before
-- we start, to satisfy the lookupIdSubst invariants (#20200 and #20294)
-addLvl :: Level -> VarEnv Level -> OutVar -> VarEnv Level
+ctxtLevel :: LevelEnv -> Level
+ctxtLevel = le_ctxt_lvl
+
+addLvl :: Level -> VarEnv Level -> InVar -> VarEnv Level
addLvl dest_lvl env v' = extendVarEnv env v' dest_lvl
-addLvls :: Level -> VarEnv Level -> [OutVar] -> VarEnv Level
+addLvls :: Level -> VarEnv Level -> [InVar] -> VarEnv Level
addLvls dest_lvl env vs = foldl' (addLvl dest_lvl) env vs
floatLams :: LevelEnv -> Maybe Int
@@ -1751,9 +1753,6 @@ floatOverSat le = floatOutOverSatApps (le_switches le)
floatTopLvlOnly :: LevelEnv -> Bool
floatTopLvlOnly le = floatToTopLevelOnly (le_switches le)
-incMinorLvlFrom :: LevelEnv -> Level
-incMinorLvlFrom env = incMinorLvl (le_ctxt_lvl env)
-
-- extendCaseBndrEnv adds the mapping case-bndr->scrut-var if it can
-- See Note [Binder-swap during float-out]
extendCaseBndrEnv :: LevelEnv
@@ -1769,34 +1768,25 @@ extendCaseBndrEnv le@(LE { le_subst = subst, le_env = id_env })
, le_env = add_id id_env (case_bndr, scrut_var) }
extendCaseBndrEnv env _ _ = env
-maxFvLevel :: (OutVar -> Bool) -> LevelEnv -> DVarSet -> Level
-maxFvLevel max_me env var_set
- = nonDetStrictFoldDVarSet (maxIn max_me env) tOP_LEVEL var_set
+maxFvLevel :: Bool -> LevelEnv -> DVarSet -> Level
+-- True <=> include type variables
+maxFvLevel include_tyvars (LE { le_lvl_env = env }) var_set
+ = nonDetStrictFoldDVarSet (maxIn include_tyvars env) tOP_LEVEL var_set
-- It's OK to use a non-deterministic fold here because maxIn commutes.
-maxFvLevel' :: (OutVar -> Bool) -> LevelEnv -> TyCoVarSet -> Level
+maxFvLevel' :: Bool -> LevelEnv -> TyCoVarSet -> Level
-- Same but for TyCoVarSet
-maxFvLevel' max_me env var_set
- = nonDetStrictFoldUniqSet (maxIn max_me env) tOP_LEVEL var_set
+maxFvLevel' include_tyvars (LE { le_lvl_env = env }) var_set
+ = nonDetStrictFoldUniqSet (maxIn include_tyvars env) tOP_LEVEL var_set
-- It's OK to use a non-deterministic fold here because maxIn commutes.
-maxIn :: (OutVar -> Bool) -> LevelEnv -> InVar -> Level -> Level
-maxIn max_me (LE { le_lvl_env = lvl_env, le_env = id_env, le_subst = subst }) in_var lvl
- | isId in_var
- = case lookupVarEnv id_env in_var of
- Just (abs_vars, _) -> foldr max_out lvl abs_vars
- Nothing -> max_out in_var lvl
- | otherwise -- TyVars
- = case lookupTyVar subst in_var of
- Just ty -> nonDetStrictFoldVarSet max_out lvl (tyCoVarsOfType ty)
- Nothing -> max_out in_var lvl
- where
- max_out :: OutVar -> Level -> Level
- max_out out_var lvl
- | max_me out_var = case lookupVarEnv lvl_env out_var of
- Just lvl' -> maxLvl lvl' lvl
- Nothing -> lvl
- | otherwise = lvl -- Ignore some vars depending on max_me
+maxIn :: Bool -> VarEnv Level -> InVar -> Level -> Level
+maxIn include_tyvars lvl_env var lvl
+ | not include_tyvars, isTyVar var = lvl
+ | otherwise = maxLvl lvl (lookupLevel lvl_env var)
+
+lookupLevel :: VarEnv Level -> InVar -> Level
+lookupLevel env v = lookupVarEnv env v `orElse` tOP_LEVEL
lookupVar :: LevelEnv -> Id -> LevelledExpr
lookupVar le v = case lookupVarEnv (le_env le) v of
@@ -1841,18 +1831,17 @@ type LvlM result = UniqSM result
initLvl :: UniqSupply -> UniqSM a -> a
initLvl = initUs_
-newPolyBndrs :: Level -> LevelEnv -> [OutVar] -> [InId]
- -> LvlM (LevelEnv, [OutId])
+newPolyBndrs :: LevelEnv -> Level -> [OutVar] -> [InId]
+ -> LvlM (LevelEnv, [LevelledBndr])
-- The envt is extended to bind the new bndrs to dest_lvl, but
-- the le_ctxt_lvl is unaffected
-newPolyBndrs dest_lvl
- env@(LE { le_lvl_env = lvl_env, le_subst = subst, le_env = id_env })
- abs_vars bndrs
+newPolyBndrs env@(LE { le_lvl_env = lvl_env, le_subst = subst, le_env = id_env })
+ dest_lvl abs_vars in_bndrs
= assert (all (not . isCoVar) bndrs) $ -- What would we add to the CoSubst in this case. No easy answer.
do { uniqs <- getUniquesM
; let new_bndrs = zipWith mk_poly_bndr bndrs uniqs
bndr_prs = bndrs `zip` new_bndrs
- env' = env { le_lvl_env = addLvls dest_lvl lvl_env new_bndrs
+ env' = env { le_lvl_env = addLvls dest_lvl lvl_env in_bndrs
, le_subst = foldl' add_subst subst bndr_prs
, le_env = foldl' add_id id_env bndr_prs }
; return (env', new_bndrs) }
@@ -1860,12 +1849,15 @@ newPolyBndrs dest_lvl
add_subst env (v, v') = extendIdSubst env v (mkVarApps (Var v') abs_vars)
add_id env (v, v') = extendVarEnv env v ((v':abs_vars), mkVarApps (Var v') abs_vars)
- mk_poly_bndr bndr uniq = transferPolyIdInfo bndr abs_vars $ -- Note [transferPolyIdInfo] in GHC.Types.Id
- transfer_join_info bndr $
- mkSysLocal str uniq (idMult bndr) poly_ty
- where
- str = fsLit "poly_" `appendFS` occNameFS (getOccName bndr)
- poly_ty = mkLamTypes abs_vars (substTyUnchecked subst (idType bndr))
+ mk_poly_bndr :: InId -> Unique -> LevelledBndr
+ mk_poly_bndr bndr uniq
+ = TB new_bndr (FloatMe dest_lvl)
+ where
+ new_bndr = transferPolyIdInfo bndr abs_vars $ -- Note [transferPolyIdInfo] in GHC.Types.Id
+ transfer_join_info bndr $
+ mkSysLocal str uniq (idMult bndr) poly_ty
+ str = fsLit "poly_" `appendFS` occNameFS (getOccName bndr)
+ poly_ty = mkLamTypes abs_vars (substTyUnchecked subst (idType bndr))
-- If we are floating a join point to top level, it stops being
-- a join point. Otherwise it continues to be a join point,
@@ -1900,21 +1892,22 @@ newLvlVar lvld_rhs join_arity_maybe is_mk_static
= mkSysLocal (mkFastString "lvl") uniq ManyTy rhs_ty
-- | Clone the binders bound by a single-alternative case.
-cloneCaseBndrs :: LevelEnv -> Level -> [Var] -> LvlM (LevelEnv, [Var])
+cloneCaseBndrs :: LevelEnv -> Level -> [Var] -> LvlM (LevelEnv, [LevelledBndr])
cloneCaseBndrs env@(LE { le_subst = subst, le_lvl_env = lvl_env, le_env = id_env })
- new_lvl vs
+ dest_lvl vs
= do { (subst', vs') <- cloneBndrsM subst vs
-- N.B. We are not moving the body of the case, merely its case
-- binders. Consequently we should *not* set le_ctxt_lvl.
-- See Note [Setting levels when floating single-alternative cases].
- ; let env' = env { le_lvl_env = addLvls new_lvl lvl_env vs'
+ ; let lvld_bndrs = stayPut dest_lvl vs'
+ env' = env { le_lvl_env = addLvls dest_lvl lvl_env vs'
, le_subst = subst'
- , le_env = foldl' add_id id_env (vs `zip` vs') }
+ , le_env = foldl' add_id id_env (vs `zip` lvld_bndrs) }
- ; return (env', vs') }
+ ; return (env', lvld_bndrs) }
cloneLetVars :: RecFlag -> LevelEnv -> Level -> [InVar]
- -> LvlM (LevelEnv, [OutVar])
+ -> LvlM (LevelEnv, [LevelledBndr])
-- See Note [Need for cloning during float-out]
-- Works for Ids bound by let(rec)
-- The dest_lvl is attributed to the binders in the new env,
@@ -1927,12 +1920,13 @@ cloneLetVars is_rec
NonRecursive -> cloneBndrsM subst vs1
Recursive -> cloneRecIdBndrsM subst vs1
- ; let prs = vs `zip` vs2
- env' = env { le_lvl_env = addLvls dest_lvl lvl_env vs2
+ ; let lvld_bndrs = [ TB v2 (FloatMe dest_lvl) | v2 <- vs2 ]
+ prs = vs `zip` lvld_bndrs
+ env' = env { le_lvl_env = addLvls dest_lvl lvl_env vs
, le_subst = subst'
, le_env = foldl' add_id id_env prs }
- ; return (env', vs2) }
+ ; return (env', lvld_bndrs) }
where
zap :: Var -> Var
-- See Note [Floatifying demand info when floating]
@@ -1944,10 +1938,11 @@ cloneLetVars is_rec
zap_join | isTopLvl dest_lvl = zapJoinId
| otherwise = id
-add_id :: IdEnv ([Var], LevelledExpr) -> (Var, Var) -> IdEnv ([Var], LevelledExpr)
-add_id id_env (v, v1)
+add_id :: IdEnv ([LevelledBndr], LevelledExpr) -> (Var, LevelledBndr)
+ -> IdEnv ([LevelledBndr], LevelledExpr)
+add_id id_env (v, lb@(TB v1 _))
| isTyVar v = delVarEnv id_env v
- | otherwise = extendVarEnv id_env v ([v1], assert (not (isCoVar v1)) $ Var v1)
+ | otherwise = extendVarEnv id_env v ([lb], assert (not (isCoVar v1)) $ Var v1)
{- Note [Zapping JoinId when floating]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/459bd467af024a2570e5d3ac6ca5328…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/459bd467af024a2570e5d3ac6ca5328…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
19 Dec '25
Rodrigo Mesquita pushed to branch wip/romes/25636 at Glasgow Haskell Compiler / GHC
Commits:
96c451aa by Rodrigo Mesquita at 2025-12-19T10:21:32+00:00
wip
- - - - -
e8aeb770 by Rodrigo Mesquita at 2025-12-19T13:57:27+00:00
No such StaticConObj needed
- - - - -
8 changed files:
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Builtin/Types/Prim.hs
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Linker.hs
- libraries/ghci/GHCi/CreateBCO.hs
- rts/PrimOps.cmm
- utils/genprimopcode/Main.hs
Changes:
=====================================
compiler/GHC/Builtin/Names.hs
=====================================
@@ -2099,9 +2099,6 @@ exceptionContextTyConKey = mkPreludeTyConUnique 420
unsafeUnpackJSStringUtf8ShShKey = mkPreludeMiscIdUnique 805
-staticConObjPrimTyConKey :: Unique
-staticConObjPrimTyConKey = mkPreludeTyConUnique 501
-
{-
************************************************************************
* *
=====================================
compiler/GHC/Builtin/Types/Prim.hs
=====================================
@@ -82,7 +82,6 @@ module GHC.Builtin.Types.Prim(
stableNamePrimTyCon, mkStableNamePrimTy,
compactPrimTyCon, compactPrimTy,
bcoPrimTyCon, bcoPrimTy,
- staticConObjPrimTyCon, staticConObjPrimTy,
weakPrimTyCon, mkWeakPrimTy,
threadIdPrimTyCon, threadIdPrimTy,
stackSnapshotPrimTyCon, stackSnapshotPrimTy,
@@ -310,7 +309,7 @@ charPrimTyConName, intPrimTyConName, int8PrimTyConName, int16PrimTyConName, int3
mutableArrayPrimTyConName, mutableByteArrayPrimTyConName,
smallMutableArrayPrimTyConName, mutVarPrimTyConName, mVarPrimTyConName,
tVarPrimTyConName, stablePtrPrimTyConName,
- stableNamePrimTyConName, compactPrimTyConName, bcoPrimTyConName, staticConObjPrimTyConName,
+ stableNamePrimTyConName, compactPrimTyConName, bcoPrimTyConName,
weakPrimTyConName, threadIdPrimTyConName,
eqPrimTyConName, eqReprPrimTyConName, eqPhantPrimTyConName,
stackSnapshotPrimTyConName, promptTagPrimTyConName :: Name
@@ -348,7 +347,6 @@ stableNamePrimTyConName = mkPrimTc (fsLit "StableName#") stableNamePrimTyC
compactPrimTyConName = mkPrimTc (fsLit "Compact#") compactPrimTyConKey compactPrimTyCon
stackSnapshotPrimTyConName = mkPrimTc (fsLit "StackSnapshot#") stackSnapshotPrimTyConKey stackSnapshotPrimTyCon
bcoPrimTyConName = mkPrimTc (fsLit "BCO") bcoPrimTyConKey bcoPrimTyCon
-staticConObjPrimTyConName = mkPrimTc (fsLit "StaticConObj#") staticConObjPrimTyConKey staticConObjPrimTyCon
weakPrimTyConName = mkPrimTc (fsLit "Weak#") weakPrimTyConKey weakPrimTyCon
threadIdPrimTyConName = mkPrimTc (fsLit "ThreadId#") threadIdPrimTyConKey threadIdPrimTyCon
promptTagPrimTyConName = mkPrimTc (fsLit "PromptTag#") promptTagPrimTyConKey promptTagPrimTyCon
@@ -1401,12 +1399,6 @@ bcoPrimTy = mkTyConTy bcoPrimTyCon
bcoPrimTyCon :: TyCon
bcoPrimTyCon = pcPrimTyCon0 bcoPrimTyConName liftedRepTy
--- A static constructor object is never a thunk, unlike BCOs
-staticConObjPrimTy :: Type
-staticConObjPrimTy = mkTyConTy staticConObjPrimTyCon
-staticConObjPrimTyCon :: TyCon
-staticConObjPrimTyCon = pcPrimTyCon0 staticConObjPrimTyConName unliftedRepTy
-
{-
************************************************************************
* *
=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -3909,9 +3909,6 @@ section "Bytecode operations"
primtype BCO
{ Primitive bytecode type. }
-primtype StaticConObj#
- { Primitive static constructor allocated on the heap type. }
-
primop AddrToAnyOp "addrToAny#" GenPrimOp
Addr# -> (# a_levpoly #)
{ Convert an 'Addr#' to a followable Any type. }
@@ -3951,7 +3948,7 @@ primop NewBCOOp "newBCO#" GenPrimOp
out_of_line = True
primop NewStaticConOp "newStaticCon#" GenPrimOp
- Array# a -> Int# -> State# s -> (# State# s, StaticConObj# #)
+ Addr# -> Array# a -> Int# -> State# s -> (# State# s, a #)
{ @'newStaticCon#' data size@ creates a new static constructor object. The
resulting object points to the given data laid out contiguously on a heap allocated location.
The first element of the @data@ array must be a pointer to the info table representing the
=====================================
compiler/GHC/ByteCode/Asm.hs
=====================================
@@ -161,9 +161,9 @@ assembleBCOs profile proto_bcos tycons top_strs modbreaks spt_entries = do
--
data RunAsmReader = RunAsmReader { isn_array :: {-# UNPACK #-} !(Array.IOUArray Int Word16)
- , ptr_array :: {-# UNPACK #-} !(SmallMutableArrayIO BCOPtr)
- , lit_array :: {-# UNPACK #-} !(SmallMutableArrayIO BCONPtr )
- }
+ , ptr_array :: {-# UNPACK #-} !(SmallMutableArrayIO BCOPtr)
+ , lit_array :: {-# UNPACK #-} !(SmallMutableArrayIO BCONPtr)
+ }
data RunAsmResult = RunAsmResult { final_isn_array :: !(Array.UArray Int Word16)
, final_ptr_array :: !(SmallArray BCOPtr)
=====================================
compiler/GHC/ByteCode/Linker.hs
=====================================
@@ -65,9 +65,7 @@ linkBCO
-> IO ResolvedBCO
linkBCO interp pkgs_loaded le lb bco_ix
(UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do
- -- fromIntegral Word -> Word64 should be a no op if Word is Word64
- -- otherwise it will result in a cast to longlong on 32bit systems.
- (lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le lb) (elemsFlatBag lits0)
+ (lits :: [Word]) <- mapM (lookupLiteral interp pkgs_loaded le lb) (elemsFlatBag lits0)
ptrs <- mapM (resolvePtr interp pkgs_loaded le lb bco_ix) (elemsFlatBag ptrs0)
let lits' = listArray (0 :: Int, fromIntegral (sizeFlatBag lits0)-1) lits
return $ ResolvedBCO { resolvedBCOIsLE = isLittleEndian
=====================================
libraries/ghci/GHCi/CreateBCO.hs
=====================================
@@ -33,6 +33,7 @@ import GHC.Internal.Base ( BCO, mkApUpd0#, newBCO# )
import GHC.IO
import Control.Exception ( ErrorCall(..) )
import Data.Kind
+import Data.Maybe
createBCOs :: [ResolvedBCO] -> IO [HValueRef]
createBCOs bcos = do
@@ -52,7 +53,7 @@ createBCO _ obj | resolvedBCOIsLE obj /= isLittleEndian
createBCO arr bco
= do linked_thing <- linkBCO' arr bco
case linked_thing of
- LeftL linked_bco -> do
+ Left linked_bco -> do
-- Note [Updatable CAF BCOs]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~
-- Why do we need mkApUpd0 here? Otherwise top-level
@@ -72,10 +73,10 @@ createBCO arr bco
then return (HValue (unsafeCoerce linked_bco))
else case mkApUpd0# linked_bco of { (# final_bco #) ->
return (HValue final_bco) }
- RightU linked_static_con -> do
+ Right linked_static_con -> do
return (HValue (unsafeCoerce linked_static_con))
-linkBCO' :: Array Int HValue -> ResolvedBCO -> IO (EitherLU BCO StaticConObj#)
+linkBCO' :: Array Int HValue -> ResolvedBCO -> IO (Either BCO HValue)
linkBCO' arr ResolvedBCO{..} = do
let
ptrs = ssElts resolvedBCOPtrs
@@ -97,7 +98,7 @@ linkBCO' arr ResolvedBCO{..} = do
}}
linkBCO' arr ResolvedStaticCon{..} = do
- let data_size@(I# data_size#)
+ let data_size@(W# data_size#)
= sizeSS resolvedStaticConData
data_els = ssElts resolvedStaticConData
@@ -105,17 +106,17 @@ linkBCO' arr ResolvedStaticCon{..} = do
PtrsArr marr <- mkPtrsArray arr data_size $
mapMaybe (\case
(Left _,_) -> Nothing
- (Right p,_) -> Just p
+ (Right p,i) -> Just (p, i)
) (zip data_els [0..])
-- Second, write literals at the remaining location
- writeLiterals marr $
+ writeLiterals (unsafeCoerce# marr) $
mapMaybe (\case
- (Left l,_) -> Just l
+ (Left l,i) -> Just (l, i)
(Right _,_) -> Nothing
) (zip data_els [0..])
IO $ \s ->
- case unsafeFreezeArray# marr' s of { (# s, arr #) ->
+ case unsafeFreezeArray# marr s of { (# s, arr #) ->
newStaticCon# arr data_size# s
}
where
@@ -126,9 +127,6 @@ linkBCO' arr ResolvedStaticCon{..} = do
writeLiteral arr w i = IO $ \s ->
case writeArray# arr i w s of s' -> (# s', () #)
--- | Either for lifted @a@ and unlifted @b@
-data EitherLU (a :: Type) (b :: UnliftedType) = LeftL a | RightU b
-
-- we recursively link any sub-BCOs while making the ptrs array
mkPtrsArray :: Array Int HValue -> Word -> [(ResolvedBCOPtr, Int{-index of array at which to write ResolvedBCOPtr-})] -> IO PtrsArr
mkPtrsArray arr n_ptrs ptrs = do
=====================================
rts/PrimOps.cmm
=====================================
@@ -2185,15 +2185,24 @@ stg_newStaticConzh ( P_ data, W_ size )
{
W_ staticConObj, itbl, bytes;
+ // TODO: Could probably use the bytes from the StgArrBytes
bytes = WDS(size);
ALLOC_PRIM (bytes);
staticConObj = Hp - bytes;
- // No memory barrier necessary as this is a new allocation.
- SET_HDR(staticConObj, stg_BCO_info, CCS_MAIN);
- TODOOOOOOO
+ // Copy the data (which includes the itbl pointer for this static con)
+ W_ i;
+ i = 0;
+for:
+ if (i < size) {
+ W_[staticConObj + WDS(i)] = StgArrBytes_payload(data,i);
+ i = i + 1;
+ goto for;
+ }
+
+ return (staticConObj);
}
stg_mkApUpd0zh ( P_ bco )
=====================================
utils/genprimopcode/Main.hs
=====================================
@@ -944,7 +944,6 @@ ppType (TyApp (TyCon "RealWorld") []) = "realWorldTy"
ppType (TyApp (TyCon "ThreadId#") []) = "threadIdPrimTy"
ppType (TyApp (TyCon "ForeignObj#") []) = "foreignObjPrimTy"
ppType (TyApp (TyCon "BCO") []) = "bcoPrimTy"
-ppType (TyApp (TyCon "StaticConObj#") []) = "staticConObjPrimTy"
ppType (TyApp (TyCon "Compact#") []) = "compactPrimTy"
ppType (TyApp (TyCon "StackSnapshot#") []) = "stackSnapshotPrimTy"
ppType (TyApp (TyCon "()") []) = "unitTy" -- unitTy is GHC.Builtin.Types's name for ()
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5aaacfeb18855e50cafe15b6667ddf…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5aaacfeb18855e50cafe15b6667ddf…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Zubin pushed new tag ghc-9.14.1-release at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/ghc-9.14.1-release
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/mp/iface-patches-9.10] Refactor the Binary serialisation interface
by Matthew Pickering (@mpickering) 19 Dec '25
by Matthew Pickering (@mpickering) 19 Dec '25
19 Dec '25
Matthew Pickering pushed to branch wip/mp/iface-patches-9.10 at Glasgow Haskell Compiler / GHC
Commits:
b15caeb0 by Fendor at 2025-12-19T09:43:37+00:00
Refactor the Binary serialisation interface
The goal is simplifiy adding deduplication tables to `ModIface`
interface serialisation.
We identify two main points of interest that make this difficult:
1. UserData hardcodes what `Binary` instances can have deduplication
tables. Moreover, it heavily uses partial functions.
2. GHC.Iface.Binary hardcodes the deduplication tables for 'Name' and
'FastString', making it difficult to add more deduplication.
Instead of having a single `UserData` record with fields for all the
types that can have deduplication tables, we allow to provide custom
serialisers for any `Typeable`.
These are wrapped in existentials and stored in a `Map` indexed by their
respective `TypeRep`.
The `Binary` instance of the type to deduplicate still needs to
explicitly look up the decoder via `findUserDataReader` and
`findUserDataWriter`, which is no worse than the status-quo.
`Map` was chosen as microbenchmarks indicate it is the fastest for a
small number of keys (< 10).
To generalise the deduplication table serialisation mechanism, we
introduce the types `ReaderTable` and `WriterTable` which provide a
simple interface that is sufficient to implement a general purpose
deduplication mechanism for `writeBinIface` and `readBinIface`.
This allows us to provide a list of deduplication tables for
serialisation that can be extended more easily, for example for
`IfaceTyCon`, see the issue https://gitlab.haskell.org/ghc/ghc/-/issues/24540
for more motivation.
In addition to this refactoring, we split `UserData` into `ReaderUserData`
and `WriterUserData`, to avoid partial functions and reduce overall
memory usage, as we need fewer mutable variables.
Bump haddock submodule to accomodate for `UserData` split.
-------------------------
Metric Increase:
MultiLayerModulesTH_Make
MultiLayerModulesRecomp
T21839c
-------------------------
Split `BinHandle` into `ReadBinHandle` and `WriteBinHandle`
A `BinHandle` contains too much information for reading data.
For example, it needs to keep a `FastMutInt` and a `IORef BinData`,
when the non-mutable variants would suffice.
Additionally, this change has the benefit that anyone can immediately
tell whether the `BinHandle` is used for reading or writing.
Bump haddock submodule BinHandle split.
Add Eq and Ord instance to `IfaceType`
We add an `Ord` instance so that we can store `IfaceType` in a
`Data.Map` container.
This is required to deduplicate `IfaceType` while writing `.hi` files to
disk. Deduplication has many beneficial consequences to both file size
and memory usage, as the deduplication enables implicit sharing of
values.
See issue #24540 for more motivation.
The `Ord` instance would be unnecessary if we used a `TrieMap` instead
of `Data.Map` for the deduplication process. While in theory this is
clerarly the better option, experiments on the agda code base showed
that a `TrieMap` implementation has worse run-time performance
characteristics.
To the change itself, we mostly derive `Eq` and `Ord`. This requires us
to change occurrences of `FastString` with `LexicalFastString`, since
`FastString` has no `Ord` instance.
We change the definition of `IfLclName` to a newtype of
`LexicalFastString`, to make such changes in the future easier.
Bump haddock submodule for IfLclName changes
Move out LiteralMap to avoid cyclic module dependencies
Add deduplication table for `IfaceType`
The type `IfaceType` is a highly redundant, tree-like data structure.
While benchmarking, we realised that the high redundancy of `IfaceType`
causes high memory consumption in GHCi sessions when byte code is
embedded into the `.hi` file via `-fwrite-if-simplified-core` or
`-fbyte-code-and-object-code`.
Loading such `.hi` files from disk introduces many duplicates of
memory expensive values in `IfaceType`, such as `IfaceTyCon`,
`IfaceTyConApp`, `IA_Arg` and many more.
We improve the memory behaviour of GHCi by adding an additional
deduplication table for `IfaceType` to the serialisation of `ModIface`,
similar to how we deduplicate `Name`s and `FastString`s.
When reading the interface file back, the table allows us to automatically
share identical values of `IfaceType`.
To provide some numbers, we evaluated this patch on the agda code base.
We loaded the full library from the `.hi` files, which contained the
embedded core expressions (`-fwrite-if-simplified-core`).
Before this patch:
* Load time: 11.7 s, 2.5 GB maximum residency.
After this patch:
* Load time: 7.3 s, 1.7 GB maximum residency.
This deduplication has the beneficial side effect to additionally reduce
the size of the on-disk interface files tremendously.
For example, on agda, we reduce the size of `.hi` files (with
`-fwrite-if-simplified-core`):
* Before: 101 MB on disk
* Now: 24 MB on disk
This has even a beneficial side effect on the cabal store. We reduce the
size of the store on disk:
* Before: 341 MB on disk
* Now: 310 MB on disk
Note, none of the dependencies have been compiled with
`-fwrite-if-simplified-core`, but `IfaceType` occurs in multiple
locations in a `ModIface`.
We also add IfaceType deduplication table to .hie serialisation and
refactor .hie file serialisation to use the same infrastrucutre as
`putWithTables`.
Bump haddock submodule to accomodate for changes to the deduplication
table layout and binary interface.
Add run-time configurability of `.hi` file compression
Introduce the flag `-fwrite-if-compression=<n>` which allows to
configure the compression level of writing .hi files.
The motivation is that some deduplication operations are too expensive
for the average use case. Hence, we introduce multiple compression
levels with variable impact on performance, but still reduce the
memory residency and `.hi` file size on disk considerably.
We introduce three compression levels:
* `1`: `Normal` mode. This is the least amount of compression.
It deduplicates only `Name` and `FastString`s, and is naturally the
fastest compression mode.
* `2`: `Safe` mode. It has a noticeable impact on .hi file size and is
marginally slower than `Normal` mode. In general, it should be safe to
always use `Safe` mode.
* `3`: `Full` deduplication mode. Deduplicate as much as we can,
resulting in minimal .hi files, but at the cost of additional
compilation time.
Reading .hi files doesn't need to know the initial compression level,
and can always deserialise a `ModIface`, as we write out a byte that
indicates the next value has been deduplicated.
This allows users to experiment with different compression levels for
packages, without recompilation of dependencies.
Note, the deduplication also has an additional side effect of reduced
memory consumption to implicit sharing of deduplicated elements.
See https://gitlab.haskell.org/ghc/ghc/-/issues/24540 for example where
that matters.
-------------------------
Metric Decrease:
MultiLayerModulesDefsGhciWithCore
T16875
T21839c
T24471
hard_hole_fits
libdir
-------------------------
Improve sharing of duplicated values in `ModIface`, fixes #24723
As a `ModIface` often contains duplicated values that are not
necessarily shared, we improve sharing by serialising the `ModIface`
to an in-memory byte array. Serialisation uses deduplication tables, and
deserialisation implicitly shares duplicated values.
This helps reducing the peak memory usage while compiling in
`--make` mode. The peak memory usage is especially smaller when
generating interface files with core expressions
(`-fwrite-if-simplified-core`).
On agda, this reduces the peak memory usage:
* `2.2 GB` to `1.9 GB` for a ghci session.
On `lib:Cabal`, we report:
* `570 MB` to `500 MB` for a ghci session
* `790 MB` to `667 MB` for compiling `lib:Cabal` with ghc
There is a small impact on execution time, around 2% on the agda code
base.
Avoid unneccessarily re-serialising the `ModIface`
To reduce memory usage of `ModIface`, we serialise `ModIface` to an
in-memory byte array, which implicitly shares duplicated values.
This serialised byte array can be reused to avoid work when we actually
write the `ModIface` to disk.
We introduce a new field to `ModIface` which allows us to save the byte
array, and write it direclty to disk if the `ModIface` wasn't changed
after the initial serialisation.
This requires us to change absolute offsets, for example to jump to the
deduplication table for `Name` or `FastString` with relative offsets, as
the deduplication byte array doesn't contain header information, such as
fingerprints.
To allow us to dump the binary blob to disk, we need to replace all
absolute offsets with relative ones.
We introduce additional helpers for `ModIface` binary serialisation, which
construct relocatable binary blobs. We say the binary blob is relocatable,
if the binary representation can be moved and does not contain any
absolute offsets.
Further, we introduce new primitives for `Binary` that allow to create
relocatable binaries, such as `forwardGetRel` and `forwardPutRel`.
-------------------------
Metric Decrease:
MultiLayerModulesDefsGhcWithCore
Metric Increase:
MultiComponentModules
MultiLayerModules
T10421
T12150
T12234
T12425
T13035
T13253-spj
T13701
T13719
T14697
T15703
T16875
T18698b
T18140
T18304
T18698a
T18730
T18923
T20049
T24582
T5837
T6048
T9198
T9961
mhu-perf
-------------------------
These metric increases may look bad, but they are all completely benign,
we simply allocate 1 MB per module for `shareIface`. As this allocation
is quite quick, it has a negligible impact on run-time performance.
In fact, the performance difference wasn't measurable on my local
machine. Reducing the size of the pre-allocated 1 MB buffer avoids these
test failures, but also requires us to reallocate the buffer if the
interface file is too big. These reallocations *did* have an impact on
performance, which is why I have opted to accept all these metric
increases, as the number of allocated bytes is merely a guidance.
This 1MB allocation increase causes a lot of tests to fail that
generally have a low allocation number. E.g., increasing from 40MB to
41MB is a 2.5% increase.
In particular, the tests T12150, T13253-spj, T18140, T18304, T18698a,
T18923, T20049, T24582, T5837, T6048, and T9961 only fail on i386-darwin
job, where the number of allocated bytes seems to be lower than in other
jobs.
The tests T16875 and T18698b fail on i386-linux for the same reason.
WIP: Lazy loading of IfaceDecl
- - - - -
44 changed files:
- compiler/GHC.hs
- compiler/GHC/Core/Map/Expr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Data/TrieMap.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Env.hs
- compiler/GHC/Iface/Ext/Binary.hs
- compiler/GHC/Iface/Ext/Fields.hs
- compiler/GHC/Iface/Ext/Utils.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Recomp/Binary.hs
- compiler/GHC/Iface/Recomp/Flags.hs
- compiler/GHC/Iface/Rename.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/IfaceToCore.hs-boot
- compiler/GHC/Stg/CSE.hs
- compiler/GHC/StgToJS/Object.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/FieldLabel.hs
- compiler/GHC/Types/Name.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Unit/Module/ModIface.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Binary/Typeable.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/Language/Haskell/Syntax/Type.hs-boot
- docs/users_guide/using-optimisation.rst
- testsuite/tests/plugins/simple-plugin/Simple/RemovePlugin.hs
- utils/haddock
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b15caeb035b418021ab45b259a33a33…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b15caeb035b418021ab45b259a33a33…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
19 Dec '25
Simon Peyton Jones pushed to branch wip/T23162-part2 at Glasgow Haskell Compiler / GHC
Commits:
0432673b by Simon Peyton Jones at 2025-12-19T08:31:15+00:00
Add release notes
- - - - -
1 changed file:
- docs/users_guide/9.16.1-notes.rst
Changes:
=====================================
docs/users_guide/9.16.1-notes.rst
=====================================
@@ -42,6 +42,13 @@ Compiler
bound to variables. The very similar pattern ``Foo{bar = Bar{baz = 42}}``
will will not yet mark ``bar`` or ``baz`` as covered.
+- GHC uses the information from the definition of a *closed* type family to
+ generate some extra functional dependencies for type equalities involving
+ that type family. As a consequence:
+
+ * typechecking will succeed a bit more often (see :ghc-ticket:`23162`)
+ * pattern-match incompleteness checking is a bit smarter, giving fewer false warnings (see :ghc-ticket:`#22652`)
+
- When multiple ``-msse*`` flags are given, the maximum version takes effect.
For example, ``-msse4.2 -msse2`` is now equivalent to ``-msse4.2``.
Previously, only the last flag took effect.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0432673bdcba2c3c696f713b59c3ef9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0432673bdcba2c3c696f713b59c3ef9…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] wasm: fix handling of ByteArray#/MutableByteArray# arguments in JSFFI imports
by Marge Bot (@marge-bot) 19 Dec '25
by Marge Bot (@marge-bot) 19 Dec '25
19 Dec '25
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
f69c5f14 by Cheng Shao at 2025-12-19T03:19:45-05:00
wasm: fix handling of ByteArray#/MutableByteArray# arguments in JSFFI imports
This patch fixes the handling of ByteArray#/MutableByteArray#
arguments in JSFFI imports, see the amended note and manual for
explanation. Also adds a test to witness the fix.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
7 changed files:
- compiler/GHC/HsToCore/Foreign/Wasm.hs
- docs/users_guide/wasm.rst
- testsuite/tests/jsffi/all.T
- + testsuite/tests/jsffi/bytearrayarg.hs
- + testsuite/tests/jsffi/bytearrayarg.mjs
- + testsuite/tests/jsffi/bytearrayarg.stdout
- testsuite/tests/perf/should_run/all.T
Changes:
=====================================
compiler/GHC/HsToCore/Foreign/Wasm.hs
=====================================
@@ -224,6 +224,25 @@ especially since leaving all the boxing/unboxing business to C unifies
the implementation of JSFFI imports and exports
(rts_mkJSVal/rts_getJSVal).
+We don't support unboxed FFI types like Int# etc. But we do support
+one kind of unlifted FFI type for JSFFI import arguments:
+ByteArray#/MutableByteArray#. The semantics is the same in C: the
+pointer to the ByteArray# payload is passed instead of the ByteArray#
+closure itself. This allows efficient zero-copy data exchange between
+Haskell and JavaScript using unpinned ByteArray#, and the following
+conditions must be met:
+
+- The JSFFI import itself must be a sync import marked as unsafe
+- The JavaScript code must not re-enter Haskell when a ByteArray# is
+ passed as argument
+
+There's no magic in the handling of ByteArray#/MutableByteArray#
+arguments. When generating C stub, we treat them like Ptr that points
+to the payload, just without the rts_getPtr() unboxing call. After
+lowering to C import, the backend takes care of adding the offset, see
+add_shim in GHC.StgToCmm.Foreign and
+Note [Unlifted boxed arguments to foreign calls].
+
Now, each sync import calls a generated C function with a unique
symbol. The C function uses rts_get* to unbox the arguments, call into
JavaScript, then boxes the result with rts_mk* and returns it to
@@ -517,8 +536,9 @@ importCStub sync cfun_name arg_tys res_ty js_src = CStub c_doc [] []
cfun_ret
| res_ty `eqType` unitTy = cfun_call_import <> semi
| otherwise = text "return" <+> cfun_call_import <> semi
- cfun_make_arg arg_ty arg_val =
- text ("rts_get" ++ ffiType arg_ty) <> parens arg_val
+ cfun_make_arg arg_ty arg_val
+ | isByteArrayPrimTy arg_ty = arg_val
+ | otherwise = text ("rts_get" ++ ffiType arg_ty) <> parens arg_val
cfun_make_ret ret_val
| res_ty `eqType` unitTy = ret_val
| otherwise =
@@ -543,7 +563,11 @@ importCStub sync cfun_name arg_tys res_ty js_src = CStub c_doc [] []
| res_ty `eqType` unitTy = text "void"
| otherwise = text "HaskellObj"
cfun_arg_list =
- [text "HaskellObj" <+> char 'a' <> int n | n <- [1 .. length arg_tys]]
+ [ text (if isByteArrayPrimTy arg_ty then "HsPtr" else "HaskellObj")
+ <+> char 'a'
+ <> int n
+ | (arg_ty, n) <- zip arg_tys [1 ..]
+ ]
cfun_args = case cfun_arg_list of
[] -> text "void"
_ -> hsep $ punctuate comma cfun_arg_list
@@ -746,8 +770,18 @@ lookupGhcInternalTyCon m t = do
n <- lookupOrig (mkGhcInternalModule m) (mkTcOcc t)
dsLookupTyCon n
+isByteArrayPrimTy :: Type -> Bool
+isByteArrayPrimTy ty
+ | Just tc <- tyConAppTyCon_maybe ty,
+ tc == byteArrayPrimTyCon || tc == mutableByteArrayPrimTyCon =
+ True
+ | otherwise =
+ False
+
ffiType :: Type -> String
-ffiType = occNameString . getOccName . fst . splitTyConApp
+ffiType ty
+ | isByteArrayPrimTy ty = "Ptr"
+ | otherwise = occNameString $ getOccName $ tyConAppTyCon ty
commonCDecls :: SDoc
commonCDecls =
=====================================
docs/users_guide/wasm.rst
=====================================
@@ -265,7 +265,7 @@ backend’s JavaScript FFI, which we’ll now abbreviate as JSFFI.
Marshalable types and ``JSVal``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-JSFFI supports all boxed marshalable foreign types in C FFI:
+JSFFI supports all lifted marshalable foreign types in C FFI:
- ``Bool``
- ``Char``
@@ -298,8 +298,14 @@ types in JSFFI. Some caveats to keep in mind:
results in type errors, so keep this in mind. As for ``Int`` /
``Word``, they are 32-bit since the GHC wasm backend is based on
``wasm32`` .
-- JSFFI doesn’t support unboxed foreign types like ``Int#``,
- ``ByteArray#``, etc, even when ``UnliftedFFITypes`` is enabled.
+- JSFFI doesn’t support unboxed foreign types like ``Int#``, even
+ when ``UnliftedFFITypes`` is enabled. The only supported unlifted
+ types are ``ByteArray#`` and ``MutableByteArray#``, they may only
+ be used as JSFFI import argument types, with the same semantics in
+ C FFI: the pointer to the payload is passed to JavaScript. Be
+ careful and avoid calling back into Haskell in such cases,
+ otherwise GC may occur and the pointer may be invalidated if it's
+ unpinned!
In addition to the above types, JSFFI supports the ``JSVal`` type and
its ``newtype``\ s as argument/result types. ``JSVal`` is defined in
=====================================
testsuite/tests/jsffi/all.T
=====================================
@@ -25,4 +25,6 @@ test('jsffion', [], compile_and_run, ['-optl-Wl,--export=main'])
test('jsffisleep', [], compile_and_run, ['-optl-Wl,--export=testWouldBlock,--export=testLazySleep,--export=testThreadDelay,--export=testInterruptingSleep'])
+test('bytearrayarg', [], compile_and_run, ['-optl-Wl,--export=main'])
+
test('textconv', [], compile_and_run, ['-optl-Wl,--export=main'])
=====================================
testsuite/tests/jsffi/bytearrayarg.hs
=====================================
@@ -0,0 +1,39 @@
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnliftedFFITypes #-}
+
+module Test where
+
+import GHC.Exts
+import GHC.IO
+import GHC.Word (Word8(W8#))
+
+foreign import javascript unsafe "(() => { const u8 = new Uint8Array(__exports.memory.buffer, $1, 4); return (u8[0] === 0x12 && u8[1] === 0x34 && u8[2] === 0x56 && u8[3] === 0x78) ? 1 : 0; })()"
+ js_check_mba :: MutableByteArray# RealWorld -> IO Int
+
+foreign import javascript unsafe "(() => { const u8 = new Uint8Array(__exports.memory.buffer, $1, 4); return (u8[0] === 0x12 && u8[1] === 0x34 && u8[2] === 0x56 && u8[3] === 0x78) ? 1 : 0; })()"
+ js_check_ba :: ByteArray# -> IO Int
+
+foreign export javascript "main"
+ main :: IO ()
+
+main :: IO ()
+main =
+ IO $ \s0 ->
+ case newPinnedByteArray# 4# s0 of
+ (# s1, mba# #) ->
+ case (0x12 :: Word8) of { W8# b0# ->
+ case (0x34 :: Word8) of { W8# b1# ->
+ case (0x56 :: Word8) of { W8# b2# ->
+ case (0x78 :: Word8) of { W8# b3# ->
+ let s2 = writeWord8Array# mba# 0# b0# s1
+ s3 = writeWord8Array# mba# 1# b1# s2
+ s4 = writeWord8Array# mba# 2# b2# s3
+ s5 = writeWord8Array# mba# 3# b3# s4
+ in case unIO (js_check_mba mba#) s5 of
+ (# s6, ok_mba #) -> case unsafeFreezeByteArray# mba# s6 of
+ (# s7, ba# #) -> case unIO (js_check_ba ba#) s7 of
+ (# s8, ok_ba #) -> case unIO (print ok_mba) s8 of
+ (# s9, _ #) -> case unIO (print ok_ba) s9 of
+ (# s10, _ #) -> (# s10, () #)
+ }}}}
=====================================
testsuite/tests/jsffi/bytearrayarg.mjs
=====================================
@@ -0,0 +1,4 @@
+export default async (__exports) => {
+ await __exports.main();
+ process.exit();
+}
=====================================
testsuite/tests/jsffi/bytearrayarg.stdout
=====================================
@@ -0,0 +1,2 @@
+1
+1
=====================================
testsuite/tests/perf/should_run/all.T
=====================================
@@ -420,6 +420,7 @@ test('T17949', [collect_stats('bytes allocated', 1), only_ways(['normal'])], com
test('ByteCodeAsm',
[ extra_run_opts('"' + config.libdir + '"')
, js_broken(22261)
+ , when(arch('wasm32'), run_timeout_multiplier(10))
, collect_stats('bytes allocated', 10),
],
compile_and_run,
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f69c5f1492b275da7d2947612574d5c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f69c5f1492b275da7d2947612574d5c…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Remove unused known keys and names for generics classes
by Marge Bot (@marge-bot) 19 Dec '25
by Marge Bot (@marge-bot) 19 Dec '25
19 Dec '25
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
73ee7e38 by Wolfgang Jeltsch at 2025-12-19T03:19:02-05:00
Remove unused known keys and names for generics classes
This removes the known-key and corresponding name variables for
`Datatype`, `Constructor`, and `Selector` from `GHC.Generics`, as they
are apparently nowhere used in GHC’s source code.
- - - - -
1 changed file:
- compiler/GHC/Builtin/Names.hs
Changes:
=====================================
compiler/GHC/Builtin/Names.hs
=====================================
@@ -476,7 +476,6 @@ basicKnownKeyNames
-- Generics
, genClassName, gen1ClassName
- , datatypeClassName, constructorClassName, selectorClassName
-- Monad comprehensions
, guardMName
@@ -1480,15 +1479,10 @@ readClassName :: Name
readClassName = clsQual gHC_INTERNAL_READ (fsLit "Read") readClassKey
-- Classes Generic and Generic1, Datatype, Constructor and Selector
-genClassName, gen1ClassName, datatypeClassName, constructorClassName,
- selectorClassName :: Name
+genClassName, gen1ClassName :: Name
genClassName = clsQual gHC_INTERNAL_GENERICS (fsLit "Generic") genClassKey
gen1ClassName = clsQual gHC_INTERNAL_GENERICS (fsLit "Generic1") gen1ClassKey
-datatypeClassName = clsQual gHC_INTERNAL_GENERICS (fsLit "Datatype") datatypeClassKey
-constructorClassName = clsQual gHC_INTERNAL_GENERICS (fsLit "Constructor") constructorClassKey
-selectorClassName = clsQual gHC_INTERNAL_GENERICS (fsLit "Selector") selectorClassKey
-
genericClassNames :: [Name]
genericClassNames = [genClassName, gen1ClassName]
@@ -1739,15 +1733,10 @@ applicativeClassKey = mkPreludeClassUnique 34
foldableClassKey = mkPreludeClassUnique 35
traversableClassKey = mkPreludeClassUnique 36
-genClassKey, gen1ClassKey, datatypeClassKey, constructorClassKey,
- selectorClassKey :: Unique
+genClassKey, gen1ClassKey :: Unique
genClassKey = mkPreludeClassUnique 37
gen1ClassKey = mkPreludeClassUnique 38
-datatypeClassKey = mkPreludeClassUnique 39
-constructorClassKey = mkPreludeClassUnique 40
-selectorClassKey = mkPreludeClassUnique 41
-
-- KnownNat: see Note [KnownNat & KnownSymbol and EvLit] in GHC.Tc.Instance.Class
knownNatClassNameKey :: Unique
knownNatClassNameKey = mkPreludeClassUnique 42
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/73ee7e38f5792c3bb9d5d61d9621d54…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/73ee7e38f5792c3bb9d5d61d9621d54…
You're receiving this email because of your account on gitlab.haskell.org.
1
0