Fil-C on Nix

Filnix wiki

the formal campaign

rocq/backend/EmitInst.v

# Instructions

The code of one instruction of a plan, as filc_amd64.pl's inst//4 and abi_action//4 give it in the reference emission: every temporary in its stack slot, the split bounds check, no inline copies. A form that is not ported yet is a todo line (Layout).

From Stdlib Require Import String ZArith List Bool
From Nanofil Require Import Term Syntax Maps
From Backend Require Import Text Asm Plan Fuse PlanTerm FrameSlots Layout EmitOps
Import ListNotations
Open Scope string_scope
Open Scope Z_scope
Open Scope list_scope

Heap checks

19Definition rights_writer : rights : bool ≔
match r with
⇒
true
⇒
false

As aux_pointer_mask/1: the low 48 bits of an aux word are the aux pointer; the high 16 are the object's flags.

23Definition aux_pointer_mask: Z ≔
281474976710655

As aux_bits/2 of special_type and of function.

25Definition special_type_mask: Z ≔
540431955284459520
26Definition function_bits: Z ≔
36028797018963968

As write_check//2: a write needs an object that is neither read-only nor free.

30Definition write_checkwrite : bool fail : string : listline ≔
write
→
ins"test" "b" imm6; mem−2 "rcx"; ins0"jnz" symfail
else
[ ]

As align_check//2.

34Definition align_checkalign : Z fail : string : listline ≔
align =? 1
→
[ ]
align =? 2 || align =? 4 || align =? 8
→
ins"test" "b" immalign − 1; reg"al"; ins0"jnz" symfail
else
todo"alignment"

As access_check//2 with the split bounds: with the pointer in %rax and its lower in %rcx, a jump to the kind's failure block unless the lower is not null, lower <= pointer and pointer + size <= upper, and the flags and alignment permit.

44Definition access_checkcx : ctx k : check_kind : listline ≔
let fail ≔ check_fail_labelcx k in
ins"test" "q" reg"rcx"; reg"rcx"; ins0"jz" symfail; ins"cmp" "q" reg"rcx"; reg"rax"; ins0"jb" symfail; ins"mov" "q" mem−16 "rcx"; reg"rdx"; ins"sub" "q" immck_sizek; reg"rdx"; ins0"jb" symfail; ins"cmp" "q" reg"rdx"; reg"rax"; ins0"ja" symfail ++ write_checkck_writek fail ++ align_checkck_alignk fail

Raw accesses

After its check, an access has its address in %rax and the lower of the pointer in %rcx.

As raw_load//6: a scalar load of the type t at the class k into the temporary d.

61Definition raw_loadcx : ctx t : load_type k : class d : name : listline ≔
match t with
⇒
ins"fld" "t" mem0 "rax" :: x87_popcx d
_
⇒
load_insnt k ++ slot_storecx "rax" KTmpd

As width_value_class/2: the class a store of the width w reads its value at.

69Definition width_value_classw : width : optionclass ≔
match w with
Wb | Wh | Ww
⇒
SomeW
⇒
SomeL
⇒
SomeSingle
⇒
SomeDouble
Wp | Wx
⇒
None

As raw_store//6.

79Definition raw_storecx : ctx w : width v : value : listline ≔
match w with
⇒
x87_pushcx v ++ ins"fstp" "t" mem0 "rax"
_
⇒
match width_value_classw with
Somek
⇒
loadcx v k "d" ++ store_insnw "d"
None
⇒
todo"store width"

As aux_of_lower//0: the aux pointer of the object at the lower in %rcx into %rdx, setting ZF if it has none.

91Definition aux_of_lower: listline ≔
ins"mov" "q" mem−8 "rcx"; reg"rdx"; ins"movabs" "q" immaux_pointer_mask; reg"rsi"; ins"and" "q" reg"rsi"; reg"rdx"

As pointer_load_effect//4: one step of a pointer load's protocol, at the instruction index of the block b.

