ffi 0.10: extend 94-foreign-global with cross-file companion

97/97 regression tests pass (94 expected updated; +issue-0037 from
the prior commit).

The companion `94-foreign-global-helper.sx` ALSO declares
`__stdinp : *void #foreign;`. Two sx files referencing the same
extern symbol must link cleanly — LLVM dedupes the named global at
the module level, and the C linker resolves both refs to the one
libSystem definition.

The full ergonomic story (helper computes the *same* address as the
main file's direct read) is blocked on issue-0037: lower.zig's
`address_of(global)` branch produces `undef` when the body is a
non-main function, even single-file. Once issue-0037 closes, fold
the helper's address back into an equality check here.

The cross-file link itself works today and is the lemma we're
locking in. This is also the closest thing today to the cross-file
extern-global ergonomic issue-0030 wants — `#foreign` already works
across files; the missing piece is sx-side `extern` decls for
sx-defined globals.
This commit is contained in:
agra
2026-05-19 12:06:08 +03:00
parent 161254f5bb
commit 831b46ac35
3 changed files with 32 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
// Companion module for examples/94-foreign-global.sx (PLAN-FFI 0.10).
// Declares the same `#foreign` extern global as the main file; the
// linker should treat both decls as one symbol. We deliberately don't
// READ `@__stdinp` from inside a helper fn body — that path is busted
// today (see examples/issue-0037.sx) — we just expose a trivial fn so
// this file participates in the link and the cross-file decl
// coexistence is exercised.
__stdinp : *void #foreign;
stdinp_addr_present :: () -> s32 {
1;
}

View File

@@ -2,13 +2,31 @@
// reference libSystem / framework symbols (NSConcreteStackBlock,
// __stdinp, etc.) for FFI bridges. Mirrors the long-standing
// `<fn> :: (...) -> ... #foreign;` form on the function side.
//
// Cross-file dimension (PLAN-FFI step 0.10): the helper companion
// `94-foreign-global-helper.sx` ALSO declares `__stdinp : *void #foreign;`.
// Both files referencing the same extern symbol must link cleanly —
// LLVM dedupes the named global, the C linker resolves both refs to
// the one libSystem symbol.
//
// We *don't* check that the helper computes the same address — see
// issue-0037 (helper-function-scoped `@foreign_global` lowers to
// undef today). When that fixes, fold the helper's address back into
// the equality check here.
#import "modules/std.sx";
#import "94-foreign-global-helper.sx";
__stdinp : *void #foreign;
main :: () -> s32 {
addr_bits : u64 = xx @__stdinp;
print("stdin extern global non-null: {}\n", addr_bits != 0);
// Force the helper symbol to participate in linking (otherwise the
// imported file's #foreign decl might get dropped by the
// dead-code stripper). The actual return value is busted today
// — see issue-0037.
_ := stdinp_addr_present();
print("helper file linked: true\n");
0;
}

View File

@@ -1 +1,2 @@
stdin extern global non-null: true
helper file linked: true