Fil-C on Nix

Filnix wiki

the formal campaign

rocq/theories/Semantics.v

The small-step semantics of the core subset of the checked IR, transcribed from the interpreter's run/5 (interp.pl).

The interpreter is a big-step relation over blocks: block_outcome/7 runs a block and everything after it, and a call runs its callee to an outcome inside the instruction. The model takes the same steps one at a time over an explicit configuration (formal.md's decision: small-step, not interaction trees), so that Campaign 3's invariants can be stated between any two steps.

The configuration

PartIsinterp.pl
c_framethe running invocationthe ctx(...) term, Env and the block being run
c_callersthe suspended callers, each with how it reads the resultProlog's own stack
c_memmemorys(Mem, Fuel)'s Mem, less Next
c_fuelblocks left to runs(Mem, Fuel)'s Fuel

Outcomes

Gallinainterp.pl
Retxret(V)
Retsxsrets([X1, X2])
RetVoidret
Unreachableunreachable
UBwhyub(Reason): here only float_conversion, an invalid float-to-integer conversion
Trapwhytrap(Reason)
Uncheckedwhyunchecked(Reason)
OutOfFuelout_of_fuel
From Stdlib Require Import String ZArith List Bool Relations
From Nanofil Require Import Term Syntax Values Memory Ops
Import ListNotations
Open Scope string_scope
Open Scope Z_scope

How a run ends (the table above): a return of one word, of several, or of none; an unreachable jump reached; undefined behaviour; a trap with its reason; an unchecked access, which only a broken pass produces; or no fuel left.

45Inductive outcome: Type ≔
|Ret
x : word
|Rets
xs : listword
|RetVoid
|Unreachable
|UB
why : term
|Trap
why : reason
|Unchecked
why : reason
|OutOfFuel

The prepared module

A function the module names: one with a body in the core subset, or one outside it, kept only by its name n.

59Inductive fn_def: Type ≔
|Defined
f : func
|Outside
n : name

The global environment: the module ready to run (module_prepared/2's Fns and Globals, each global's name with its pointer), and the runtime's free that a call of libc's free runs: Memory.v's free_res in the interpreter, R.free of a Runtime R (Run.v's Driver, Machine.v).

66Record genv: Type ≔ mkGenv
ge_module
 : module
ge_globals
 : listname × ptr
ge_free
 : word → mem → optionresunit × mem

The function or outside function of the module items named n, not looking through aliases.

74Fixpoint find_directn : name items : module : optionfn_def ≔
match items with
[ ]
⇒
None
IFuncf :: rest
⇒
IOutsidef _ :: rest
⇒
→
SomeOutsidef
else
_ :: rest
⇒

The target of the alias named n among the module items, if there is one.

84Fixpoint find_aliasn : name items : module : optionname ≔
match items with
[ ]
⇒
None
IAliasa _ t :: rest
⇒
→
Somet
else
_ :: rest
⇒

The function a call of the name n runs, as get_assoc(F, Fns, Fn) finds it in the prepared module's Fns: a function by its own name, or an alias of one by the alias's name.

94Definition find_fnge : genv n : name : optionfn_def ≔
match find_directn ge_modulege with
Somed
⇒
Somed
None
⇒

Values

An environment: each temporary assigned so far, with its word.

104Definition env ≔
listname × word

As value_x/5: the IR value v read at class k in the environment e. A constant at p is a pointer with no capability; a symbol the module does not define is ptr(0, ext(Name)), a pointer with an external capability.

110Definition value_xge : genv e : env k : class v : value : optionword ≔
match v with
⇒
let* x ≔ lookupn e in
⇒
let* m ≔ modulusk in
match k with
⇒
SomeWPtrmkPtrn mod m CNone
_
⇒
SomeWIntn mod m
⇒
match lookups ge_globalsge with
Somep
⇒
SomeWPtrp
None
⇒

f applied to every element of xs, or None if it fails on any.

