Fil-C on Nix

Filnix wiki

the formal campaign

rocq/theories/Shutdown.v

Serialized shutdown of the selected user-glibc: callbacks, stdout obligations and a soft or hard host-exit handoff. This is a logical lifecycle, not native callback execution or host termination. In particular, a handoff does not itself emit ProcessExit.

From Stdlib Require Import ZArith List Bool Lia Sorting.Permutation
From Nanofil Require Import Term Syntax Values Memory Ops Semantics ExternalCalls Startup Stdio
Import ListNotations
Open Scope Z_scope
Open Scope list_scope

Callback calling conventions retain their argument, not just its address.

13Inductive exit_callback: Type ≔
|AtExit
function : name
|OnExit
function : name argument : word
|CxaExit
function : name argument : word

A registration instance: registering one function twice gives two tokens.

19Record registration: Type ≔ mkRegistration
registration_token
 : nat
registration_callback

Soft handoff calls host exit; hard handoff calls host _Exit.

25Inductive handoff_kind: Type ≔
|SoftExit
|HardExit

The selected TLS destructor loop is empty. Done is derived from phase: registration has closed in Cleanup and cannot reopen.

29Inductive shutdown_phase: Type ≔
|Tls
|Handlers
|InCallback
active : registration
|Cleanup
|HandedOff
kind : handoff_kind

Pending registrations are newest first; consumed tokens retain history even when a recursive exit abandons the active callback.

35Record shutdown_state: Type ≔ mkShutdown
shutdown_at
shutdown_status
 : Z
shutdown_pending
 : listregistration
shutdown_consumed
 : listnat
shutdown_stdout

Protocol actions are not arbitrary callback traces or native events.

44Inductive shutdown_action: Type ≔
|EmptyTls
|InvokeCallback
entry : registration status : Z
|ReturnCallback
|RegisterCallback
entry : registration
|RecursiveExit
status : Z
|ShutdownOutput
action : stream_action
|StartCleanup
|Handoff
kind : handoff_kind status : Z

The protocol permits finite unfinished callbacks/cleanup. Successful registration is conditional, and fresh tokens cannot reuse an instance. Cleanup only projects settlement/error, not all of native _IO_cleanup. Hard exit does not flush or discard outstanding output.

54Inductive shutdown_step: shutdown_state → shutdown_action → shutdown_state → Prop ≔
∀ status pending consumed q
shutdown_stepmkShutdownTls status pending consumed q EmptyTls mkShutdownHandlers status pending consumed q
shutdown_tls
∀ status entry pending consumed q
shutdown_stepmkShutdownHandlers status entry :: pending consumed q InvokeCallbackentry status mkShutdownInCallbackentry status pending consumed ++ registration_tokenentry q
shutdown_invoke
∀ status entry pending consumed q
shutdown_stepmkShutdownInCallbackentry status pending consumed q ReturnCallback mkShutdownHandlers status pending consumed q
shutdown_return
∀ status active entry pending consumed q
¬Inregistration_tokenentry consumed ++ mapregistration_token pending
shutdown_register
shutdown_stepmkShutdownInCallbackactive status pending consumed q RegisterCallbackentry mkShutdownInCallbackactive status entry :: pending consumed q
∀ status active pending consumed q status′
shutdown_stepmkShutdownInCallbackactive status pending consumed q RecursiveExitstatus′ mkShutdownTls status′ pending consumed q
shutdown_recursive
∀ status active pending consumed q action q′
stream_stepq action q′
shutdown_callback_output
shutdown_stepmkShutdownInCallbackactive status pending consumed q ShutdownOutputaction mkShutdownInCallbackactive status pending consumed q′
∀ status consumed q
shutdown_stepmkShutdownHandlers status [ ] consumed q StartCleanup mkShutdownCleanup status [ ] consumed q
shutdown_cleanup
∀ status consumed q action q′
∀bytes, action ≠ Acceptbytes
stream_stepq action q′
shutdown_cleanup_output
shutdown_stepmkShutdownCleanup status [ ] consumed q ShutdownOutputaction mkShutdownCleanup status [ ] consumed q′
∀ status consumed q
shutdown_stepmkShutdownCleanup status [ ] consumed q HandoffSoftExit status mkShutdownHandedOffSoftExit status [ ] consumed q
shutdown_soft

A source and selected action fix the logical endpoint. This lets a caller name its next cutpoint without supplying endpoint validity again.

96Lemma shutdown_step_target
∀ sh action left right
shutdown_stepsh action left
shutdown_stepsh action right
left = right
Explore proof 3 tactics

Initial goal

⊢
∀sh : shutdown_state action : shutdown_action left right : shutdown_state, shutdown_stepsh action left → shutdown_stepsh action right → left = right

intros sh action left right Hl Hr

left, right :
Hl :
shutdown_stepsh action left
Hr :
shutdown_stepsh action right
⊢
left = right

inversion Hl ; subst ; inversion Hr ; subst ; try reflexivity

