Skip to content

jit: the JIT runtime entry points get their own file; three AOT emitter fixes - #3999

Merged
borisbat merged 3 commits into
masterfrom
aleksisch/jit-runtime-split
Sep 11, 2026
Merged

jit: the JIT runtime entry points get their own file; three AOT emitter fixes#3999
borisbat merged 3 commits into
masterfrom
aleksisch/jit-runtime-split

Conversation

@aleksisch

@aleksisch aleksisch commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Two commits lifted out of #3927 so that PR carries only its own feature.

jit: the runtime entry points JIT code calls move to their own file

src/builtin/module_jit.cpp held two unrelated things: the das module (bindings, linker invocation, emit orchestration) and the set of extern "C" symbols jitted and LLVM-AOT-emitted code links against. The second set moves to src/builtin/jit_runtime.cpp, which registers no module - 2020 lines become 759 + 1265.

A pure move: sorting both files' lines and diffing against the original shows no line removed and no line changed, only the new file's include block, its namespace das { wrapper and the fio forward declarations it repeats.

src/builtin/jit_runtime.h carries the 48 address takers the module binds, so they leave include/daScript/simulate/aot_builtin_jit.h - the header Module_Jit::aotRequire injects into generated AOT C++. They are codegen-time queries that AOT output never calls: modules/dasLLVM/daslib/*.das is outside the AOT glob, and the one generated .cpp that carries the include uses nothing from it. What stays in the public header is the instrumentation API a das program can legitimately call and have AOT-compiled.

The new header opens with the rule that keeps it short: an entry point here is a call boundary the optimizer cannot see through, so an operation that can be expressed as LLVM IR should be, and a runtime entry point is for what cannot.

aot: the C++ emitter qualifies a name, types a lane, and keeps a field's module

Three independent AOT emitter defects:

  • a member pointer emitted unqualified, which fails to compile when the member's class is not the enclosing one;
  • a vector lane extract emitted untyped, so v_extract_*i fed a signed/unsigned comparison and tripped -Wsign-compare;
  • a struct field's module dropped from the used-module walk, so a context could reference a module it never required.

The name table is also cleared before each emission, which a second emission in one process needs.

@aleksisch
aleksisch requested a review from borisbat September 11, 2026 12:29
@aleksisch
aleksisch force-pushed the aleksisch/jit-runtime-split branch from 45821e1 to f17ce67 Compare September 11, 2026 12:34
src/builtin/jit_runtime.cpp is not a module - it is the set of extern "C"
symbols jitted and LLVM-AOT-emitted code links against, plus the address
takers the jit module binds. module_jit.cpp keeps the das module: bindings,
linker invocation and emit orchestration.
@aleksisch
aleksisch force-pushed the aleksisch/jit-runtime-split branch 3 times, most recently from 779e500 to c90c578 Compare September 11, 2026 12:53
… field's module

A member-pointer expression spelled its structure with the module's own name rather
than aotModuleName, so a namespaced module - every standalone context - emitted
`&Node::next` against an undeclared Node. A raw `?` in an emitted literal read as a
trigraph. dumpAnnotationInfo clears its name table before writing rather than after.

A used structure keeps its field types' modules alive: a handled field is the only
thing reaching the module that declares it, and dropping that module dropped its
aot_require include. A standalone context emits its own module's structures whether
or not code reaches them, so an unreferenced one is walked too.
@aleksisch
aleksisch force-pushed the aleksisch/jit-runtime-split branch from c90c578 to 458ba4c Compare September 11, 2026 13:28
`daslang -aot script.das out.cpp -aot-macros` core dumped whenever the module graph
carried a dasbind [extern], which covers every dasLLVM binding:

    Should be unreachable. We handled it in transformCall. Failed on: c_strlen.

-aot-macros sets export_all, which force-marks every function of every module and skips
removeUnusedSymbols, so an [extern] declaration - which has no body - reached simulate.
Simulating has to succeed there, so the annotation answers a node that throws if anything
actually calls it: transformCall rewrites every CALL site, so only an address-taken extern
reaches the body, and an empty one would answer uninitialized stack.

That placeholder is no more compilable than it is runnable, so the extern asks for no JIT
the way it already asks for no AOT - taking its address otherwise walks the JIT emitter
into a declaration it cannot type.
@aleksisch
aleksisch force-pushed the aleksisch/jit-runtime-split branch from 458ba4c to f79bacf Compare September 11, 2026 14:32
@borisbat
borisbat merged commit 920e5a9 into master Sep 11, 2026
34 checks passed
@borisbat
borisbat deleted the aleksisch/jit-runtime-split branch September 11, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants