# 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 1. **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 existing `dwline` hook is the annotation point — every expression already passes through it carrying `e.Tast.loc`. 2. **A frame map per function.** `-0x20(%rbp)` means nothing without a key, and the key exists: `fn.snames` says what the source called each slot, `f.slots` says where each one landed, and `xfer_off` / `sret_off` / `retval` name the three the compiler adds. This is the single biggest difference from an LLVM listing. 3. **The calling convention, stated per function** — which register each argument arrived in, where the transfer channel is, whether there is a hidden `sret`. 4. **The bookkeeping named**: the post-call guard, the bounds-check triple, the indirection cell load in a `--dev` build, `rep movsb` block 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.