A smaller hunk, and the restart-case shape that is not a counterexample

This commit is contained in:
Joseph Ferano 2026-09-13 22:46:16 +07:00
parent 1e816702b6
commit 624a94af7b
2 changed files with 10 additions and 3 deletions

View File

@ -63,6 +63,11 @@ foreign call gets neither, correctly: a transfer cannot cross a C frame, because
signature C sees. So `unwound` is false **exactly** when no transfer can arrive, and the defers on that exit are
dead in fact and not merely by assumption.
The one shape that looks like a counterexample and is not: a function whose every call sits inside a `restart-case`,
so that no `guard` ever finds an empty pad stack. It still sets `unwound`, because the guard sets that pad's `used`,
which is what causes the pad to be emitted at all, and the pad's tail — line 1358, the transfer aimed further out
than any clause it offers — re-propagates through `current_pad` with its own frame already popped off `f.pads`.
### The edit, for the merge
`lib/x86.ml`, in `emit_fn`, the tail of the transfer-exit block. The six lines that were

View File

@ -2230,7 +2230,7 @@ let emit_fn (md : Emit.m) ~externs ~fns (fn : Tast.fn) : string * string =
end
end
else begin zero_return (); jmp_lbl f.b f.retlbl end
end
end;
(* And if [f.unwound] is false there is nothing to emit: the defers on the
transfer exit are dead because no path names that exit. This used to be a
refusal, on the theory that a function with a defer and no transfer exit
@ -2244,8 +2244,10 @@ let emit_fn (md : Emit.m) ~externs ~fns (fn : Tast.fn) : string * string =
emits [guard] [Signal], [bounds_call], the two [rt_signals] entry
points, and every call by name or by pointer or jumps to [current_pad]
outright, which is [invoke-restart] and the three re-propagating pads. So
[unwound] is false exactly when no transfer can arrive. *)
;
[unwound] is false exactly when no transfer can arrive. A function whose
every call sits inside a [restart-case] is not a counterexample: the
guard sets that pad's [used], the pad is emitted, and its tail
re-propagates through [current_pad] with the pad stack already popped. *)
(* The prologue, now that the frame size is known. *)
let pb = create () in