98Definition pointer_load_effectcx : ctx b : name index : string e : effect : listline ≔
let nolower ≔ local_labelcx b index "nolower" in
let have ≔ local_labelcx b index "have" in
match e with
⇒
aux_of_lower ++ ins0"jz" symnolower; ins"mov" "q" reg"rax"; reg"rsi"; ins"sub" "q" reg"rcx"; reg"rsi"; ins"mov" "q" mem_index0 "rdx" "rsi"; reg"rsi"
⇒
ins"test" "b" imm1; reg"sil"; ins0"jz" symhave; ins"and" "q" imm−2; reg"rsi"; ins"mov" "q" mem8 "rsi"; reg"rsi"; ins0"jmp" symhave; labelnolower; ins"xor" "l" reg"esi"; reg"esi"; labelhave
⇒
ins"mov" "q" reg"rax"; reg"rdi"; ins"mov" "q" reg"rcx"; reg"rsi" ++ origin_storecx "c" ++ ins0"call" plt"filc_load_ptr_atomic_with_manual_tracking_outline"; ins"mov" "q" reg"rdx"; reg"rcx"
⇒
ins"mov" "q" mem0 "rax"; reg"rax"; ins"mov" "q" reg"rsi"; reg"rcx"
_
⇒
todo"pointer load effect"

As pointer_store_effect//6: one step of the protocol of a store of the pointer v at the pointer a. Ensuring the aux may exit, so rooted_reload reads both again from their roots before the lower and then the address are written.

132Definition pointer_store_effectcx : ctx b : name index : string v a : value e : effect : listline ≔
match e with
⇒
let haveaux ≔ local_labelcx b index "haveaux" in
aux_of_lower ++ ins0"jnz" symhaveaux ++ slot_loadcx KThread "rdi" ++ ins"lea" "q" mem−16 "rcx"; reg"rsi"; ins0"call" plt"filc_object_ensure_aux_ptr_outline"; ins"mov" "q" reg"rax"; reg"rdx"; labelhaveaux ++ slot_storecx "rdx" KAux
⇒
let nobarrier ≔ local_labelcx b index "nobarrier" in
lower_loadcx v "rsi" ++ ins"test" "q" reg"rsi"; reg"rsi"; ins0"jz" symnobarrier; ins"mov" "q" gotpcrel"filc_current_marking_state"; reg"rax"; ins"cmp" "l" imm0; mem0 "rax"; ins0"je" symnobarrier ++ slot_loadcx KThread "rdi" ++ ins0"call" plt"filc_store_barrier_for_lower_slow"; labelnobarrier
⇒
flight_loadcx a ++ slot_loadcx KAux "rdx" ++ ins"mov" "q" reg"rax"; reg"r8"; ins"sub" "q" reg"rcx"; reg"r8" ++ lower_loadcx v "rsi" ++ loadcx v L "r9"
⇒
ins"mov" "q" reg"rax"; reg"rsi"; ins"mov" "q" reg"rcx"; reg"rdx" ++ origin_storecx "c" ++ slot_loadcx KThread "rdi" ++ loadcx v L "c" ++ lower_loadcx v "r8" ++ ins0"call" plt"filc_store_ptr_atomic_outline"
⇒
ins"mov" "q" reg"rsi"; mem_index0 "rdx" "r8"
⇒
ins"mov" "q" reg"r9"; mem0 "rax"
_
⇒
todo"pointer store effect"

As raw_access//4: the access a at a heap pointer.

174Definition raw_accesscx : ctx b : name index : string a : access : listline ≔
match a with
ALoadd k t _ _
⇒
raw_loadcx t k d
AStorew _ v _
⇒
raw_storecx w v
ALoadPointerd _ es _
⇒
flat_mappointer_load_effectcx b index es ++ flight_storecx d
⇒
flat_mappointer_store_effectcx b index v p es
⇒
todo"pointer store at a local"
⇒
[ ]

Named locals

As local_address//5: the address of the access's aux word into %rdx and of its payload into %rax. The check has passed, so an offset in range and aligned is a constant displacement.

