The LLVM cell declaration for a lifted def initialiser, pinned in the IR

Session hands global/<n> to the redefinition when a def is re-evaluated,
and that target is not a sibling — its fparent is the global — so its cell
declaration comes from Emit.redefinition's targets pass, a path no test
compiled: the dev-rerun leg runs on x86 merged, which reaches host cells
through the GOT and never needed the declaration. reload.flan carries a
(def paint i64 7) now and test_reload greps the module text for the cell
extern and the hidden body, which is the idiom the file already uses.
This commit is contained in:
Joseph Ferano 2026-09-20 22:51:12 +07:00
parent a4c6b996ff
commit 801c70bd0d
2 changed files with 23 additions and 0 deletions

View File

@ -27,6 +27,14 @@
;;; question.
(defonce spare i64)
;;; Unused too, and here for the redefinition-module question a [def] adds:
;;; its initialiser is lifted into [global/paint] whatever it is — a literal
;;; included — so re-evaluating the form republishes that function through
;;; its cell, and [global/paint] is a *non-sibling* target (its parent is the
;;; global, not a function in the form). test_reload greps the module's IR
;;; for the cell declaration that publish needs.
(def paint i64 7)
;;; Also unused, and for the same reason: a defconst's value and an enum
;;; member are folded into every call site, so a session has to refuse changing
;;; either. Nothing here reads them, so the checker has no opinion and the

View File

@ -125,6 +125,21 @@ let () =
fail "redefinition's own body is interposable";
if not (has ir2 "@\"flan.cell.helper\" = external global ptr") then
fail "redefinition defines a cell instead of using the host's";
(* A def's lifted initialiser as the target, which is what [Session]'s
[def_inits] hands in when the form is re-evaluated. [global/paint] is
not a sibling its [fparent] is the global it initialises, not a
function in [fns] so its cell declaration comes from the targets
pass in [Emit.redefinition]; without that pass the publish store
names a symbol the module never declared and the IR does not compile.
The x86 side needs no twin: it reaches a host cell through the GOT by
name, declared or not. *)
(let irdef =
Emit.redefinition ~dev:true ~known p1 ~fns:[ "global/paint" ]
in
if not (has irdef "@\"flan.cell.global/paint\" = external global ptr")
then fail "a lifted def initialiser's cell is not declared";
if not (has irdef "define hidden i64 @\"flan.global/paint\"") then
fail "a lifted def initialiser's body is missing or interposable");
(* A name the host has is a symbol; a name it lacks is a registry lookup
cached in a module-local slot. Getting this backwards either fails to
link or silently gives each module its own copy. *)