2 open

status :
Z
active :
pending :
consumed :
listnat
action0 :
Hl :
shutdown_stepshutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q ShutdownOutputaction0 shutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q′
Hr :
shutdown_stepshutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q ShutdownOutputaction0 shutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q'0
H :
stream_stepq action0 q′
H7 :
stream_stepq action0 q'0
⊢
shutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q′ = shutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q'0
focused goal
status :
Z
consumed :
listnat
action0 :
Hl :
Hr :
H :
∀bytes : listZ, action0 ≠ Acceptbytes
H0 :
stream_stepq action0 q′
H6 :
∀bytes : listZ, action0 ≠ Acceptbytes
H7 :
stream_stepq action0 q'0
⊢
shutdown_at ≔ Cleanup; shutdown_status ≔ status; shutdown_pending ≔ [ ]; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q′ = shutdown_at ≔ Cleanup; shutdown_status ≔ status; shutdown_pending ≔ [ ]; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q'0

all: match goal withH1 : stream_step?q ?a ?q1 , H2 : stream_step?q ?a ?q2 |- _⇒assert q1 = q2 by eapply stream_step_target ; eauto ; subst ; reflexivityend

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros sh action left right Hl Hr
inversion Hl ; subst ; inversion Hr ; subst ; try reflexivity
all: match goal withH1 : stream_step?q ?a ?q1 , H2 : stream_step?q ?a ?q2 |- _⇒assert q1 = q2 by eapply stream_step_target ; eauto ; subst ; reflexivityend

A finite shutdown prefix; no rule promises eventual completion.

105Inductive shutdown_run: shutdown_state → listshutdown_action → shutdown_state → Prop ≔
∀ s
shutdown_refl
∀ s action s1 actions s′
shutdown_steps action s1
shutdown_runs1 actions s′
shutdown_next
shutdown_runs action :: actions s′

All pending and consumed registration-instance tokens are distinct.

112Definition shutdown_uniques : shutdown_state : Prop ≔

Moving a fresh registration token into the pending stack preserves uniqueness.

116Lemma shutdown_unique_insert
∀ before after : listnat token
NoDupbefore ++ after
¬Intoken before ++ after
NoDupbefore ++ token :: after
Explore proof 3 tactics

Initial goal

⊢
∀before after : listnat token : nat, NoDupbefore ++ after → ¬Intoken before ++ after → NoDupbefore ++ token :: after

intros before after token Hnd Hfresh

before, after :
listnat
token :
nat
Hnd :
NoDupbefore ++ after
Hfresh :
¬Intoken before ++ after
⊢
NoDupbefore ++ token :: after

apply Permutation_NoDupPermutation_middlebefore after token

before, after :
listnat
token :
nat
Hnd :
NoDupbefore ++ after
Hfresh :
¬Intoken before ++ after
⊢
NoDuptoken :: before ++ after

constructor ; assumption

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros before after token Hnd Hfresh
apply Permutation_NoDupPermutation_middlebefore after token
constructor ; assumption

Pop-before-call and fresh successful registration preserve instance uniqueness.

126Lemma shutdown_step_unique
∀ s action s′
Explore proof 5 tactics

Initial goal

⊢
∀s : shutdown_state action : shutdown_action s′ : shutdown_state, shutdown_steps action s′ → shutdown_uniques → shutdown_uniques′

intros s action s′ H Hunique

destruct H ; unfold shutdown_unique in * ; simpl in * ; auto

2 open

status :
Z
pending :
consumed :
listnat
Hunique :
NoDupconsumed ++ registration_tokenentry :: mapregistration_token pending
⊢
NoDupconsumed ++ registration_tokenentry ++ mapregistration_token pending
focused goal
status :
Z
active, entry :
pending :
consumed :
listnat
H :
¬Inregistration_tokenentry consumed ++ mapregistration_token pending
Hunique :
NoDupconsumed ++ mapregistration_token pending
⊢
NoDupconsumed ++ registration_tokenentry :: mapregistration_token pending

–rewrite <- app_assoc

2 open

status :
Z
pending :
consumed :
listnat
Hunique :
NoDupconsumed ++ registration_tokenentry :: mapregistration_token pending
⊢
NoDupconsumed ++ registration_tokenentry ++ mapregistration_token pending
deferred goal
status :
Z
active, entry :
pending :
consumed :
listnat
H :
¬Inregistration_tokenentry consumed ++ mapregistration_token pending
Hunique :
NoDupconsumed ++ mapregistration_token pending
⊢
NoDupconsumed ++ registration_tokenentry :: mapregistration_token pending

exact Hunique

deferred goal
status :
Z
active, entry :
pending :
consumed :
listnat
H :
¬Inregistration_tokenentry consumed ++ mapregistration_token pending
Hunique :
NoDupconsumed ++ mapregistration_token pending
⊢
NoDupconsumed ++ registration_tokenentry :: mapregistration_token pending