190Definition local_addressoff limit mask a p : Z : listline ≔
0 ≤? off && off ≤? limit && Z.landoff mask =? 0
→
ins"lea" "q" mema + off "rbp"; reg"rdx"; ins"lea" "q" memp + off "rbp"; reg"rax"
else
ins"lea" "q" mem_indexa "rbp" "rax"; reg"rdx"; ins"lea" "q" mem_indexp "rbp" "rax"; reg"rax"

As local_check//6: the exact bounds of the named local x, with no heap lower. The offset and the size are the stack reporter's arguments; the address is formed only after the check.

201Definition local_checkcx : ctx b : name index : string x : name off : Z k : check_kind : listline ≔
match nm_findx cx_localscx with
None
⇒
todo"no local"
Somes
⇒
let mask ≔ ck_alignk − 1 in
let limit ≔ ls_sizes − ck_sizek in
let fail ≔ local_labelcx b index "localfail" in
let good ≔ local_labelcx b index "localok" in
loadcx Constoff L "a" ++ loadcx Constls_sizes L "c" ++ loadcx Constlimit L "d" ++ ins"test" "q" reg"rdx"; reg"rdx"; ins0"js" symfail; ins"cmp" "q" reg"rdx"; reg"rax"; ins0"ja" symfail; ins"test" "q" immmask; reg"rax"; ins0"jnz" symfail; ins0"jmp" symgood; labelfail; ins"mov" "q" reg"rax"; reg"rdi"; ins"mov" "q" reg"rcx"; reg"rsi"; ins"lea" "q" ripcheck_origin_labelcx_namecx k; reg"rdx"; ins0"call" plt"filc_optimized_stack_access_check_fail"; ins0"ud2" [ ]; labelgood ++ local_addressoff limit mask eight − ls_auxs −ls_payloads

As local_raw_access//4: the access a at a named local, with the payload address in %rax and the aux word's in %rdx. Only what a pointer load reads or a pointer store writes has a heap lower.

231Definition local_raw_accesscx : ctx b : name index : string a : access : listline ≔
match a with
ALoadPointerd _ es _
⇒
flat_map
λ e  ⇒
match e with
⇒
ins"mov" "q" mem0 "rdx"; reg"rcx"
⇒
ins"mov" "q" mem0 "rax"; reg"rax"
_
⇒
todo"local load effect"
es
++
⇒
flat_map
λ e  ⇒
match e with
⇒
lower_loadcx v "rcx" ++ ins"mov" "q" reg"rcx"; mem0 "rdx"
⇒
loadcx v L "si" ++ ins"mov" "q" reg"rsi"; mem0 "rax"
_
⇒
todo"local store effect"
es
_
⇒
raw_accesscx b index a

Values

As integer_inst//5: the op's value in %rax, then into the temporary d.

256Definition integer_instcx : ctx o : op k : class args : listvalue d : name : listline ≔
compute_opcx o k args ++ slot_storecx "rax" KTmpd
260Definition int32_min: Z ≔
−2147483648
261Definition int32_max: Z ≔
2147483647

As span_end//2: the pointer in %rax plus off, modulo 2^64, into the register r.

265Definition span_endoff : Z r : string : listline ≔
int32_min ≤? off && off ≤? int32_max
→
ins"lea" "q" memoff "rax"; regr
else
ins"movabs" "q" immoff mod two64; reg"rsi"; ins"lea" "q" mem_index0 "rax" "rsi"; regr

As the span_test clause of kind_inst//8: 1 when the lower of p is not null and lower <= p + lo < p + hi <= upper, unsigned; else 0. It reads only what a full check reads and never traps.

