Both comments predated the marker, and now neither does

This commit is contained in:
Joseph Ferano 2026-09-14 07:57:41 +07:00
parent 64e4f6cc7e
commit 0251cf4aaa

View File

@ -744,18 +744,20 @@ let executable ?(opts = default) ?(csrcs = []) ?(lflags = []) ?(pnames = [])
by this backend and the module that would redefine through them arrives
with the lane that writes it.
That lane inherits one thing this comment should say out loud rather than
leave for it to find. [x86.ml]'s header licenses its own calling
convention on the grounds that a dev build is compiled entirely by it and
a release build entirely by LLVM, so the two never meet in one process.
Publishing a cell an LLVM-built module can store into is the first thing
that could make that false: the two conventions agree on scalars and
disagree on every aggregate, so an [Emit.redefinition] module dlopened
into an [--x86] host would be correct until the first redefined function
took or returned a struct. Nothing in the toolchain does that today
[flan reload] and [flan dev] both build host and module through LLVM
and the fix when something does is to emit the module through this
backend too, not to grow a classifier. *)
[X86.redefinition] is that lane, and it has landed, so the paragraph this
comment used to end with that no counterpart existed is no longer
true. What remains true is why it had to be written here rather than
borrowed from LLVM. [x86.ml]'s header licenses its own calling convention
on the grounds that a dev build is compiled entirely by it and a release
build entirely by LLVM, so the two never meet in one process. Publishing
a cell an LLVM-built module can store into is the first thing that could
make that false: the two conventions agree on scalars and disagree on
every aggregate, so an [Emit.redefinition] module dlopened into an
[--x86] host is correct until the first redefined function takes or
returns a struct. That pair is now refused at [dlopen] by a marker symbol
each backend defines and each backend's module references see [shared]
below rather than left to die at the call. The answer was to emit the
module through this backend too, and never to grow a classifier. *)
(* [--debug] used to be in this list too. It is not any more: [x86.ml] emits
a compile unit, a subprogram per function and a line table, all written
out as bytes because [.loc] cannot work against a file whose instructions
@ -911,12 +913,17 @@ let shared ?(opts = default) ~ir ~out () : timing =
than it is is worse than none. It catches a caller holding one option
record and reaching for the wrong builder. It does not catch a caller
holding two and picking the wrong one the crossed pair that was measured
segfaulting passes this check and still segfaults, because it hands an
LLVM record to the LLVM builder and simply loads the result into an x86
host. [flan reload] is precisely that caller. The complete answer is a
marker symbol the host defines and a module references, so the loader
refuses the pair at dlopen rather than the processor refusing it at a
call. See docs/handoffs/HANDOFF-x86-aggregates.md. *)
segfaulting passes this check, because it hands an LLVM record to the LLVM
builder and simply loads the result into an x86 host. [flan reload] is
precisely that caller, and it is why this guard was never the whole
answer. The whole answer is the marker symbol: a dev build defines
[flan.abi.x86] or [flan.abi.llvm] according to which backend emitted it,
each backend's redefinition module holds a pointer to its own, and the
loader has to resolve that pointer while it maps the object so a crossed
pair is refused at [dlopen], naming both backends, before any new body
runs. That landed; this check is the cheap first line rather than the only
one. See docs/handoffs/HANDOFF-x86-aggregates.md and
docs/handoffs/HANDOFF-x86-abi-marker.md. *)
if opts.x86 then
failwith
"--x86: Build.shared is the LLVM redefinition path, and an --x86 host \