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.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%