127Fixpoint map_optionX Y : Type f : X → optionY xs : listX : optionlistY ≔
match xs with
[ ]
⇒
Some[ ]
x :: xs′
⇒
let* y ≔ fx in
let* ys ≔ map_optionf xs′ in
Somey :: ys

f applied to the elements of xs and ys pairwise, or None if it fails on any pair or the lists differ in length.

135Fixpoint map2_optionX Y Z : Type f : X → Y → optionZ xs : listX ys : listY : optionlistZ ≔
match xs, ys with
[ ], [ ]
⇒
Some[ ]
x :: xs′, y :: ys′
⇒
let* z ≔ fx y in
let* zs ≔ map2_optionf xs′ ys′ in
Somez :: zs
_, _
⇒
None

As arg_x/4: a call argument's value read at its own class.

144Definition arg_xge : genv e : env a : arg : optionword ≔
match a with
Argk v
⇒
value_xge e k v

As flight_arg_x/4: an argument of a flight's address computation. An address projection takes the low 64 bits of a pointer's address; any other argument is read at class l.

150Definition flight_arg_xge : genv e : env a : flight_arg : optionword ≔
match a with
⇒
let* x ≔ value_xge e P v in
match x with
⇒
SomeWIntptr_addrp mod 2 ^ 64
_
⇒
None
⇒
value_xge e L v

As flight_cap/4: the capability a flight gives its pointer. A lower source copies its pointer's capability, and so the object's identity; none gives no capability.

161Definition flight_capge : genv e : env lw : flight_lower : optioncap ≔
match lw with
⇒
let* x ≔ value_xge e P v in
match x with
⇒
Someptr_capp
_
⇒
None

Frames and configurations

Where a frame is in its function:

  • Snapshotxs l: a variadic callee about to take the snapshot of its arguments xs, an allocation, before entering its entry block l;
  • Enterl from: about to run block l, entered from the block from (None for the entry); entering costs one unit of fuel, and with none left the run is OutOfFuel, as block_outcome/7 says;
  • Execl insts j: inside block l, with the instructions insts and then the jump j left to run.
179Inductive point: Type ≔
|Snapshot
xs : listword l : name
|Enter
l : name from : optionname
|Exec
l : name insts : listinst j : jump

One invocation of a function: the function, its environment of temporaries, each named local with its object's base once allocated, the reason it is doomed if an early check_ahead failed, and where it is.

188Record frame: Type ≔ mkFrame
fr_fn
 : func
fr_env
 : env
fr_locals
 : listname × optionZ
fr_doomed
 : optionreason
fr_at
 : point