275Definition span_test_linescx : ctx b : name index : string lo hi : Z p : value d : name : listline ≔
let zero ≔ local_labelcx b index "span0" in
let done ≔ local_labelcx b index "span1" in
flight_loadcx p ++ ins"test" "q" reg"rcx"; reg"rcx"; ins0"jz" symzero ++ span_endlo "rdx" ++ ins"cmp" "q" reg"rcx"; reg"rdx"; ins0"jb" symzero ++ span_endhi "rax" ++ ins"cmp" "q" reg"rdx"; reg"rax"; ins0"jbe" symzero; ins"cmp" "q" mem−16 "rcx"; reg"rax"; ins0"ja" symzero; ins"mov" "l" imm1; reg"eax"; ins0"jmp" symdone; labelzero; ins"xor" "l" reg"eax"; reg"eax"; labeldone ++ slot_storecx "rax" KTmpd

As kind_inst//8: the temporary d, of class k, is o of args, at the instruction index of the block b.

295Definition let_linescx : ctx b : name index : string d : name k : class o : op args : listvalue : listline ≔
→
x87_instcx o k args d
else
match o with
⇒
match k with
⇒
integer_instcx o k args d
_
⇒
todo"class"
Mul | Div | Udiv | Rem | Urem | And | Or | Xor | Sar | Shr | Shl | Neg | Cmp_ _ | Ext_ | ExtF_ | Truncd | Truncx | FloatToInt_ _ | IntToFloat_ _ | Cast
⇒
integer_instcx o k args d
⇒
match k, args with
L, p
⇒
loadcx p L "a" ++ slot_storecx "rax" KTmpd
_, _
⇒
todo"ptoi"
Allocalign
⇒
match k, args with
P, n
⇒
loadcx n L "si"
++
++
align ≥? sixteen
→
ins"mov" "l" immalign; reg"edx"; ins0"call" plt"filc_allocate_with_alignment"
else
ins0"call" plt"filc_allocate"
++
ins"lea" "q" memsixteen "rax"; reg"rax"; ins"mov" "q" reg"rax"; reg"rcx" ++ flight_storecx d
_, _
⇒
todo"alloc"
⇒
match k, args with
W, p
⇒
span_test_linescx b index lo hi p d
_, _
⇒
todo"span_test"
_
⇒
todo"let"

As flight_address_load//3: an address operand of a flight into the short register r.

337Definition flight_address_loadcx : ctx a : flight_arg r : string : listline ≔
match a with
⇒
loadcx p L r
⇒
loadcx v L r

As shared_lower/3: the flight d's lower is the root of its donor, which already holds it.

345Definition shared_lowercx : ctx lower : flight_lower d : name : bool ≔
match lower with
⇒
negbname_eqbp d
&&
match slotcx KLowerKTmpp, slotcx KLowerKTmpd with
Someo1, Someo2
⇒
o1 =? o2
_, _
⇒
false
_
⇒
false

As the flight clause of inst//4: every input is read before the destination is written. The second address goes by %rdx; %rcx holds the lower.

359Definition flight_linescx : ctx d : name o : op args : listflight_arg lower : flight_lower : listline ≔
match args with
[ ]
⇒
todo"flight arguments"
a :: rest
⇒
let calc ≔
match o, rest with
Copy, [ ]
⇒
[ ]
Add, x
⇒
flight_address_loadcx x "d" ++ ins"add" "q" reg"rdx"; reg"rax"
Sub, x
⇒
flight_address_loadcx x "d" ++ ins"sub" "q" reg"rdx"; reg"rax"
_, _
⇒
todo"flight"
in
shared_lowercx lower d
→
flight_address_loadcx a "a" ++ calc ++ slot_storecx "rax" KTmpd
else
++
match lower with
⇒
lower_loadcx p "rcx"
⇒
ins"xor" "l" reg"ecx"; reg"ecx"
++
calc ++ flight_storecx d

Calls

As word_reg_load//4: a word of a call into the short register r.

385Definition word_reg_loadcx : ctx s : source r : string : listline ≔
match s with
⇒
loadcx v L r
⇒
loadcx v k r
_
⇒
todo"call word"

As typed_stack_args//4: the words that travel on the stack, through %rax.

