Fil-C on Nix

Filnix wiki

mbrock/filnix/nanofil

amd64_contract.pl

Audited machine forms for the scalar stack cache. Unknown forms fail, selecting the unchanged implementation, rather than guessing effects. Reads name register families. write(Family,Bits) records partial writes: 32 bits zero-extend, 8/16 preserve the rest. Memory effects include addressing-register reads; flags and control/frame effects are separate. This describes selected instructions, not IR liveness or GC roots. Calls are unconditional cache boundaries; their ABI argument reads are not enumerated. Do not use this as a general call-liveness contract.

useslists
12:- discontiguousinstruction_effects/2
register?Name, ?Family, ?Bitsnondet

Name is the Bits-wide name of the general-purpose register Family (rax, ..., r15, rsp, rbp): register(eax, rax, 32). Concrete names index directly; family and width queries generate the name without searching every family for every operand in a large function.

register
20raxrax64
20eaxrax32
21axrax16
21alrax8
22rcxrcx64
22ecxrcx32
23cxrcx16
23clrcx8
24rdxrdx64
24edxrdx32
25dxrdx16
25dlrdx8
26rbxrbx64
26ebxrbx32
27bxrbx16
27blrbx8
28rsirsi64
28esirsi32
29sirsi16
29silrsi8
30rdirdi64
30edirdi32
31dirdi16
31dilrdi8
32rbprbp64
32ebprbp32
33bprbp16
33bplrbp8
34rsprsp64
34esprsp32
35sprsp16
35splrsp8
36r8r864
36r8dr832
37r8wr816
37r8br88
38r9r964
38r9dr932
39r9wr916
39r9br98
40r10r1064
40r10dr1032
41r10wr1016
41r10br108
42r11r1164
42r11dr1132
43r11wr1116
43r11br118
44r12r1264
44r12dr1232
45r12wr1216
45r12br128
46r13r1364
46r13dr1332
47r13wr1316
47r13br138
48r14r1464
48r14dr1432
49r14wr1416
49r14br148
50r15r1564
50r15dr1532
51r15wr1516
51r15br158
52xmm0xmm0128
52xmm1xmm1128
53xmm2xmm2128
53xmm3xmm3128
54xmm4xmm4128
54xmm5xmm5128
55xmm6xmm6128
55xmm7xmm7128
width
57b8
57w16
57l32
57q64
58expressionE ←
integerE
!
59expressionE ←
atomE
!
60expressionA + B ←
61addressmemD, B, B ←
integerD
registerB, B, 64
62addressmemD, B, I, B, I ←
integerD
registerB, B, 64
registerI, I, 64
63addressripE, [] ←
64addressgotpcrelS, [] ←
atomS
explicit_registers+Line, -Familiesdet

Families are the register families Line's operands name, addressing registers included, with repeats; [] for a label or directive.

70explicit_registersins_, _, Os, Rs ←
!
findallR,
memberO, Os
,
Rs
72explicit_registers_, []
operand_register+Operand, -Familynondet

Operand names the register Family: as a register, as a base or index of a memory operand, or under an indirection.

77operand_registerregN, F ←
registerN, F, _
78operand_registerO, R ←
addressO, Rs
memberR, Rs
79operand_registerindO, R ←
81sourceregR, W, F, [] ←
registerR, F, W
82sourceimmE, _, [], [] ←
83sourceM, W, Rs, readM, N ←
addressM, Rs
N is W//8
84destinationregR, W, [], writeF, W, [] ←
registerR, F, W
85destinationM, W, Rs, [], writeM, N ←
addressM, Rs
N is W//8

x86 does not admit a memory-to-memory two-operand instruction.

87not_two_memoryA, B ←
¬
instruction_effects+Line, -Effectsemidet

Effect is effect(Reads, Writes, Flags, Memory, Flow) for the audited asm.pl line Line: the register families it reads (addressing registers included), its writes write(Family, Bits) (32 bits zero-extend, 8 and 16 preserve the rest), its effect on the flags (preserve among them), its memory reads and writes read(M, Bytes) and write(M, Bytes), and its control or frame effect (next for a line that falls through). Fails for a form not audited here, so a caller keeps the unchanged implementation rather than guessing its effects.

