674 Commits

Author SHA1 Message Date
5b54e1b7da Merge the tidy: the crossed-pair case is the marker's, and the citations follow the move 2026-09-14 07:30:14 +07:00
9735bcc2d8 The survey numbers, measured 2026-09-14 07:29:17 +07:00
cc6c046ed1 Merge branch 'worktree-agent-a4bfc3fb14f6fdc0c' into dev-loop 2026-09-14 07:25:20 +07:00
38d402e326 The marker's name is a literal in four places, and the note says so 2026-09-14 07:24:54 +07:00
e62b3bfe04 The survey did not move, which is what the dev gate is for 2026-09-14 07:24:31 +07:00
82557df51b The agent's half of the refusal is checked where it actually ships 2026-09-14 07:22:19 +07:00
1f30d9a067 The marker, written up: what it refuses and what it deliberately does not 2026-09-14 07:19:27 +07:00
1795441140 The index names the handoffs from where it sits, not from the root 2026-09-14 07:17:28 +07:00
9dddcac821 MIT, and a note that vendor keeps its own terms 2026-09-14 07:17:02 +07:00
0afa530295 An index for docs/, and a .gitignore that explains itself 2026-09-14 07:16:46 +07:00
96b1bba265 A README that says what this is, with a flan on it 2026-09-14 07:15:31 +07:00
fa83056708 A backend mismatch is refused by the loader, and says so 2026-09-14 07:15:13 +07:00
9d5689ffa2 Every citation of a moved document now resolves from where it is written 2026-09-14 07:12:27 +07:00
eb641cf8eb Move the reports and the history into docs/ 2026-09-14 07:10:57 +07:00
b47f137b05 A plan for the ABI marker, written before the code 2026-09-14 07:10:54 +07:00
c1c1f8ed76 A plan for tidying the root 2026-09-14 07:10:46 +07:00
71495a7fc8 A flan held between two parentheses, which is the whole joke 2026-09-14 07:10:26 +07:00
682cb745ac Merge branch 'worktree-agent-a4f73ab1c6726fdc2' into dev-loop 2026-09-14 06:55:39 +07:00
4c46a56827 Merge branch 'worktree-agent-a123a91f32f4c9779' into dev-loop 2026-09-14 06:55:39 +07:00
ddaebf2516 Merge branch 'worktree-agent-affdbb9fef702b34d' into dev-loop 2026-09-14 06:55:39 +07:00
2b68262249 Merge branch 'worktree-agent-ab7f6288f142b05df' into dev-loop 2026-09-14 06:55:39 +07:00
70e95119e9 Merge branch 'worktree-agent-a03eb07b90913c874' into dev-loop 2026-09-14 06:55:39 +07:00
9486bc0ac0 The reprint header names a signature, not a count, so it is true on every path 2026-09-13 23:44:42 +07:00
a9c5cf0c26 A frame with no line does not get the wrong line
flan..init-globals and the C main shim sit inside the compile unit's range
and have no line-table sequence. The worry is that a debugger picks a row
out of a neighbouring function's sequence and reports a confident wrong
Flan line; it does not. Checked by breaking inside dev-globals.flan's
initialiser: the frame is named from the ELF symbol, the line is honestly
absent, and the unwind out to libc is the .cfi working.

So that handoff item is a gap and not a wrong answer, which is worth the
distinction because the two deserve different urgency.
2026-09-13 23:43:41 +07:00
ae1b113ad4 Re-measured after the rebase onto the arithmetic-condition lane
101 MATCH rather than 99, and neither number is this lane's doing -- that
lane added two probes to spike/x86. Zero DIFFER, zero REFUSED, zero NOX86
on both sides, the skip breakdown unmoved, cells 4/4, dune test exit 0 with
232 checks and no failures.
2026-09-13 23:42:37 +07:00
3eb53d0f85 The measured baselines, and why a survey that says 143 is not a regression 2026-09-13 23:41:52 +07:00
ce72f03a0d The offset the walk never reaches, and a stat that was running sixty times a second 2026-09-13 23:36:03 +07:00
c8464abc18 The handoff, with every number in it measured on this tree
The baseline rows, the twelve-program DWARF sweep re-run against the code
that was actually committed rather than a superseded version of it, the
lldb transcript, the unwind out of flan_bounds_error, and the compile
unit's range checked against nm rather than asserted.
2026-09-13 23:32:35 +07:00
78368811c0 The x86 backend's DWARF is checked by a debugger, not by a transcript
test_acceptance.ml's lldb case is the only part of the suite that says a
person can debug a Flan program: a breakpoint on a Flan name, a backtrace
with .flan files and lines, and locals with their own types. It ran against
the LLVM backend only.

