cmd/wcc/check+test: don't fold (*T | !void) into nullable-ptr ABI
resolve_type for N_TTAGGED was peeling NAMED aliases to TY_VOID before deciding the union is a nullable pointer, which caught (*T | nomem) (nomem = !void) and routed it through cstage's ptr-in-AX shortcut. wwstage's isnullabletype is purely AST-keyed on bare `void`, so any alias or error-tagged void naturally fell through to the general AX=tag, DX=word0 ABI. Rule 10 says align richer DOWN: gate the cstage classifier on iserror==0 so only the literal (*T | void) shape still folds to nullable-ptr. The literal void case stays intact for 700_e2e:642/661/1129. Smoke test selfhost/test/tagged_ptr_ret.ww exercises (*u8 | nomem) across both arms; cstage and wwstage now emit byte-identical asm modulo the pre-existing #20 fmt.formatfield divergence.
This commit is contained in:
@@ -402,18 +402,21 @@ resolve_type(Checker *c, Node *n)
|
||||
/* Nullable pointer folding: `(*T | void)` collapses to a
|
||||
* single 8-byte pointer slot; null bit pattern is the void
|
||||
* variant. Mirrors Hare's `(*T | null)`. Detected on exact
|
||||
* two-variant shape with one TY_PTR and one TY_VOID. */
|
||||
* two-variant shape with one TY_PTR and one literal TY_VOID
|
||||
* (not NAMED, not `!`-flagged): aligns DOWN to wwstage's
|
||||
* isnullabletype which is AST-keyed and only matches a bare
|
||||
* `void` name. Task #25 — `(*T | nomem)` where `nomem = !void`
|
||||
* must take the general tagged-return ABI (AX=tag, DX=word0)
|
||||
* so cstage and wwstage emit byte-identical asm. */
|
||||
if (nv == 2) {
|
||||
Tparam *a = head;
|
||||
Tparam *b = head->next;
|
||||
Type *au = (a->type && a->type->kind == TY_NAMED)
|
||||
? a->type->under : a->type;
|
||||
Type *bu = (b->type && b->type->kind == TY_NAMED)
|
||||
? b->type->under : b->type;
|
||||
int aptr = au && au->kind == TY_PTR;
|
||||
int bptr = bu && bu->kind == TY_PTR;
|
||||
int avoid = au && au->kind == TY_VOID;
|
||||
int bvoid = bu && bu->kind == TY_VOID;
|
||||
int aptr = a->type && a->type->kind == TY_PTR;
|
||||
int bptr = b->type && b->type->kind == TY_PTR;
|
||||
int avoid = a->type && a->type->kind == TY_VOID
|
||||
&& !a->type->iserror;
|
||||
int bvoid = b->type && b->type->kind == TY_VOID
|
||||
&& !b->type->iserror;
|
||||
if ((aptr && bvoid) || (avoid && bptr)) {
|
||||
t->nullable = 1;
|
||||
t->size = 8;
|
||||
|
||||
Reference in New Issue
Block a user