–apply shutdown_unique_insert ; assumption

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s action s′ H Hunique
destruct H ; unfold shutdown_unique in * ; simpl in * ; auto
–rewrite <- app_assoc
exact Hunique
–apply shutdown_unique_insert ; assumption

No registration instance is invoked twice, even across recursive exit.

135Theorem shutdown_run_unique
∀ s actions s′
Explore proof 5 tactics

Initial goal

⊢
∀s : shutdown_state actions : listshutdown_action s′ : shutdown_state, shutdown_runs actions s′ → shutdown_uniques → shutdown_uniques′

intros s actions s′ H

induction H ; auto |

actions :
H :
shutdown_steps action s1
H0 :
shutdown_runs1 actions s′
IHshutdown_run :

intros Hu

actions :
H :
shutdown_steps action s1
H0 :
shutdown_runs1 actions s′
IHshutdown_run :

apply IHshutdown_run

actions :
H :
shutdown_steps action s1
H0 :
shutdown_runs1 actions s′
IHshutdown_run :

eapply shutdown_step_unique ; eauto

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s actions s′ H
induction H ; auto |
intros Hu
apply IHshutdown_run
eapply shutdown_step_unique ; eauto

Tokens invoked by one action; registering and returning invoke none.

143Definition invoked_byaction : shutdown_action : listnat ≔
match action with
_
⇒
[ ]

Consumed history grows by exactly the invoked instances, in invocation order.

147Lemma shutdown_step_consumed
∀ s action s′
shutdown_steps action s′
Explore proof 2 tactics

Initial goal

⊢
∀s : shutdown_state action : shutdown_action s′ : shutdown_state, shutdown_steps action s′ → shutdown_consumeds′ = shutdown_consumeds ++ invoked_byaction

intros s action s′ H

destruct H ; simpl ; try reflexivity ; symmetry ; apply app_nil_r

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s action s′ H
destruct H ; simpl ; try reflexivity ; symmetry ; apply app_nil_r

The history accounts for every callback invocation in a finite run.

155Theorem shutdown_consumption
∀ s actions s′
shutdown_runs actions s′
shutdown_consumeds′ = shutdown_consumeds ++ flat_mapinvoked_by actions
Explore proof 4 tactics

Initial goal

⊢
∀s : shutdown_state actions : listshutdown_action s′ : shutdown_state, shutdown_runs actions s′ → shutdown_consumeds′ = shutdown_consumeds ++ flat_mapinvoked_by actions

intros s actions s′ H

actions :
H :
shutdown_runs actions s′
⊢
shutdown_consumeds′ = shutdown_consumeds ++ flat_mapinvoked_by actions

induction H ; simpl ; symmetry ; apply app_nil_r |

actions :
H :
shutdown_steps action s1
H0 :
shutdown_runs1 actions s′
IHshutdown_run :
shutdown_consumeds′ = shutdown_consumeds1 ++ flat_mapinvoked_by actions
⊢
shutdown_consumeds′ = shutdown_consumeds ++ invoked_byaction ++ flat_mapinvoked_by actions

rewrite IHshutdown_run , shutdown_step_consumed_ _ _ H , app_assoc

actions :
H :
shutdown_steps action s1
H0 :
shutdown_runs1 actions s′
IHshutdown_run :
shutdown_consumeds′ = shutdown_consumeds1 ++ flat_mapinvoked_by actions
⊢
shutdown_consumeds ++ invoked_byaction ++ flat_mapinvoked_by actions = shutdown_consumeds ++ invoked_byaction ++ flat_mapinvoked_by actions

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s actions s′ H
induction H ; simpl ; symmetry ; apply app_nil_r |
rewrite IHshutdown_run , shutdown_step_consumed_ _ _ H , app_assoc
reflexivity

Every invoked token occurs once in the trace, not merely in final pending state.

164Theorem shutdown_invocations_unique
∀ s actions s′
NoDupflat_mapinvoked_by actions
Explore proof 7 tactics

Initial goal

⊢
∀s : shutdown_state actions : listshutdown_action s′ : shutdown_state, shutdown_runs actions s′ → shutdown_uniques → NoDupflat_mapinvoked_by actions

intros s actions s′ H Hu

⊢
NoDupflat_mapinvoked_by actions

pose proof shutdown_run_unique_ _ _ H Hu as Hfinal

⊢
NoDupflat_mapinvoked_by actions

unfold shutdown_unique in Hfinal

⊢
NoDupflat_mapinvoked_by actions

apply NoDup_app_remove_r in Hfinal

actions :
H :
shutdown_runs actions s′
Hfinal :
⊢
NoDupflat_mapinvoked_by actions

rewrite shutdown_consumption_ _ _ H in Hfinal

actions :
H :
shutdown_runs actions s′
Hfinal :
NoDupshutdown_consumeds ++ flat_mapinvoked_by actions
⊢
NoDupflat_mapinvoked_by actions

apply NoDup_app_remove_l in Hfinal

