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
|
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.
|
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
|
### The edit, for the merge
|
||||||
|
|
||||||
`lib/x86.ml`, in `emit_fn`, the tail of the transfer-exit block. The six lines that were
|
`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
|
||||||
end
|
end
|
||||||
else begin zero_return (); jmp_lbl f.b f.retlbl 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
|
(* 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
|
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
|
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
|
emits [guard] — [Signal], [bounds_call], the two [rt_signals] entry
|
||||||
points, and every call by name or by pointer — or jumps to [current_pad]
|
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
|
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. *)
|
(* The prologue, now that the frame size is known. *)
|
||||||
let pb = create () in
|
let pb = create () in
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user