99instruction_effectsinsmov, S, A, B, effectRs, Ws, preserve, Ms, next ←
widthS, W
sourceA, W, R1, M1
destinationB, W, R2, Ws, M2
appendR1, R2, Rs
appendM1, M2, Ms
102instruction_effectsinsmovabs, q, immN, regR, effect[], writeF, 64, preserve, [], next ←
integerN
registerR, F, 64
105instruction_effectsinsOp, S, A, regR, effectRs, writeF, W, preserve, Ms, next ←
extensionOp, From
widthS, W
W > From
sourceA, From, Rs, Ms
A ≠ imm_
registerR, F, W
108instruction_effectsinslea, q, M, regR, effectRs, writeF, 64, preserve, [], next ←
addressM, Rs
registerR, F, 64

leal computes the 64-bit address and writes its low 32 bits, zero-extended, like any 32-bit write.

112instruction_effectsinslea, l, M, regR, effectRs, writeF, 32, preserve, [], next ←
addressM, Rs
registerR, F, 32
114instruction_effectsinsOp, S, A, B, effectRs, Ws, write, Ms, next ←
memberchkOp, add, sub, and, or, xor, imul, btc
widthS, W
memberchkOp, imul, btc
→
W ≥ 16
B = reg_
else
true
sourceA, W, R1, M1
sourceB, W, R2, M2
B ≠ imm_
destinationB, W, _, Ws, M3
appendR1, R2, Rs
appendM1, M2, M3, Ms
120instruction_effectsinsOp, S, A, B, effectRs, [], write, Ms, next ←
memberchkOp, cmp, test
widthS, W
sourceA, W, R1, M1
sourceB, W, R2, M2
B ≠ imm_
appendR1, R2, Rs
appendM1, M2, Ms
124instruction_effectsinsneg, S, A, effectRs, Ws, write, Ms, next ←
widthS, W
sourceA, W, Rs, M1
destinationA, W, _, Ws, M2
appendM1, M2, Ms
127instruction_effectsinsOp, S, Count, A, effectRs, Ws, read_write, Ms, next ←
memberchkOp, shl, shr, sar
widthS, W
shift_countCount, R1
sourceA, W, R2, M1
destinationA, W, _, Ws, M2
appendR1, R2, Rs
appendM1, M2, Ms
131instruction_effectsinsOp, none, regR, effectF, writeF, 8, read, [], next ←
atom_concatset, CC, Op
registerR, F, 8
133instruction_effectsinsOp, q, regA, regB, effectFA, FB, writeFB, 64, read, [], next ←
atom_concatcmov, CC, Op
registerA, FA, 64
registerB, FB, 64
135instruction_effectsinscltd, none, [], effectrax, writerdx, 32, preserve, [], next
136instruction_effectsinscqto, none, [], effectrax, writerdx, 64, preserve, [], next
137instruction_effectsinsOp, S, A, effectrax, rdx|Rs, Ws, write, Ms, next ←
memberchkOp, div, idiv
widthS, W
memberchkW, 32, 64
sourceA, W, Rs, Ms
A ≠ imm_
Ws = writerax, W, writerdx, W
extension
141movzb8
141movsb8
142movzw16
142movsw16
142movsl32
143shift_countregcl, rcx
144shift_countimmN, [] ←
integerN
N ≥ 0
N ≤ 255
145conditionCC ←
memberchkCC, e, ne, z, nz, b, be, a, ae, l, le, g, ge, s, ns, p, np

SSE forms use full-family symbolic outputs: the cache never changes one, so the validator need not emulate floating arithmetic or lanes.

