Fil-C on Nix

Filnix wiki

the formal campaign

rocq/backend/Plan.v

The ABI plan of a function, as filc_abi.pl's abi_function/10 states it before any register or frame offset is chosen: a frame of named slots, entry actions, blocks whose calls, getters and returns are lists of ABI actions, and the function's public object. It is what Fuse.v and Abi.v build and what instruction selection reads.

The instructions inside it are Syntax.v's, the model's own: the plan adds only the forms the checked IR has no term for, which are a check fused with its access, a reused proof, and abi(Actions). PlanTerm.v writes a plan as the term the Prolog compiler prints for it.

From Stdlib Require Import String ZArith List
From Nanofil Require Import Term Syntax Validate
Import ListNotations
Open Scope Z_scope

f of every element of xs, or nothing if any has none.

20Fixpoint all_someX Y : Type f : X → optionY xs : listX : optionlistY ≔
match xs with
[ ]
⇒
Some[ ]
x :: xs′
⇒
match fx with
Somey
⇒
match all_somef xs′ with
Someys
⇒
Somey :: ys
None
⇒
None
None
⇒
None

Fused instructions

Where a fused access is: at the pointer P its check proved, or at local(X, Off), the named local x plus off, which check_local proves.

35Inductive place: Type ≔
|AtValue
p : value
|AtLocal
x : name off : Z

A raw access with its proof replaced by the place proven: the raw loads and stores of Syntax.v's inst, which read a proof temporary there.

42Inductive access: Type ≔
|ALoad
d : name k : class t : load_type off : Z p : place
let(tmp(D), K, raw_load(T, Off), [P])
|AStore
w : width off : Z v : value p : place
raw_store(W, Off, V, P)
|ALoadPointer
d : name off : Z es : listeffect p : place
let(tmp(D), p, raw_load_pointer(Off, Es), [P])
|AStorePointer
off : Z v : value p : place es : listeffect
raw_store_pointer(Off, V, P, Es)
|ATouch
p : place
touch(P): the check alone, with no access after it