actions :
H :
shutdown_runs actions s′
Hfinal :
NoDupflat_mapinvoked_by actions
⊢
NoDupflat_mapinvoked_by actions

exact Hfinal

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s actions s′ H Hu
pose proof shutdown_run_unique_ _ _ H Hu as Hfinal
unfold shutdown_unique in Hfinal
apply NoDup_app_remove_r in Hfinal
rewrite shutdown_consumption_ _ _ H in Hfinal
apply NoDup_app_remove_l in Hfinal
exact Hfinal

Recursive exit and _exit install their own signed status, not the old exit's.

177Lemma shutdown_step_status
∀ s action s′
shutdown_steps action s′
Explore proof 2 tactics

Initial goal

⊢
∀s : shutdown_state action : shutdown_action s′ : shutdown_state, shutdown_steps action s′ → shutdown_statuss′ = shutdown_statuss ∨ action = RecursiveExitshutdown_statuss′ ∨ action = HandoffHardExit shutdown_statuss′

intros s action s′ H

destruct H ; simpl ; auto

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s action s′ H
destruct H ; simpl ; auto

Cleanup and either handoff have closed registration.

184Definition shutdown_closedphase : shutdown_phase : Prop ≔
match phase with
⇒
True
_
⇒
False

Closing registration is permanent through every remaining finite prefix.

188Theorem shutdown_closed_sticky
Explore proof 5 tactics

Initial goal

intros s actions s′ H

induction H ; auto |

intros Hclosed

apply IHshutdown_run

destruct H ; simpl in * ; tauto

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s actions s′ H
induction H ; auto |
intros Hclosed
apply IHshutdown_run
destruct H ; simpl in * ; tauto

A user-glibc handoff has no further lifecycle step.

197Theorem shutdown_handoff_stopped
∀ s kind action s′
¬shutdown_steps action s′
Explore proof 4 tactics

Initial goal

⊢
∀s : shutdown_state kind : handoff_kind action : shutdown_action s′ : shutdown_state, shutdown_ats = HandedOffkind → ¬shutdown_steps action s′

intros s kind action s′ Hat H

⊢
False

destruct H ; simpl in Hat ; try discriminate

Hat :
status :
Z
H :
∀kind : handoff_kind, shutdown_ats ≠ HandedOffkind
⊢
False

apply Hkind

Hat :
status :
Z
H :
∀kind : handoff_kind, shutdown_ats ≠ HandedOffkind

exact Hat

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s kind action s′ Hat H
destruct H ; simpl in Hat ; try discriminate
apply Hkind
exact Hat

Once cleanup starts, registration cannot succeed.

205Theorem shutdown_done_no_registration
∀ s entry s′
Explore proof 3 tactics

Initial goal

intros s entry s′ Hat H

inversion H ; subst

status :
Z
active :
pending :
consumed :
listnat
H :
shutdown_stepshutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q RegisterCallbackentry shutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ entry :: pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q
Hat :
shutdown_atshutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q = Cleanup
H2 :
¬Inregistration_tokenentry consumed ++ mapregistration_token pending
⊢
False

discriminate

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s entry s′ Hat H
inversion H ; subst
discriminate

Project only the stdout actions; handoff is not an output error/discard.

210Definition shutdown_outputaction : shutdown_action : liststream_action ≔
match action with
_
⇒
[ ]

The stdout projection is exactly a stream run, including unfinished obligations.

214Theorem shutdown_stream_run
∀ s actions s′
shutdown_runs actions s′
Explore proof 5 tactics

Initial goal

⊢
∀s : shutdown_state actions : listshutdown_action s′ : shutdown_state, shutdown_runs actions s′ → stream_runshutdown_stdouts flat_mapshutdown_output actions shutdown_stdouts′

intros s actions s′ H

induction H ; constructor |

actions :
H :
shutdown_steps action s1
H0 :
shutdown_runs1 actions s′
IHshutdown_run :
⊢

destruct H ; simpl in * ; try exact IHshutdown_run

2 open

actions :
status :
Z
active :
pending :
consumed :
listnat
H :
stream_stepq action q′
H0 :
shutdown_runshutdown_at ≔ InCallbackactive; shutdown_status ≔ status; shutdown_pending ≔ pending; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q′ actions s′
IHshutdown_run :
⊢
stream_runq action :: flat_mapshutdown_output actions shutdown_stdouts′
focused goal
actions :
status :
Z
consumed :
listnat
H :
∀bytes : listZ, action ≠ Acceptbytes
H1 :
stream_stepq action q′
H0 :
shutdown_runshutdown_at ≔ Cleanup; shutdown_status ≔ status; shutdown_pending ≔ [ ]; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q′ actions s′
IHshutdown_run :
⊢
stream_runq action :: flat_mapshutdown_output actions shutdown_stdouts′

–eapply stream_next ; eassumption | exact IHshutdown_run

