edn.flan crashed by jumping into .rodata, several statements after the
mistake, and the assembly at the jump read correctly. Item 15 said this
is how hand-encoding fails, and it is: the crash and the cause were in
different functions.
The cause is one line of design. A form whose value is thrown away was
handed the sink, and the sink was spelled as an address — rbp+0. That is
the saved rbp, and rbp+8 is the return address, so a non-void form in
statement position stored its value straight over both. A 16-byte slice
did it in one rep movsb.
The sink is now compared by identity and never used as an address:
anything with a value that is handed it gets a frame temporary instead,
reclaimed immediately. The point is not the temporary, it is that the
store has somewhere legal to go.
edn.flan matches the LLVM build now — 60 lines of a hand-written EDN
reader, unions, options, nested collections and all.