An instruction after fusion (filc_amd64.pl's fused_blocks/5).

50Inductive finst: Type ≔
|FPlain
i : inst
an instruction of the checked IR, unchanged
|FFused
c : op a : access
fused(Check, Access): a check and the access it proves, at one index
|FReused
a : access
reused(Access): an access under an earlier check's proof, with no check
|FCall
r : call_result p : value args : listarg
fused(check_function, call(Res, P, Args))

The temporaries a place reads: its pointer, if a temporary.

57Definition place_usesp : place : listname ≔
match p with

The temporaries an access reads.

64Definition access_usesa : access : listname ≔
match a with
ALoad_ _ _ _ p | ALoadPointer_ _ _ p | ATouchp
⇒
AStore_ _ v p | AStorePointer_ v p _
⇒

The temporary an access defines, with its class.

71Definition access_defsa : access : listname × class ≔
match a with
ALoadd k _ _ _
⇒
d, k
⇒
d, P
AStore_ _ _ _ | AStorePointer_ _ _ _ | ATouch_
⇒
[ ]

As cfg:inst_uses/2 of live_inst/2: the temporaries a fused instruction reads, as liveness and the frame layout see it: the bare access at its checked pointer, or the call of the checked pointer. The proof is not among them: it is a register value and has no slot.

83Definition finst_usesi : finst : listname ≔
match i with
FPlaini′
⇒
FCall_ p args
⇒
value_tempsp :: maparg_value args

As cfg:inst_def/2 of live_inst/2: the temporaries a fused instruction defines, each with its class.

92Definition finst_defsi : finst : listname × class ≔
match i with
FCallr _ _
⇒
match r with
⇒
[ ]
⇒
d, k
⇒
rs

Frames

A pool of the frame's slots (frame_slots.pl): PoolScalar holds the w, l, s and d temporaries, PoolPointer the p ones, each slot an address and its lower, and PoolWide the x ones.

105Inductive pool: Type ≔
|PoolScalar
|PoolPointer
|PoolWide

The name of something a frame holds.

108Inductive key: Type ≔
|KTmp
n : name
tmp(N): the payload of the temporary n
|KShadow
n : name
shadow(N): the copy of the phi n that an edge's parallel moves read
|KStorage
p : pool i : Z
storage(Pool, I): the slot i of a pool
|KThread
thread: the saved thread pointer
|KAux
aux: a scratch word
|KRetbuf
retbuf: the caller's return buffer
|KLocal
x : name size : Z
local(X, Size): the bytes of a named local
|KLower
k : key
lower(K): the capability beside the address K, a root
|KStackAux
x : name
stack_aux(X): the aux of a named local, a root

As frame(Plain, Roots, Aliases): the payload slots, the roots the collector scans, in order, and the slot each temporary's payload or lower is kept in.

122Record frame: Type ≔ mkFrame
fr_plain
 : listkey
fr_roots
 : listkey
fr_aliases
 : listkey × key

Words, cells and results

How a function returns: registers, or buffer(N), through a buffer of n words when more than two integer words come back.

132Inductive protocol: Type ≔
|Registers
|Buffer
n : Z

Where a fast word comes from or goes.

135Inductive source: Type ≔
|SrcSlot
k : key
a parameter's slot, tmp(N) or lower(tmp(N))
|SrcAddr
v : value
addr(V): the address of the pointer v
|SrcLower
v : value
lower(V): its capability
|SrcVal
k : class v : value
val(K, V): the value v at class k
|SrcData
i : Z
data(I): the data word of the generic cell i
|SrcAux
i : Z
aux(I): its aux word
|SrcSnapshot
snapshot: a variadic entry's promoted argument packet

As wf(K, Source): one word of a fast call, at the class k (l for both words of a pointer).

146Inductive word: Type ≔
|Wf
k : class s : source

What a generic cell holds: a value, or saved(W), the fast word w a thunk saved.

150Inductive cell_source: Type ≔
|CellValue
v : value
|CellSaved
w : Z

As cell(I, K, Source, Lower): the eightbyte i of a generic packet, with the capability beside it if it is a pointer.

154Inductive cell: Type ≔
|Cell
i : Z k : class s : cell_source lower : optioncell_source

The channels a fast call's results come back in.

158Inductive channels: Type ≔
|ChSlots
ks : listkey
slots([...]): integer words, to these slots
|ChFloat
k : class d : name
float(K, tmp(D)): one float
|ChTyped
ks : listclass × key
typed([K-Slot, ...]): a tuple with a float in it

A direct call's signature in its symbol: its number, or never(R-A) for a call of more than 16 words, which has no fast signature.

166Inductive sigref: Type ≔
|SigNumber
n : Z
|SigNever
r a : Z

What a direct call invokes.

169Inductive call_target: Type ≔
|TImplementation
f : name sig : Z
implementation(F, Sig): the private body of a function of this module
|TEntry
f : name sig : sigref
entry(F, Sig): the weak thunk of this symbol and signature

The getter that gives a symbol's address.

174Inductive getter: Type ≔
|GetLocal
s : name
local_getter(S): this module defines s
|GetWeak
s : name
weak_getter(S): declared weak; may be null
|GetExternal
s : name
external_getter(S)

Actions

One step of an abi(Actions) instruction. Each list of them occupies the one index of the instruction it lowers.

183Inductive action: Type ≔
|AOrigin
origin(c): record the catching origin before a safepoint
|AReserveResult
r : protocol
reserve_result(R)
|AInvoke
t : call_target r : protocol ws : listword
invoke(Target, R, Words)
|AResult
r : protocol c : channels
result(R, Channels)
|AReleaseResult
r : protocol
release_result(R)
|ACopyFilter
d s : value n : Z res : call_result
copy_filter(D, S, N, Res): a small memcpy's inline filter
|ACopyJoin
copy_join
|ADispatch
p : value sig : Z r : protocol ws : listword c : channels size : Z cells : listcell need : Z results : listcell

dispatch(P, Sig, R, Words, result(R, C), Size, Cells, receive_generic(Need, Results)): an indirect call, fast if the callee has this signature, else generic

|AGetter
g : getter d : name
getter(G, c, D)
|ASnapshotCursor
off : Z d : name
snapshot_cursor(tmp(hidden(va_snapshot)), Off, D)
|AConsumeVa
k : class p : value size : Z d : name
consume_va(K, P, Size, D)
|AInitializeLocal
x : name
initialize_local(X)

An instruction of a plan: a fused instruction passed through, or abi(Actions).

201Inductive pinst: Type ≔
|PInst
i : finst
|PAbi
acts : listaction

The jump that ends a plan's block: a jump of the IR, or abi_return(Actions), the actions of a return.

207Inductive pjump: Type ≔
|PJump
j : jump
goto, branch or unreachable, unchanged
|PReturnValue
r : ret_type v : value p : protocol
[return_value(Ret, V), pop_frame, success(P)]
|PReturnBuffer
ws : listword
[return_buffer(Words), success_buffer, pop_frame, native_return]
|PReturnTyped
ks : listclass vs : listvalue
[return_typed(Ks, Vs), pop_frame, success(registers)]
|PReturnRegisters
vs : listvalue
[return_registers(Vs), pop_frame, success(registers)]
|PReturnVoid
p : protocol
[pop_frame, success(P)]

A block of a plan.

216Record pblock: Type ≔ mkPBlock
pb_label
 : name
pb_phis
 : listphi
pb_insts
 : listpinst
pb_jump
 : pjump

Public objects and thunks

The channel a generic adapter takes the fast result from.

226Inductive adapter_channel: Type ≔
|AdVoid
|AdFloat
k : class
|AdTyped
ks : listclass
|AdWords

As adapter_result(R, Channel, Size, packet(Copies, Zeros)): how an adapter turns a fast result into a generic packet of size bytes: the words it copies and those it zeroes.

232Record adapter_result: Type ≔ mkAdapterResult
ar_return
ar_channel
ar_size
 : Z
ar_copies
 : listsource
ar_zeros
 : listsource

A function's public object.

241Inductive object: Type ≔
|FastAndGeneric
sig need : Z ws : listword r : adapter_result

fast_and_generic(Sig, adapt(Need, Words, Result))

|GenericOnly
need : Z ws : listword r : adapter_result

generic_only(promote_incoming(Need, Words, Result)): a variadic function

How a thunk refers to its callee.

248Inductive thunk_ref: Type ≔
|RefWeak
|RefLocal
|RefStrong

As thunk(F, Ref, Sig, Words, Cells, ArgsSize, Result, Need): the weak thunk of a symbol and signature that the module calls directly and does not define.

253Record thunk: Type ≔ mkThunk
th_name
 : name
th_ref
th_sig
 : sigref
th_words
 : listword
th_cells
 : listcell
th_args_size
 : Z
th_result
th_need
 : Z

The plan

As abi_function(Name, Linkage, Ret, Sig, Frame, Entry, Blocks, Exit, Object, Origins). The entry actions, the exception exit and the origins have one shape each, so the plan keeps what they vary in: the return protocol, the words received, the payload slots a setjmp would snapshot, and the numbers of roots and named locals.

272Record plan: Type ≔ mkPlan
pl_name
 : name
pl_linkage
 : term
pl_ret
pl_sig
 : Z
pl_frame
 : frame
pl_return
pl_incoming
 : listword
pl_payload
 : listkey
pl_blocks
 : listpblock
pl_object
 : object
pl_nlocals
 : Z