rocq/theories/Syntax.v
The core subset of the checked IR, transcribed from ir.pl: its grammar as inductive types, one constructor per functor of the intermediate representation (IR), and the small tables of facts the semantics reads.
The subset is formal.md's: filc mode, the checked stage, the integer and pointer classes, check and its reuse vocabulary, the raw_* accesses, flight, poll edges, call, raw_call and free, and named locals, touch (a vector access's check, whose proof it uses without accessing anything); and, for the Lua suite, the float classes with their conversions (Ieee.v) and variadic functions (va_args, va_arg); and setjmp, whose syntax and validation are ir.pl's while its step is stuck, as the interpreter refuses it. Vectors, cas and atomics, asm_fixed and plain mode are deferred: a function that uses them is IOutside, which has an address but no body (Transport.v decides).
Items, blocks and instructions
| Gallina | ir.pl |
|---|---|
IFuncf | func(Name, Linkage, Ret, Params, Blocks) |
IOutsiden t | a func named n outside the core subset, kept as its term t |
IDatan lk al items | data(Name, Linkage, Align, Items) |
IAliasn lk t | alias(Name, Linkage, Target) |
Phid k pairs | phi(tmp(D), K, [Pred-Value]) |
Letd k o args | let(tmp(D), K, Op, Args) |
Flightd o args lower | flight(tmp(D), Op, Args, Lower) |
RawStorew off v a | raw_store(Width, Off, Value, Addr) |
RawStorePointeroff v a es | raw_store_pointer(Off, Value, Addr, Effects) |
Callr callee args | call(Res, Callee, [arg(K, Value)]) |
RawCallr callee args | raw_call(Res, Callee, Args) |
LocalAllocx size | local_alloc(Name, Size) |
Locfile line | loc(File, Line) |
Touchq | touch(tmp(Q)) |
Classes and widths
As class(K, Kind, Bits): the class of a value, one letter in ir.pl. Besides the integer, pointer and float classes there are the two proof classes of the checked stage, whose values are pointers a check has cleared.
| Class | ir.pl | Value |
|---|---|---|
W | w | a 32-bit integer |
L | l | a 64-bit integer |
P | p | a pointer: an address with its capability |
A | a | a proven address, the result of a check |
F | f | a proven function, the result of check_function |
Single | s | an IEEE binary32 float, held as its 32-bit pattern |
Double | d | an IEEE binary64 float, held as its 64-bit pattern |
Extended | x | an x87 extended float, held as its 80-bit pattern |
Extended is C's long double, never a parameter, result, call argument or phi.
| | | W | ||
| | | L | ||
| | | P | ||
| | | A | ||
| | | F | ||
| | | Single | ||
| | | Double | ||
| | | Extended |
Equality of classes.
As float_class(K): whether the class k is a float class, s, d or x.
As int_class(K): whether the class k is an integer class, w or l.
As class_bits(K, Bits): the width in bits of an integer class k.
As half_modulus(K, Half): half the modulus of an integer class k; the values from Half up to Mod - 1 are the negative ones when read as signed, in two's complement.
| | | Wb | ||
| | | Wh | ||
| | | Ww | ||
| | | Wl | ||
| | | Wp | ||
| | | Ws | ||
| | | Wd | ||
| | | Wx |
As width_bytes(Width, Size): the bytes a width w writes; an x87 extended float takes 10.
A narrow integer type, the T of a narrow load and of ext(T): ir.pl's sw uw sh uh sb ub, a signed or unsigned word (4 bytes), halfword (2) or byte (1).
| | | Sw | ||
| | | Uw | ||
| | | Sh | ||
| | | Uh | ||
| | | Sb | ||
| | | Ub |
Whether an integer is read as signed, in two's complement, or as unsigned.
| | | Signed | ||
| | | Unsigned |
As narrow_type(T, Bytes, Signedness): the size in bytes and the signedness of the narrow type t.
The type of a raw load: LdL for l, LdS, LdD and LdX for the float classes s d x, or a narrow type. This is load_type/1 without p, which RawLoadPointer reads instead.
Ops
| | | Eq | ||
| | | Ne | ||
| | | Sle | ||
| | | Slt | ||
| | | Sge | ||
| | | Sgt | ||
| | | Ule | ||
| | | Ult | ||
| | | Uge | ||
| | | Ugt | ||
| | | Le | ||
| | | Lt | ||
| | | Ge | ||
| | | Gt | ||
| | | Ord | ||
| | | Unord |
The rights an access asks for: to read, or to write, which a read-only object refuses.
| | | Read | ||
| | | Write |
Equality of rights.
Which end of an object's bounds a half check tests natively, ir.pl's upper or lower; an earlier check proves the other.
| | | Upper | ||
| | | Lower |
One step of the protocol by which a pointer load or store moves an address and its capability, as pointer_memory_effects/2 lists them:
- a heap load reads the aux word (
AuxRead), resolves the lower from it (LowerResolve), then reads the address (AddressRead); - a heap store makes sure the aux exists (
AuxEnsure), applies the collector's barrier to the stored lower (LowerBarrier), reloads its destination from a root (RootedReload), then writes the lower (LowerWrite) before the address (AddressWrite); AtomicReadandAtomicWriteare Fil-C's atomic pointer helpers, each a whole protocol.
| | | AuxRead | ||
| | | LowerResolve | ||
| | | AddressRead | ||
| | | AtomicRead | ||
| | | AuxEnsure | ||
| | | LowerBarrier | ||
| | | RootedReload | ||
| | | LowerWrite | ||
| | | AddressWrite | ||
| | | AtomicWrite |
Equality of effects.
Equality of two effect lists, step by step.
As pointer_memory_effects(load, Effects): the protocol of a heap pointer load, one of the two that evidence_preserving accepts.
As pointer_memory_effects(local_load, Effects): the protocol of a pointer load from a named local, whose explicit stack aux has no atomic box, so there is no lower to resolve.
Which of the three returns-twice calls a setjmp(Kind) is: setjmp, '_setjmp' or sigsetjmp (op_kind/2).
| | | SjSetjmp | ||
| | | SjUnderscore | ||
| | | SjSig |
An operation, the Op of a let (ir.pl's Ops table): one constructor per functor in the core subset, with the functor's parameters as its arguments. The arithmetic and conversions come first, then the alloc, the checks of the checked stage and their reuse forms, the raw loads, the variadic ops and setjmp. What each reads is op_arg_classes.
| | | Add | ||
| | | Sub | ||
| | | Mul | ||
| | | Div | ||
| | | Udiv | ||
| | | Rem | ||
| | | Urem | ||
| | | And | ||
| | | Or | ||
| | | Xor | ||
| | | Sar | ||
| | | Shr | ||
| | | Shl | ||
| | | Neg | ||
| | | Copy | ||
| | | Ptoi | ||
| | | Itop | ||
| | | Cmp | 1 if two values of class k compare by c, else 0 | |
| | | Ext | t : narrow | the low bytes of a w, extended by t |
The float conversions: | |||
| | | ExtF | k : class | widen a float of class k |
| | | Truncd | ||
| | | Truncx | ||
| | | FloatToInt | k : class sg : signedness | a float of class k to an integer, truncated |
| | | IntToFloat | k : class sg : signedness | an integer of class k to the nearest float |
| | | Cast | the same bits at the other class: w and s, l and d | |
| | | Sqrt | the square root of a float, rounded to nearest | |
| | | Alloc | align : Z | a new zeroed heap object of the l size read |
| | | Check | check of a pointer P: trap unless P may access from P+lo up to P+hi | |
| | | CheckAhead | a check whose bytes from ahi up to hi are for a later access: check_ahead | |
| | | Renew | reuse a dominating check's bounds: renew | |
| | | RenewHull | a renew whose bounds two earlier proofs cover: renew_hull | |
| | | HalfCheck | a check that tests only the bound b: half_check | |
| | | SpanTest | lo hi : Z | 1 if the pointer's object holds the span, else 0: span_test |
| | | RenewIf | a check whose bounds a passing span test proves: renew_if | |
| | | Limit | size : Z | an opaque snapshot of the pointer's bounds: limit |
| | | CheckLimit | a check of the bounds against a limit: check_limit | |
| | | CheckLocal | prove an access to the named local x | |
| | | CheckFunction | trap unless the pointer is a function's exact address | |
| | | RawLoad | t : load_type off : Z | a non-pointer load at the proven address plus off |
| | | RawLoadPointer | off : Z es : listeffect | a pointer load at the proven address plus off, by the protocol es |
| |||
| | | VaArgs | ||
| | | VaArg | ||
| |||
| | | Setjmp | kind : setjmp_kind | |
Values, instructions and jumps
A value an instruction reads (ir.pl's Values table).
| | | Tmp | n : name | tmp(N), a temporary, defined once |
| | | Const | n : Z | const(N), an integer; at a float class, its bit pattern |
| | | Global | s : name | global(S), the address of the function or data object s |
A flight's Lower, where its capability comes from: none, or lower(P), exactly the capability of the pointer P.
A call's Res, where its results go.
| | | CVoid | void: none | |
| | | CResult | result(tmp(D), K): the temporary d, of class k | |
| | | CTuple | tuple([result(tmp(D1), K1), ...]): a pair of results |
As arg(K, Value): a call's argument, the value v passed at class k.
| | | Let | d, of class k, is o of args | |
| | | Flight | the pointer d: the address o computes, with the capability lower names | |
| | | RawStore | store v at the proven address a plus off | |
| | | RawStorePointer | store the pointer v there, by the protocol es | |
| | | Call | call callee, a symbol or a pointer | |
| | | RawCall | call the proven function callee, of class F | |
| | | LocalAlloc | x : name size : Z | declare the named local x, of size zeroed bytes |
| | | Loc | file : term line : Z | a source position; does nothing |
| | | Touch | q : name | touch(tmp(Q)): use the proof q of the check just before it, and do nothing else |
As edge_label(T, L): the label a target t goes to, polling or not.
The jump that ends a block (ir.pl's Jumps table).
| | | JGoto | t : target | goto(L) |
| | | JBranch | to t1 if v is nonzero, else to t2 | |
| | | JRet | v : value | ret(V): return v |
| | | JRets | vs : listvalue | rets([V1, V2]): return a tuple |
| | | JRetVoid | ret, from a void function | |
| | | JUnreachable | stop the program, a trap instruction |
As phi(tmp(D), K, [Pred-Value]): a phi at the head of a block, defining d, of class k, as the value paired with the block control came from.
As block(Label, Phis, Insts, Jump): a block, its phis, then its instructions, then the one jump that ends it.
A function's Ret: a class, void, or tuple([K1, K2]).
As func(Name, Linkage, Ret, Params, Blocks): a function.
| fn_name | : name | |
| fn_linkage | : term | export, local or weak, kept as its term |
| fn_ret | : ret_type | |
| fn_params | each a class and a temporary | |
| fn_blocks | : listblock | the entry block first |
As variadic_func(Func): whether the function f takes the entry argument snapshot of a variadic function, which it does with a va_args anywhere in its blocks.
Data
| | | LExport | ||
| | | LLocal | ||
| | | LWeak | ||
| | | LRo | l : term | |
| | | LTls | l : term | |
| | | LInit | which prio : term | init(ctor or dtor, Priority): a constructor or destructor table entry, not an object |
| | | LExternWeak | extern(weak): a weak declaration of a symbol defined elsewhere, not an object | |
| | | LOther | t : term | any other Linkage term: valid_module/1 rejects it, so only the validator meets it |
A data Item, a piece of a data object's initial contents. item(l, sym(Name, Off)) is plain mode's, outside the subset; item(p, sym(Name, Off)) is Sym.
| | | Item | w : width n : Z | item(W, const(N)): n at width w |
| | | Str | codes : listZ | item(b, str(Chars)): the bytes themselves |
| | | Sym | s : name off : Z | a pointer to s plus off, with the capability of s |
| | | Zero | n : Z | zero(N): n zero bytes |
| | | ItemOther | t : term | any other term, kept as it is: valid_module/1 rejects it (data_item_shape/1), so only the validator meets it |
As item_size(Item, Size0, Size): the bytes a data item takes.
The bytes a list of data items takes, the size of the object they make.
Modules
An item of a module; the table at the top of the page gives each one's ir.pl term.
| | | IFunc | f : func | a function of the core subset |
| | | IOutside | a function outside it: an address, no body | |
| | | IData | a data object | |
| | | IAlias | a second symbol n for the function or data object target |
A module, as module(Items): its items in order.
Facts about instructions
As op_arg_classes(Op, K, filc, Classes): the classes at which the op o reads its arguments when its result has class k; none where o cannot have a result of class k.
Whether the value v is a symbol's address, a Global.
As ahead_transparent(Inst): the instruction i may come between a check_ahead and the access whose need it checks early. It is evidence_preserving, and not a division, whose fault would end the program otherwise than a Fil-C trap.
As setjmp_func/1: the function f calls setjmp somewhere, reachable or not. Its second return is a control edge the blocks do not show (docs/setjmp.md), so the validator refuses what would need it.
As local_objects(Func, Objects): the named locals the function f declares, each with its size, in instruction order.