An --x86 arm, with a narrower claim: the breakpoint and the backtrace, and
that the program still prints what it printed. No frame variable, because
x86.ml emits no DW_TAG_variable -- a slot there is a bump-allocated frame
temporary whose lifetime the backend does not model. That gap between the
two backends is now recorded in the place it will be read.

Worth pinning rather than leaving to a handoff, because everything it
exercises is bytes x86.ml wrote by hand -- a line program, a compile unit,
an abbreviation table -- and a wrong byte in any of them is silent.

debug_compile grows an ~x86 flag beside the ~dev one it already had.
2026-09-13 23:32:35 +07:00
c9c23c5079 Call frame information, which is the thing the assembler gets right
The debug-information section added in the last commit is about what GAS
gets wrong against a file with no instructions in it: .loc is flushed when
an instruction is assembled, and this backend assembles none. CFI is the
opposite case and worth recording beside it. Its advances come from frag
positions, so .cfi_def_cfa_offset interleaved with .byte comes out exact --
measured, readelf --debug-dump=frames on a .byte-only function gives the
right advances.

The content is a constant, and that is the header's claim about the frame
model paying for itself. rsp is written exactly twice, so: on entry the CFA
is rsp+8; push rbp makes it rsp+16 with the saved rbp at cfa-16; mov rsp,rbp
moves the rule onto rbp and it stays there for the whole body; after leave
rsp is rbp+8 and the CFA is rsp+8 again. Five directives, three sites --
emit_fn, emit_main and emit_globals_init, which have the same prologue.

emit_main has no closing rule because it has no epilogue: it leaves through
flan_exit and the ud2 after that is unreachable, so the rbp rule holds to
the last byte, which is what a backtrace out of anything main called wants.

gdb did not need this -- its prologue analyser already unwound out of
flan_bounds_error into flan.main with a line number, because push rbp;
mov rbp,rsp; sub rsp,N is the pattern it recognises. It is here because the
description is now stated rather than guessed, and because a break at the
very first byte of a function -- before the push -- now unwinds from a rule
rather than from a heuristic.

Gated on --debug so a release build's assembly stays byte-for-byte what it
was. That is conservative rather than principled: the description is correct
in every build and a release build is where a crash would most want it. What
stops it being unconditional is only that nothing measures the .eh_frame it
would add, and another lane is measuring backend cost right now.
2026-09-13 23:32:35 +07:00
201cd87bc9 Debug information for --x86, written out as bytes
--x86 --debug was refused in build.ml for want of DWARF. It emits it now:
a compile unit, a subprogram per function, and a line table, so gdb breaks
by Flan file and line and a backtrace names Flan source.

The reason it is written as data rather than as .loc directives is the
finding worth carrying forward, and HANDOFF-x86-debug.md leads with it.
GAS builds its line table out of dwarf2_emit_insn, which runs only when an
instruction is assembled, and this backend assembles none -- everything is
a .byte blob. A pending .loc therefore sits until the next .loc and is
flushed at whatever the location counter has reached by then: every row
comes out one statement late and the last statement of every function gets
no row at all. Measured on GAS 2.44, and interposing labels does not help.

So .debug_line is emitted here the way the instructions are. Every row is
a full DW_LNE_set_address on a label rather than an advance_pc with a
computed delta, because a delta would be a difference of two labels inside
a .uleb128 -- a value whose size changes the offsets after it, and whose
failure would look exactly like a DWARF bug.

The .file 1 directive at the top of the assembly is not about our table at
all: without it clang's integrated assembler generates a compile unit of
its own over the .s, whose rows land at the call mnemonics, and those
addresses are inside the functions we already describe. -gdwarf-4 goes
with it so the empty stub it leaves behind parses.

