[Git][ghc/ghc][wip/az/ghc-cpp] 123 commits: Add LoongArch NCG support
by Alan Zimmerman (@alanz) 15 May '25
by Alan Zimmerman (@alanz) 15 May '25
15 May '25
Alan Zimmerman pushed to branch wip/az/ghc-cpp at Glasgow Haskell Compiler / GHC
Commits:
652cba7e by Peng Fan at 2025-05-14T04:24:35-04:00
Add LoongArch NCG support
Not supported before.
- - - - -
c01f4374 by Lin Runze at 2025-05-14T04:24:35-04:00
ci: Add LoongArch64 cross-compile CI for testing
- - - - -
ce6cf240 by Ben Gamari at 2025-05-14T04:25:18-04:00
rts/linker: Don't fail due to RTLD_NOW
In !12264 we started using the NativeObj machinery introduced some time
ago for loading of shared objects. One of the side-effects of this
change is shared objects are now loaded eagerly (i.e. with `RTLD_NOW`).
This is needed by NativeObj to ensure full visibility of the mappings of
the loaded object, which is in turn needed for safe shared object
unloading.
Unfortunately, this change subtly regressed, causing compilation
failures in some programs. Specifically, shared objects which refer to
undefined symbols (e.g. which may be usually provided by either the
executable image or libraries loaded via `dlopen`) will fail to load
with eager binding. This is problematic as GHC loads all package
dependencies while, e.g., evaluating TemplateHaskell splices. This
results in compilation failures in programs depending upon (but not
using at compile-time) packages with undefined symbol references.
To mitigate this NativeObj now first attempts to load an object via
eager binding, reverting to lazy binding (and disabling unloading) on
failure.
See Note [Don't fail due to RTLD_NOW].
Fixes #25943.
- - - - -
88ee8bb5 by Sylvain Henry at 2025-05-14T04:26:15-04:00
Deprecate GHC.JS.Prim.Internal.Build (#23432)
Deprecated as per CLC proposal 329 (https://github.com/haskell/core-libraries-committee/issues/329)
- - - - -
b4ed465b by Cheng Shao at 2025-05-14T04:26:57-04:00
libffi: update to 3.4.8
Bumps libffi submodule.
- - - - -
a3e71296 by Matthew Pickering at 2025-05-14T04:27:38-04:00
Remove leftover trace
- - - - -
2d0ecdc6 by Cheng Shao at 2025-05-14T04:28:19-04:00
Revert "ci: re-enable chrome for wasm ghci browser tests"
This reverts commit fee9b351fa5a35d5778d1252789eacaaf5663ae8.
Unfortunately the chrome test jobs may still timeout on certain
runners (e.g. OpenCape) for unknown reasons.
- - - - -
2f63ebb0 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
GHC-CPP: first rough proof of concept
Processes
#define FOO
#ifdef FOO
x = 1
#endif
Into
[ITcppIgnored [L loc ITcppDefine]
,ITcppIgnored [L loc ITcppIfdef]
,ITvarid "x"
,ITequal
,ITinteger (IL {il_text = SourceText "1", il_neg = False, il_value = 1})
,ITcppIgnored [L loc ITcppEndif]
,ITeof]
In time, ITcppIgnored will be pushed into a comment
- - - - -
96b5a640 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Tidy up before re-visiting the continuation mechanic
- - - - -
3252d373 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Switch preprocessor to continuation passing style
Proof of concept, needs tidying up
- - - - -
68621389 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Small cleanup
- - - - -
6ab7e8b1 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Get rid of some cruft
- - - - -
b2718948 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Starting to integrate.
Need to get the pragma recognised and set
- - - - -
12ea9390 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Make cppTokens extend to end of line, and process CPP comments
- - - - -
c911a9ec by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Remove unused ITcppDefined
- - - - -
f396e819 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Allow spaces between # and keyword for preprocessor directive
- - - - -
261da91b by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Process CPP continuation lines
They are emited as separate ITcppContinue tokens.
Perhaps the processing should be more like a comment, and keep on
going to the end.
BUT, the last line needs to be slurped as a whole.
- - - - -
036858d6 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Accumulate CPP continuations, process when ready
Can be simplified further, we only need one CPP token
- - - - -
0bdb4532 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Simplify Lexer interface. Only ITcpp
We transfer directive lines through it, then parse them from scratch
in the preprocessor.
- - - - -
e39f243b by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Deal with directive on last line, with no trailing \n
- - - - -
b42886a2 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Start parsing and processing the directives
- - - - -
352bc688 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Prepare for processing include files
- - - - -
d0b47755 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Move PpState into PreProcess
And initParserState, initPragState too
- - - - -
94bed0ea by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Process nested include files
Also move PpState out of Lexer.x, so it is easy to evolve it in a ghci
session, loading utils/check-cpp/Main.hs
- - - - -
83b00a80 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Split into separate files
- - - - -
b405a2d9 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Starting on expression parser.
But it hangs. Time for Text.Parsec.Expr
- - - - -
2418a2a0 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Start integrating the ghc-cpp work
From https://github.com/alanz/ghc-cpp
- - - - -
22a64399 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
WIP
- - - - -
746b22df by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Fixup after rebase
- - - - -
c5566266 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
WIP
- - - - -
bd1a0f1b by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Fixup after rebase, including all tests pass
- - - - -
66987b54 by Alan Zimmerman at 2025-05-14T18:19:19+01:00
Change pragma usage to GHC_CPP from GhcCPP
- - - - -
d9a2b76d by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Some comments
- - - - -
6f3f52c1 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Reformat
- - - - -
764cda90 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Delete unused file
- - - - -
ea5f32d7 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Rename module Parse to ParsePP
- - - - -
1f2ae7ca by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Clarify naming in the parser
- - - - -
9633ea57 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
WIP. Switching to alex/happy to be able to work in-tree
Since Parsec is not available
- - - - -
445630a3 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Layering is now correct
- GHC lexer, emits CPP tokens
- accumulated in Preprocessor state
- Lexed by CPP lexer, CPP command extracted, tokens concated with
spaces (to get rid of token pasting via comments)
- if directive lexed and parsed by CPP lexer/parser, and evaluated
- - - - -
6325ba58 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
First example working
Loading Example1.hs into ghci, getting the right results
```
{-# LANGUAGE GHC_CPP #-}
module Example1 where
y = 3
x =
"hello"
"bye now"
foo = putStrLn x
```
- - - - -
b523d99e by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Rebase, and all tests pass except whitespace for generated parser
- - - - -
fd66b3a8 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
More plumbing. Ready for testing tomorrow.
- - - - -
474ad311 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Proress. Renamed module State from Types
And at first blush it seems to handle preprocessor scopes properly.
- - - - -
022c30e5 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Insert basic GHC version macros into parser
__GLASGOW_HASKELL__
__GLASGOW_HASKELL_FULL_VERSION__
__GLASGOW_HASKELL_PATCHLEVEL1__
__GLASGOW_HASKELL_PATCHLEVEL2__
- - - - -
a27f36b0 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Re-sync check-cpp for easy ghci work
- - - - -
64e50680 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Get rid of warnings
- - - - -
109fc742 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Rework macro processing, in check-cpp
Macros kept at the top level, looked up via name, multiple arity
versions per name can be stored
- - - - -
cf5bf32a by Alan Zimmerman at 2025-05-14T18:19:20+01:00
WIP. Can crack arguments for #define
Next step it to crack out args in an expansion
- - - - -
2e0f5a7c by Alan Zimmerman at 2025-05-14T18:19:20+01:00
WIP on arg parsing.
- - - - -
1e203004 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Progress. Still screwing up nested parens.
- - - - -
0ef50414 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Seems to work, but has redundant code
- - - - -
d2bd34af by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Remove redundant code
- - - - -
27fc83c3 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Reformat
- - - - -
3892339b by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Expand args, single pass
Still need to repeat until fixpoint
- - - - -
de56efc9 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Fixed point expansion
- - - - -
1e1dde58 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Sync the playground to compiler
- - - - -
9b0c8026 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Working on dumping the GHC_CPP result
But We need to keep the BufSpan in a comment
- - - - -
69c6ac89 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Keep BufSpan in queued comments in GHC.Parser.Lexer
- - - - -
43b13276 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Getting close to being able to print the combined tokens
showing what is in and what is out
- - - - -
09a01436 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
First implementation of dumpGhcCpp.
Example output
First dumps all macros in the state, then the source, showing which
lines are in and which are out
------------------------------
- |#define FOO(A,B) A + B
- |#define FOO(A,B,C) A + B + C
- |#if FOO(1,FOO(3,4)) == 8
- |-- a comment
|x = 1
- |#else
- |x = 5
- |#endif
- - - - -
1bbf1d7a by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Clean up a bit
- - - - -
bc261c64 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Add -ddump-ghc-cpp option and a test based on it
- - - - -
55a5adae by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Restore Lexer.x rules, we need them for continuation lines
- - - - -
19d05f60 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Lexer.x: trying to sort out the span for continuations
- We need to match on \n at the end of the line
- We cannot simply back up for it
- - - - -
1cbf8b49 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Inserts predefined macros. But does not dump properly
Because the cpp tokens have a trailing newline
- - - - -
4421462d by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Remove unnecessary LExer rules
We *need* the ones that explicitly match to the end of the line.
- - - - -
f204d7ea by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Generate correct span for ITcpp
Dump now works, except we do not render trailing `\` for continuation
lines. This is good enough for use in test output.
- - - - -
a240d600 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Reduce duplication in lexer
- - - - -
e7ec23a8 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Tweaks
- - - - -
a5032dfb by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Insert min_version predefined macros into state
The mechanism now works. Still need to flesh out the full set.
- - - - -
cf2e55c1 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Trying my alternative pragma syntax.
It works, but dumpGhcCpp is broken, I suspect from the ITcpp token
span update.
- - - - -
e04ac38e by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Pragma extraction now works, with both CPP and GHC_CPP
For the following
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 913
{-# LANGUAGE GHC_CPP #-}
#endif
We will enable GHC_CPP only
- - - - -
7c192ee2 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Remove some tracing
- - - - -
39606949 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Fix test exes for changes
- - - - -
c8ac21b5 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
For GHC_CPP tests, normalise config-time-based macros
- - - - -
4752335f by Alan Zimmerman at 2025-05-14T18:19:20+01:00
WIP
- - - - -
fccb48e5 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
WIP again. What is wrong?
- - - - -
2f207455 by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Revert to dynflags for normal not pragma lexing
- - - - -
07f0908a by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Working on getting check-exact to work properly
- - - - -
5f18753a by Alan Zimmerman at 2025-05-14T18:19:20+01:00
Passes CppCommentPlacement test
- - - - -
05d23c50 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Starting on exact printing with GHC_CPP
While overriding normal CPP
- - - - -
413e8011 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Correctly store CPP ignored tokens as comments
By populating the lexeme string in it, based on the bufpos
- - - - -
63ebbea0 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
WIP
- - - - -
03b84f2d by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Simplifying
- - - - -
96e512ba by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Update the active state logic
- - - - -
d4b97464 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Work the new logic into the mainline code
- - - - -
8d49b2c1 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Process `defined` operator
- - - - -
fba9491d by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Manage lexer state while skipping tokens
There is very intricate layout-related state used when lexing. If a
CPP directive blanks out some tokens, store this state when the
blanking starts, and restore it when they are no longer being blanked.
- - - - -
31eeb8ad by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Track the last token buffer index, for ITCppIgnored
We need to attach the source being skipped in an ITCppIgnored token.
We cannot simply use its BufSpan as an index into the underlying
StringBuffer as it counts unicode chars, not bytes.
So we update the lexer state to store the starting StringBuffer
location for the last token, and use the already-stored length to
extract the correct portion of the StringBuffer being parsed.
- - - - -
998520b7 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Process the ! operator in GHC_CPP expressions
- - - - -
36381727 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Predefine a constant when GHC_CPP is being used.
- - - - -
16e87acb by Alan Zimmerman at 2025-05-14T18:19:21+01:00
WIP
- - - - -
3f43657f by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Skip lines directly in the lexer when required
- - - - -
bb3a00eb by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Properly manage location when accepting tokens again
- - - - -
e839d8e7 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Seems to be working now, for Example9
- - - - -
ea5ee1c4 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Remove tracing
- - - - -
561ac7f1 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Fix parsing '*' in block comments
Instead of replacing them with '-'
- - - - -
ee86e580 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Keep the trailing backslash in a ITcpp token
- - - - -
58ad089d by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Deal with only enabling one section of a group.
A group is an instance of a conditional introduced by
#if/#ifdef/#ifndef,
and ending at the final #endif, including intermediate #elsif sections
- - - - -
4d401a98 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Replace remaining identifiers with 0 when evaluating
As per the spec
- - - - -
99c373a5 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Snapshot before rebase
- - - - -
3bcdd146 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Skip non-processed lines starting with #
- - - - -
60046877 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Export generateMacros so we can use it in ghc-exactprint
- - - - -
26984a2a by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Fix rebase
- - - - -
3aca4e6e by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Expose initParserStateWithMacrosString
- - - - -
3bf073b0 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Fix buggy lexer cppSkip
It was skipping all lines, not just ones prefixed by #
- - - - -
9350d1e8 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Fix evaluation of && to use the correct operator
- - - - -
2fc71268 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Deal with closing #-} at the start of a line
- - - - -
11ac7351 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Add the MIN_VERSION_GLASGOW_HASKELL predefined macro
- - - - -
3957dc93 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Include MIN_VERSION_GLASGOW_HASKELL in GhcCpp01.stderr
- - - - -
40364d92 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Use a strict map for macro defines
- - - - -
b590d71d by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Process TIdentifierLParen
Which only matters at the start of #define
- - - - -
1bfc2787 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Do not provide TIdentifierLParen paren twice
- - - - -
e968ea61 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Handle whitespace between identifier and '(' for directive only
- - - - -
1312a310 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Expose some Lexer bitmap manipulation helpers
- - - - -
f2869803 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Deal with line pragmas as tokens
Blows up for dumpGhcCpp though
- - - - -
6c3355e3 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Allow strings delimited by a single quote too
- - - - -
8c83f87b by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Allow leading whitespace on cpp directives
As per https://timsong-cpp.github.io/cppwp/n4140/cpp#1
- - - - -
4ce93134 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Implement GHC_CPP undef
- - - - -
92b16e5f by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Sort out expansion of no-arg macros, in a context with args
And make the expansion bottom out, in the case of recursion
- - - - -
f94500fc by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Fix GhcCpp01 test
The LINE pragma stuff works in ghc-exactprint when specifically
setting flag to emit ITline_pragma tokens
- - - - -
c1a50d52 by Alan Zimmerman at 2025-05-14T18:19:21+01:00
Process comments in CPP directives
- - - - -
06b64dd4 by Alan Zimmerman at 2025-05-15T22:13:54+01:00
Correctly lex pragmas with finel #-} on a newline
- - - - -
112 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/CodeGen.Platform.h
- compiler/GHC.hs
- compiler/GHC/Cmm/CLabel.hs
- compiler/GHC/Cmm/Lexer.x
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/Cmm/Parser/Monad.hs
- compiler/GHC/CmmToAsm.hs
- compiler/GHC/CmmToAsm/Dwarf/Constants.hs
- + compiler/GHC/CmmToAsm/LA64.hs
- + compiler/GHC/CmmToAsm/LA64/CodeGen.hs
- + compiler/GHC/CmmToAsm/LA64/Cond.hs
- + compiler/GHC/CmmToAsm/LA64/Instr.hs
- + compiler/GHC/CmmToAsm/LA64/Ppr.hs
- + compiler/GHC/CmmToAsm/LA64/RegInfo.hs
- + compiler/GHC/CmmToAsm/LA64/Regs.hs
- compiler/GHC/CmmToAsm/PIC.hs
- compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs
- compiler/GHC/CmmToAsm/Reg/Linear.hs
- compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
- + compiler/GHC/CmmToAsm/Reg/Linear/LA64.hs
- compiler/GHC/CmmToAsm/Reg/Target.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Parser.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Parser.hs-boot
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- + compiler/GHC/Parser/PreProcess.hs
- + compiler/GHC/Parser/PreProcess/Eval.hs
- + compiler/GHC/Parser/PreProcess/Lexer.x
- + compiler/GHC/Parser/PreProcess/Macro.hs
- + compiler/GHC/Parser/PreProcess/ParsePP.hs
- + compiler/GHC/Parser/PreProcess/Parser.y
- + compiler/GHC/Parser/PreProcess/ParserM.hs
- + compiler/GHC/Parser/PreProcess/State.hs
- compiler/GHC/Parser/Utils.hs
- compiler/GHC/Platform/LoongArch64.hs → compiler/GHC/Platform/LA64.hs
- compiler/GHC/Platform/Regs.hs
- compiler/GHC/SysTools/Cpp.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/ghc.cabal.in
- docs/users_guide/debugging.rst
- ghc/GHCi/UI.hs
- hadrian/bindist/config.mk.in
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Rules/SourceDist.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/stack.yaml.lock
- libffi-tarballs
- libraries/base/changelog.md
- libraries/base/src/GHC/JS/Prim/Internal/Build.hs
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- rts/linker/LoadNativeObjPosix.c
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/driver/T4437.hs
- testsuite/tests/ghc-api/T11579.hs
- + testsuite/tests/ghc-cpp/GhcCpp01.hs
- + testsuite/tests/ghc-cpp/GhcCpp01.stderr
- + testsuite/tests/ghc-cpp/all.T
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- + testsuite/tests/printer/CppCommentPlacement.hs
- testsuite/tests/rts/all.T
- + utils/check-cpp/.ghci
- + utils/check-cpp/.gitignore
- + utils/check-cpp/Eval.hs
- + utils/check-cpp/Example1.hs
- + utils/check-cpp/Example10.hs
- + utils/check-cpp/Example11.hs
- + utils/check-cpp/Example12.hs
- + utils/check-cpp/Example13.hs
- + utils/check-cpp/Example2.hs
- + utils/check-cpp/Example3.hs
- + utils/check-cpp/Example4.hs
- + utils/check-cpp/Example5.hs
- + utils/check-cpp/Example6.hs
- + utils/check-cpp/Example7.hs
- + utils/check-cpp/Example8.hs
- + utils/check-cpp/Example9.hs
- + utils/check-cpp/Lexer.x
- + utils/check-cpp/Macro.hs
- + utils/check-cpp/Main.hs
- + utils/check-cpp/ParsePP.hs
- + utils/check-cpp/ParseSimulate.hs
- + utils/check-cpp/Parser.y
- + utils/check-cpp/ParserM.hs
- + utils/check-cpp/PreProcess.hs
- + utils/check-cpp/README.md
- + utils/check-cpp/State.hs
- + utils/check-cpp/run.sh
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Preprocess.hs
- utils/check-exact/Utils.hs
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cc.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/315240e0f3ccd6f2d882b9b598b104…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/315240e0f3ccd6f2d882b9b598b104…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T25989] 27 commits: Fix lexing "\^\" (#25937)
by Ben Gamari (@bgamari) 15 May '25
by Ben Gamari (@bgamari) 15 May '25
15 May '25
Ben Gamari pushed to branch wip/T25989 at Glasgow Haskell Compiler / GHC
Commits:
6467d61e by Brandon Chinn at 2025-04-29T18:36:03-04:00
Fix lexing "\^\" (#25937)
This broke in the refactor in !13128, where the old code parsed escape
codes and collapsed string gaps at the same time, but the new code
collapsed gaps first, then resolved escape codes. The new code used a
naive heuristic to skip escaped backslashes, but didn't account for
"\^\".
- - - - -
99868a86 by Jens Petersen at 2025-04-29T18:36:44-04:00
hadrian: default selftest to disabled
- - - - -
aba2a4a5 by Zubin Duggal at 2025-04-30T06:35:59-04:00
get-win32-tarballs.py: List tarball files to be downloaded if we cannot find them
Fixes #25929
- - - - -
d99a617b by Ben Gamari at 2025-04-30T06:36:40-04:00
Move Data ModuleName instance to Language.Haskell.Syntax.Module.Name
Fixes #25968.
- - - - -
9995c2b7 by Serge S. Gulin at 2025-05-04T17:13:36+03:00
Support for ARM64 Windows (LLVM-enabled) (fixes #24603)
1. Add Windows AArch64 cross-compilation support via CI jobs
Introduce new CI configurations for cross-compiling to Windows ARM64 using Debian12Wine, FEX, and MSYS2.
Configure toolchain variables for LLVM MinGW and Wine emulation in CI pipelines.
2. Adjust compiler and RTS for AArch64 Windows compatibility
Reserve register `x18` on Windows and Darwin platforms in AArch64 codegen.
Handle Windows-specific relocations and data sections in AArch64 assembler.
Update PEi386 linker to recognize ARM64 binaries and support exception handling.
Adjust LLVM target definitions and data layouts for new architectures.
Update `ghc-toolchain` and build scripts to handle `TablesNextToCode` on Windows ARM64.
3. Enhance CI scripts and stability
Modify `ci.sh` to handle mingw cross-targets, fixing GHC executable paths and test execution.
Use `diff -w` in tests to ignore whitespace differences, improving cross-platform consistency.
4. Refactor and clean up code
Remove redundant imports in hello.hs test.
Improve error messages and checks for unsupported configurations in the driver.
Add `EXDEV` error code to `errno.js`.
Add async/sync flags to IO logs at `base.js`.
Improve POSIX compatibility for file close at `base.js`: decrease indeterminism for mixed cases of async and sync code.
5. Update dependencies: `Cabal`, `Win32`, `directory`, `process`, `haskeline`, and `unix`.
submodule
Co-authored-by: Cheng Shao <terrorjack(a)type.dance>
Co-authored-by: Dmitrii Egorov <egorov.d.i(a)icloud.com>
Co-authored-by: Andrei Borzenkov <root(a)sandwitch.dev>
- - - - -
50fa8165 by Javran Cheng at 2025-05-05T05:55:39-04:00
Suppress unused do-binding if discarded variable is Any or ZonkAny.
Consider example (#25895):
> do { forever (return ()); blah }
where `forever :: forall a b. IO a -> IO b`.
Nothing constrains `b`, so it will be instantiates with `Any` or
`ZonkAny`.
But we certainly don't want to complain about a discarded do-binding.
Fixes #25895
- - - - -
e46c6b18 by Rodrigo Mesquita at 2025-05-06T09:01:57-04:00
Refactor mkTopLevImportedEnv out of mkTopLevEnv
This makes the code clearer and allows the top-level import context to
be fetched directly from the HomeModInfo through the API (e.g. useful
for the debugger).
- - - - -
0ce0d263 by Rodrigo Mesquita at 2025-05-06T09:01:57-04:00
Export sizeOccEnv from GHC.Types.Name.Occurrence
Counts the number of OccNames in an OccEnv
- - - - -
165f98d8 by Simon Peyton Jones at 2025-05-06T09:02:39-04:00
Fix a bad untouchability bug im simplifyInfer
This patch addresses #26004. The root cause was that simplifyInfer
was willing to unify variables "far out". The fix, in
runTcSWithEvBinds', is to initialise the inert set given-eq level with
the current level. See
(TGE6) in Note [Tracking Given equalities]
in GHC.Tc.Solver.InertSet
Two loosely related refactors:
* Refactored approximateWCX to return just the free type
variables of the un-quantified constraints. That avoids duplication
of work (these free vars are needed in simplifyInfer) and makes it
clearer that the constraints themselves are irrelevant.
* A little local refactor of TcSMode, which reduces the number of
parameters to runTcSWithEvBinds
- - - - -
6e67fa08 by Ben Gamari at 2025-05-08T06:21:21-04:00
llvmGen: Fix built-in variable predicate
Previously the predicate to identify LLVM builtin global variables was
checking for `$llvm` rather than `@llvm` as it should.
- - - - -
a9d0a22c by Ben Gamari at 2025-05-08T06:21:22-04:00
llvmGen: Fix linkage of built-in arrays
LLVM now insists that built-in arrays use Appending linkage, not
Internal.
Fixes #25769.
- - - - -
9c6d2b1b by sheaf at 2025-05-08T06:22:11-04:00
Use mkTrAppChecked in ds_ev_typeable
This change avoids violating the invariant of mkTrApp according to which
the argument should not be a fully saturated function type.
This ensures we don't return false negatives for type equality
involving function types.
Fixes #25998
- - - - -
75cadf81 by Ryan Hendrickson at 2025-05-08T06:22:55-04:00
haddock: Preserve indentation in multiline examples
Intended for use with :{ :}, but doesn't look for those characters. Any
consecutive lines with birdtracks will only have initial whitespace
stripped up to the column of the first line.
- - - - -
fee9b351 by Cheng Shao at 2025-05-08T06:23:36-04:00
ci: re-enable chrome for wasm ghci browser tests
Currently only firefox is enabled for wasm ghci browser tests, for
some reason testing with chrome works on my machine but gets stuck on
gitlab instance runners. This patch re-enables testing with chrome by
passing `--no-sandbox`, since chrome sandboxing doesn't work in
containers without `--cap-add=SYS_ADMIN`.
- - - - -
282df905 by Vladislav Zavialov at 2025-05-09T03:18:25-04:00
Take subordinate 'type' specifiers into account
This patch fixes multiple bugs (#22581, #25983, #25984, #25991)
in name resolution of subordinate import lists.
Bug #22581
----------
In subordinate import lists, the use of the `type` namespace specifier
used to be ignored. For example, this import statement was incorrectly
accepted:
import Prelude (Bool(type True))
Now it results in an error message:
<interactive>:2:17: error: [GHC-51433]
In the import of ‘Prelude’:
a data type called ‘Bool’ is exported,
but its subordinate item ‘True’ is not in the type namespace.
Bug #25983
----------
In subordinate import lists within a `hiding` clause, non-existent
items led to a poor warning message with -Wdodgy-imports. Consider:
import Prelude hiding (Bool(X))
The warning message for this import statement used to misreport the
cause of the problem:
<interactive>:3:24: warning: [GHC-56449] [-Wdodgy-imports]
In the import of ‘Prelude’:
an item called ‘Bool’ is exported, but it is a type.
Now the warning message is correct:
<interactive>:2:24: warning: [GHC-10237] [-Wdodgy-imports]
In the import of ‘Prelude’:
a data type called ‘Bool’ is exported, but it does not export
any constructors or record fields called ‘X’.
Bug #25984
----------
In subordinate import lists within a `hiding` clause, non-existent
items resulted in the entire import declaration being discarded.
For example, this program was incorrectly accepted:
import Prelude hiding (Bool(True,X))
t = True
Now it results in an error message:
<interactive>:2:5: error: [GHC-88464]
Data constructor not in scope: True
Bug #25991
----------
In subordinate import lists, it was not possible to refer to a class
method if there was an associated type of the same name:
module M_helper where
class C a b where
type a # b
(#) :: a -> b -> ()
module M where
import M_helper (C((#)))
This import declaration failed with:
M.hs:2:28: error: [GHC-10237]
In the import of ‘M_helper’:
an item called ‘C’ is exported, but it does not export any children
(constructors, class methods or field names) called ‘#’.
Now it is accepted.
Summary
-------
The changes required to fix these bugs are almost entirely confined to
GHC.Rename.Names. Other than that, there is a new error constructor
BadImportNonTypeSubordinates with error code [GHC-51433].
Test cases:
T22581a T22581b T22581c T22581d
T25983a T25983b T25983c T25983d T25983e T25983f T25983g
T25984a T25984b
T25991a T25991b1 T25991b2
- - - - -
51b0ce8f by Simon Peyton Jones at 2025-05-09T03:19:07-04:00
Slighty improve `dropMisleading`
Fix #26105, by upgrading the (horrible, hacky) `dropMisleading`
function.
This fix makes things a bit better but does not cure the underlying
problem.
- - - - -
7b2d1e6d by Simon Peyton Jones at 2025-05-11T03:24:47-04:00
Refine `noGivenNewtypeReprEqs` to account for quantified constraints
This little MR fixes #26020. We are on the edge of completeness
for newtype equalities (that doesn't change) but this MR makes GHC
a bit more consistent -- and fixes the bug reported.
- - - - -
eaa8093b by Cheng Shao at 2025-05-11T03:25:28-04:00
wasm: mark freeJSVal as INLINE
This patch marks `freeJSVal` as `INLINE` for the wasm backend. I
noticed that the `freeJSVal` invocations are not inlined when
inspecting STG/Cmm dumps of downstream libraries that use release
build of the wasm backend. The performance benefit of inlining here is
very modest, but so is the cost anyway; if you are using `freeJSVal`
at all then you care about every potential chance to improve
performance :)
- - - - -
eac196df by Cheng Shao at 2025-05-11T03:25:28-04:00
wasm: add zero length fast path for fromJSString
This patch adds a zero length fast path for `fromJSString`; when
marshaling a zero-length `JSString` we don't need to allocate an empty
`ByteArray#` at all.
- - - - -
652cba7e by Peng Fan at 2025-05-14T04:24:35-04:00
Add LoongArch NCG support
Not supported before.
- - - - -
c01f4374 by Lin Runze at 2025-05-14T04:24:35-04:00
ci: Add LoongArch64 cross-compile CI for testing
- - - - -
ce6cf240 by Ben Gamari at 2025-05-14T04:25:18-04:00
rts/linker: Don't fail due to RTLD_NOW
In !12264 we started using the NativeObj machinery introduced some time
ago for loading of shared objects. One of the side-effects of this
change is shared objects are now loaded eagerly (i.e. with `RTLD_NOW`).
This is needed by NativeObj to ensure full visibility of the mappings of
the loaded object, which is in turn needed for safe shared object
unloading.
Unfortunately, this change subtly regressed, causing compilation
failures in some programs. Specifically, shared objects which refer to
undefined symbols (e.g. which may be usually provided by either the
executable image or libraries loaded via `dlopen`) will fail to load
with eager binding. This is problematic as GHC loads all package
dependencies while, e.g., evaluating TemplateHaskell splices. This
results in compilation failures in programs depending upon (but not
using at compile-time) packages with undefined symbol references.
To mitigate this NativeObj now first attempts to load an object via
eager binding, reverting to lazy binding (and disabling unloading) on
failure.
See Note [Don't fail due to RTLD_NOW].
Fixes #25943.
- - - - -
88ee8bb5 by Sylvain Henry at 2025-05-14T04:26:15-04:00
Deprecate GHC.JS.Prim.Internal.Build (#23432)
Deprecated as per CLC proposal 329 (https://github.com/haskell/core-libraries-committee/issues/329)
- - - - -
b4ed465b by Cheng Shao at 2025-05-14T04:26:57-04:00
libffi: update to 3.4.8
Bumps libffi submodule.
- - - - -
a3e71296 by Matthew Pickering at 2025-05-14T04:27:38-04:00
Remove leftover trace
- - - - -
2d0ecdc6 by Cheng Shao at 2025-05-14T04:28:19-04:00
Revert "ci: re-enable chrome for wasm ghci browser tests"
This reverts commit fee9b351fa5a35d5778d1252789eacaaf5663ae8.
Unfortunately the chrome test jobs may still timeout on certain
runners (e.g. OpenCape) for unknown reasons.
- - - - -
3b3a5dec by Ben Gamari at 2025-05-15T16:10:01-04:00
Don't emit unprintable characters when printing Uniques
When faced with an unprintable tag we now instead print the codepoint
number.
Fixes #25989.
(cherry picked from commit e832b1fadee66e8d6dd7b019368974756f8f8c46)
- - - - -
161 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/hello.hs
- .gitlab/jobs.yaml
- compiler/CodeGen.Platform.h
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Builtin/Types.hs
- compiler/GHC/Cmm/CLabel.hs
- compiler/GHC/CmmToAsm.hs
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/CmmToAsm/AArch64/Instr.hs
- compiler/GHC/CmmToAsm/AArch64/Ppr.hs
- compiler/GHC/CmmToAsm/Dwarf/Constants.hs
- + compiler/GHC/CmmToAsm/LA64.hs
- + compiler/GHC/CmmToAsm/LA64/CodeGen.hs
- + compiler/GHC/CmmToAsm/LA64/Cond.hs
- + compiler/GHC/CmmToAsm/LA64/Instr.hs
- + compiler/GHC/CmmToAsm/LA64/Ppr.hs
- + compiler/GHC/CmmToAsm/LA64/RegInfo.hs
- + compiler/GHC/CmmToAsm/LA64/Regs.hs
- compiler/GHC/CmmToAsm/PIC.hs
- compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs
- compiler/GHC/CmmToAsm/Reg/Linear.hs
- compiler/GHC/CmmToAsm/Reg/Linear/AArch64.hs
- compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
- + compiler/GHC/CmmToAsm/Reg/Linear/LA64.hs
- compiler/GHC/CmmToAsm/Reg/Target.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/CmmToLlvm/Data.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/String.hs
- compiler/GHC/Platform/LoongArch64.hs → compiler/GHC/Platform/LA64.hs
- compiler/GHC/Platform/Regs.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Name/Occurrence.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Types.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- compiler/ghc.cabal.in
- docs/users_guide/9.14.1-notes.rst
- docs/users_guide/exts/explicit_namespaces.rst
- hadrian/README.md
- hadrian/bindist/config.mk.in
- hadrian/hadrian.cabal
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Settings/Builders/RunTest.hs
- libffi-tarballs
- libraries/Cabal
- libraries/Win32
- libraries/base/changelog.md
- libraries/base/src/GHC/JS/Prim/Internal/Build.hs
- libraries/base/src/System/CPUTime/Windows.hsc
- libraries/base/tests/perf/encodingAllocations.hs
- libraries/directory
- libraries/ghc-internal/jsbits/base.js
- libraries/ghc-internal/jsbits/errno.js
- libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs
- libraries/haskeline
- libraries/process
- libraries/unix
- llvm-targets
- m4/fp_cc_supports_target.m4
- m4/fp_setup_windows_toolchain.m4
- m4/fptools_set_platform_vars.m4
- m4/ghc_tables_next_to_code.m4
- rts/StgCRun.c
- rts/linker/LoadNativeObjPosix.c
- rts/linker/PEi386.c
- rts/win32/veh_excn.c
- testsuite/tests/driver/RecompExports/RecompExports1.stderr
- testsuite/tests/driver/RecompExports/RecompExports4.stderr
- testsuite/tests/ghc-api/fixed-nodes/all.T
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/module/T21826.stderr
- testsuite/tests/module/mod81.stderr
- testsuite/tests/module/mod91.stderr
- + testsuite/tests/parser/should_run/T25937.hs
- + testsuite/tests/parser/should_run/T25937.stdout
- testsuite/tests/parser/should_run/all.T
- + testsuite/tests/parser/should_run/parser_unit_tests.hs
- testsuite/tests/printer/T17697.stderr
- + testsuite/tests/rename/should_compile/T22581c.hs
- + testsuite/tests/rename/should_compile/T22581c_helper.hs
- + testsuite/tests/rename/should_compile/T22581d.script
- + testsuite/tests/rename/should_compile/T22581d.stdout
- + testsuite/tests/rename/should_compile/T25983a.hs
- + testsuite/tests/rename/should_compile/T25983a.stderr
- + testsuite/tests/rename/should_compile/T25983b.hs
- + testsuite/tests/rename/should_compile/T25983b.stderr
- + testsuite/tests/rename/should_compile/T25983c.hs
- + testsuite/tests/rename/should_compile/T25983c.stderr
- + testsuite/tests/rename/should_compile/T25983d.hs
- + testsuite/tests/rename/should_compile/T25983d.stderr
- + testsuite/tests/rename/should_compile/T25983e.hs
- + testsuite/tests/rename/should_compile/T25983e.stderr
- + testsuite/tests/rename/should_compile/T25983f.hs
- + testsuite/tests/rename/should_compile/T25983f.stderr
- + testsuite/tests/rename/should_compile/T25983g.hs
- + testsuite/tests/rename/should_compile/T25983g.stderr
- + testsuite/tests/rename/should_compile/T25984a.hs
- + testsuite/tests/rename/should_compile/T25984a.stderr
- + testsuite/tests/rename/should_compile/T25984a_helper.hs
- + testsuite/tests/rename/should_compile/T25991a.hs
- + testsuite/tests/rename/should_compile/T25991a_helper.hs
- testsuite/tests/rename/should_compile/all.T
- + testsuite/tests/rename/should_fail/T22581a.hs
- + testsuite/tests/rename/should_fail/T22581a.stderr
- + testsuite/tests/rename/should_fail/T22581a_helper.hs
- + testsuite/tests/rename/should_fail/T22581b.hs
- + testsuite/tests/rename/should_fail/T22581b.stderr
- + testsuite/tests/rename/should_fail/T22581b_helper.hs
- + testsuite/tests/rename/should_fail/T25984b.hs
- + testsuite/tests/rename/should_fail/T25984b.stderr
- + testsuite/tests/rename/should_fail/T25991b1.hs
- + testsuite/tests/rename/should_fail/T25991b1.stderr
- + testsuite/tests/rename/should_fail/T25991b2.hs
- + testsuite/tests/rename/should_fail/T25991b2.stderr
- + testsuite/tests/rename/should_fail/T25991b_helper.hs
- testsuite/tests/rename/should_fail/T9006.stderr
- testsuite/tests/rename/should_fail/all.T
- testsuite/tests/rts/all.T
- + testsuite/tests/typecheck/should_compile/T26020.hs
- + testsuite/tests/typecheck/should_compile/T26020a.hs
- + testsuite/tests/typecheck/should_compile/T26020a_help.hs
- testsuite/tests/typecheck/should_compile/all.T
- + testsuite/tests/typecheck/should_fail/T26004.hs
- + testsuite/tests/typecheck/should_fail/T26004.stderr
- + testsuite/tests/typecheck/should_fail/T26015.hs
- + testsuite/tests/typecheck/should_fail/T26015.stderr
- testsuite/tests/typecheck/should_fail/T7453.stderr
- testsuite/tests/typecheck/should_fail/all.T
- + testsuite/tests/typecheck/should_run/T25998.hs
- + testsuite/tests/typecheck/should_run/T25998.stdout
- testsuite/tests/typecheck/should_run/all.T
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cc.hs
- utils/haddock/haddock-library/src/Documentation/Haddock/Parser.hs
- utils/haddock/haddock-library/test/Documentation/Haddock/ParserSpec.hs
- utils/hsc2hs
- utils/llvm-targets/gen-data-layout.sh
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5ddbe01c7202cb9bd9c998c55b4db4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5ddbe01c7202cb9bd9c998c55b4db4…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/bco-docs] 2 commits: compiler: Use field selectors when creating BCOs
by Ben Gamari (@bgamari) 15 May '25
by Ben Gamari (@bgamari) 15 May '25
15 May '25
Ben Gamari pushed to branch wip/bco-docs at Glasgow Haskell Compiler / GHC
Commits:
acd08fcd by Ben Gamari at 2025-05-15T13:05:59-04:00
compiler: Use field selectors when creating BCOs
This makes it easier to grep for these fields.
- - - - -
882ffdec by Ben Gamari at 2025-05-15T13:06:02-04:00
compiler: Clarify BCO size
Previously the semantics and size of StgBCO was a bit unclear.
Specifically, the `size` field was documented to contain the size of the
bitmap whereas it was actually the size of the closure *and* bitmap.
Additionally, it was not as clear as it could be that the bitmap was a
full StgLargeBitmap with its own `size` field.
- - - - -
4 changed files:
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Linker.hs
- rts/PrimOps.cmm
- rts/include/rts/storage/Closures.h
Changes:
=====================================
compiler/GHC/ByteCode/Asm.hs
=====================================
@@ -266,7 +266,13 @@ assembleBCO platform
let !insns_arr = mkBCOByteArray $ final_isn_array
!bitmap_arr = mkBCOByteArray $ mkBitmapArray bsize bitmap
- ul_bco = UnlinkedBCO nm arity insns_arr bitmap_arr (fromSmallArray final_lit_array) (fromSmallArray final_ptr_array)
+ ul_bco = UnlinkedBCO { unlinkedBCOName = nm
+ , unlinkedBCOArity = arity
+ , unlinkedBCOInstrs = insns_arr
+ , unlinkedBCOBitmap = bitmap_arr
+ , unlinkedBCOLits = fromSmallArray final_lit_array
+ , unlinkedBCOPtrs = fromSmallArray final_ptr_array
+ }
-- 8 Aug 01: Finalisers aren't safe when attached to non-primitive
-- objects, since they might get run too early. Disable this until
@@ -275,6 +281,7 @@ assembleBCO platform
return ul_bco
+-- | Construct a word-array containing an @StgLargeBitmap@.
mkBitmapArray :: Word -> [StgWord] -> UArray Int Word
-- Here the return type must be an array of Words, not StgWords,
-- because the underlying ByteArray# will end up as a component
=====================================
compiler/GHC/ByteCode/Linker.hs
=====================================
@@ -65,11 +65,13 @@ linkBCO interp pkgs_loaded le bco_ix
(lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le) (elemsFlatBag lits0)
ptrs <- mapM (resolvePtr interp pkgs_loaded le bco_ix) (elemsFlatBag ptrs0)
let lits' = listArray (0 :: Int, fromIntegral (sizeFlatBag lits0)-1) lits
- return (ResolvedBCO isLittleEndian arity
- insns
- bitmap
- (mkBCOByteArray lits')
- (addListToSS emptySS ptrs))
+ return $ ResolvedBCO { resolvedBCOIsLE = isLittleEndian
+ , resolvedBCOArity = arity
+ , resolvedBCOInstrs = insns
+ , resolvedBCOBitmap = bitmap
+ , resolvedBCOLits = mkBCOByteArray lits'
+ , resolvedBCOPtrs = addListToSS emptySS ptrs
+ }
lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> BCONPtr -> IO Word
lookupLiteral interp pkgs_loaded le ptr = case ptr of
=====================================
rts/PrimOps.cmm
=====================================
@@ -2440,6 +2440,7 @@ stg_newBCOzh ( P_ instrs,
W_ arity,
P_ bitmap_arr )
{
+ // N.B. bitmap_arr contains a full StgLargeBitmap object.
W_ bco, bytes, words;
words = BYTES_TO_WDS(SIZEOF_StgBCO) + BYTE_ARR_WDS(bitmap_arr);
=====================================
rts/include/rts/storage/Closures.h
=====================================
@@ -427,7 +427,7 @@ typedef struct {
StgArrBytes *literals; // literals used by the instructions
StgMutArrPtrs *ptrs; // free variables
StgHalfWord arity; // arity of this BCO
- StgHalfWord size; // size of the bitmap
+ StgHalfWord size; // size of the closure and bitmap
StgWord bitmap[]; // an StgLargeBitmap
} StgBCO;
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0bf1212af899941e6e11347a8b20ad…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0bf1212af899941e6e11347a8b20ad…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Ben Gamari pushed new branch wip/bco-docs at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/bco-docs
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T25974] Add `.exe` to `WindresCmd` environment var and more debugging info around it
by Serge S. Gulin (@gulin.serge) 15 May '25
by Serge S. Gulin (@gulin.serge) 15 May '25
15 May '25
Serge S. Gulin pushed to branch wip/T25974 at Glasgow Haskell Compiler / GHC
Commits:
caa9b692 by Serge S. Gulin at 2025-05-15T18:58:16+04:00
Add `.exe` to `WindresCmd` environment var and more debugging info around it
- - - - -
3 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- m4/fp_settings.m4
Changes:
=====================================
.gitlab/generate-ci/gen_ci.hs
=====================================
@@ -1338,7 +1338,7 @@ cross_jobs = [
. setVariable "SIZE" (llvm_prefix ++ "size")
. setVariable "STRINGS" (llvm_prefix ++ "strings")
. setVariable "STRIP" (llvm_prefix ++ "strip")
- . setVariable "WindresCmd" (llvm_prefix ++ "windres")
+ . setVariable "WindresCmd" (llvm_prefix ++ "windres" ++ exe_suffix)
. setVariable "LLVMAS" (llvm_prefix ++ "clang")
. setVariable "LD" (llvm_prefix ++ "ld")
-- See Note [Empty MergeObjsCmd]
=====================================
.gitlab/jobs.yaml
=====================================
@@ -560,7 +560,7 @@
"STRIP": "C:/msys64/opt/ghc-bootstrap/mingw/bin/aarch64-w64-mingw32-strip",
"TEST_ENV": "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate-_wine_full_build",
"TOOLCHAIN_SOURCE": "env",
- "WindresCmd": "C:/msys64/opt/ghc-bootstrap/mingw/bin/aarch64-w64-mingw32-windres"
+ "WindresCmd": "C:/msys64/opt/ghc-bootstrap/mingw/bin/aarch64-w64-mingw32-windres.exe"
}
},
"i386-linux-alpine3_20-validate": {
@@ -1317,7 +1317,7 @@
"STRIP": "C:/msys64/opt/ghc-bootstrap/mingw/bin/aarch64-w64-mingw32-strip",
"TEST_ENV": "aarch64-linux-deb12-wine-int_native-cross_aarch64-unknown-mingw32-validate-_wine_full_build",
"TOOLCHAIN_SOURCE": "env",
- "WindresCmd": "C:/msys64/opt/ghc-bootstrap/mingw/bin/aarch64-w64-mingw32-windres",
+ "WindresCmd": "C:/msys64/opt/ghc-bootstrap/mingw/bin/aarch64-w64-mingw32-windres.exe",
"XZ_OPT": "-9"
}
},
=====================================
m4/fp_settings.m4
=====================================
@@ -79,10 +79,13 @@ AC_DEFUN([FP_SETTINGS],
[AC_MSG_ERROR(Unknown CPPSupportsG0 value $CmmCPPSupportsG0)]
)
+ AC_MSG_CHECKING([whether $WindresCmd exists])
if test -z "$WindresCmd"; then
SettingsWindresCommand="/bin/false"
+ AC_MSG_RESULT([no, use $SettingsWindresCommand])
else
SettingsWindresCommand="$WindresCmd"
+ AC_MSG_RESULT([yes])
fi
# LLVM backend tools
@@ -92,6 +95,7 @@ AC_DEFUN([FP_SETTINGS],
SettingsLlvmAsFlags="$LlvmAsFlags"
if test "$EnableDistroToolchain" = "YES"; then
+ AC_MSG_NOTICE([--enable-distro-toolchain is specified, applying basename])
# If the user specified --enable-distro-toolchain then we just use the
# executable names, not paths.
SettingsCCompilerCommand="$(basename $SettingsCCompilerCommand)"
@@ -108,6 +112,7 @@ AC_DEFUN([FP_SETTINGS],
fi
if test "$windows" = YES -a "$EnableDistroToolchain" = "NO"; then
+ AC_MSG_NOTICE([--enable-distro-toolchain is not specified at Windows])
# Handle the Windows toolchain installed in FP_SETUP_WINDOWS_TOOLCHAIN.
# We need to issue a substitution to use $tooldir,
# See Note [tooldir: How GHC finds mingw on Windows]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/caa9b692569eb03a2a4d1e4ae990cbc…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/caa9b692569eb03a2a4d1e4ae990cbc…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/step-out] debugger: Implement step-out feature
by Rodrigo Mesquita (@alt-romes) 15 May '25
by Rodrigo Mesquita (@alt-romes) 15 May '25
15 May '25
Rodrigo Mesquita pushed to branch wip/romes/step-out at Glasgow Haskell Compiler / GHC
Commits:
ff887a62 by Rodrigo Mesquita at 2025-05-15T15:57:29+01:00
debugger: Implement step-out feature
Implements support for stepping-out of a function (aka breaking right after
returning from a function) in the interactive debugger.
It also introduces a GHCi command :stepout to step-out of a function
being debugged in the interpreter. The feature is described as:
Stop at the first breakpoint immediately after returning from the current
function scope.
Known limitations: because a function tail-call does not push a stack
frame, if step-out is used inside of a function that was tail-called,
execution will not be returned to its caller, but rather its caller's
first non-tail caller. On the other hand, it means the debugger
follows the more realistic execution of the program.
In the following example:
.. code-block:: none
f = do
a
b <--- (1) set breakpoint then step in here
c
b = do
...
d <--- (2) step-into this tail call
d = do
...
something <--- (3) step-out here
...
Stepping-out will stop execution at the `c` invokation in `f`, rather than
stopping at `b`.
The key implementation bit is simple:
When step-out is set and the interpreter hits a RETURN instruction,
enable "stop at the immediate next breakpoint" (aka single-step).
See also `Note [Debugger Step-out]` in `rts/Interpreter.c`
Note [Debugger Step-out]
~~~~~~~~~~~~~~~~~~~~~~~~
When the global debugger step-out flag is set (`rts_stop_after_return`),
the interpreter must yield execution right after the first RETURN.
When stepping-out, we simply enable `rts_stop_next_breakpoint` when we hit a
return instruction (in `do_return_pointer` and `do_return_nonpointer`).
The step-out flag is cleared and must be re-enabled explicitly to step-out again.
A limitation of this approach is that stepping-out of a function that was
tail-called will skip its caller since no stack frame is pushed for a tail
call (i.e. a tail call returns directly to its caller's first non-tail caller).
Fixes #26042
- - - - -
17 changed files:
- compiler/GHC/Driver/Config.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Eval/Types.hs
- docs/users_guide/ghci.rst
- ghc/GHCi/UI.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- rts/Interpreter.c
- rts/RtsSymbols.c
- rts/include/stg/MiscClosures.h
- + testsuite/tests/ghci.debugger/scripts/T26042a.hs
- + testsuite/tests/ghci.debugger/scripts/T26042a.script
- + testsuite/tests/ghci.debugger/scripts/T26042b.hs
- + testsuite/tests/ghci.debugger/scripts/T26042b.script
- + testsuite/tests/ghci.debugger/scripts/T26042c.hs
- + testsuite/tests/ghci.debugger/scripts/T26042c.script
- testsuite/tests/ghci.debugger/scripts/all.T
Changes:
=====================================
compiler/GHC/Driver/Config.hs
=====================================
@@ -3,6 +3,7 @@ module GHC.Driver.Config
( initOptCoercionOpts
, initSimpleOpts
, initEvalOpts
+ , EvalStep(..)
)
where
@@ -28,13 +29,28 @@ initSimpleOpts dflags = SimpleOpts
, so_inline = True
}
+-- | Instruct the interpreter evaluation to break...
+data EvalStep
+ -- | ... at every breakpoint tick
+ = EvalStepSingle
+ -- | ... after every return stmt
+ | EvalStepOut
+ -- | ... only on explicit breakpoints
+ | EvalStepNone
+
-- | Extract GHCi options from DynFlags and step
-initEvalOpts :: DynFlags -> Bool -> EvalOpts
+initEvalOpts :: DynFlags -> EvalStep -> EvalOpts
initEvalOpts dflags step =
EvalOpts
{ useSandboxThread = gopt Opt_GhciSandbox dflags
- , singleStep = step
+ , singleStep = singleStep
+ , stepOut = stepOut
, breakOnException = gopt Opt_BreakOnException dflags
, breakOnError = gopt Opt_BreakOnError dflags
}
+ where
+ (singleStep, stepOut) = case step of
+ EvalStepSingle -> (True, False)
+ EvalStepOut -> (False, True)
+ EvalStepNone -> (False, False)
=====================================
compiler/GHC/Runtime/Eval.hs
=====================================
@@ -343,7 +343,12 @@ handleRunStatus step expr bindings final_ids status history0 = do
setSession hsc_env2
return (ExecBreak names Nothing)
- -- Just case: we stopped at a breakpoint
+ -- EvalBreak (Just ...) case: the interpreter stopped at a breakpoint
+ --
+ -- The interpreter yields on a breakpoint if:
+ -- - the breakpoint was explicitly enabled (in @BreakArray@)
+ -- - or @singleStep = True@ in EvalOpts
+ -- - or @stepOut = True@ in EvalOpts
EvalBreak apStack_ref (Just eval_break) resume_ctxt ccs -> do
let ibi = evalBreakpointToId eval_break
tick_brks <- liftIO $ readModBreaks hsc_env (ibi_tick_mod ibi)
@@ -351,13 +356,14 @@ handleRunStatus step expr bindings final_ids status history0 = do
span = modBreaks_locs tick_brks ! ibi_tick_index ibi
decl = intercalate "." $ modBreaks_decls tick_brks ! ibi_tick_index ibi
+ -- Was the breakpoint explicitly enabled?
b <- liftIO $ breakpointStatus interp (modBreaks_flags tick_brks) (ibi_tick_index ibi)
apStack_fhv <- liftIO $ mkFinalizedHValue interp apStack_ref
resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt
- -- This breakpoint is explicitly enabled; we want to stop
- -- instead of just logging it.
+ -- This breakpoint is enabled or we mean to break here;
+ -- we want to stop instead of just logging it.
if b || breakHere step span then do
-- This function only returns control to ghci with 'ExecBreak' when it is really meant to break.
-- Specifically, for :steplocal or :stepmodule, don't return control
@@ -1247,7 +1253,7 @@ compileParsedExprRemote expr@(L loc _) = withSession $ \hsc_env -> do
_ -> panic "compileParsedExprRemote"
updateFixityEnv fix_env
- let eval_opts = initEvalOpts dflags False
+ let eval_opts = initEvalOpts dflags EvalStepNone
status <- liftIO $ evalStmt interp eval_opts (EvalThis hvals_io)
case status of
EvalComplete _ (EvalSuccess [hval]) -> return hval
=====================================
compiler/GHC/Runtime/Eval/Types.hs
=====================================
@@ -17,6 +17,7 @@ import GHC.Prelude
import GHCi.RemoteTypes
import GHCi.Message (EvalExpr, ResumeContext)
+import GHC.Driver.Config (EvalStep(..))
import GHC.Types.Id
import GHC.Types.Name
import GHC.Types.TyThing
@@ -46,6 +47,9 @@ data SingleStep
-- | :step [expr]
| SingleStep
+ -- | :stepout [expr]
+ | StepOut
+
-- | :steplocal [expr]
| LocalStep
{ breakAt :: SrcSpan }
@@ -55,10 +59,12 @@ data SingleStep
{ breakAt :: SrcSpan }
-- | Whether this 'SingleStep' mode requires instructing the interpreter to
--- step at every breakpoint.
-enableGhcStepMode :: SingleStep -> Bool
-enableGhcStepMode RunToCompletion = False
-enableGhcStepMode _ = True
+-- step at every breakpoint or after every return (see @'EvalStep'@).
+enableGhcStepMode :: SingleStep -> EvalStep
+enableGhcStepMode RunToCompletion = EvalStepNone
+enableGhcStepMode StepOut = EvalStepOut
+-- for the remaining step modes we need to stop at every single breakpoint.
+enableGhcStepMode _ = EvalStepSingle
-- | Given a 'SingleStep' mode and the SrcSpan of a breakpoint we hit, return
-- @True@ if based on the step-mode alone we should stop at this breakpoint.
@@ -70,6 +76,7 @@ breakHere :: SingleStep -> SrcSpan -> Bool
breakHere step break_span = case step of
RunToCompletion -> False
RunAndLogSteps -> False
+ StepOut -> True -- hmm. this function may not be a good abstraction?
SingleStep -> True
LocalStep span -> break_span `isSubspanOf` span
ModuleStep span -> srcSpanFileName_maybe span == srcSpanFileName_maybe break_span
=====================================
docs/users_guide/ghci.rst
=====================================
@@ -2980,6 +2980,35 @@ commonly used commands.
hit by an error (:ghc-flag:`-fbreak-on-error`) or an
exception (:ghc-flag:`-fbreak-on-exception`).
+.. ghci-cmd:: :stepout
+
+ Stop at the first breakpoint immediately after returning from the current
+ function scope.
+
+ Known limitations: because a function tail-call does not push a stack
+ frame, if step-out is used inside of a function that was tail-called,
+ execution will not be returned to its caller, but rather its caller's
+ first non-tail caller. On the other hand, it means the debugger
+ follows the more realistic execution of the program.
+ In the following example:
+
+ .. code-block:: none
+
+ f = do
+ a
+ b <--- (1) set breakpoint then step in here
+ c
+ b = do
+ ...
+ d <--- (2) step-into this tail call
+ d = do
+ ...
+ something <--- (3) step-out here
+ ...
+
+ Stepping-out will stop execution at the `c` invokation in `f`, rather than
+ stopping at `b`.
+
.. ghci-cmd:: :stepmodule
Enable only breakpoints in the current module and resume evaluation
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -247,6 +247,7 @@ ghciCommands = map mkCmd [
("sprint", keepGoing sprintCmd, completeExpression),
("step", keepGoing stepCmd, completeIdentifier),
("steplocal", keepGoing stepLocalCmd, completeIdentifier),
+ ("stepout", keepGoing stepOutCmd, completeIdentifier),
("stepmodule",keepGoing stepModuleCmd, completeIdentifier),
("type", keepGoingMulti' typeOfExpr, completeExpression),
("trace", keepGoing traceCmd, completeExpression),
@@ -407,6 +408,7 @@ defFullHelpText =
" :step single-step after stopping at a breakpoint\n"++
" :step <expr> single-step into <expr>\n"++
" :steplocal single-step within the current top-level binding\n"++
+ " :stepout stop at the first breakpoint after returning from the current scope\n"++
" :stepmodule single-step restricted to the current module\n"++
" :trace trace after stopping at a breakpoint\n"++
" :trace <expr> evaluate <expr> with tracing on (see :history)\n"++
@@ -3793,6 +3795,12 @@ stepCmd arg = withSandboxOnly ":step" $ step arg
step [] = doContinue GHC.SingleStep
step expression = runStmt expression GHC.SingleStep >> return ()
+stepOutCmd :: GhciMonad m => String -> m ()
+stepOutCmd arg = withSandboxOnly ":stepout" $ step arg
+ where
+ step [] = doContinue GHC.StepOut
+ step expression = stepCmd expression
+
stepLocalCmd :: GhciMonad m => String -> m ()
stepLocalCmd arg = withSandboxOnly ":steplocal" $ step arg
where
=====================================
libraries/ghci/GHCi/Message.hs
=====================================
@@ -374,6 +374,7 @@ putTHMessage m = case m of
data EvalOpts = EvalOpts
{ useSandboxThread :: Bool
, singleStep :: Bool
+ , stepOut :: Bool
, breakOnException :: Bool
, breakOnError :: Bool
}
=====================================
libraries/ghci/GHCi/Run.hs
=====================================
@@ -210,6 +210,7 @@ evalOptsSeq :: EvalOpts
evalOptsSeq = EvalOpts
{ useSandboxThread = True
, singleStep = False
+ , stepOut = False
, breakOnException = False
, breakOnError = False
}
@@ -333,6 +334,7 @@ withBreakAction opts breakMVar statusMVar act
poke breakPointIOAction stablePtr
when (breakOnException opts) $ poke exceptionFlag 1
when (singleStep opts) $ setStepFlag
+ when (stepOut opts) $ poke stepOutFlag 1
return stablePtr
-- Breaking on exceptions is not enabled by default, since it
-- might be a bit surprising. The exception flag is turned off
@@ -363,6 +365,7 @@ withBreakAction opts breakMVar statusMVar act
resetBreakAction stablePtr = do
poke breakPointIOAction noBreakStablePtr
poke exceptionFlag 0
+ poke stepOutFlag 0
resetStepFlag
freeStablePtr stablePtr
@@ -398,6 +401,7 @@ abandonStmt hvref = do
foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt
foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt
+foreign import ccall "&rts_stop_after_return" stepOutFlag :: Ptr CInt
setStepFlag :: IO ()
setStepFlag = poke stepFlag 1
=====================================
rts/Interpreter.c
=====================================
@@ -194,6 +194,24 @@ See also Note [Width of parameters] for some more motivation.
#define WITHIN_CHUNK_BOUNDS(n, s) \
(RTS_LIKELY((StgWord*)(Sp_plusW(n)) < ((s)->stack + (s)->stack_size - sizeofW(StgUnderflowFrame))))
+// Note [Debugger Step-out]
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+// When the global debugger step-out flag is set (`rts_stop_after_return`),
+// the interpreter must yield execution right after the first RETURN.
+//
+// When stepping-out, we simply enable `rts_stop_next_breakpoint` when we hit a
+// return instruction (in `do_return_pointer` and `do_return_nonpointer`).
+// The step-out flag is cleared and must be re-enabled explicitly to step-out again.
+//
+// A limitation of this approach is that stepping-out of a function that was
+// tail-called will skip its caller since no stack frame is pushed for a tail
+// call (i.e. a tail call returns directly to its caller's first non-tail caller).
+#define CHECK_BRK_AFTER_RET() \
+ if (rts_stop_after_return) \
+ { \
+ rts_stop_next_breakpoint = true; \
+ rts_stop_after_return = false; \
+ } \
/* Note [PUSH_L underflow]
~~~~~~~~~~~~~~~~~~~~~~~
@@ -245,6 +263,7 @@ allocate_NONUPD (Capability *cap, int n_words)
int rts_stop_next_breakpoint = 0;
int rts_stop_on_exception = 0;
+int rts_stop_after_return = 0;
#if defined(INTERP_STATS)
@@ -734,6 +753,8 @@ do_return_pointer:
IF_DEBUG(sanity,checkStackChunk(Sp, cap->r.rCurrentTSO->stackobj->stack+cap->r.rCurrentTSO->stackobj->stack_size));
+ CHECK_BRK_AFTER_RET();
+
switch (get_itbl((StgClosure *)Sp)->type) {
case RET_SMALL: {
@@ -883,6 +904,8 @@ do_return_nonpointer:
// get the offset of the header of the next stack frame
offset = stack_frame_sizeW((StgClosure *)Sp);
+ CHECK_BRK_AFTER_RET();
+
switch (get_itbl((StgClosure*)(Sp_plusW(offset)))->type) {
case RET_BCO:
=====================================
rts/RtsSymbols.c
=====================================
@@ -908,6 +908,7 @@ extern char **environ;
SymI_NeedsDataProto(rts_breakpoint_io_action) \
SymI_NeedsDataProto(rts_stop_next_breakpoint) \
SymI_NeedsDataProto(rts_stop_on_exception) \
+ SymI_NeedsDataProto(rts_stop_after_return) \
SymI_HasProto(stopTimer) \
SymI_HasProto(n_capabilities) \
SymI_HasProto(max_n_capabilities) \
=====================================
rts/include/stg/MiscClosures.h
=====================================
@@ -619,6 +619,7 @@ RTS_FUN_DECL(stg_castFloatToWord32zh);
// Interpreter.c
extern StgWord rts_stop_next_breakpoint[];
extern StgWord rts_stop_on_exception[];
+extern StgWord rts_stop_after_return[];
extern StgWord rts_breakpoint_io_action[];
// Schedule.c
=====================================
testsuite/tests/ghci.debugger/scripts/T26042a.hs
=====================================
@@ -0,0 +1,17 @@
+module Main where
+
+main :: IO ()
+main = do
+ a <- foo
+ print a
+
+foo :: IO Int
+foo = do
+ let x = 3
+ y = 4
+ b <- bar (x + y)
+ return b
+
+bar :: Int -> IO Int
+bar z = return (z * 2)
+
=====================================
testsuite/tests/ghci.debugger/scripts/T26042a.script
=====================================
@@ -0,0 +1,19 @@
+-- simple use of stepout
+:break main
+main
+:list
+:stepout
+:list
+:stepout
+:list
+-- from here on we're going to evaluate the thunks for `a` in `print a`
+:stepout
+:list
+:stepout
+:list
+:stepout
+:list
+:stepout
+:list
+-- finish execution
+:stepout
=====================================
testsuite/tests/ghci.debugger/scripts/T26042b.hs
=====================================
@@ -0,0 +1,22 @@
+module Main where
+
+main :: IO ()
+main = do
+ a <- foo False undefined
+ print a
+
+foo :: Bool -> Int -> IO Int
+foo True i = return i
+foo False _ = do
+ let x = 3
+ y = 4
+ n <- bar (x + y)
+ return n
+
+bar :: Int -> IO Int
+bar z = do
+ let t = z * 2
+ y <- foo True t
+ return y
+
+
=====================================
testsuite/tests/ghci.debugger/scripts/T26042b.script
=====================================
@@ -0,0 +1,15 @@
+-- break on the True branch of foo
+:break 9
+main
+:list
+-- stepout of foo True to caller (ie bar)
+:stepout
+:list
+-- stepout of bar (to branch of foo False, where bar was called)
+:stepout
+:list
+-- stepout to right after the call to foo False in main
+:stepout
+:list
+-- done
+:continue
=====================================
testsuite/tests/ghci.debugger/scripts/T26042c.hs
=====================================
@@ -0,0 +1,19 @@
+module Main where
+
+main :: IO ()
+main = do
+ a <- foo False undefined
+ print a
+
+foo :: Bool -> Int -> IO Int
+foo True i = return i
+foo False _ = do
+ let x = 3
+ y = 4
+ bar (x + y)
+
+bar :: Int -> IO Int
+bar z = do
+ let t = z * 2
+ foo True t
+
=====================================
testsuite/tests/ghci.debugger/scripts/T26042c.script
=====================================
@@ -0,0 +1,23 @@
+-- similar to T26042b, but uses tail calls
+-- recall: for step-out, we skip the caller of tail calls
+-- (because we don't push a stack frame for tail calls, so
+-- there's no RET instruction to stop after)
+
+-- break on foo True branch
+:break 9
+main
+:list
+-- step out of foo True and observe that we have skipped its call in bar,
+-- and the call of bar in foo False.
+-- we go straight to `main`.
+:stepout
+:list
+-- stepping out from here will jump into the thunk because it's where we'll
+-- go after returning.
+:stepout
+:list
+-- and so on
+:stepout
+:list
+-- finish
+:continue
=====================================
testsuite/tests/ghci.debugger/scripts/all.T
=====================================
@@ -144,3 +144,6 @@ test('T24306', normal, ghci_script, ['T24306.script'])
test('T24712', normal, ghci_script, ['T24712.script'])
test('T25109', normal, ghci_script, ['T25109.script'])
test('T25932', extra_files(['T25932.hs']), ghci_script, ['T25932.script'])
+test('T26042a', extra_files(['T26042a.hs']), ghci_script, ['T26042a.script'])
+test('T26042b', extra_files(['T26042b.hs']), ghci_script, ['T26042b.script'])
+test('T26042c', extra_files(['T26042c.hs']), ghci_script, ['T26042c.script'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ff887a6290fc3248934cbd9a54ed499…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ff887a6290fc3248934cbd9a54ed499…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T25974] Relax the requirements of `set_up_tarballs` Windows toolchain check
by Serge S. Gulin (@gulin.serge) 15 May '25
by Serge S. Gulin (@gulin.serge) 15 May '25
15 May '25
Serge S. Gulin pushed to branch wip/T25974 at Glasgow Haskell Compiler / GHC
Commits:
49d94b1d by Serge S. Gulin at 2025-05-15T15:26:22+04:00
Relax the requirements of `set_up_tarballs` Windows toolchain check
- - - - -
5 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- hadrian/src/Builder.hs
- hadrian/src/Rules/BinaryDist.hs
- m4/fp_setup_windows_toolchain.m4
Changes:
=====================================
.gitlab/generate-ci/gen_ci.hs
=====================================
@@ -873,10 +873,6 @@ job arch opsys buildConfig = NamedJob { name = jobName, jobInfo = Job {..} }
, "/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh configure"
-- We have to trigger cabal build in an independent way to mitigate Wine hangs at MSYS2/Arm64EC
, "/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l -c './hadrian/build-cabal clean'"
- -- We use "--enable-distro-toolchain" due of TOOLCHAIN_SOURCE="env", so we have to manually copy
- -- bootstrap's compiler mingw into `_build` because binary-dist-dir requires it at Windows.
- -- After './hadrian/build-cabal clean' we have to recreate the build root directory.
- , "mkdir ./_build && cp -r ~/.wine/drive_c/msys64/opt/ghc-bootstrap/mingw ./_build/"
, "/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh build_hadrian"
, "/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh test_hadrian"
]
=====================================
.gitlab/jobs.yaml
=====================================
@@ -523,7 +523,6 @@
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh setup",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh configure",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l -c './hadrian/build-cabal clean'",
- "mkdir ./_build && cp -r ~/.wine/drive_c/msys64/opt/ghc-bootstrap/mingw ./_build/",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh build_hadrian",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh test_hadrian"
],
@@ -1281,7 +1280,6 @@
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh setup",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh configure",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l -c './hadrian/build-cabal clean'",
- "mkdir ./_build && cp -r ~/.wine/drive_c/msys64/opt/ghc-bootstrap/mingw ./_build/",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh build_hadrian",
"/opt/wine-arm64ec-msys2-deb12/bin/wine c:/msys64/usr/bin/bash.exe -l .gitlab/ci.sh test_hadrian"
],
=====================================
hadrian/src/Builder.hs
=====================================
@@ -26,7 +26,7 @@ import Hadrian.Builder.Tar
import Hadrian.Oracles.Path
import Hadrian.Oracles.TextFile
import Hadrian.Utilities
-import Oracles.Setting (bashPath, targetStage, isWinHost)
+import Oracles.Setting (bashPath, targetStage, isWinHost, isWinTarget)
import System.Exit
import System.IO (stderr)
@@ -240,12 +240,14 @@ instance H.Builder Builder where
Ghc _ st -> do
root <- buildRoot
unlitPath <- builderPath Unlit
+ win_target <- isWinTarget
+ win_host <- isWinHost
distro_mingw <- settingsFileSetting ToolchainSetting_DistroMinGW
libffi_adjustors <- useLibffiForAdjustors
use_system_ffi <- flag UseSystemFfi
return $ [ unlitPath ]
- ++ [ root -/- mingwStamp | windowsHost, distro_mingw == "NO" ]
+ ++ [ root -/- mingwStamp | win_target, win_host, distro_mingw == "NO" ]
-- proxy for the entire mingw toolchain that
-- we have in inplace/mingw initially, and then at
-- root -/- mingw.
=====================================
hadrian/src/Rules/BinaryDist.hs
=====================================
@@ -256,7 +256,10 @@ bindistRules = do
copyFile ("libraries" -/- "prologue.txt") (bindistFilesDir -/- "docs-utils" -/- "prologue.txt")
copyFile ("libraries" -/- "gen_contents_index") (bindistFilesDir -/- "docs-utils" -/- "gen_contents_index" )
- when windowsHost $ do
+ win_host <- isWinHost
+ win_target <- isWinTarget
+ distro_mingw <- settingsFileSetting ToolchainSetting_DistroMinGW
+ when (win_host && win_target && distro_mingw == "NO") $ do
copyDirectory (root -/- "mingw") bindistFilesDir
-- we use that opportunity to delete the .stamp file that we use
-- as a proxy for the whole mingw toolchain, there's no point in
=====================================
m4/fp_setup_windows_toolchain.m4
=====================================
@@ -9,7 +9,19 @@ AC_DEFUN([FP_INSTALL_WINDOWS_TOOLCHAIN],[
fi
set_up_tarballs() {
- AC_MSG_NOTICE([Checking for Windows toolchain tarballs...])
+ AC_MSG_CHECKING([for Windows toolchain tarballs...])
+
+ # We are leaving an option to substitute the toolchain with manually prepared one at the CI due of cross-compile targets.
+ # Builtin toolchain does not support cross-compile nor we have other reasons why it should.
+ # Probably we shouldn't ship GHC with a built-in toolchain for all cross-compile options.
+ # Cross-compile support is a relatively new and experimental option for Windows target but
+ # important to support AArch64. Same as Darwin.
+ if test -d inplace/mingw
+ then
+ AC_MSG_RESULT([skipping, inplace/mingw exists])
+ return 0
+ fi
+
local action
if test "$TarballsAutodownload" = "NO"
then
@@ -17,6 +29,9 @@ AC_DEFUN([FP_INSTALL_WINDOWS_TOOLCHAIN],[
else
action="download"
fi
+ readonly action
+ AC_MSG_RESULT([$action...])
+
$PYTHON mk/get-win32-tarballs.py $action $mingw_arch
case $? in
0)
@@ -45,22 +60,19 @@ AC_DEFUN([FP_INSTALL_WINDOWS_TOOLCHAIN],[
esac
# Extract all the tarballs in one go
- if ! test -d inplace/mingw
- then
- AC_MSG_NOTICE([Extracting Windows toolchain from archives (may take a while)...])
- rm -rf inplace/mingw
- local base_dir="../ghc-tarballs/${tarball_dest_dir}"
- ( cd inplace &&
- find "${base_dir}" -name "*.tar.xz" -exec tar --xz -xf {} \; &&
- find "${base_dir}" -name "*.tar.zst" -exec tar --zstd -xf {} \; &&
- rm ".MTREE" &&
- rm ".PKGINFO" &&
- cd .. ) || AC_MSG_ERROR([Could not extract Windows toolchains.])
-
- mv "inplace/${tarball_mingw_dir}" inplace/mingw &&
- touch inplace/mingw
- AC_MSG_NOTICE([In-tree MingW-w64 tree created])
- fi
+ AC_MSG_NOTICE([Extracting Windows toolchain from archives (may take a while)...])
+ rm -rf inplace/mingw
+ local base_dir="../ghc-tarballs/${tarball_dest_dir}"
+ ( cd inplace &&
+ find "${base_dir}" -name "*.tar.xz" -exec tar --xz -xf {} \; &&
+ find "${base_dir}" -name "*.tar.zst" -exec tar --zstd -xf {} \; &&
+ rm ".MTREE" &&
+ rm ".PKGINFO" &&
+ cd .. ) || AC_MSG_ERROR([Could not extract Windows toolchains.])
+
+ mv "inplace/${tarball_mingw_dir}" inplace/mingw &&
+ touch inplace/mingw
+ AC_MSG_NOTICE([In-tree MingW-w64 tree created])
}
# See Note [How we configure the bundled windows toolchain]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/49d94b1dcb8a161d3988f02d8ad4773…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/49d94b1dcb8a161d3988f02d8ad4773…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Simon Peyton Jones pushed to branch wip/T23109a at Glasgow Haskell Compiler / GHC
Commits:
76b01916 by Simon Peyton Jones at 2025-05-15T06:54:29-04:00
Wibble
- - - - -
1 changed file:
- compiler/GHC/Core/Opt/OccurAnal.hs
Changes:
=====================================
compiler/GHC/Core/Opt/OccurAnal.hs
=====================================
@@ -1114,7 +1114,7 @@ occAnalNonRecRhs !env lvl imp_rule_edges mb_join bndr rhs
mkNonRecRhsCtxt :: TopLevelFlag -> Id -> Unfolding -> OccEncl
-- Precondition: Id is not a join point
-mkNonRecRhsCtxt lvl bndr unf
+mkNonRecRhsCtxt _lvl bndr unf
| certainly_inline = OccVanilla -- See Note [Cascading inlines]
| otherwise = OccRhs
where
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/76b019160e730140ee0a51f0bf83896…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/76b019160e730140ee0a51f0bf83896…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Simon Peyton Jones pushed to branch wip/T23109a at Glasgow Haskell Compiler / GHC
Commits:
e1482394 by Simon Peyton Jones at 2025-05-14T23:21:36-04:00
Improvements
esp inline top level things not-under-lambda only if it's a function.
Beware extra iterations in T18698a
- - - - -
2 changed files:
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
Changes:
=====================================
compiler/GHC/Core/Opt/OccurAnal.hs
=====================================
@@ -1124,7 +1124,7 @@ mkNonRecRhsCtxt lvl bndr unf
-- Distressing delicacy ... has to line up with preInlineUnconditionally
case idOccInfo bndr of
OneOcc { occ_in_lam = NotInsideLam, occ_n_br = 1 }
- -> active && not (isTopLevel lvl) && not stable_unf
+ -> active && not stable_unf
_ -> False
active = isAlwaysActive (idInlineActivation bndr)
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -1465,7 +1465,7 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
, occ_in_lam = NotInsideLam
, occ_int_cxt = int_cxt }
= isNotTopLevel top_lvl -- Get rid of allocation
- || (int_cxt==IsInteresting) -- Function is applied
+ || (int_cxt==IsInteresting && idArity bndr > 0) -- Function is applied
-- || (early_phase && not (isConLikeUnfolding unf)) -- See early_phase
one_occ OneOcc{ occ_n_br = 1
, occ_in_lam = IsInsideLam
@@ -1632,6 +1632,7 @@ postInlineUnconditionally env bind_cxt old_bndr bndr rhs
unfolding = idUnfolding bndr
-- arity = idArity bndr
is_cheap = isCheapUnfolding unfolding
+ is_exp = isExpandableUnfolding unfolding
uf_opts = seUnfoldingOpts env
phase = sePhase env
active = isActive phase (idInlineActivation bndr)
@@ -1639,6 +1640,8 @@ postInlineUnconditionally env bind_cxt old_bndr bndr rhs
-- Check for code-size blow-up from inlining in multiple places
code_dup_ok n_br
+ | is_top_lvl -- Don't inline top-level datacons, ever; no advantage,
+ , is_exp = False -- and float-out may have carefully created them
| n_br == 1 = True -- No duplication
| n_br >= 100 = False -- See #23627
| is_demanded = False -- Demanded => no allocation (it'll be a case expression
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e14823948401b7dad78cc4f2eddb03b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e14823948401b7dad78cc4f2eddb03b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/step-out] debugger: Implement step-out feature
by Rodrigo Mesquita (@alt-romes) 14 May '25
by Rodrigo Mesquita (@alt-romes) 14 May '25
14 May '25
Rodrigo Mesquita pushed to branch wip/romes/step-out at Glasgow Haskell Compiler / GHC
Commits:
a043f051 by Rodrigo Mesquita at 2025-05-14T17:56:40+01:00
debugger: Implement step-out feature
Implements support for stepping-out of a function (aka breaking right after
returning from a function) in the interactive debugger.
It also introduces a GHCi command :stepout to step-out of a function
being debugged in the interpreter. The feature is described as:
Stop at the first breakpoint immediately after returning from the current
function scope.
Known limitations: because a function tail-call does not push a stack
frame, if step-out is used inside of a function that was tail-called,
execution will not be returned to its caller, but rather its caller's
first non-tail caller. In the following example:
.. code-block:: none
f = do
a
b <--- (1) set breakpoint then step in here
c
b = do
...
d <--- (2) step-into this tail call
d = do
...
something <--- (3) step-out here
...
Stepping-out will stop execution at the `c` invokation in `f`, rather than
stopping at `b`.
The key implementation bit is simple:
When step-out is set and the interpreter hits a RETURN instruction,
enable "stop at the immediate next breakpoint" (aka single-step).
See also `Note [Debugger Step-out]` in `rts/Interpreter.c`
Note [Debugger Step-out]
~~~~~~~~~~~~~~~~~~~~~~~~
When the global debugger step-out flag is set (`rts_stop_after_return`),
the interpreter must yield execution right after the first RETURN.
When stepping-out, we simply enable `rts_stop_next_breakpoint` when we hit a
return instruction (in `do_return_pointer` and `do_return_nonpointer`).
The step-out flag is cleared and must be re-enabled explicitly to step-out again.
A limitation of this approach is that stepping-out of a function that was
tail-called will skip its caller since no stack frame is pushed for a tail
call (i.e. a tail call returns directly to its caller's first non-tail caller).
Fixes #26042
- - - - -
10 changed files:
- compiler/GHC/Driver/Config.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Eval/Types.hs
- docs/users_guide/ghci.rst
- ghc/GHCi/UI.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- rts/Interpreter.c
- rts/RtsSymbols.c
- rts/include/stg/MiscClosures.h
Changes:
=====================================
compiler/GHC/Driver/Config.hs
=====================================
@@ -3,6 +3,7 @@ module GHC.Driver.Config
( initOptCoercionOpts
, initSimpleOpts
, initEvalOpts
+ , EvalStep(..)
)
where
@@ -28,13 +29,28 @@ initSimpleOpts dflags = SimpleOpts
, so_inline = True
}
+-- | Instruct the interpreter evaluation to break...
+data EvalStep
+ -- | ... at every breakpoint tick
+ = EvalStepSingle
+ -- | ... after every return stmt
+ | EvalStepOut
+ -- | ... only on explicit breakpoints
+ | EvalStepNone
+
-- | Extract GHCi options from DynFlags and step
-initEvalOpts :: DynFlags -> Bool -> EvalOpts
+initEvalOpts :: DynFlags -> EvalStep -> EvalOpts
initEvalOpts dflags step =
EvalOpts
{ useSandboxThread = gopt Opt_GhciSandbox dflags
- , singleStep = step
+ , singleStep = singleStep
+ , stepOut = stepOut
, breakOnException = gopt Opt_BreakOnException dflags
, breakOnError = gopt Opt_BreakOnError dflags
}
+ where
+ (singleStep, stepOut) = case step of
+ EvalStepSingle -> (True, False)
+ EvalStepOut -> (False, True)
+ EvalStepNone -> (False, False)
=====================================
compiler/GHC/Runtime/Eval.hs
=====================================
@@ -343,7 +343,12 @@ handleRunStatus step expr bindings final_ids status history0 = do
setSession hsc_env2
return (ExecBreak names Nothing)
- -- Just case: we stopped at a breakpoint
+ -- EvalBreak (Just ...) case: the interpreter stopped at a breakpoint
+ --
+ -- The interpreter yields on a breakpoint if:
+ -- - the breakpoint was explicitly enabled (in @BreakArray@)
+ -- - or @singleStep = True@ in EvalOpts
+ -- - or @stopAfterRet = True@ in EvalOpts
EvalBreak apStack_ref (Just eval_break) resume_ctxt ccs -> do
let ibi = evalBreakpointToId eval_break
tick_brks <- liftIO $ readModBreaks hsc_env (ibi_tick_mod ibi)
@@ -351,13 +356,14 @@ handleRunStatus step expr bindings final_ids status history0 = do
span = modBreaks_locs tick_brks ! ibi_tick_index ibi
decl = intercalate "." $ modBreaks_decls tick_brks ! ibi_tick_index ibi
+ -- Was the breakpoint explicitly enabled?
b <- liftIO $ breakpointStatus interp (modBreaks_flags tick_brks) (ibi_tick_index ibi)
apStack_fhv <- liftIO $ mkFinalizedHValue interp apStack_ref
resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt
- -- This breakpoint is explicitly enabled; we want to stop
- -- instead of just logging it.
+ -- This breakpoint is enabled or we mean to break here;
+ -- we want to stop instead of just logging it.
if b || breakHere step span then do
-- This function only returns control to ghci with 'ExecBreak' when it is really meant to break.
-- Specifically, for :steplocal or :stepmodule, don't return control
@@ -1247,7 +1253,7 @@ compileParsedExprRemote expr@(L loc _) = withSession $ \hsc_env -> do
_ -> panic "compileParsedExprRemote"
updateFixityEnv fix_env
- let eval_opts = initEvalOpts dflags False
+ let eval_opts = initEvalOpts dflags EvalStepNone
status <- liftIO $ evalStmt interp eval_opts (EvalThis hvals_io)
case status of
EvalComplete _ (EvalSuccess [hval]) -> return hval
=====================================
compiler/GHC/Runtime/Eval/Types.hs
=====================================
@@ -17,6 +17,7 @@ import GHC.Prelude
import GHCi.RemoteTypes
import GHCi.Message (EvalExpr, ResumeContext)
+import GHC.Driver.Config (EvalStep(..))
import GHC.Types.Id
import GHC.Types.Name
import GHC.Types.TyThing
@@ -46,6 +47,9 @@ data SingleStep
-- | :step [expr]
| SingleStep
+ -- | :stepout [expr]
+ | StepOut
+
-- | :steplocal [expr]
| LocalStep
{ breakAt :: SrcSpan }
@@ -55,10 +59,12 @@ data SingleStep
{ breakAt :: SrcSpan }
-- | Whether this 'SingleStep' mode requires instructing the interpreter to
--- step at every breakpoint.
-enableGhcStepMode :: SingleStep -> Bool
-enableGhcStepMode RunToCompletion = False
-enableGhcStepMode _ = True
+-- step at every breakpoint or after every return (see @'EvalStep'@).
+enableGhcStepMode :: SingleStep -> EvalStep
+enableGhcStepMode RunToCompletion = EvalStepNone
+enableGhcStepMode StepOut = EvalStepOut
+-- for the remaining step modes we need to stop at every single breakpoint.
+enableGhcStepMode _ = EvalStepSingle
-- | Given a 'SingleStep' mode and the SrcSpan of a breakpoint we hit, return
-- @True@ if based on the step-mode alone we should stop at this breakpoint.
@@ -70,6 +76,7 @@ breakHere :: SingleStep -> SrcSpan -> Bool
breakHere step break_span = case step of
RunToCompletion -> False
RunAndLogSteps -> False
+ StepOut -> True -- hmm. this function may not be a good abstraction?
SingleStep -> True
LocalStep span -> break_span `isSubspanOf` span
ModuleStep span -> srcSpanFileName_maybe span == srcSpanFileName_maybe break_span
=====================================
docs/users_guide/ghci.rst
=====================================
@@ -2980,6 +2980,33 @@ commonly used commands.
hit by an error (:ghc-flag:`-fbreak-on-error`) or an
exception (:ghc-flag:`-fbreak-on-exception`).
+.. ghci-cmd:: :stepout
+
+ Stop at the first breakpoint immediately after returning from the current
+ function scope.
+
+ Known limitations: because a function tail-call does not push a stack
+ frame, if step-out is used inside of a function that was tail-called,
+ execution will not be returned to its caller, but rather its caller's
+ first non-tail caller. In the following example:
+
+ .. code-block:: none
+
+ f = do
+ a
+ b <--- (1) set breakpoint then step in here
+ c
+ b = do
+ ...
+ d <--- (2) step-into this tail call
+ d = do
+ ...
+ something <--- (3) step-out here
+ ...
+
+ Stepping-out will stop execution at the `c` invokation in `f`, rather than
+ stopping at `b`.
+
.. ghci-cmd:: :stepmodule
Enable only breakpoints in the current module and resume evaluation
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -247,6 +247,7 @@ ghciCommands = map mkCmd [
("sprint", keepGoing sprintCmd, completeExpression),
("step", keepGoing stepCmd, completeIdentifier),
("steplocal", keepGoing stepLocalCmd, completeIdentifier),
+ ("stepout", keepGoing stepOutCmd, completeIdentifier),
("stepmodule",keepGoing stepModuleCmd, completeIdentifier),
("type", keepGoingMulti' typeOfExpr, completeExpression),
("trace", keepGoing traceCmd, completeExpression),
@@ -407,6 +408,7 @@ defFullHelpText =
" :step single-step after stopping at a breakpoint\n"++
" :step <expr> single-step into <expr>\n"++
" :steplocal single-step within the current top-level binding\n"++
+ " :stepout stop at the first breakpoint after returning from the current scope\n"++
" :stepmodule single-step restricted to the current module\n"++
" :trace trace after stopping at a breakpoint\n"++
" :trace <expr> evaluate <expr> with tracing on (see :history)\n"++
@@ -3793,6 +3795,12 @@ stepCmd arg = withSandboxOnly ":step" $ step arg
step [] = doContinue GHC.SingleStep
step expression = runStmt expression GHC.SingleStep >> return ()
+stepOutCmd :: GhciMonad m => String -> m ()
+stepOutCmd arg = withSandboxOnly ":stepout" $ step arg
+ where
+ step [] = doContinue GHC.StepOut
+ step expression = stepCmd expression
+
stepLocalCmd :: GhciMonad m => String -> m ()
stepLocalCmd arg = withSandboxOnly ":steplocal" $ step arg
where
=====================================
libraries/ghci/GHCi/Message.hs
=====================================
@@ -374,6 +374,7 @@ putTHMessage m = case m of
data EvalOpts = EvalOpts
{ useSandboxThread :: Bool
, singleStep :: Bool
+ , stepOut :: Bool
, breakOnException :: Bool
, breakOnError :: Bool
}
=====================================
libraries/ghci/GHCi/Run.hs
=====================================
@@ -210,6 +210,7 @@ evalOptsSeq :: EvalOpts
evalOptsSeq = EvalOpts
{ useSandboxThread = True
, singleStep = False
+ , stepOut = False
, breakOnException = False
, breakOnError = False
}
@@ -333,6 +334,7 @@ withBreakAction opts breakMVar statusMVar act
poke breakPointIOAction stablePtr
when (breakOnException opts) $ poke exceptionFlag 1
when (singleStep opts) $ setStepFlag
+ when (breakOnException opts) $ poke stepOutFlag 1
return stablePtr
-- Breaking on exceptions is not enabled by default, since it
-- might be a bit surprising. The exception flag is turned off
@@ -363,6 +365,7 @@ withBreakAction opts breakMVar statusMVar act
resetBreakAction stablePtr = do
poke breakPointIOAction noBreakStablePtr
poke exceptionFlag 0
+ poke stepOutFlag 0
resetStepFlag
freeStablePtr stablePtr
@@ -398,6 +401,7 @@ abandonStmt hvref = do
foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt
foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt
+foreign import ccall "&rts_stop_after_return" stepOutFlag :: Ptr CInt
setStepFlag :: IO ()
setStepFlag = poke stepFlag 1
=====================================
rts/Interpreter.c
=====================================
@@ -194,6 +194,24 @@ See also Note [Width of parameters] for some more motivation.
#define WITHIN_CHUNK_BOUNDS(n, s) \
(RTS_LIKELY((StgWord*)(Sp_plusW(n)) < ((s)->stack + (s)->stack_size - sizeofW(StgUnderflowFrame))))
+// Note [Debugger Step-out]
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+// When the global debugger step-out flag is set (`rts_stop_after_return`),
+// the interpreter must yield execution right after the first RETURN.
+//
+// When stepping-out, we simply enable `rts_stop_next_breakpoint` when we hit a
+// return instruction (in `do_return_pointer` and `do_return_nonpointer`).
+// The step-out flag is cleared and must be re-enabled explicitly to step-out again.
+//
+// A limitation of this approach is that stepping-out of a function that was
+// tail-called will skip its caller since no stack frame is pushed for a tail
+// call (i.e. a tail call returns directly to its caller's first non-tail caller).
+#define CHECK_BRK_AFTER_RET() \
+ if (rts_stop_after_return) \
+ { \
+ rts_stop_next_breakpoint = true; \
+ rts_stop_after_return = false; \
+ } \
/* Note [PUSH_L underflow]
~~~~~~~~~~~~~~~~~~~~~~~
@@ -245,6 +263,7 @@ allocate_NONUPD (Capability *cap, int n_words)
int rts_stop_next_breakpoint = 0;
int rts_stop_on_exception = 0;
+int rts_stop_after_return = 0;
#if defined(INTERP_STATS)
@@ -734,6 +753,8 @@ do_return_pointer:
IF_DEBUG(sanity,checkStackChunk(Sp, cap->r.rCurrentTSO->stackobj->stack+cap->r.rCurrentTSO->stackobj->stack_size));
+ CHECK_BRK_AFTER_RET();
+
switch (get_itbl((StgClosure *)Sp)->type) {
case RET_SMALL: {
@@ -883,6 +904,8 @@ do_return_nonpointer:
// get the offset of the header of the next stack frame
offset = stack_frame_sizeW((StgClosure *)Sp);
+ CHECK_BRK_AFTER_RET();
+
switch (get_itbl((StgClosure*)(Sp_plusW(offset)))->type) {
case RET_BCO:
=====================================
rts/RtsSymbols.c
=====================================
@@ -908,6 +908,7 @@ extern char **environ;
SymI_NeedsDataProto(rts_breakpoint_io_action) \
SymI_NeedsDataProto(rts_stop_next_breakpoint) \
SymI_NeedsDataProto(rts_stop_on_exception) \
+ SymI_NeedsDataProto(rts_stop_after_return) \
SymI_HasProto(stopTimer) \
SymI_HasProto(n_capabilities) \
SymI_HasProto(max_n_capabilities) \
=====================================
rts/include/stg/MiscClosures.h
=====================================
@@ -619,6 +619,7 @@ RTS_FUN_DECL(stg_castFloatToWord32zh);
// Interpreter.c
extern StgWord rts_stop_next_breakpoint[];
extern StgWord rts_stop_on_exception[];
+extern StgWord rts_stop_after_return[];
extern StgWord rts_breakpoint_io_action[];
// Schedule.c
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a043f05102cb9357e58c30cb1a2cbb9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a043f05102cb9357e58c30cb1a2cbb9…
You're receiving this email because of your account on gitlab.haskell.org.
1
0