2.9 KiB
Handoff — flan emit --x86 annotated, so its output can be read
Branch dev-loop, from f772162. Stub: written before the code, per the working rules. Kept updated as
the work lands.
The x86 backend exists so that a dev build is ours end to end and so that the editor can be told why each
instruction is there. Until now flan emit --x86 printed a three-line file header and then nothing but
.byte blobs: no source form, no frame key, no statement of the calling convention, nothing naming the
bookkeeping. Reading it meant as plus objdump, and even that only answers what, never why.
What is being built
- A comment per Flan form, carrying the form's own source text and its
file:line:col, above the run of bytes that form produced.lower's existingdwlinehook is the annotation point — every expression already passes through it carryinge.Tast.loc. - A frame map per function.
-0x20(%rbp)means nothing without a key, and the key exists:fn.snamessays what the source called each slot,f.slotssays where each one landed, andxfer_off/sret_off/retvalname the three the compiler adds. This is the single biggest difference from an LLVM listing. - The calling convention, stated per function — which register each argument arrived in, where the
transfer channel is, whether there is a hidden
sret. - The bookkeeping named: the post-call guard, the bounds-check triple, the indirection cell load in a
--devbuild,rep movsbblock copies, the prologue and the epilogue.
The two decisions
Annotation is always on for flan emit --x86 and always off for a --x86 build. flan emit exists to be
read by a person; there is no reason to make a reader ask for the thing the command is for. A build's .s is
a temporary file handed straight to clang and read by nobody, so leaving it exactly as it was keeps
survey.sh's 103 MATCH a statement about the same text it has always been. --no-annotate is accepted by
emit --x86 for the one consumer that wants the old spelling, which is the byte-identity check below.
None of this belongs to the LLVM path. flan emit already prints IR that names its values, carries
!dbg on every instruction and !DILocalVariable on every slot. The problem being fixed here is one this
backend has and LLVM does not.
Byte identity
Annotation must not change one byte of emitted code. Comments and the splitting of one .byte directive into
several are both invisible to the assembler, but "invisible" is a claim to be measured rather than asserted:
for every program in the corpus, emit both ways, assemble both, and compare each section's bytes.
survey.sh at 103 MATCH / 0 DIFFER / 0 REFUSED and dune test are the regression check on the edits to
buf and lower — they say the backend still compiles what it compiled — and the section comparison is the
check on annotation itself.
Status
Stub. Nothing below this line has landed yet.