Repository navigation
Discharge and structure the exception channel (EH-09..EH-11) - #152
Merged
Merged
Conversation
The P9 discharge turns a call to a psrs:runtime-exception binding into the
design's inline try region, and the structurer emits it as a try_table unit;
the two boundaries the design names are enforced.
- bindings/runtime/exception.rs: the checked source contract for the
psrs:runtime-exception provider — one guarded callable operand taking the
erased Unit and a Boolean result, rechecked at the physical boundary; no
host ABI, so plan_import plans no import (mir/runtime/context.rs collects
the provider for live direct calls only).
- mir/lower/exception.rs: the discharge builds Try { protected, catch_all }
inline — the protected block fabricates the Unit operand, applies the
callable through ClosureCall, and jumps to the shared join with false; the
handler jumps with true; the join's parameter is the assignment's
destination. A disabled profile rejects the call at the binding's own span.
- wasm/lower/structure/cfg/try_context.rs: the structurer's checked view —
all clauses of one region must agree on the payload and handler they
deliver to (one synthesized unwind block), claims close transitively over
nested tries, and try/loop overlap must nest (try inside loop, loop inside
protected region) or stay disjoint.
- wasm/lower/structure/cfg/build.rs: UnitPlan::Try occupies one slot in the
enclosing region's topological order; the protected sub-region is the raw
dominated set (inner tries and loops reappear as nested units) and claim
bubbling keeps every inline-emitted block claimed exactly once.
- wasm/lower/structure/region/try_unit.rs: emit_try_unit — the try block's
instructions, one synthesized unwind Op::Block whose result is the caught
payload enclosing the try_table, every clause targeting that block at
depth 0, the payload copied into the handler's parameter locals like jump
arguments, then the handler's instructions and terminator. The design's
sketch writes br to the normal join after the try_table; the emitted body
ends in unreachable instead — every protected block's terminator leaves
the region, the dead path carries none of the join's per-path arguments,
and the unreachable discharges the payload-typed result for the validator.
The watermark save/restore points (EH-14) are marked, nothing budget-
related exists yet. Label gains the two anonymous entries (Unwind,
TryTable) so branch depths stay correct.
- wasm/lower/mod.rs: each tag's function type is appended and its TagDef
recorded; the tag section is filled from the MIR tag table. Throw emits
its payload and throw; a Try terminator outside a try unit is rejected.
- The try-region partition's dominance input is now the CFG including
unwind edges (mir/cfg.rs unwind_successors, dominators_with_unwind_edges),
per the design's invariant section: the handler edge keeps a join shared
by the protected and catch paths out of the region. The region plan's
reachability walk follows unwind edges too, so catch-path blocks are
planned.
- cfg/mod.rs (773 lines), region.rs (504), and the structuring test file
(533) are split into module directories with content preserved;
mir/mod.rs sits at 498 lines.
Checklist rows EH-09..EH-11 verified: direct-MIR discharge and structuring
fixtures executed under wasmtime 48.0.1 (nested tries, named catch payload,
try re-armed across loop iterations, loop inside the protected region,
try-free irreducible dispatcher input), the disabled-profile rejection and
the irreducible-with-try rejection asserted locally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What lands
Slice 3 of the exception-handling adoption (rows EH-09..EH-11), per the design from PR #149:
bindings/runtime/exception.rs: the checkedpsrs:runtime-exception#checkThrowscontract ((Unit -> a) -> Boolean, payload-erased closure operand, no host ABI —plan_importplans no import);mir/lower/exception.rs: the P9 discharge into the inline try region (Try { protected, catch_all }shape; guarded callable called in the protected block; handler value returned through the join); disabled-profile rejection at the binding's span.UnitPlan::Trycomposite unit: synthesized unwindOp::Blockenclosing thetry_tablewith result = the caught payload, payload copied into handler parameters like jump arguments, anonymous label entries (unwind block + the try_table's internal label); nested tries, try inside loop (re-armed per iteration), loop inside protected region all have fixtures.Design-conformance notes recorded in the checklist's slice-3 record: the normal join after a try_table emits
unreachable(protected blocks always leave the region, so the try_table never completes normally); the try-region partition's dominance is now computed over the CFG that includes unwind edges (per the design's own invariant, fixing a join-sharing gap); a clause-uniformity rule (one unwind block ⇒ all clauses agree on payload/handler) is checked at P10.Evidence (coordinator verified fmt + clippy; full suite run by the slice)
PSRS_STDLIB_ROOT=… PSRS_REQUIRE_WASMTIME=1 cargo test --workspace— 2179 passed, 0 failed, wasmtime CLI 48.0.1: discharge normal path (exit 0), catch path (exit 1), nested tries (exit 10, inner handler catches), named catch payload (exit 7), try re-armed across loop iterations (exit 99), loop inside protected region (exit 42), try-free irreducible dispatcher input (exit 1). Checklist rows EH-09..11 → Verified with evidence; D-04 untouched; profile default unchanged. 500-line rule:cfg/mod.rs,region.rs, and one test split into module directories with content preserved.