ffi 1.15: #jni_call(void) codegen — make-green
New `.jni_msg_send` IR opcode carrying `{env, target, name, sig,
args[], is_static}`. `lowerFfiIntrinsicCall` now dispatches on
`fic.kind`: `.objc_call` keeps the existing path; `.jni_call` and
`.jni_static_call` route through `lowerJniCall`, which emits the new
opcode.
emit_llvm.zig expands `.jni_msg_send` into the JNI vtable
indirection:
%ifs = load ptr, %env ; vtable
%get_obj_class = load ptr, gep(%ifs, i32 31)
%cls = call ptr %get_obj_class(%env, %target)
%get_method_id = load ptr, gep(%ifs, i32 33)
%mid = call ptr %get_method_id(%env, %cls, %name, %sig)
%call_void_method = load ptr, gep(%ifs, i32 61)
call void %call_void_method(%env, %target, %mid, args...)
Per step 1.15's scope: only `.jni_call` (instance) + `void` return
are wired through the switch. `.jni_static_call` (1.23) and the
non-void returns (1.18–1.22) drop to a placeholder `LLVMGetUndef` so
the build doesn't fault — the next-step commits flip those arms one
shape at a time. Method-ID caching is step 1.17.
Two small helpers landed alongside:
- `loadJniFn(ifs, offset, name)` — GEP into the vtable + load.
- `extractSlicePtr(val)` — string literals lower as `{ptr, i64}`
slices in sx IR; JNI's `GetMethodID` expects raw C strings, so
this extracts field 0 when the source is a slice.
Android cross-compile now passes for `examples/ffi-jni-call-02-void.sx`
(2/2 cross targets green). Host run_examples still passes 112/112.
Chess iOS-sim + Android both compile clean.
This commit is contained in:
@@ -188,6 +188,14 @@ pub const Op = union(enum) {
|
||||
/// per signature shape.
|
||||
objc_msg_send: ObjcMsgSend,
|
||||
|
||||
/// `#jni_call(ReturnT)(env, target, name, sig, args...)` and
|
||||
/// `#jni_static_call(ReturnT)(env, class, name, sig, args...)`.
|
||||
/// emit_llvm.zig expands this into the JNI vtable indirection:
|
||||
/// `(*env)->GetObjectClass` (instance only) → `GetMethodID` /
|
||||
/// `GetStaticMethodID` → `Call<Type>Method` / `CallStatic<Type>Method`.
|
||||
/// Method-ID caching across call sites is added in step 1.17.
|
||||
jni_msg_send: JniMsgSend,
|
||||
|
||||
// ── Protocol dispatch ───────────────────────────────────────────
|
||||
protocol_call_dynamic: ProtocolCall, // vtable/inline dispatch
|
||||
protocol_erase: ProtocolErase, // concrete → protocol value (xx)
|
||||
@@ -304,6 +312,20 @@ pub const ObjcMsgSend = struct {
|
||||
args: []const Ref, // additional args after recv + sel
|
||||
};
|
||||
|
||||
/// JNI dispatch payload. `env` is `JNIEnv*` (typed as ptr); `target`
|
||||
/// is a `jobject` for instance calls and a `jclass` for static calls.
|
||||
/// `name` and `sig` are pointers to NUL-terminated bytes (typically
|
||||
/// `[*]u8` from a string-literal `.ptr`). The dispatch sequence is
|
||||
/// expanded in emit_llvm.zig — see `Inst.jni_msg_send`.
|
||||
pub const JniMsgSend = struct {
|
||||
env: Ref,
|
||||
target: Ref,
|
||||
name: Ref,
|
||||
sig: Ref,
|
||||
args: []const Ref,
|
||||
is_static: bool,
|
||||
};
|
||||
|
||||
pub const BuiltinCall = struct {
|
||||
builtin: BuiltinId,
|
||||
args: []const Ref,
|
||||
|
||||
Reference in New Issue
Block a user