ffi 1.22: #jni_call(*void) → CallObjectMethod (slot 34) — make-green

Closes the return-type matrix. Pointer-return types aren't a simple
`TypeId` enum case (they're user-defined types interned into the
table), so the dispatch checks `TypeInfo.pointer | .many_pointer`
ahead of the primitive switch:

  const is_pointer_ret = switch (types.get(ret_ty_id)) {
      .pointer, .many_pointer => true,
      else => false,
  };
  const offset = if (is_pointer_ret)
      Jni.CallObjectMethod
  else switch (ret_ty_id) { .void => ..., .s32 => ..., ... };

LocalRef cleanup deferred: returned jobjects are JNI LocalRefs
bounded by the native frame. Chains of calls within one frame
consume them inline; cross-frame use must promote via `NewGlobalRef`
(already wired in the slot-interning path from 1.17). The chess
Android backend will consume objects inline, matching the manual
pattern in `sx_android_jni.c`.

Return-type matrix done: void, s32, s64, f64, bool, *void all
dispatch through their respective vtable slots. Static dispatch
(1.23) is next.
This commit is contained in:
agra
2026-05-19 22:38:09 +03:00
parent 908b6d19a3
commit b5694cc42d
2 changed files with 34 additions and 2 deletions

View File

@@ -1239,7 +1239,13 @@ pub const LLVMEmitter = struct {
return;
}
const ret_ty_id = instruction.ty;
const call_method_offset: u32 = switch (ret_ty_id) {
const is_pointer_ret = switch (self.ir_mod.types.get(ret_ty_id)) {
.pointer, .many_pointer => true,
else => false,
};
const call_method_offset: u32 = if (is_pointer_ret)
Jni.CallObjectMethod
else switch (ret_ty_id) {
.void => Jni.CallVoidMethod,
.s32 => Jni.CallIntMethod,
.s64 => Jni.CallLongMethod,