395Fixpoint typed_stack_argscx : ctx ws : listword ls : listlocation : listline ≔
match ws, ls with
Wf_ s :: ws′, l :: ls′
⇒
match l with
⇒
word_reg_loadcx s "a" ++ ins"mov" "q" reg"rax"; memeight × i "rsp"
_
⇒
[ ]
++
typed_stack_argscx ws′ ls′
_, _
⇒
[ ]

As typed_register_args//4.

407Fixpoint typed_register_argscx : ctx ws : listword ls : listlocation : listline ≔
match ws, ls with
Wfk s :: ws′, l :: ls′
⇒
match l with
⇒
[ ]
⇒
word_reg_loadcx s "a" ++ to_xmmk "a" x
++
typed_register_argscx ws′ ls′
_, _
⇒
[ ]

As entry_call//4: the entry registers and the call of a fast entry: of the operand callee, or without one of the function object whose lower is in the aux slot. A buffered return's buffer sits above the pop bytes of stack words.

423Definition entry_callcx : ctx r : protocol callee : optionoperand pop : Z : listline ≔
match r, callee with
Registers, Sometarget
⇒
slot_loadcx KThread "rdi" ++ ins"xor" "l" reg"esi"; reg"esi"; ins0"call" target
Registers, None
⇒
slot_loadcx KThread "rdi" ++ slot_loadcx KAux "rsi" ++ ins"call" "q" indmemfunction_object_fast_entry "rsi"
Buffer_, Sometarget
⇒
slot_loadcx KThread "rsi" ++ ins"lea" "q" mempop "rsp"; reg"rdi"; ins"xor" "l" reg"edx"; reg"edx"; ins0"call" target
Buffer_, None
⇒
slot_loadcx KThread "rsi" ++ slot_loadcx KAux "rdx" ++ ins"lea" "q" mempop "rsp"; reg"rdi"; ins"call" "q" indmemfunction_object_fast_entry "rdx"

As fast_call//4: the arguments, the entry registers and the call, in the fast convention.

445Definition fast_callcx : ctx r : protocol ws : listword callee : optionoperand : listline ≔
let 'ls, ns, _ ≔ typed_locationsws r in
let pop ≔ stack_bytesns in
pop >? 0
→
ins"sub" "q" immpop; reg"rsp"
else
[ ]
++
++
++
entry_callcx r callee pop
++
pop >? 0
→
ins"add" "q" immpop; reg"rsp"
else
[ ]

As reg_slot_stores//3.

456Fixpoint reg_slot_storescx : ctx ks : listkey rs : liststring : listline ≔
match ks, rs with
[ ], _
⇒
[ ]
k :: ks′, r :: rs′
⇒
slot_storecx r k ++ reg_slot_storescx ks′ rs′
_ :: _, [ ]
⇒
todo"result registers"

As buffer_slot_copies//3: each word of a returned buffer into its slot.

465Fixpoint buffer_slot_copiescx : ctx ks : listkey off : Z : listline ≔
match ks with
[ ]
⇒
[ ]
k :: ks′
⇒
ins"mov" "q" memoff "rsp"; reg"rax" :: slot_storecx "rax" k ++ buffer_slot_copiescx ks′ off + eight

As typed_result_gprs//3 and typed_result_xmms//3, over the registers result_registers/2 gives a returned tuple's words. The integer registers are stored first, since a float goes to its slot through %rax.

477Fixpoint typed_result_gprscx : ctx ts : listkey rs : listresult_reg : listline ≔
match ts, rs with
[ ], [ ]
⇒
[ ]
t :: ts′, r :: rs′
⇒
match r with
⇒
⇒
[ ]
++
typed_result_gprscx ts′ rs′
_, _
⇒
todo"result registers"
486Fixpoint typed_result_xmmscx : ctx ts : listkey rs : listresult_reg : listline ≔
match ts, rs with
[ ], [ ]
⇒
[ ]
t :: ts′, r :: rs′
⇒
match r with
⇒
from_xmmk x "a" ++ slot_storecx "rax" t
⇒
[ ]
++
typed_result_xmmscx ts′ rs′
_, _
⇒
todo"result registers"

As typed_result_stores//3, with result_registers/2.

