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.
This commit is contained in:
Joseph Ferano 2026-09-13 23:30:42 +07:00
parent c9c23c5079
commit 78368811c0

View File

@ -3105,11 +3105,12 @@ ERR@7 unexpected token: not the kind the caller was reading
else print_endline "acceptance: the DWARF verifier cases skipped (no opt)";
(* A debug build and a release build must still be the same program. *)
let debug_compile ?(dev = false) path =
let debug_compile ?(dev = false) ?(x86 = false) path =
let exe =
Filename.concat scratch
("flan-dbg-" ^ Filename.remove_extension (Filename.basename path)
^ if dev then "-dev" else "")
^ (if dev then "-dev" else "")
^ if x86 then "-x86" else "")
in
let l = Load.program ~file:path (Reader.read_file path) in
let p = Check.program l.Load.decls in
@ -3125,7 +3126,7 @@ ERR@7 unexpected token: not the kind the caller was reading
in
let p, csrcs, lflags = Reach.link ~dev l p in
ignore
(Build.executable ~opts:{ Build.default with debug = true; dev }
(Build.executable ~opts:{ Build.default with debug = true; dev; x86 }
~csrcs ~lflags ~pnames p ~out:exe);
exe
in
@ -3258,7 +3259,47 @@ ERR@7 unexpected token: not the kind the caller was reading
n;
print_endline text
end)
[ "flan.tick"; "flan.main at debug.flan:" ]
[ "flan.tick"; "flan.main at debug.flan:" ];
(* And the same program through the hand-written x86-64 backend, which
emits its own DWARF rather than handing LLVM metadata.
The claim is narrower than the one above and deliberately so: a
breakpoint resolved on a Flan name, and a backtrace whose frames name
a .flan file and a line. 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, and a name
attached to an offset something else reuses would be a lie. That is
the gap between the two backends and this is where it is recorded.
Worth pinning rather than leaving to a handoff's transcript, because
everything this exercises is bytes [x86.ml] wrote by hand -- a line
program, a compile unit and an abbreviation table -- and a wrong byte
in any of them is silent. The program still printing the same four
lines is checked too, since debug information that breaks the build
it describes has helped nobody. *)
let exe = debug_compile ~x86:true "programs/debug.flan" in
let code, text = run exe None in
if text <> expected || code <> 0 then begin
incr failures;
Printf.printf
"FAIL an --x86 --debug build of debug.flan runs the same\n\
\ got: %S (exit %d)\n wanted: %S\n"
text code expected
end;
let _, text =
lldb_run exe [ "breakpoint set --name flan.tick"; "run"; "bt" ]
in
List.iter
(fun n ->
if not (contains text n) then begin
incr failures;
Printf.printf
"FAIL lldb: --x86 --debug names Flan files and lines\n\
\ wanted %S\n" n;
print_endline text
end)
[ "flan.tick"; "at debug.flan:"; "flan.main at debug.flan:" ]
end
else print_endline "acceptance: lldb cases skipped (no lldb on PATH)";