diff --git a/examples/ffi-jni-env-03-tl-fallback.sx b/examples/ffi-jni-env-03-tl-fallback.sx new file mode 100644 index 0000000..e7a1f12 --- /dev/null +++ b/examples/ffi-jni-env-03-tl-fallback.sx @@ -0,0 +1,37 @@ +// Phase 2 step 2.16c (PLAN-FFI.md): xfail then green for the +// thread-local env fallback in `#jni_call`. When a `#jni_call` site +// has its env arg omitted AND no `#jni_env` block exists in the same +// function (e.g., we're in a helper called FROM such a block), the +// compiler emits a TL load instead of a sema error. +// +// The TL is pushed/popped by the `#jni_env(env) { ... }` enclosing +// scope at runtime; helpers that don't see the lexical scope still +// pick up the env transparently. Cross-function callers no longer +// need to thread env as an explicit parameter. +// +// Today (2.16b only): lowerJniCall errors when env is omitted and +// jni_env_stack is empty, because TL emission isn't wired yet. + +#import "modules/std.sx"; + +g_should_call : bool = false; + +// Helper fn — no `#jni_env` block in scope. Without TL fallback this +// errors because the omitted env can't be resolved. +helper :: (target: *void) { + #jni_call(void)(target, "noop", "()V"); +} + +unused :: (env: *void, target: *void) { + #jni_env(env) { + helper(target); + } +} + +main :: () -> s32 { + if g_should_call { + unused(null, null); + } + print("ok\n"); + 0; +} diff --git a/tests/expected/ffi-jni-env-03-tl-fallback.exit b/tests/expected/ffi-jni-env-03-tl-fallback.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/expected/ffi-jni-env-03-tl-fallback.exit @@ -0,0 +1 @@ +1 diff --git a/tests/expected/ffi-jni-env-03-tl-fallback.txt b/tests/expected/ffi-jni-env-03-tl-fallback.txt new file mode 100644 index 0000000..e8dc2da --- /dev/null +++ b/tests/expected/ffi-jni-env-03-tl-fallback.txt @@ -0,0 +1,14 @@ +LLVM verification failed: Load operand must be a pointer. + %jni.ifs = load ptr, i64 undef, align 8 +Call parameter type does not match function signature! +i64 undef + ptr %jni.cls = call ptr %jni.GetObjectClass(i64 undef, ptr %load) +Call parameter type does not match function signature! +i64 undef + ptr %jni.global.cls = call ptr %jni.NewGlobalRef(i64 undef, ptr %jni.cls) +Call parameter type does not match function signature! +i64 undef + ptr %jni.fresh.mid = call ptr %jni.GetMethodID(i64 undef, ptr %jni.global.cls, ptr @str, ptr @str.1) +Call parameter type does not match function signature! +i64 undef + ptr call void %jni.callfn(i64 undef, ptr %load, ptr %jni.mid)