149instruction_effectsinsOp, none, A, B, effectRs, Ws, preserve, Ms, next ←
sse_transferA, B, W, Rs, Ws, Ms
151instruction_effectsinsOp, S, regA, regB, effectA, B, writeB, 128, preserve, [], next ←
memberchkOp, add, sub, mul, div
memberchkS, ss, sd
registerA, A, 128
registerB, B, 128
155instruction_effectsinsOp, none, regA, regB, effectA, B, [], write, [], next ←
memberchkOp, ucomiss, ucomisd
registerA, A, 128
registerB, B, 128
157instruction_effectsinsOp, none, regA, regB, effectA, B, writeB, 128, preserve, [], next ←
memberchkOp, cvtss2sd, cvtsd2ss
registerA, A, 128
registerB, B, 128
160instruction_effectsinsOp, S, regA, regB, effectA, writeF, W, preserve, [], next ←
memberchkOp, cvttss2si, cvttsd2si
widthS, W
memberchkW, 32, 64
registerA, A, 128
registerB, F, W
164instruction_effectsinsOp, S, regA, regB, effectF, B, writeB, 128, preserve, [], next ←
memberchkOp, cvtsi2ss, cvtsi2sd
widthS, W
memberchkW, 32, 64
registerA, F, W
registerB, B, 128
168sse_movemovd, 32
168sse_movemovq, 64
169sse_transferregA, regB, W, F, writeB, 128, [] ←
registerA, F, W
registerB, B, 128
171sse_transferregA, regB, W, A, writeF, W, [] ←
registerA, A, 128
registerB, F, W
174instruction_effectsinsjmp, none, T, effectRs, [], preserve, Ms, branch ←
targetT, Rs, Ms
176instruction_effectsinsOp, none, T, effect[], [], read, [], branch ←
atom_concatj, CC, Op
targetT, [], []
178instruction_effectsinscall, S, T, effectrsp|Rs, Ws, write, Ms, call ←
memberchkS, none, q
targetT, Rs, M
findallwriteR, W, caller_clobberR, W, Ws
appendM, read_writeruntime, unknown, Ms
182instruction_effectsinspush, q, regR, effectF, rsp, writersp, 64, preserve, writestack, 8, frame ←
registerR, F, 64
185instruction_effectsinspop, q, regR, effectrsp, writeF, 64, writersp, 64, preserve, readstack, 8, frame ←
registerR, F, 64
188instruction_effectsinsleave, none, [], effectrbp, writerbp, 64, writersp, 64, preserve, readstack, 8, frame
190instruction_effectsinsret, none, [], effectrsp, writersp, 64, preserve, readstack, 8, terminal
192instruction_effectsinsud2, none, [], effect[], [], preserve, [], terminal

A fence orders memory; it reads and writes no register or frame slot.

194instruction_effectsinsmfence, none, [], effect[], [], preserve, [], next

lock cmpxchg R, M compares %rax's low W bits with M; equal, it writes R to M, else M to them. It reads rax, R and M's addressing registers, reads and writes M (the write happens either way), and defines the flags. At 32 bits a failure zero-extends rax and a success leaves it, so 32 and 64 record a whole write of an unknown value; 8 and 16 preserve the rest either way. A locked access is also a full fence.

201instruction_effectsins'lock cmpxchg', S, regR, M, effectrax, F|Rs, writerax, WA, write, readM, N, writeM, N, next ←
widthS, W
registerR, F, W
addressM, Rs
N is W//8
W ≥ 32
→
WA = 64
else
WA = W

A fixed-register asm line (docs/asm-fixed.md) is not an ins/3, so the register checker treats it as a region boundary. Its writes are 32 bits; cpuid's line saves rbx in rsi and brings its b result out in edi, so rbx is preserved. None of them changes the flags.

209instruction_effectsasm_fixedcpuid, effectrax, rcx, writerax, 32, writercx, 32, writerdx, 32, writersi, 64, writerdi, 32, preserve, [], next
212instruction_effectsasm_fixedxgetbv, effectrcx, writerax, 32, writerdx, 32, preserve, [], next
213instruction_effectsasm_fixedrdtsc, effect[], writerax, 32, writerdx, 32, preserve, [], next
214instruction_effectsasm_fixedrdtscp, effect[], writerax, 32, writercx, 32, writerdx, 32, preserve, [], next
216instruction_effectsasm_fixedM, effect[], [], preserve, [], next ←
memberchkM, lfence, sfence, pause
218instruction_effectslabelS, effect[], [], preserve, [], label ←
atomS
219instruction_effectsD, effect[], [], preserve, [], directive ←
221targetsymS, [], [] ←
atomS
222targetpltS, [], [] ←
atomS
223targetindO, Rs, Ms ←
sourceO, 64, Rs, Ms
O ≠ imm_
224caller_clobberR, 64 ←
memberR, rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11, rsp
225caller_clobberR, 128 ←
registerR, R, 128
226directivesectiontext
227directivep2alignN ←
integerN
228directivegloblS ←
atomS
229directivetypeS, function ←
atomS
230directivesizeS ←
atomS