wcc: nullable pointer folding for (*T | void)
A tagged union with exactly one `*T` variant and one `void` variant collapses to a single 8-byte pointer slot, where the null bit pattern is the void variant and any non-null is the *T variant. Mirrors Hare's `(*T | null)` ABI optimisation. Detected in resolve_type when the post-flatten variant list has exactly two entries of the right shape; Type.nullable = 1 and size = 8. Codegen branches every tagged-handling site on the flag: - match: discriminator = pointer-vs-zero, not slot+0 tag word. Binding for the *T case copies the same word (the pointer itself) rather than slot+8. - is/as: same ptr-vs-zero discriminator. - ?: null = error (propagate AX=0 to caller's matching null encoding); non-null = success (AX is already the pointer). - !: null aborts; non-null falls through with AX = pointer. - let-init / return: spill or set just AX (no tag/value pair). - call-arg push: push only AX, not the now-unused DX/CX. Prologue spill already pulled size/8 = 1 arg register via the existing tagged-arg loop, so no change needed there. Two existing helpers in cgen.c get nullable-aware spelling: type_isnullable() and nullable_ptr_tag() (which variant index is the *T side; the void side is the other one). The Hare-style `(*T | null)` spelling isn't supported — `null` is not a type keyword in ww. Callers use `void` instead, which is already a real type. The result is the same bit-level layout.
This commit is contained in:
@@ -408,6 +408,10 @@ struct Type {
|
||||
* through NAMED aliases. Variants with
|
||||
* iserror=1 are the propagation target of
|
||||
* the `?` operator. */
|
||||
int nullable;/* TY_TAGGED with exactly `(*T | void)` —
|
||||
* stored as a single 8-byte pointer; null
|
||||
* is the void variant. Mirrors Hare's
|
||||
* `(*T | null)` folding. */
|
||||
};
|
||||
|
||||
extern Type *ty_void, *ty_bool, *ty_rune;
|
||||
|
||||
Reference in New Issue
Block a user