Rodrigo Mesquita pushed to branch wip/romes/step-out-5 at Glasgow Haskell Compiler / GHC
Commits:
271ae51e by Rodrigo Mesquita at 2025-07-02T09:24:40+00:00
Apply 6 suggestion(s) to 4 file(s)
Co-authored-by: Ben Gamari
- - - - -
4 changed files:
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Driver/Config.hs
- compiler/GHC/StgToByteCode.hs
- rts/Interpreter.c
Changes:
=====================================
compiler/GHC/ByteCode/Types.hs
=====================================
@@ -203,7 +203,7 @@ A stack with a BCO stack frame at the top looks like:
In the case of bytecode objects found on the heap (e.g. thunks and functions),
the bytecode may refer to free variables recorded in the BCO closure itself.
-By contrast, in /case continuation/ BCOsthe code may additionally refer to free
+By contrast, in /case continuation/ BCOs the code may additionally refer to free
variables in their stack frame. These are references by way of statically known
stack offsets (tracked using `BCEnv` in `StgToByteCode`).
=====================================
compiler/GHC/Driver/Config.hs
=====================================
@@ -33,7 +33,7 @@ initSimpleOpts dflags = SimpleOpts
data EvalStep
-- | ... at every breakpoint tick
= EvalStepSingle
- -- | ... after any return stmt
+ -- | ... after any evaluation to WHNF
| EvalStepOut
-- | ... only on explicit breakpoints
| EvalStepNone
=====================================
compiler/GHC/StgToByteCode.hs
=====================================
@@ -1407,25 +1407,49 @@ ensuring that we stop exactly when we return to the continuation.
However, case continuation BCOs (produced by PUSH_ALTS and which merely compute
which case alternative BCO to enter next) contain no user-facing breakpoint
-ticks (BRK_FUN):
+ticks (BRK_FUN). While we could in principle add breakpoints in case continuation
+BCOs, there are a few reasons why this is not an attractive option:
1) It's not useful to a user stepping through the program to always have a
breakpoint after the scrutinee is evaluated but before the case alternative
is selected. The source span associated with such a breakpoint would also be
slightly awkward to choose.
- 2) It's not easy to add a source-tick before the case alternatives because in
+ 2) It's not easy to add a breakpoint tick before the case alternatives because in
essentially all internal representations they are given as a list of Alts
rather than an expression.
-To provide the debugger a way to enable at runtime the case continuation
-breakpoints despite the lack of BRK_FUNs, we introduce at the start
-of every case continuation BCO a BRK_ALTS instruction.
-
-The BRK_ALTS instruction, if enabled (by its single arg), ensures we stop at
-the breakpoint heading the case alternative we take. Under the hood, this means
-that when BRK_ALTS is enabled we set TSO_STOP_NEXT_BREAKPOINT just before
-selecting the alternative.
+To provide the debugger a way to break in a case continuation
+despite the BCOs' lack of BRK_FUNs, we introduce an alternative
+type of breakpoint, represented by the BRK_ALTS instruction,
+at the start of every case continuation BCO. For instance,
+
+ case x of
+ 0# -> ...
+ _ -> ...
+
+will produce a continuation of the form (N.B. the below bytecode
+is simplified):
+
+ PUSH_ALTS P
+ BRK_ALTS 0
+ TESTEQ_I 0 lblA
+ PUSH_BCO
+ BRK_FUN 0
+ -- body of 0# alternative
+ ENTER
+
+ lblA:
+ PUSH_BCO
+ BRK_FUN 1
+ -- body of wildcard alternative
+ ENTER
+
+When enabled (by its single boolean operand), the BRK_ALTS instruction causes
+the program to break at the next encountered breakpoint (implemented
+by setting the TSO's TSO_STOP_NEXT_BREAKPOINT flag). Since the case
+continuation BCO will ultimately jump to one of the alternatives (each of
+which having its own BRK_FUN) we are guaranteed to stop in the taken alternative.
It's important that BRK_ALTS (just like BRK_FUN) is the first instruction of
the BCO, since that's where the debugger will look to enable it at runtime.
=====================================
rts/Interpreter.c
=====================================
@@ -351,7 +351,7 @@ To achieve this, when the flag is set as the interpreter is re-entered:
(2a) For PUSH_ALT BCOs, the breakpoint instruction will be BRK_ALTS
(as explained in Note [Debugger: BRK_ALTS]) and it can be enabled by
- overriding its first argument to 1.
+ setting its first operand to 1.
(2b) Otherwise, the instruction will be BRK_FUN and the breakpoint can be
enabled by setting the associated BreakArray at the associated tick
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/271ae51e199ea0f8bef1c31bd8e94dc8...
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/271ae51e199ea0f8bef1c31bd8e94dc8...
You're receiving this email because of your account on gitlab.haskell.org.