Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Summary * simplify MIR control-flow constructs * lower `finally` into a `block` + `case` dispatcher in `mirgen` * emit exception stack management code in `mirgen` already * inline scope cleanup directly at `break` and `return` ## Details The goals are to: * use a unified exception runtime across all backends * make the MIR simpler * reduce the complexity of the language reaching the code generators, and thus the amount of translation work for the code generators For the MIR: * target lists are removed; jumps only need to specify a single target * `Finally` can only be used as the target for exceptional jumps; unstructured control-flow out of a `Finally` section is disallowed * only a single exceptional target can be specified for `Continue` * `Raise` is decoupled from exception management; it only initiates unwinding now The various MIR processing, rendering, and translation is adjusted accordingly. The CGIR equivalents to the MIR constructs change in the same way. Since `Finally` can no longer be used with non-exceptional control-flow (`Goto`, `Case`, etc.), translation of both scope cleanup and `finally` needs to change in `mirgen`. The exception runtime calls for managing the exception stack also have to be injected in `mirgen` already. ### `finally` Lowering `finally` is translated into continuation passing. However, instead of reifying the `finally` into a standalone procedure, all "invocations" of (read, jumps to) the `finally` record their original destination in a local variable, which a dispatcher emitted at the end of the `finally` clause then uses to jump to the target (or another intercepting `finally`). ### Scope Cleanup Scope cleanup in response to an exception being raised still uses `Finally`. For cleanup in response to `break` or `return`, all necessary cleanup is emitted directly before the `Goto`. This increases the workload for the move analysis / destructor elision pass, but it also results in more efficient code (since there are usually less dynamic invocations of destructors). ### Code Generation All three code generators are updated to consider the new syntax and semantics of `Finally`, `Continue`, etc. Notably: * `ccgflow` is obsolete and thus removed; code generation for `Finally`, `Continue`, etc. is now simple enough to implement directly in `cgen` * `jsgen` now translates `Finally` to a JavaScript `catch` clause (so as to not interfere with `break`s), which simplifies code generation (no more enabling/disabling of `finally` clauses for breaks) and also improves code size / performance in some cases ### Exception Runtime * `nimAbortException` has a `viaRaise` parameter now, as the C-specific error flag cannot be used anymore for detecting what causes the abort * `prepareException` is merged back into `raiseExceptionAux` The JavaScript target also using the C exception runtime now fixes a bug where breaking out of a `finally` didn't clean up the current exception properly. ### VM Exception stack management is partially decoupled from the core VM and moved to `vmops` (which hooks and implements the various exception runtime procedures). Generating the stacktrace still needs to be done directly by the VM, which prevents the exception stack management from being fully decoupled. --------- Co-authored-by: Saem Ghani <[email protected]>
- Loading branch information