deferred goal
actions :
status :
Z
consumed :
listnat
H :
∀bytes : listZ, action ≠ Acceptbytes
H1 :
stream_stepq action q′
H0 :
shutdown_runshutdown_at ≔ Cleanup; shutdown_status ≔ status; shutdown_pending ≔ [ ]; shutdown_consumed ≔ consumed; shutdown_stdout ≔ q′ actions s′
IHshutdown_run :
⊢
stream_runq action :: flat_mapshutdown_output actions shutdown_stdouts′

–eapply stream_next ; eassumption | exact IHshutdown_run

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros s actions s′ H
induction H ; constructor |
destruct H ; simpl in * ; try exact IHshutdown_run
–eapply stream_next ; eassumption | exact IHshutdown_run
–eapply stream_next ; eassumption | exact IHshutdown_run

Shutdown neither loses accepted bytes nor mistakes error discard for delivery.

225Theorem shutdown_output_accounting
∀ s actions s′
shutdown_runs actions s′
Explore proof 4 tactics

Initial goal

⊢
∀s : shutdown_state actions : listshutdown_action s′ : shutdown_state, shutdown_runs actions s′ → outstandingshutdown_stdouts ++ acceptedflat_mapshutdown_output actions = resolvedflat_mapshutdown_output actions ++ outstandingshutdown_stdouts′

intros

apply stream_accounting

apply shutdown_stream_run

actions :
H :
shutdown_runs actions s′
⊢
shutdown_runs actions s′

assumption

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros
assumption

Host completion is a separate, uninstantiated contract. Requiring its witness does not claim native host handlers or loader finalization safe.

233Inductive shutdown_observationhost_complete : handoff_kind → Z → stream_state → Prop : shutdown_state → listevent → Prop ≔
∀ kind status pending consumed q
host_completekind status q
observe_host_exit
shutdown_observationhost_complete mkShutdownHandedOffkind status pending consumed q ProcessExitprocess_statusstatus

Completion contributes exactly one exit observation, never a callback trace.

241Theorem shutdown_observation_single
∀ host s events
Explore proof 3 tactics

Initial goal

⊢
∀host : handoff_kind → Z → stream_state → Prop s : shutdown_state events : listevent, shutdown_observationhost s events → events = ProcessExitprocess_statusshutdown_statuss

intros host s events H

host :
handoff_kind → Z → stream_state → Prop
events :
listevent
H :

destruct H

host :
handoff_kind → Z → stream_state → Prop
status :
Z
pending :
consumed :
listnat
H :
hostkind status q

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros host s events H
destruct H
reflexivity

Read main's W-class return as a signed C int, before callbacks see it.

247Definition main_statusbits : Z : Z ≔
sign_extension2 ^ 32 2 ^ 31 bits

Signed interpretation does not change the final process low byte.

250Lemma main_status_low_byte
Explore proof 11 tactics

Initial goal

⊢
∀bits : Z, process_statusmain_statusbits = process_statusbits

intros bits

unfold main_status , sign_extension , process_status

bits :
Z
⊢
2 ^ 31 ≤? bits mod 2 ^ 32
→
bits mod 2 ^ 32 − 2 ^ 32
else
bits mod 2 ^ 32
mod
256
=
bits mod 256

assert Hmod : bits mod 2 ^ 32 mod 256 = bits mod 256

2 open

bits :
Z
⊢
bits mod 2 ^ 32 mod 256 = bits mod 256
focused goal
bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
2 ^ 31 ≤? bits mod 2 ^ 32
→
bits mod 2 ^ 32 − 2 ^ 32
else
bits mod 2 ^ 32
mod
256
=
bits mod 256