Rows are deduplicated on the byte counter as well as on the position.
lower recurses, so an outer form and the inner one that emits its first
byte both ask for a row at the same address; keeping the first is smaller
and is the better answer, since a debugger takes the last of a run. buf.n
already existed and was written but never read. This is its first reader.

No locals and no types, deliberately. A slot here is a bump-allocated
frame temporary whose offset is known but whose lifetime is not modelled
-- scoped reclaims temporaries and a later expression reuses the bytes --
so a DW_TAG_variable would be right at some addresses and confidently
wrong at others. That is the call build.ml already makes about wasm32's
member offsets.

Verified under gdb against test/programs/debug.flan, and against an LLVM
--debug build of the same program. Identical bar the parameter values,
which is the locals work. Transcript in the handoff.
2026-09-13 23:32:35 +07:00
853bc35be7 A release build stops calling into a registry that is switched off
emit.ml:1918 drops the allocation registry's notes in a release build --
the checker builds a Tast.Rt it cannot know is unwanted, because it does
not know whether this is a dev build. The x86 backend had no counterpart
and emitted the calls for real: correct, since the registry answers
nothing when it is disabled, but one call per container operation into a
function that returns immediately.

The guard is emit.ml's byte for byte, strict > 17 included: bare
flan_dev_reg_note is the runtime's own C entry point and is never a
Tast.Rt, and what check.ml builds is the _vec, _map and _pool wrappers.
emit.ml drops the note before the arguments are walked so that taking the
address of the container does not leave an escaped alloca behind; here the
arguments are not touched until call_rt, so answering () is already early
enough.

Measured, call sites of flan_dev_reg_note in the disassembly:

  vec.flan       46 -> 1     (--dev: 46)
  maps.flan      55 -> 1     (--dev: 55)
  registry.flan  36 -> 1     (--dev: 36)

The one left in each is not emitted code -- it is inside the runtime's own
flan_dev_reg_note_vec. An LLVM release build of vec.flan has the same one,
so the two backends now agree.

HANDOFF-x86-debug.md is the stub for item 6, which is next, and it leads
with the finding that changes that item's plan: .loc does not work against
a backend that emits .byte blobs, so the line table has to be written out
by hand.
2026-09-13 23:32:35 +07:00
69e5a777e7 The two ports' findings, and the one arm in the header check that would close them 2026-09-13 23:32:04 +07:00
4c184e68ce A poem of forty-seven kana, and the one raylib call a Flan string cannot make 2026-09-13 23:28:40 +07:00
acc928a203 The b3 note belongs under the table, not inside it 2026-09-13 23:28:39 +07:00
35c33c7b8b The idiv in b3 is most of the denominator, and the two b2 numbers now agree 2026-09-13 23:28:27 +07:00
219a42ed5b The handoff carries the headline and what was left undone 2026-09-13 23:27:29 +07:00
f9f37e524a A note that the old handoff's environment note is now stale 2026-09-13 23:27:20 +07:00
69129fc29f p2's -O0 build is smaller because nothing unrolled the loop 2026-09-13 23:27:07 +07:00
65eeb09378 The corpus numbers, and the rows they came from 2026-09-13 23:26:48 +07:00
1195e90476 The noise is gone and the reporting half is verified by breaking the test on purpose 2026-09-13 23:25:48 +07:00
3c4ca20fea The robustness fixture says its failure is deliberate, and stops printing a linker's words 2026-09-13 23:24:21 +07:00
fdf7531c37 Nine filters that rewrite the buffer they are handed, and the half of them a headless run can pin 2026-09-13 23:22:37 +07:00
fbaf376281 The linker error in dune test is deliberate, and a plan to stop it looking otherwise 2026-09-13 23:21:42 +07:00
eacf7c489f The arithmetic condition landed without restarts, and why that is a question 2026-09-13 23:20:11 +07:00
c9394a6bcd The mismatch is reachable from flan reload, and the guard does not close it 2026-09-13 23:18:25 +07:00
ed32915501 The two redefinition builders refuse to be crossed 2026-09-13 23:15:40 +07:00
11474ecbda The benchmark table, filled in 2026-09-13 23:15:17 +07:00
f9f476dc41 COST.md, with the benchmarks measured and the corpus table still to come 2026-09-13 23:14:57 +07:00
1933295a70 A pixel format is twenty-four names, not an int 2026-09-13 23:13:49 +07:00