499Definition typed_result_storescx : ctx ks : listclass × key : listline ≔
match result_registersmapfst ks "rdx"; "rcx" "xmm0"; "xmm1" with
Somers
⇒
typed_result_gprscx mapsnd ks rs ++ typed_result_xmmscx mapsnd ks rs
None
⇒
todo"result registers"

As fast_result//3: the exception flag, then the results from their registers or the buffer into their slots.

507Definition fast_resultcx : ctx r : protocol c : channels : listline ≔
let exc ≔ special_labelcx "exc" in
let flag ≔ ins"test" "b" imm1; reg"al"; ins0"jnz" symexc in
match r, c with
⇒
flag ++ from_xmmk "xmm0" "a" ++ slot_storecx "rax" KTmpd
⇒
flag ++ reg_slot_storescx ks "rdx"; "rcx"
⇒
ins"cmp" "b" imm0; mem0 "rsp"; ins0"jne" symexc ++ buffer_slot_copiescx ks eight
Buffer_, _
⇒
todo"buffered result"

As function_check//1: with a pointer in %rax and %rcx, a jump to fail unless it is the address of a function object.

523Definition function_checkfail : string : listline ≔
ins"test" "q" reg"rcx"; reg"rcx"; ins0"jz" symfail; ins"mov" "q" mem−8 "rcx"; reg"rdx"; ins"movabs" "q" immspecial_type_mask; reg"rsi"; ins"and" "q" reg"rdx"; reg"rsi"; ins"movabs" "q" immfunction_bits; reg"rdi"; ins"cmp" "q" reg"rdi"; reg"rsi"; ins0"jne" symfail; ins"movabs" "q" immaux_pointer_mask; reg"rsi"; ins"and" "q" reg"rsi"; reg"rdx"; ins"cmp" "q" reg"rdx"; reg"rax"; ins0"jne" symfail

The generic packet: 32 cells are inline in the thread.

538Definition inline_cells: Z ≔
32
539Definition inline_bytes: Z ≔
256

As cell_stores//2: the argument cell i from %rax and its lower from %rcx, with the thread in the register t: in the inline buffers, or past them in the outline ones, by %rsi.

544Definition cell_storesi : Z t : string : listline ≔
→
ins"mov" "q" reg"rax"; memthread_cc_inline_buffer + eight × i t; ins"mov" "q" reg"rcx"; memthread_cc_inline_aux_buffer + eight × i t
else
let off ≔ eight × i − inline_cells in
ins"mov" "q" memthread_cc_outline_buffer t; reg"rsi"; ins"mov" "q" reg"rax"; memoff "rsi"; ins"mov" "q" memthread_cc_outline_aux_buffer t; reg"rsi"; ins"mov" "q" reg"rcx"; memoff "rsi"

As generic_call_args//3: each argument into the thread's generic argument area.

556Definition generic_call_argcx : ctx c : cell : listline ≔
match c with
Celli k CellValuev lower
⇒
loadcx v k "a"
++
match lower with
⇒
lower_loadcx p "rcx"
⇒
todo"saved lower"
None
⇒
ins"xor" "l" reg"ecx"; reg"ecx"
++
slot_loadcx KThread "rdx" ++ cell_storesi "rdx"
⇒
todo"saved cell"

As outline_ensure//3: a packet of more than the inline bytes needs the thread's outline buffers to hold the rest, before any cell is set.

573Definition outline_ensurecx : ctx size : Z ok : string : listline ≔
size >? inline_bytes
→
slot_loadcx KThread "rdi" ++ ins"cmp" "q" immsize − inline_bytes; memthread_cc_outline_size "rdi"; ins0"jae" symok; ins"mov" "q" immsize − inline_bytes; reg"rsi"; ins0"call" plt"filc_thread_ensure_cc_outline_buffer_slow"; labelok
else
[ ]

As generic_slot_copies//2: a generic return's words, from the thread at %rsi, into their slots.

