compiler: a test program may hold a phase handler - the test runner called @rt_init whenever the program had systems, and a handler alone makes none (LLVM: use of undefined value '@rt_init'); it calls it only when it exists, as an entry program's main does; a ludic test case with a handler (added, not run); reseeded, bootstrap-cfree fixpoint holds

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-30 00:34:34 +03:00
parent eaeadc6a52
commit 9a0011c38f
5 changed files with 3187 additions and 3150 deletions

View file

@ -0,0 +1,6 @@
bump: patch
type: fix
**A test program may hold a phase handler.** A program with `test` blocks and a `handler ... phase`
(its own, or one a module it imports declares) failed to compile with LLVM's "use of undefined value
'@rt_init'": the test runner called the runtime's `rt_init` whenever the program had systems, and a
handler alone makes none. It now calls it only when it exists, as an `entry` program's `main` does.

View file

@ -161,7 +161,7 @@ function emit_test_runner() -> void {
emit(`{lrun0}:\n`) emit(`{lrun0}:\n`)
emit(" call void @L_init_runtime()\n") emit(" call void @L_init_runtime()\n")
if has_ecs() { emit(" call void @L_grow(i32 1)\n") } if has_ecs() { emit(" call void @L_grow(i32 1)\n") }
if has_ecs() { emit(" call void @rt_init()\n") } if (find_fn("rt_init") != null) { emit(" call void " + fn_sym("rt_init") + "()\n") } # as emit_main: a handler alone makes no rt_init
emit(" call void @L_init_globals()\n") emit(" call void @L_init_globals()\n")
i = 0 i = 0
while i < len(g_tests) { while i < len(g_tests) {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -786,6 +786,11 @@ function test_dir_case() -> void {
if not shq(`cd {work} && {root}/bin/ludic test pk/tests -j 2 > out3.txt 2>&1`) { bad2(lbl2, capture(`cat {work}/out3.txt`)); return } if not shq(`cd {work} && {root}/bin/ludic test pk/tests -j 2 > out3.txt 2>&1`) { bad2(lbl2, capture(`cat {work}/out3.txt`)); return }
if not shq(`grep -q 'pk/tests/scratch.ludic (2 tests)' {work}/out3.txt`) { bad2(lbl2, capture(`cat {work}/out3.txt`)); return } if not shq(`grep -q 'pk/tests/scratch.ludic (2 tests)' {work}/out3.txt`) { bad2(lbl2, capture(`cat {work}/out3.txt`)); return }
ok(lbl2) ok(lbl2)
# a test program holding a phase handler: the runner boots no frame loop and calls no rt_init it lacks
let lbl3 = "ludic test: a program with a phase handler compiles and runs its tests"
write_file(`{work}/pk/tests/handler.ludic`, "program D {\n handler K phase Input { }\n test \"d\" {\n expect_eq(1, 1)\n }\n}\n")
if not shq(`cd {work} && {root}/bin/ludic test pk/tests/handler.ludic > out4.txt 2>&1`) { bad2(lbl3, capture(`cat {work}/out4.txt`)); return }
ok(lbl3)
} }
# package.ludic drives the CLI: `entry` (or the one program under src/) is what # package.ludic drives the CLI: `entry` (or the one program under src/) is what