{apply Z.mod_mod_divide

2 open

bits :
Z
⊢
256 | 2 ^ 32
deferred goal
bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
2 ^ 31 ≤? bits mod 2 ^ 32
→
bits mod 2 ^ 32 − 2 ^ 32
else
bits mod 2 ^ 32
mod
256
=
bits mod 256

exists 2 ^ 24

2 open

bits :
Z
⊢
2 ^ 32 = 2 ^ 24 × 256
deferred goal
bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
2 ^ 31 ≤? bits mod 2 ^ 32
→
bits mod 2 ^ 32 − 2 ^ 32
else
bits mod 2 ^ 32
mod
256
=
bits mod 256

reflexivity

deferred goal
bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
2 ^ 31 ≤? bits mod 2 ^ 32
→
bits mod 2 ^ 32 − 2 ^ 32
else
bits mod 2 ^ 32
mod
256
=
bits mod 256

destruct 2 ^ 31 ≤? bits mod 2 ^ 32 ; | exact Hmod

bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
bits mod 2 ^ 32 − 2 ^ 32 mod 256 = bits mod 256

rewrite Zminus_mod , Hmod

bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
bits mod 256 − 2 ^ 32 mod 256 mod 256 = bits mod 256

replace 2 ^ 32 mod 256 with 0 by reflexivity

bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
bits mod 256 − 0 mod 256 = bits mod 256

rewrite Z.sub_0_r , Z.mod_mod by lia

bits :
Z
Hmod :
bits mod 2 ^ 32 mod 256 = bits mod 256
⊢
bits mod 256 = bits mod 256

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros bits
assert Hmod : bits mod 2 ^ 32 mod 256 = bits mod 256
{apply Z.mod_mod_divide
exists 2 ^ 24
reflexivity
destruct 2 ^ 31 ≤? bits mod 2 ^ 32 ; | exact Hmod
rewrite Zminus_mod , Hmod
replace 2 ^ 32 mod 256 with 0 by reflexivity
rewrite Z.sub_0_r , Z.mod_mod by lia
reflexivity

No locals means the core return invalidates exactly nothing.

263Lemma return_no_locals_memory
Explore proof 3 tactics

Initial goal

intros c H

rewrite H

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros c H
rewrite H
reflexivity

Evidence for the narrow main-return bridge: no callers or locals, non-doomed W return, and an actual evaluated integer at the return site.

270Definition main_return_sitege : genv c : config bits : Z : Prop ≔
∃label value, fr_atc_framec = Execlabel [ ] JRetvalue ∧ fr_doomedc_framec = None ∧ fr_localsc_framec = [ ] ∧ c_callersc = [ ] ∧ fn_retfr_fnc_framec = RClassW ∧ value_xge fr_envc_framec W value = SomeWIntbits

This return really produces the core terminal, and its retained snapshot is final memory. No successor is added to ExternalMachine.Stopped.

279Theorem main_return_step
∀ ge c bits
Semantics.stepge c = DoneRetWIntbits ∧ invalidate_localsfr_localsc_framec c_memc = Somec_memc
Explore proof 9 tactics

Initial goal

⊢
∀ge : genv c : config bits : Z, main_return_sitege c bits → stepge c = DoneRetWIntbits ∧ invalidate_localsfr_localsc_framec c_memc = Somec_memc

intros ge c bits label & value & Hat & Hd & Hl & Hc & Hr & Hv

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits

split ; | apply return_no_locals_memory ; assumption

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
stepge c = DoneRetWIntbits

unfold Semantics.step

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
match fr_atc_framec with
Snapshot_ :: _ as xs l
⇒
negbforallbsnapshot_word xs
→
StuckString.StringAscii.Asciitrue true false false true true true false String.StringAscii.Asciifalse true true true false true true false String.StringAscii.Asciitrue false false false false true true false String.StringAscii.Asciifalse false false false true true true false String.StringAscii.Asciitrue true false false true true true false String.StringAscii.Asciifalse false false true false true true false String.StringAscii.Asciitrue true true true false true true false String.StringAscii.Asciifalse false true false true true true false String.EmptyString
else
Freshheap_req16 8 × Z.of_natlengthxs λbase : Z ⇒ c_frame ≔ fr_fn ≔ fr_fnc_framec; fr_env ≔ putva_snapshot WPtrptr_addr ≔ base; ptr_cap ≔ Robase fr_envc_framec; fr_locals ≔ fr_localsc_framec; fr_doomed ≔ fr_doomedc_framec; fr_at ≔ Enterl None; c_callers ≔ c_callersc; c_mem ≔ snapshot_valuesxs base allocatedc_memc heap_req16 8 × Z.of_natlengthxs base; c_fuel ≔ c_fuelc
Enterl from
⇒
else
or_stuckString.StringAscii.Asciifalse true false false false true true false String.StringAscii.Asciifalse false true true false true true false String.StringAscii.Asciitrue true true true false true true false String.StringAscii.Asciitrue true false false false true true false String.StringAscii.Asciitrue true false true false true true false String.EmptyString
Execl [ ] j
⇒
jump_stepge c l j
Execl i :: rest j
⇒
match let* why ≔ fr_doomedc_framec in if ahead_transparenti then None else Somewhy with
Somewhy
⇒
None
⇒
or_stuckString.StringAscii.Asciitrue false false true false true true false String.StringAscii.Asciifalse true true true false true true false String.StringAscii.Asciitrue true false false true true true false String.StringAscii.Asciifalse false true false true true true false String.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false true true true false String.StringAscii.Asciitrue true false false false true true false String.StringAscii.Asciifalse false true false true true true false String.StringAscii.Asciitrue false false true false true true false String.StringAscii.Asciitrue true true true false true true false String.StringAscii.Asciifalse true true true false true true false String.EmptyString
let* out0 ≔ inst_stepge c_framec c_memc i in
let* od ≔ doomed_resultge c_framec c_memc i out0 in
Someinst_nextc l rest j fstod sndod
=

rewrite Hat

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
jump_stepge c label JRetvalue = DoneRetWIntbits

unfold jump_step

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
match fr_doomedc_framec with
Somewhy
⇒
None
⇒
or_stuckString.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false false true true false String.StringAscii.Asciifalse false true false true true true false String.EmptyString
match fn_retfr_fnc_framec with
⇒
let* x ≔ value_xge fr_envc_framec k value in
_
⇒
None
=

rewrite Hd , Hr , Hv

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
or_stuckString.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false false true true false String.StringAscii.Asciifalse false true false true true true false String.EmptyString Somereturn_stepc RetWIntbits = DoneRetWIntbits

unfold return_step

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
or_stuckString.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false false true true false String.StringAscii.Asciifalse false true false true true true false String.EmptyString
Some
or_stuckString.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false false true true false String.StringAscii.Asciifalse false true false true true true false String.StringAscii.Asciitrue false true false true true true false String.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciifalse true true true false true true false String.EmptyString
match c_callersc with
[ ]
⇒
SomeDoneRetWIntbits
caller, pd :: callers
⇒
let* o′ ≔
match pd_convpd with
Somecw, kw
⇒
None
⇒
SomeRetWIntbits
in
let* e ≔ returned_envpd_respd o′ fr_envcaller in
SomeNextc_frame ≔ fr_fn ≔ fr_fncaller; fr_env ≔ e; fr_locals ≔ fr_localscaller; fr_doomed ≔ fr_doomedcaller; fr_at ≔ fr_atcaller; c_callers ≔ callers; c_mem ≔ m; c_fuel ≔ c_fuelc
=

rewrite Hl , Hc

ge :
bits :
Z
label :
value :
value
Hat :
fr_atc_framec = Execlabel [ ] JRetvalue
Hd :
Hl :
Hc :
c_callersc = [ ]
Hv :
value_xge fr_envc_framec W value = SomeWIntbits
⊢
or_stuckString.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false false true true false String.StringAscii.Asciifalse false true false true true true false String.EmptyString
Some
or_stuckString.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciitrue false true false false true true false String.StringAscii.Asciifalse false true false true true true false String.StringAscii.Asciitrue false true false true true true false String.StringAscii.Asciifalse true false false true true true false String.StringAscii.Asciifalse true true true false true true false String.EmptyString
let* _ ≔ invalidate_locals[ ] c_memc in
SomeDoneRetWIntbits
=

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros ge c bits label & value & Hat & Hd & Hl & Hc & Hr & Hv
split ; | apply return_no_locals_memory ; assumption
unfold Semantics.step
rewrite Hat
unfold jump_step
rewrite Hd , Hr , Hv
rewrite Hl , Hc
reflexivity

A doomed return cannot use this bridge, regardless of its evaluated word.

291Lemma main_return_not_doomed
∀ ge c bits why
fr_doomedc_framec ≠ Somewhy
Explore proof 3 tactics

Initial goal

⊢
∀ge : genv c : config bits : Z why : reason, main_return_sitege c bits → fr_doomedc_framec ≠ Somewhy

intros ge c bits why _ & _ & _ & Hd & _

ge :
bits :
Z
why :
Hd :
⊢
fr_doomedc_framec ≠ Somewhy

rewrite Hd

ge :
bits :
Z
why :
Hd :
⊢
None ≠ Somewhy

discriminate

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros ge c bits why _ & _ & _ & Hd & _
rewrite Hd
discriminate

A live-local return needs a different final-memory argument.

296Lemma main_return_no_live_locals
∀ ge c bits
Explore proof 2 tactics

Initial goal

⊢
∀ge : genv c : config bits : Z, main_return_sitege c bits → fr_localsc_framec = [ ]

intros ge c bits _ & _ & _ & _ & Hl & _

ge :
bits :
Z
Hl :
⊢

exact Hl

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros ge c bits _ & _ & _ & _ & Hl & _
exact Hl

Main initializes the lifecycle only with actual return-site evidence.

301Definition main_shutdownge : genv c : config bits : Z pending : listregistration q : stream_state s : shutdown_state : Prop ≔
main_return_sitege c bits ∧ s = mkShutdownTls main_statusbits pending [ ] q

The two's-complement -1 reaches callbacks as -1, and the host reports 255.

307Example main_minus_one: main_status4294967295 = −1 ∧ process_statusmain_status4294967295 = 255
Explore proof 2 tactics

Initial goal

⊢
main_status4294967295 = −1 ∧ process_statusmain_status4294967295 = 255

vm_compute

⊢
−1 = −1 ∧ 255 = 255

auto

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
auto

Public lifecycle boundaries

Two registrations of the same function remain distinct instances.

314Definition exit_first: registration ≔

The second registration deliberately repeats the function, not its token.

316Definition exit_second: registration ≔

A handler dynamically registered by the newest callback.

318Definition exit_added: registration ≔

A dynamically added callback runs before the older pending registration.

Explore proof 12 tactics

Initial goal

intros q

eapply shutdown_next ; apply shutdown_tls |

eapply shutdown_next ; apply shutdown_invoke |

eapply shutdown_next ; apply shutdown_register ; simpl ; intuition congruence |

eapply shutdown_next ; apply shutdown_return |

eapply shutdown_next ; apply shutdown_invoke |

eapply shutdown_next ; apply shutdown_return |

eapply shutdown_next ; apply shutdown_invoke |

eapply shutdown_next ; apply shutdown_return |

eapply shutdown_next ; apply shutdown_cleanup |

eapply shutdown_next ; apply shutdown_soft |

constructor

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros q
eapply shutdown_next ; apply shutdown_tls |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_register ; simpl ; intuition congruence |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_soft |
constructor

Recursive exit abandons the active callback and supplies -1 to older ones.

Explore proof 10 tactics

Initial goal

intros q

eapply shutdown_next ; apply shutdown_tls |

eapply shutdown_next ; apply shutdown_invoke |

eapply shutdown_next ; apply shutdown_recursive |

eapply shutdown_next ; apply shutdown_tls |

eapply shutdown_next ; apply shutdown_invoke |

eapply shutdown_next ; apply shutdown_return |

eapply shutdown_next ; apply shutdown_cleanup |

eapply shutdown_next ; apply shutdown_soft |

constructor

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros q
eapply shutdown_next ; apply shutdown_tls |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_tls |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_soft |
constructor

An active registration instance cannot be registered again with its old token.

360Example shutdown_no_instance_reuse: ∀q s′, ¬shutdown_stepmkShutdownInCallbackexit_second 31 exit_first 2%nat q RegisterCallbackexit_second s′
Explore proof 4 tactics

Initial goal

intros q s′ H

inversion H ; subst

simpl in *

tauto

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros q s′ H
inversion H ; subst
simpl in *
tauto

A callback's _exit(98) replaces exit(31), leaving handlers and output untouched.

Explore proof 3 tactics

Initial goal

apply shutdown_hard

intros kind H

discriminate

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros kind H
discriminate

Hard exit can replace status after cleanup has closed registration too.

376Example shutdown_cleanup_hard: ∀q, shutdown_stepmkShutdownCleanup 31 [ ] 2; 1%nat q HandoffHardExit 98 mkShutdownHandedOffHardExit 98 [ ] 2; 1%nat q
Explore proof 4 tactics

Initial goal

intros q

apply shutdown_hard

⊢
∀kind : handoff_kind, shutdown_atshutdown_at ≔ Cleanup; shutdown_status ≔ 31; shutdown_pending ≔ [ ]; shutdown_consumed ≔ 2%nat; 1%nat; shutdown_stdout ≔ q ≠ HandedOffkind

intros kind H

⊢
False

discriminate

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros q
intros kind H
discriminate

Its conditional host observation reports the hard exit's own status.

382Example shutdown_hard_observation: ∀host q, hostHardExit 98 q → shutdown_observationhost mkShutdownHandedOffHardExit 98 exit_first 2%nat q ProcessExit98
Explore proof 3 tactics

Initial goal

intros host q H

apply observe_host_exit

host :
handoff_kind → Z → stream_state → Prop
H :
hostHardExit 98 q
⊢
hostHardExit 98 q

exact H

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros host q H
exact H

Partial delivery followed by output error can leave a byte outstanding at handoff.

Explore proof 10 tactics

Initial goal

eapply shutdown_next

3 open

focused goal
shelved goal

–apply shutdown_cleanup_output ; intros bytes H ; discriminate |

3 open

⊢
stream_steporientation ≔ ByteOriented; outstanding ≔ 65; 66; 90; stream_error ≔ false Deliver65 ?q′
deferred goal
shelved goal

apply stream_deliver65 66; 90 false

2 open

⊢
65 ≠ [ ]
deferred goal

discriminate

deferred goal

–eapply shutdown_next

3 open

focused goal
shelved goal

+apply shutdown_cleanup_output ; intros bytes H ; discriminate |

3 open

⊢
deferred goal
shelved goal

apply stream_discard66 90 false

2 open

⊢
66 ≠ [ ]
deferred goal

discriminate

deferred goal

+eapply shutdown_next ; apply shutdown_soft |

constructor

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
–apply shutdown_cleanup_output ; intros bytes H ; discriminate |
apply stream_deliver65 66; 90 false
discriminate
–eapply shutdown_next
+apply shutdown_cleanup_output ; intros bytes H ; discriminate |
apply stream_discard66 90 false
discriminate
+eapply shutdown_next ; apply shutdown_soft |
constructor

A concrete no-locals main return: there is no invented stopped-state evidence.

404Definition returning_mainm : mem : config ≔
let f ≔ mkFuncTInt0 TInt0 RClassW [ ] [ ] in
mkConfigmkFramef [ ] [ ] None ExecTInt1 [ ] JRetConst4294967295 [ ] m 10

The return-site predicate checks the concrete return value and core transition.

409Example returning_main_bridge: ∀ge m, main_return_sitege returning_mainm 4294967295
Explore proof 3 tactics

Initial goal

⊢
∀ge : genv m : mem, main_return_sitege returning_mainm 4294967295

intros ge m

ge :
m :

exists TInt1, Const4294967295

repeat split ; reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros ge m
exists TInt1, Const4294967295
repeat split ; reflexivity