Fil-C on Nix

Filnix wiki

the formal campaign

rocq/backend/Compile.v

# From an unchecked module to its lines

As main.pl's compile command for a Fil-C module, without -O: the module is pizlonated (Pizlonate.v), read as the model's syntax (Transport.v), judged by the model's validator (Validate.v), and its lines are those of EmitModule.v. Nothing of Prolog is in the path; the gate (tests/compile.sh) holds the printed lines to those of nanofilcompile.

Two things the Prolog compiler does are not done here, so it refuses some modules that compile takes:

  • It runs valid_module/1 on the module as written, before pizlonation. Here only the checked module is judged.
  • It checks the context/2 items (provenance's records), which pizlonation drops here.

The lines of a module both take are the same.

compile_promoted is main.pl's compile − promoted command: before pizlonation the module is promoted (Promote.v) and its copies are propagated (Copy.v), and the emission selects its branches (Emit.v). The same gate, with COMMAND=compile-promoted, holds its lines to those of nanofilcompile − promoted.

From Stdlib Require Import String ZArith List Bool
From Nanofil Require Import Term Syntax Validate ValidFast Transport
From Backend Require Import Text Asm Pizlonate Copy Promote EmitModule Regs
Import ListNotations
Open Scope string_scope

What becomes of a module.

34Inductive compiled ≔
|Refused
why : string

Not a valid module: the Prolog compiler refuses it too.

|Outside
why : string

A module this compiler does not take, though it may be valid.

|Pieces
ps : listunit → optionlistlistline

Its lines, a piece at a time (module_pieces). A piece is nothing for a function the backend builds no plan for.

Whether the item is not a function, or is one named by an atom. ir.pl's validator takes any term as a name, and the Prolog emission throws at a function whose name is not an atom, since the name is also a string of the function's origin.

48Definition func_named_by_atomit : term : bool ≔
match it with
TAppf name; _; _; _; _
⇒
negbString.eqbf "func"
||
match name with
⇒
true
_
⇒
false
_
⇒
true

The lines of the unchecked Fil-C module m, its branches selected or not: pizlonated, read as the model's syntax, judged and emitted. Outside if it has a function outside the core subset, which the validator cannot judge.

59Definition checked_linesselected : bool m : term : compiled ≔
match pizlonate_modulem with
None
⇒
Refused"an item is not of the unchecked grammar"
Somechecked
⇒
match decode_modulechecked with
None
⇒
Refused"the checked module does not read back"
Somemd
⇒
match valid_fastmd with
None
⇒
Outside"a function is outside the subset"
Somefalse
⇒
Refused"the checked module is not valid"
Sometrue
⇒

The module m, as read, compiled. A plain module is outside: its backend (amd64.pl) is not ported.

With promoted, as optimize(passes([promote, copy])) and emit(stack, selected, call): the module is promoted (Promote.v), its copies are propagated (Copy.v), and its branches are selected (Emit.v). Whether the module is plain is asked of the module as read, as main.pl's compile asks it, since promotion can remove every pointer.

83Definition compile_aspromoted : bool m : term : compiled ≔
match m with
TAppf TListitems
⇒
negbString.eqbf "module"
→
Refused"not a module"
negbforallbfunc_named_by_atom items
→
Refused"a function's name is not an atom"
negbmodule_filcitems
→
Outside"a plain module"
promoted
→
match promote_modulem with
None
⇒
Refused"promotion refuses the module"
Somem1
⇒
match copy_modulem1 with
None
⇒
Refused"copy propagation refuses the module"
Somem2
⇒
else
_
⇒
Refused"not a module"

As nanofilcompile without -O.

104Definition compile: term → compiled ≔

With promotion, copy propagation and selected branches.

107Definition compile_promoted: term → compiled ≔

The lines of an unchecked Fil-C module compiled with whole-function register allocation and direct register selection (Regs.v).

111Definition checked_lines_allocatedm : term : compiled ≔
match pizlonate_modulem with
None
⇒
Refused"an item is not of the unchecked grammar"
Somechecked
⇒
match decode_modulechecked with
None
⇒
Refused"the checked module does not read back"
Somemd
⇒
match valid_fastmd with
None
⇒
Outside"a function is outside the subset"
Somefalse
⇒
Refused"the checked module is not valid"

With promotion, copy propagation, selected branches and register allocation (nanofil − backendcompile − allocated).

128Definition compile_allocatedm : term : compiled ≔
match m with
TAppf TListitems
⇒
negbString.eqbf "module"
→
Refused"not a module"
negbforallbfunc_named_by_atom items
→
Refused"a function's name is not an atom"
negbmodule_filcitems
→
Outside"a plain module"
else
match promote_modulem with
None
⇒
Refused"promotion refuses the module"
Somem1
⇒
match copy_modulem1 with
None
⇒
Refused"copy propagation refuses the module"
_
⇒
Refused"not a module"

A module of one function that returns its argument is taken, and one with no pointer and no outside call is plain.

149Example compile_identity: match compileTApp"module" TListTApp"func" TAtom"f"; TAtom"export"; TAtom"p"; TListTApp"param" TAtom"p"; TApp"tmp" TAtom"a"; TListTApp"block" TAtom"top"; TList[ ]; TList[ ]; TApp"ret" TApp"tmp" TAtom"a" with Piecesps ⇒ Somelengthps | _ ⇒ None end = Some3%nat
Proof 1 step Qed
reflexivity
159Example compile_plain: compileTApp"module" TListTApp"func" TAtom"f"; TAtom"export"; TAtom"w"; TListTApp"param" TAtom"w"; TApp"tmp" TAtom"a"; TListTApp"block" TAtom"top"; TList[ ]; TList[ ]; TApp"ret" TApp"tmp" TAtom"a" = Outside"a plain module"
Proof 1 step Qed
reflexivity

A use with no definition is refused.

168Example compile_undefined: compileTApp"module" TListTApp"func" TAtom"f"; TAtom"export"; TAtom"p"; TListTApp"param" TAtom"p"; TApp"tmp" TAtom"a"; TListTApp"block" TAtom"top"; TList[ ]; TList[ ]; TApp"ret" TApp"tmp" TAtom"b" = Refused"the checked module is not valid"
Proof 1 step Qed
reflexivity

A function named by a term that is not an atom is refused.

177Example compile_name: compileTApp"module" TListTApp"func" TApp"tmp" TAtom"a"; TAtom"export"; TAtom"p"; TListTApp"param" TAtom"p"; TApp"tmp" TAtom"a"; TListTApp"block" TAtom"top"; TList[ ]; TList[ ]; TApp"ret" TApp"tmp" TAtom"a" = Refused"a function's name is not an atom"
Proof 1 step Qed
reflexivity