Repro found while writing PLAN-FFI step 0.10.
In a single file:
__stdinp : *void #foreign;
stdinp_addr :: () -> u64 { xx @__stdinp; }
main :: () -> s32 {
a : u64 = xx @__stdinp; // a = real symbol address
b := stdinp_addr(); // b = 0
...
}
The emitted IR for the helper is `ret i64 undef`, suggesting the
`address_of(identifier=__stdinp)` branch in lower.zig (~line 1719)
doesn't see `__stdinp` in `global_names` at the moment the helper's
body is being lowered — even though the same lookup succeeds inside
main's body in the same compilation unit.
Likely cause: lazy-body lowering ordering vs. the pass that
registers extern global decls into `global_names`. Worth verifying
which before fixing — could also be per-function scoping of the
map. Phase 1 of the FFI plan doesn't depend on this, so it stays
filed as an open issue and gets addressed when convenient (or when
sx-side `extern` cross-file globals from issue-0030 land and need
the same lookup to work everywhere).
48 lines
1.6 KiB
Plaintext
48 lines
1.6 KiB
Plaintext
// `@__stdinp` (address-of a `#foreign` global) lowers to `undef` /
|
|
// 0 when accessed from inside a non-main function body. From `main`
|
|
// directly it works:
|
|
//
|
|
// single file:
|
|
// __stdinp : *void #foreign;
|
|
// stdinp_addr :: () -> u64 { xx @__stdinp; }
|
|
// main :: () -> s32 {
|
|
// a : u64 = xx @__stdinp; // a = <real symbol address>
|
|
// b := stdinp_addr(); // b = 0
|
|
// ...
|
|
// }
|
|
//
|
|
// The emitted IR for the helper is just `ret i64 undef`, suggesting
|
|
// the `address_of(identifier=__stdinp)` branch in `lower.zig`
|
|
// (~line 1719) doesn't see `__stdinp` in `global_names` at the time
|
|
// the helper's body is being lowered — even though the same lookup
|
|
// succeeds inside main.
|
|
//
|
|
// Likely cause: lazy/lazy-deferred body lowering ordering vs. the
|
|
// pass that registers extern global decls into `global_names`. Or
|
|
// global_names is scoped per-function (?). Worth verifying which
|
|
// before fixing.
|
|
//
|
|
// Expected when fixed: the helper returns the same address as the
|
|
// direct read, prints `eq = true`. Today: prints `eq = false`.
|
|
//
|
|
// Filed during PLAN-FFI step 0.10 (cross-file `#foreign` global —
|
|
// the cross-file dimension surfaced the bug, but it reproduces in
|
|
// a single file too).
|
|
|
|
#import "modules/std.sx";
|
|
|
|
__stdinp : *void #foreign;
|
|
|
|
stdinp_addr_via_helper :: () -> u64 {
|
|
xx @__stdinp;
|
|
}
|
|
|
|
main :: () -> s32 {
|
|
direct : u64 = xx @__stdinp;
|
|
via_helper := stdinp_addr_via_helper();
|
|
print("direct non-null = {}\n", direct != 0);
|
|
print("helper non-null = {}\n", via_helper != 0);
|
|
print("eq = {}\n", direct == via_helper);
|
|
0;
|
|
}
|