-O0 follows the source and -O2 need not, and what SBCL gets for owning its code

This commit is contained in:
Joseph Ferano 2026-09-12 13:41:34 +07:00
parent b97a3dbbf1
commit f1223cde2e

View File

@ -47,16 +47,26 @@ So the options are genuinely three, and none is free:
## 2. Annotating the IR and the disassembly with the source
The compiler should interleave the originating Flan expression into both the emitted LLVM IR and the disassembly
listing.
**The IR half is nearly free and should just be done.** `emit.ml` writes `.ll` as text, so a comment costs nothing and
cannot break anything, and every typed IR node already carries a `Loc.t`.
What already exists: `emit.ml` writes `.ll` as text, so a comment costs nothing and cannot break anything. Every typed IR
node carries a `Loc.t`. DWARF is emitted under `--debug`, with a line table naming the `.flan` file, and the disassembly
listing already rebases addresses and annotates cells, calls and branch targets. So both halves have the information
already; what is missing is the interleaving.
**The disassembly half, with the optimisation question settled.** `objdump` already interleaves source into a listing
when DWARF is present (`-S`), and the daemon already shells out to objdump — so the `-O0` case is close to a flag.
The IR half is nearly free. The disassembly half is more interesting and more valuable — it is what would let you see
what one line of Flan actually costs, including the indirection cell a dev build puts on every cross-function call.
Settled in conversation: **`-O0` is expected to follow the source and gets the full annotation; `-O2` is not expected to
and gets either nothing or whatever best-effort mapping falls out.** That removes what looked like the blocking
question. `--debug` forcing `-O0` is therefore fine and does not need decoupling for this.
**How SBCL does it, since it came up.** SBCL does *not* shell out. `sb-disassem` is its own disassembler, written in
Lisp, that knows the instruction encodings directly. What that buys is annotation from the inside: it labels constants
the function references, names the functions being called, marks entry points, and shows its own calling conventions —
because it compiled the code object and still holds the metadata.
The relevant observation is that **this project is closer to SBCL's position than the objdump route suggests.** The
daemon owns the build and holds the metadata too; it simply is not feeding much of it into the listing yet. Naming the
function behind an indirection cell, or a constant by its source name, needs no instruction decoder — only the
information the daemon already has. Writing a disassembler is not the interesting part and should stay off the table;
richer annotation of objdump's output is cheap and is where SBCL's advantage actually comes from.
## 3. `def`, `defvar`, `defconst`