issue-0037: @foreign_global from a helper function lowers to undef
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).
This commit is contained in:
47
examples/issue-0037.sx
Normal file
47
examples/issue-0037.sx
Normal file
@@ -0,0 +1,47 @@
|
||||
// `@__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;
|
||||
}
|
||||
Reference in New Issue
Block a user