A smaller hunk, and the restart-case shape that is not a counterexample
This commit is contained in:
parent
1e816702b6
commit
624a94af7b
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user