585Definition generic_slot_copycx : ctx c : cell : listline ≔
match c with
Celli _ CellValueTmpd lower
⇒
ins"mov" "q" memthread_cc_inline_buffer + eight × i "rsi"; reg"rax"
::
slot_storecx "rax" KTmpd
++
match lower with
⇒
ins"mov" "q" memthread_cc_inline_aux_buffer + eight × i "rsi"; reg"rax" :: slot_storecx "rax" KLowerKTmpl
Some_
⇒
todo"result lower"
None
⇒
[ ]
_
⇒
todo"result cell"

As generic_results//3, with rets_check//2: the check that the generic return's size in %rdx is at least need, then the result cells.

603Definition generic_resultscx : ctx need : Z results : listcell retok : string : listline ≔
match results with
[ ]
⇒
need =? 0
→
[ ]
else
todo"generic results"
_
⇒
slot_loadcx KThread "rsi" ++ ins"cmp" "q" immneed; reg"rdx"; ins0"jae" symretok; ins"mov" "q" reg"rdx"; reg"rdi"; ins"mov" "l" immneed; reg"esi"; ins"xor" "l" reg"edx"; reg"edx"; ins0"call" plt"filc_cc_rets_check_failure"; ins0"ud2" [ ]; labelretok ++ flat_mapgeneric_slot_copycx results

As indirect_call//10: a call through a checked function, whose lower is in the aux slot and in %rcx: the fast entry if its signature is the call site's, else the generic entry, with each argument a cell of the thread's packet.

624Definition indirect_callcx : ctx b : name index : string sig : Z r : protocol ws : listword c : channels size : Z cells : listcell need : Z results : listcell : listline ≔
let exc ≔ special_labelcx "exc" in
let generic ≔ local_labelcx b index "generic" in
let done ≔ local_labelcx b index "done" in
ins"movabs" "q" immsig; reg"rsi"; ins"cmp" "q" reg"rsi"; memfunction_object_signature "rcx"; ins0"jne" symgeneric ++ fast_callcx r ws None ++ fast_resultcx r c ++ ins0"jmp" symdone; labelgeneric ++ outline_ensurecx size local_labelcx b index "outline" ++ flat_mapgeneric_call_argcx cells ++ slot_loadcx KThread "rdi" ++ slot_loadcx KAux "rsi" ++ ins"mov" "l" immsize; reg"edx"; ins"call" "q" indmemfunction_object_generic_entry "rsi"; ins"test" "b" imm1; reg"al"; ins0"jnz" symexc ++ generic_resultscx need results local_labelcx b index "retok" ++ labeldone

Actions

650Definition target_operandt : call_target : operand ≔

As the plain getter clause of abi_action//4: the call of a symbol's getter, which gives its address in %rax and %rdx.

658Definition getter_callcx : ctx target : operand d : name : listline ≔
slot_loadcx KThread "rdi" ++ ins"lea" "q" riporigin_labelcx_namecx "c"; reg"rsi"; ins0"call" target; ins"mov" "q" reg"rdx"; reg"rcx" ++ flight_storecx d

As va_arg_load//5: the helper has left the address of the argument's payload in %rax and of its aux word in %rdx; both are read with no safepoint between.

668Definition va_arg_loadcx : ctx b : name index : string k : class d : name : listline ≔
match k with
⇒
ins"mov" "l" mem0 "rax"; reg"eax" :: slot_storecx "rax" KTmpd
⇒
ins"mov" "q" mem0 "rax"; reg"rax" :: slot_storecx "rax" KTmpd
⇒
ins"fld" "t" mem0 "rax" :: x87_popcx d
⇒
let none ≔ local_labelcx b index "va_none" in
let have ≔ local_labelcx b index "va_have" in
ins"xor" "l" reg"ecx"; reg"ecx"; ins"test" "q" reg"rdx"; reg"rdx"; ins0"jz" symnone; ins"mov" "q" mem0 "rdx"; reg"rcx"; ins"test" "b" imm1; reg"cl"; ins0"jz" symhave; ins"and" "q" imm−2; reg"rcx"; ins"mov" "q" mem8 "rcx"; reg"rcx"; labelhave; labelnone; ins"mov" "q" mem0 "rax"; reg"rax" ++ flight_storecx d
_
⇒
todo"va_arg class"