How a suspended caller reads its callee's outcome: the call's Res, the temporaries it binds, and for a call through the generic entry the caller's and callee's word classes (indirect_call_conv/7's conv(CallerWords, CalleeWords)).

201Record pending: Type ≔ mkPending
pd_res
pd_conv
 : optionlistclass × listclass

A configuration: the running frame, the suspended callers innermost first, each with how it reads the result, the memory, and the fuel left (the table above).

209Record config: Type ≔ mkConfig
c_frame
 : frame
c_callers
 : listframe × pending
c_mem
 : mem
c_fuel
 : Z

The frame fr moved to the point pt, all else kept.

217Definition with_pointfr : frame pt : point : frame ≔

The new frame of a function f called with the words xs, as call_outcome/8 starts it: parameters bound to the first arguments as they are, each local declared and not yet allocated, at the entry block; a variadic callee first takes the snapshot of all its arguments (entry_snapshot/6). None if there are fewer arguments than parameters or f has no blocks.

226Definition call_framef : func xs : listword : optionframe ≔
let params ≔ fn_paramsf in
lengthxs <? lengthparams%nat
→
None
else
let e ≔ fold_leftλe px ⇒ putsndfstpx sndpx e combineparams firstnlengthparams xs [ ] in
match fn_blocksf with
[ ]
⇒
None
b :: _
⇒
Some
mkFramef e mapλxs ⇒ fstxs, None local_objectsf None

The entry argument snapshot

The name of the environment's hidden entry that holds the pointer to a variadic callee's argument snapshot, which va_args reads.

243Definition va_snapshot: name ≔
TApp"hidden" TAtom"va_snapshot"

As snapshot_values/5: the memory m with the argument words xs stored from address a on, 8 bytes apart, each as p if it is a pointer (its address in the bytes, its capability in the aux), else as l. The stores are into a fresh object of 8 bytes per argument, so their checks pass.

250Fixpoint snapshot_valuesxs : listword a : Z m : mem : mem ≔
match xs with
[ ]
⇒
m
WPtrp :: rest
⇒
WIntn :: rest
⇒
snapshot_valuesrest a + 8 store_bytesm a 8 n
_ :: rest
⇒
snapshot_valuesrest a + 8 m

The words snapshot_values/5 can store: integers and pointers.

260Definition snapshot_wordx : word : bool ≔
match x with
⇒
true
_
⇒
false

The block labelled l among bs.

264Fixpoint find_blockl : name bs : listblock : optionblock ≔
match bs with
[ ]
⇒
None
b :: bs′
⇒
→
Someb
else
find_blockl bs′

As phis_env/6: the environment after a block's phis, entered from the block from. Each phi reads its value for the edge from that predecessor in the environment e0 as it was on entry, so they all bind at once. An entry block (from None) has no phis.

274Definition phis_envge : genv phis : listphi from : optionname e0 : env : optionenv ≔
match from with
None
⇒
match phis with
[ ]
⇒
Somee0
_
⇒
None
Somepred
⇒
fold_left
λ acc ph  ⇒
let* e ≔ acc in
match ph with
Phid k pairs
⇒
let* v ≔ lookuppred pairs in
let* x ≔ value_xge e0 k v in
Someputd x e
phis
Somee0

As invalidate_locals/3: an invocation's named locals end with it. Their identities, bytes and aux stay; their bounds become empty, so any later access through them traps.

292Definition invalidate_localslocals : listname × optionZ m : mem : optionmem ≔
fold_left
λ acc l  ⇒
let* m ≔ acc in
match sndl with
None
⇒
Somem
Somebase
⇒
let* reg ≔ object_regionbase m_regionsm in
match r_kindreg, r_lifereg with
⇒
let* rs ≔ replace_regionbase mkRegionbase base Stack Freed m_regionsm in
_, _
⇒
None
locals
Somem

Calls

As function_check_res/3: the pointer p designates a function only with that function's capability at its exact callable address; otherwise the check traps. A pointer with an external capability has no answer here.

314Definition function_check_resge : genv p : ptr : optionresunit ≔
match ptr_capp with
⇒
Some
match lookupf ge_globalsge with
⇒
None

As result_words/2: the classes of the words a call site reads.

327Definition result_wordsr : call_result : listclass ≔
match r with
⇒
[ ]
⇒
k
⇒
mapsnd rs

As return_words(Ret, Ks) in interp.pl: the classes of the words a function returns.

336Definition return_wordst : ret_type : listclass ≔
match t with
⇒
[ ]
⇒
ks
⇒
k

The kinds of word a call passes or returns: integer, pointer, single float and double float.

345Inductive word_kind: Type ≔
|IntWord
|PtrWord
|SingleWord
|DoubleWord

As word_class/2: the kind of word a class k is. Classes w and l are the same word; p, s and d are each their own.

349Definition word_classk : class : optionword_kind ≔
match k with
W | L
⇒
⇒
_
⇒
None

Whether two word kinds are the same.

359Definition word_kind_eqba b : word_kind : bool ≔
match a, b with

The -> condition of indirect_call_conv/7: both lists of words have word classes, and the same ones.

367Definition same_wordsks ks′ : listclass : bool ≔
Somecs, Somecs′
⇒
lengthcs =? lengthcs′%nat && forallbλp ⇒ word_kind_eqbfstp sndp combinecs cs′
_, _
⇒
false

As generic_word/4: the word x written at class from and read at class to through the generic entry. An integer read as a pointer has no capability; a pointer read as an integer or a float is its address.

378Definition generic_wordfrom to : class x : word : optionword ≔
match from, to with
W | L | Single | Double, W | L
⇒
Somex
W | L | Single | Double, P
⇒
match x with
_
⇒
None
P, W | L
⇒
let* a ≔ pointer_addressx in
SomeWInta
P, P
⇒
Somex
_, _
⇒
None

What converting a call through a function pointer gives: a trap, or the converted arguments ys and, if the result words need converting too, the caller's and callee's word classes.

392Inductive conv: Type ≔
|ConvTrap
why : reason
|Converted
ys : listword words : optionlistclass × listclass

As indirect_call_conv/7: a call through a pointer to f, reading its result as r, with arguments args whose values are xs. It traps if the caller passes fewer arguments than f has parameters or reads more result words than f returns; otherwise each argument is read as f's parameter through the generic entry (generic_word).

402Definition indirect_call_convf : func r : call_result args : listarg xs : listword : optionconv ≔
let params ≔ mapfst fn_paramsf in
let np ≔ lengthparams in
let caller_words ≔ result_wordsr in
let callee_words ≔ return_wordsfn_retf in
lengthargs <? np%nat
→
lengthcallee_words <? lengthcaller_words%nat
→
else
let arg_classes ≔
map
λ a  ⇒
match a with
Argk _
⇒
k
firstnnp args
in
let* ys ≔ map2_optionλft x ⇒ generic_wordfstft sndft x combinearg_classes params firstnnp xs in
Some
same_wordscaller_words callee_words
→
None
else
Somecaller_words, callee_words

As outcome_words/2: the words a returning outcome returns; None for one that does not return.

419Definition outcome_wordso : outcome : optionlistword ≔
match o with
⇒
Some[ ]
⇒
Somex
⇒
match xs with
_ :: _ :: _
⇒
Somexs
_
⇒
None
_
⇒
None

The returning outcome that returns the words ys.

428Definition words_outcomeys : listword : outcome ≔
match ys with
[ ]
⇒
y
⇒
_
⇒

As converted_outcome/4: the callee's outcome o as a call site that reads the word classes caller reads it, each word converted from the callee's class by generic_word. An outcome that does not return passes unchanged.

439Definition converted_outcomecaller callee : listclass o : outcome : optionoutcome ≔
match outcome_wordso with
None
⇒
Someo
Somexs
⇒
let n ≔ lengthcaller in
lengthxs <? n%nat || lengthcallee <? n%nat
→
None
else
let* ys ≔ map2_optionλft x ⇒ generic_wordfstft sndft x combinefirstnn callee caller firstnn xs in

As call_outcome_result/5 for a returning outcome o: the caller's environment e with the returned words bound as its Res r reads them.

452Definition returned_envr : call_result o : outcome e : env : optionenv ≔
match o, r with
⇒
let* y ≔ word_at_classk x in
Someputd y e
⇒
Somee
⇒
negblengthxs =? lengthrs%nat
→
None
else
fold_left
λ acc rx  ⇒
let* e ≔ acc in
let* y ≔ word_at_classsndfstrx sndrx in
Someputfstfstrx y e
combiners xs
Somee
⇒
Somee
⇒
Somee
_, _
⇒
None

Instructions

What one instruction does: continue with an environment, locals and memory; stop with an outcome; call a function with the words xs, the caller to read the result as pd says; allocate for the request q, going on as k says of the new base; or call a function outside the core subset.

474Inductive inst_out: Type ≔
|IContinue
e : env locals : listname × optionZ m : mem
|IStop
o : outcome
|ICall
f : func xs : listword pd : pending
|IFresh
q : alloc_req k : Z → env × listname × optionZ × mem
|ICallOutside
f : name

As res_result/5: an operation's result r bound to the temporary d, or its trap or unchecked reason as the outcome.

483Definition bind_resd : name r : resword e : env locals m : mem : inst_out ≔
match r with
⇒
IContinueputd x e locals m

As store_res_result/4: a store's result r, going on with nothing bound, or its trap or unchecked reason as the outcome.

492Definition store_outr : resunit e : env locals m : mem : inst_out ≔
match r with

As width_value_class/2 (filc_amd64.pl): the class at which a raw store of width w reads the value it stores.

501Definition width_value_classw : width : optionclass ≔
match w with
Wb | Wh | Ww
⇒
SomeW
⇒
SomeL
⇒
SomeP
⇒
SomeSingle
⇒
SomeDouble
⇒

The name of libc's free, the one external call the model runs.

513Definition free_name: name ≔
TAtom"free"

A call of a name f the module does not define as a function: inst_result/5's call of global(F). Data the module defines is not a function, and the call traps, as native code's function check does. Otherwise it is external_call_outcome/9: only libc's void freep is modeled, through the runtime's free, the genv's ge_free; any other external call is stuck until Campaign 4 gives it a contract.

522Definition external_callge : genv f : name r : call_result args : listarg xs : listword e : env locals m : mem : optioninst_out ≔
match lookupf ge_globalsge with
None
⇒
→
None
else
match r, args, xs with
CVoid, ArgP _, x
⇒
let* rm ≔ ge_freege x m in
let r′, m′ ≔ rm in
Some
match r′ with
⇒
IContinuee locals m′
_, _, _
⇒
None

As inst_result/5 for the core subset: what the instruction i does in the frame fr with memory m. None where the interpreter throws or fails, such as a temporary read before it is assigned or an access through an external capability.

545Definition inst_stepge : genv fr : frame m : mem i : inst : optioninst_out ≔
let e ≔ fr_envfr in
let locals ≔ fr_localsfr in
match i with
Loc_ _
⇒
SomeIContinuee locals m
⇒
SomeIContinuee locals m
⇒
match lookupx locals with
SomeNone
⇒
let q ≔ local_reqsize in
SomeIFreshq λbase ⇒ e, putx Somebase locals, allocatedm q base
_
⇒
None
Letd A CheckLocalx off size r al [ ]
⇒
let* slot ≔ lookupx locals in
let* base ≔ slot in
let a ≔ base + off in
let* chk ≔ access_resm a Objbase size r al in
Somebind_resd checked_reschk WPtrmkPtra Objbase e locals m
Flightd o args lw
⇒
let* xs ≔ map_optionflight_arg_xge e args in
let* a ≔ aluo L xs in
let* c ≔ flight_capge e lw in
match a with
⇒
SomeIContinueputd WPtrmkPtrn c e locals m
_
⇒
None
⇒
let* x ≔ lookupva_snapshot e in
match x with
⇒
SomeIContinueputd WPtrmkPtrptr_addrp + off mod 2 ^ 64 ptr_capp e locals m
_
⇒
None
⇒
let* x ≔ value_xge e P v in
match x with
⇒
let* chk ≔ function_check_resge p in
Somebind_resd checked_reschk x e locals m
_
⇒
None
Letd k o args
⇒
match o with
⇒
None
_
⇒
let* classes ≔ op_arg_classeso k in
let* xs ≔ map2_optionvalue_xge e classes args in
let* out ≔ op_reso k xs m in
match out with
OpResr m′
⇒
Somebind_resd r e locals m′
OpUBwhy
⇒
SomeIStopUBwhy
OpAllocq kont
⇒
Some
λ base  ⇒
let x, m′ ≔ kontbase in
putd x e, locals, m′
RawStorew off v a
⇒
let* vk ≔ width_value_classw in
let* x ≔ value_xge e vk v in
let* pa ≔ value_xge e A a in
match pa with
⇒
let* rm ≔ store_resw m raw_addressptr_addrp off ptr_capp x in
let r, m′ ≔ rm in
Somestore_outraw_resr e locals m′
_
⇒
None
RawStorePointeroff v a es
⇒
let* x ≔ value_xge e P v in
let* pa ≔ value_xge e A a in
match pa with
⇒
let b ≔ raw_addressptr_addrp off in
let* chk ≔ access_resm b ptr_capp 8 Write 8 in
match chk with
⇒
match x with
⇒
let* m′ ≔ pointer_store_effectsb xp m es in
SomeIContinuee locals m′
_
⇒
None
_
⇒
None
Callr Globalf args
⇒
let* xs ≔ map_optionarg_xge e args in
match find_fnge f with
SomeDefinedg
⇒
SomeICallg xs mkPendingr None
SomeOutsideg
⇒
None
⇒
external_callge f r args xs e locals m
Call_ _ _
⇒
None
RawCallr callee args
⇒
let* x ≔ value_xge e F callee in
let* xs ≔ map_optionarg_xge e args in
match x with
⇒
let* chk ≔ function_check_resge p in
match raw_reschk with
⇒
match ptr_capp with
⇒
match find_fnge g with
SomeDefinedgf
⇒
let* cv ≔ indirect_call_convgf r args xs in
match cv with
⇒
SomeIStopTrapwhy
Convertedys words
⇒
let extra ≔
→
skipnlengthfn_paramsgf xs
else
[ ]
in
SomeICallgf ys ++ extra mkPendingr words

a variadic callee gets the extra arguments unconverted after its parameters

SomeOutsideg′
⇒
SomeICallOutsideg′
None
⇒
None
_
⇒
None
_
⇒
None

As doomed_result/5: an instruction's result out, adjusted for doom, with the frame's doom after it. A check_ahead whose early bytes fail yields its pointer and dooms the run (docs/schedule.md). From then on it must reach, through ahead-transparent instructions only, an access whose reference check fails: an unchecked raw access there is the program's trap, made early. A renew of another object (alias) or a wrong limit stays a broken pass.

676Definition doomed_resultge : genv fr : frame m : mem i : inst out : inst_out : optioninst_out × optionreason ≔
match i, out with
Letd A CheckAhead_ _ _ _ _ v, IStopTrapEarlywhy
⇒
let* p ≔ value_xge fr_envfr P v in
Some
match fr_doomedfr with
Somew
⇒
Somew
None
⇒
Somewhy
⇒
match fr_doomedfr, w with
Somewhy, Alias | WhyLimit
⇒
Someout, fr_doomedfr
Somewhy, _
⇒
None, _
⇒
Someout, None
_, _
⇒
Someout, fr_doomedfr

Steps

What one step gives:

  • Nextc, the next configuration;
  • Doneo, the run's outcome;
  • Freshq k, an allocation of the request q, whose next configuration is kbase for any base fresh in the memory (step_rel makes that choice nondeterministic);
  • Stuckwhy, where the interpreter throws or fails (a call to an external symbol, an access through an external capability, a temporary read before it is assigned, an ill-classed word); the step relation has no step there.
704Inductive step_result: Type ≔
|Next
c : config
|Done
o : outcome
|Fresh
q : alloc_req k : Z → config
|Stuck
why : string

The step result r, or stuck with the label why where there is none.

712Definition or_stuckwhy : string r : optionstep_result : step_result ≔
match r with
Somes
⇒
s
None
⇒

The configuration after the frame fr, in memory m, moved on.

716Definition continue_atc : config fr : frame m : mem fuel : Z : config ≔

The end of the running invocation of the configuration c with the returning outcome o (call_outcome/8 after block_outcome/7, then the caller's call_outcome_result/5): its locals end, and the caller, if any, reads the result and goes on; with no caller, o is the run's outcome.

724Definition return_stepc : config o : outcome : step_result ≔
let fr ≔ c_framec in
or_stuck"return"
match c_callersc with
[ ]
⇒
SomeDoneo
caller, pd :: callers
⇒
let* o′ ≔
match pd_convpd with
None
⇒
Someo
Somecw, kw
⇒
in
let* e ≔ returned_envpd_respd o′ fr_envcaller in
SomeNextmkConfigmkFramefr_fncaller e fr_localscaller fr_doomedcaller fr_atcaller callers m c_fuelc

As edge_outcome/7: taking the edge from the block from to the target t. A poll edge reached while doomed means the early check was not anticipated, an unchecked outcome.

744Definition edge_stepc : config from : name t : target : step_result ≔
let fr ≔ c_framec in
match t, fr_doomedfr with

As result_outcome/6 and jump_outcome/7: the step of the jump j that ends block l, a goto, a branch on a word, or a return. A doomed frame may not return: its early check was not anticipated.

755Definition jump_stepge : genv c : config l : name j : jump : step_result ≔
let fr ≔ c_framec in
let e ≔ fr_envfr in
match fr_doomedfr, j with
_, JGotot
⇒
_, JBranchv t1 t2
⇒
or_stuck"branch"
let* x ≔ value_xge e W v in
match x with
⇒
Some
n =? 0
→
t2
else
t1
_
⇒
None
_, JRetv
⇒
match fn_retfr_fnfr with
⇒
let* x ≔ value_xge e k v in
_
⇒
None
_, JRetsvs
⇒
or_stuck"rets"
match fn_retfr_fnfr with
⇒
let* xs ≔ map2_optionvalue_xge e ks vs in
_
⇒
None

The step after an instruction's result out in block l, with the instructions rest and the jump j left and the doom doomed after it: on in the block, the outcome, into a callee (the caller suspended on top of c's callers), or an allocation.

790Definition inst_nextc : config l : name rest : listinst j : jump out : inst_out doomed : optionreason : step_result ≔
let fr ≔ c_framec in
let at_rest e : env locals ≔ mkFramefr_fnfr e locals doomed Execl rest j in
match out with
IContinuee locals m′
⇒
NextmkConfigat_reste locals c_callersc m′ c_fuelc
ICallg xs pd
⇒
match call_frameg xs with
Somecallee
⇒
NextmkConfigcallee at_restfr_envfr fr_localsfr, pd :: c_callersc c_memc c_fuelc
None
⇒
Stuck"call"
⇒
λ base  ⇒
match kbase with
e, locals, m′
⇒
mkConfigat_reste locals c_callersc m′ c_fuelc
⇒
Stuck"outside the core subset"

One step of the configuration c in the global environment ge: take the argument snapshot, enter a block (spending fuel and binding its phis), run one instruction, or take the block's jump.

815Definition stepge : genv c : config : step_result ≔
let fr ≔ c_framec in
let m ≔ c_memc in
match fr_atfr with
⇒
match xs with

entry_snapshot/6 and args_snapshot/4: no arguments is a null pointer; otherwise a fresh 16-aligned object holds them, and its pointer is read-only.

[ ]
⇒
_
⇒
negbforallbsnapshot_word xs
→
Stuck"snapshot"
else
let q ≔ heap_req16 8 × Z.of_natlengthxs in
Freshq λbase ⇒ enterWPtrmkPtrbase Robase snapshot_valuesxs base allocatedm q base
Enterl from
⇒
else
or_stuck"block"
let* b ≔ find_blockl fn_blocksfr_fnfr in

block_outcome/7: fuel first, then the block's phis.

Execl [ ] j
⇒
jump_stepge c l j
Execl i :: rest j
⇒
let stop ≔
match fr_doomedfr with

insts_result/5: a doomed run stops at the first instruction that is not ahead_transparent.

Somewhy
⇒
else
Somewhy
None
⇒
None
in
match stop with
Somewhy
⇒
None
⇒
or_stuck"instruction"
let* out0 ≔ inst_stepge fr m i in
let* od ≔ doomed_resultge fr m i out0 in
Someinst_nextc l rest j fstod sndod

The step relation

The configuration c' may follow c. An allocation's base is any that is fresh in c's memory; the interpreter's choice is one.

865Inductive step_relge : genv : config → config → Prop ≔
∀ c c′
stepge c = Nextc′
step_next
step_relge c c′
∀ c q k base
stepge c = Freshq k
freshc_memc q base
step_fresh
step_relge c kbase

The run in the configuration c ends now with the outcome o.

871Definition finalge : genv c : config o : outcome : Prop ≔
stepge c = Doneo

The configuration c' follows c after any number of steps of step_rel.

875Definition reachablege : genv : config → config → Prop ≔
clos_refl_transconfig step_relge