dasLLVM: derive JIT extern function types from a das signature - #3550
Conversation
a57888e to
26f88d9
Compare
26f88d9 to
807beaf
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors dasLLVM’s LLVM JIT extern registration to derive LLVM function/struct types from daScript signatures, reducing duplicated hand-written LLVM type spelling and lowering the risk of silent JIT miscompiles from mismatched arg counts or scalar widths.
Changes:
- Added a new compile-time DSL module (
llvm_dsl.das) providingjit_fn_type(...)andjit_struct_type(...)call macros. - Introduced
jit_add_extern(...)helpers inllvm_jit_common.dasto consolidate extern declaration, global mapping, and attribute application. - Updated
llvm_jit_common.dasto use signature-derived types for the canonical extern set and tuple-derived struct layouts.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| modules/dasLLVM/daslib/llvm_jit_common.das | Replaces hand-spelled LLVM extern signatures with jit_fn_type + jit_add_extern, and uses jit_struct_type for several runtime-mirror structs. |
| modules/dasLLVM/daslib/llvm_dsl.das | New compile-time call-macro helpers for building LLVM function/struct types from daScript signatures/types. |
| modules/dasLLVM/.das_module | Registers llvm_dsl so it’s available as part of the dasLLVM module set. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| require daslib/ast_boost | ||
| require daslib/macro_boost | ||
| require daslib/templates_boost |
There was a problem hiding this comment.
apply_qmacro comes from it
| // argAttr: (attribute, argument-indices) — e.g. (nocapture, [0, 1, 2, 3]) or (nocapture, [1]). | ||
| def public jit_add_extern(name : string; typ : LLVMTypeRef; fnAddr : void?; attrs : LLVMOpaqueAttributeRef? []; argAttr : tuple<LLVMOpaqueAttributeRef?; array<int>>) { | ||
| var f = jit_add_extern(name, typ, fnAddr, attrs) | ||
| for (i in argAttr._1) { | ||
| LLVMAddAttributeToFunctionArgument(f, uint(i), argAttr._0) | ||
| } | ||
| return f | ||
| } |
There was a problem hiding this comment.
Yes, it's known limitation. Let's not complicate unless it is needed.
In future possible solution is to add overload that will take array<(array, int)>, and current one will cimply redirect.
31c0a8f to
c4cbf06
Compare
New module llvm_dsl with two compile-time helpers:
- jit_fn_type(signature): derive an LLVM function type from a das
signature — an inline $(args):ret{} block or @@Stub.
- jit_struct_type(type<tuple<...>>): derive an LLVM struct type mirroring
a C++ layout from a (named) tuple's element types.
Plus jit_add_extern in llvm_jit_common (add + global mapping + function
attrs + optional per-arg attrs as (attribute, indices)).
LLVM 22 uses opaque pointers, so every pointer lowers to `ptr` — the das
signature fully determines the type and the emitted IR is byte-identical
to the hand-written declarations. Struct forms cover only fixed-layout
mirrors; the element-typed data pointer in Array/Table is a no-op under
opaque pointers, and the explicit pad slots stay explicit tuple fields.
Converted:
- llvm_jit_common: all ~38 extern registrations, the 7 build_jit_types
struct types, table_header, and the Array/Table struct types.
- llvm_jit: line_info, the 7 RTTI type builders (TypeInfo/VarInfo/
StructInfo/EnumValueInfo/AnnotationArgumentInfo/AnnotationInfo/EnumInfo),
and the fileinfo function types.
Behavior unchanged; JIT test suite green (11790 pass).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
c4cbf06 to
a409dee
Compare
Newer @ast-grep/cli deprecated the `sg` alias and prints a "WARNING: `sg` is deprecated" banner into the captured --json output, which corrupts the parse in cpp_grep_usage / cpp_find_symbol / cpp_outline (the 21 'Failed to parse ast-grep output: invalid character =' failures in run_utils_tests). Prefer the canonical `ast-grep` binary (ships in the same package, emits clean JSON); keep `sg` as a fallback for older installs. Repo-wide CI issue, present on master too (extended checks #3550).
What
Registering a C++ runtime helper with the LLVM JIT backend used to require hand-spelling its LLVM function type —
LLVMFunctionType(RET, fixed_array<LLVMTypeRef>(g_prim_t.LLVMVoidPtrType(), t_int64, ...))— with a C-signature comment above each. ~38 of these lived inllvm_jit_common.das: verbose, duplicated (comment vs code), and a wrong arg count / scalar width silently miscompiles the JIT.This derives the type from a das signature instead.
API
New module
modules/dasLLVM/daslib/llvm_dsl.das(compile-time DSL helpers for the backend):jit_fn_type(signature)— a[call_macro]that builds the extern'sLLVMFunctionTypefrom a das signature.signatureis either an inline block$(args) : ret {}(preferred) or@@stub(a reference to a signature-carrier function). Both supported.In
llvm_jit_common.das:jit_add_extern(name, typ, fnAddr, attrs [, argAttrs])— declares one helper:LLVMAddFunctionWithType+ global mapping + function attributes, plus optional per-argument attributes.argAttrsis a list of(argIndex, attribute)pairs (built with a comprehension for ranges, e.g.[for (i in range(0,3)); (i, nocapture)]), folding away every separateLLVMAddAttributeToFunctionArgument[Range]line.jit_extern_type(t : Type)— the das-type → LLVM-type mapping.Per site collapses from ~5 lines + a comment to one call:
Why it's safe (byte-identical IR)
The bundled LLVM is 22.1.5 with opaque pointers (mandatory) — every
LLVMPointerType(*, 0)lowers to the sameptr. So the only load-bearing information in a signature is arg-count plus the non-pointer types (i32/i64/i1/float4/void), all of which the das signature spells. The emitted function types are identical to the hand-written ones. This is a readability refactor, not a behavior change.Scope
All ~35 canonical extern registrations + the 3 special ones (
jit_exceptionnoreturn/cold,jit_handled_abi_check_reportnounwind-only/empty-args,jit_init_extern) converted. Net -160 lines inllvm_jit_common.das. Not touched: thejit_simnode_interop/jit_free_simnode_interoppair (literal names, no attrs), and everything inllvm_jit.das/llvm_exe.das(per-user-function codegen, fileinfo, intrinsics, standalone/exe bootstrap).Testing
run_tests_jit) green.-jitoutput identical across arrays / iterators / string-builder+str_cat / block-invoke / tables / generators.jit_fn_typeforms (block and@@) validated end-to-end.No AOT emitter path touched, so no
LLVM_JIT_CODEGEN_VERSIONbump needed.