As zero_words//2: n zero words from off(%rbp) up.

692Fixpoint zero_wordsfuel : nat off : Z : listline ≔
match fuel with
O
⇒
[ ]
Sfuel′
⇒
ins"mov" "q" imm0; memoff "rbp" :: zero_wordsfuel′ off + eight

As abi_action//4, for the actions of an instruction. The reference emission copies nothing inline, so a copy's filter and join are empty.

701Definition action_linescx : ctx b : name index : string a : action : listline ≔
match a with
AInvoket r ws
⇒
⇒
⇒
[ ]
ADispatchp sig r ws c size cells need results
⇒
flight_loadcx p ++ function_checkspecial_labelcx "notfn" ++ slot_storecx "rcx" KAux ++ indirect_callcx b index sig r ws c size cells need results
⇒
let getter ≔ getter_symbolname_texts in
let null ≔ local_labelcx b index "weak_null" in
let done ≔ local_labelcx b index "weak_done" in
ins"cmp" "q" imm0; gotpcrelgetter; ins0"je" symnull ++ getter_callcx pltgetter d ++ ins0"jmp" symdone; labelnull; ins"xor" "l" reg"eax"; reg"eax"; ins"xor" "l" reg"ecx"; reg"ecx" ++ flight_storecx d ++ labeldone
⇒
flight_loadcx Tmpva_snapshot ++ loadcx Constoff L "d" ++ ins"add" "q" reg"rdx"; reg"rax" ++ flight_storecx d
AConsumeVak p size d
⇒
flight_loadcx p ++ ins"mov" "q" reg"rax"; reg"rdi"; ins"mov" "q" reg"rcx"; reg"rsi"; ins"mov" "l" immsize; reg"edx"; ins"mov" "l" immsize; reg"ecx"; ins0"call" plt"filc_get_next_ptr_bytes_for_va_arg" ++ va_arg_loadcx b index k d
⇒
match nm_findx cx_localscx with
None
⇒
todo"no local"
Somes
⇒
let words ≔ ls_paddeds / eight in
zero_wordsZ.to_natwords −ls_payloads ++ zero_wordsZ.to_natwords eight − ls_auxs ++ ins"mov" "q" immwords; mem−ls_auxs "rbp"; ins"lea" "q" mem−ls_auxs "rbp"; reg"rax" ++ slot_storecx "rax" KStackAuxx

Instructions

The pointer an access is at.

756Definition access_placea : access : place ≔
match a with
ALoad_ _ _ _ p | AStore_ _ _ p | ALoadPointer_ _ _ p | AStorePointer_ _ p _ | ATouchp
⇒
p

As inst//4: the code of the instruction at index i of the block b.

764Definition inst_linescx : ctx b : name i : Z pi : pinst : listline ≔
let index ≔ decimali in
match pi with
PAbiacts
⇒
flat_mapaction_linescx b index acts
PInstFPlainLetd k o args
⇒
let_linescx b index d k o args
PInstFPlainFlightd o args lower
⇒
flight_linescx d o args lower
⇒
todo"plain instruction"
PInstFFusedCheck_ size r align a
⇒
match access_placea with
⇒
flight_loadcx p ++ access_checkcx mkKindsize rights_writer align ++ raw_accesscx b index a
⇒
todo"heap check at a local"
PInstFFusedCheckLocalx off size r align a
⇒
local_checkcx b index x off mkKindsize rights_writer align ++ local_raw_accesscx b index a
⇒
todo"fused check"
⇒
match access_placea with
⇒
let off ≔ access_offseta in
match a with
_
⇒
loadcx p L "a"
++
off =? 0
→
[ ]
else
ins"add" "q" immoff; reg"rax"
++
raw_accesscx b index a
⇒
todo"reused access at a local"
⇒
todo"call that is not lowered"