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 <ben@well-typed.com> - - - - - 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.
participants (1)
-
Rodrigo Mesquita (@alt-romes)