fix(0138): diagnose @scalar-const address-of (no storage)
A scalar `::` constant folds to its value and has no storage. The unary `.address_of` lowering (src/ir/lower/expr.zig) skipped the alloca path (is_alloca == false) and resolveGlobalRef (scalar consts get no storage global), falling through to the generic addr_of arm, which reinterpreted the folded value as a pointer: `inttoptr (i64 <value> to ptr)`. That wild pointer segfaulted on deref and emitted invalid stores for inline-asm `-> @const`. Diagnose instead, in the address_of(identifier) path: a non-alloca, non-ref-capture, non-pack-elem scope binding (local scalar const) and a module_const_map name not backed by storage (module scalar const) both report "cannot take the address of constant '<name>' — a scalar '::' constant has no storage …" and return a placeholder Ref. Chose diagnose over materializing read-only storage (consistent with the fold-only scalar model). Array/struct consts keep real storage and stay addressable (@K/@LIT unchanged). Also gives the ASM stream's planned output-to-const rejection for free — asm `-> @const` lowers through the same path. Regression: examples/1177-diagnostics-addr-of-const-rejected.sx. Resolves 0138.
This commit is contained in:
@@ -1,6 +1,25 @@
|
||||
# 0138 — `@const` (address-of a `::` comptime constant) yields a wild pointer
|
||||
|
||||
**Status:** OPEN
|
||||
**Status:** RESOLVED
|
||||
|
||||
> **Resolution.** Root cause was in `src/ir/lower/expr.zig`'s unary `.address_of`
|
||||
> lowering: a scalar `::` constant binds a folded *value* (`is_alloca == false`,
|
||||
> no storage), so it skipped both the alloca path and `resolveGlobalRef`, then
|
||||
> fell through to the generic `addr_of` arm which reinterpreted the value as a
|
||||
> pointer (`inttoptr (i64 <value> to ptr)`). Fixed by diagnosing in the
|
||||
> `address_of(identifier)` path — both the lexical case (a non-alloca,
|
||||
> non-ref-capture, non-pack-elem scope binding) and the module case (a name in
|
||||
> `module_const_map` that `resolveGlobalRef` did not back with storage) now emit
|
||||
> "cannot take the address of constant '<name>' — a scalar '::' constant has no
|
||||
> storage …" and return a placeholder Ref. Chose **diagnose** over materializing
|
||||
> read-only storage (confirmed with the user): consistent with the fold-only
|
||||
> scalar model; array/struct consts keep their real storage and stay addressable
|
||||
> (`@K`/`@LIT` via `global_addr`, unchanged). This also gives the ASM stream's
|
||||
> planned "output-to-`const` rejection" for free — asm `-> @const` lowers `@place`
|
||||
> through the same path, so it now reports the clean diagnostic instead of an LLVM
|
||||
> verifier failure. Regression: `examples/1177-diagnostics-addr-of-const-rejected.sx`
|
||||
> (module const, local const, and asm `-> @const` write-through). `zig build test`
|
||||
> green (659 corpus).
|
||||
|
||||
## Symptom
|
||||
|
||||
|
||||
Reference in New Issue
Block a user