diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index 42d79f33..1aeb4691 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -1154,12 +1154,17 @@ static DefAny *defall; * supported as a writable global yet. Tagged unions are deferred. * enums route through their storage type. * Keep this tight — extending it requires the matching load/store - * code below. */ + * code below. + * The let_* family (this + the five kind-predicates below) chases the + * alias chain transitively (#77/#78 g-fold): a single peel left a + * 2-level-alias global TY_NAMED → size 0 / predicate false → never + * registered, no DATA, and reads fell to the frame-local path at + * offset 0 — silently reading saved BP. */ static int let_emit_size(Type *t) { if (t == NULL) return 0; - Type *u = (t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); if (u == NULL) return 0; switch (u->kind) { case TY_BOOL: case TY_RUNE: @@ -1203,7 +1208,7 @@ static int let_isstr(Type *t) { if (t == NULL) return 0; - Type *u = (t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); return u && u->kind == TY_STR; } @@ -1213,7 +1218,7 @@ static int let_isslice(Type *t) { if (t == NULL) return 0; - Type *u = (t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); return u && u->kind == TY_SLICE; } @@ -1224,7 +1229,7 @@ static int let_isstruct(Type *t) { if (t == NULL) return 0; - Type *u = (t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); return u && u->kind == TY_STRUCT; } @@ -1235,7 +1240,7 @@ static int let_isarray(Type *t) { if (t == NULL) return 0; - Type *u = (t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); return u && u->kind == TY_ARRAY; } @@ -1246,7 +1251,7 @@ static int let_isfloat(Type *t) { if (t == NULL) return 0; - Type *u = (t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); return u && (u->kind == TY_F32 || u->kind == TY_F64); } @@ -14232,7 +14237,11 @@ static int emit_array_lit_bytes(FILE *out, Cg *c, Type *t, Node *rhs, static int emit_struct_lit_bytes(FILE *out, Cg *c, Type *t, Node *rhs, u64 base) { - Type *u = (t && t->kind == TY_NAMED) ? t->under : t; + /* Transitive entry chase (#77/#78 g-fold, condition-3 member): the + * single peel return-0'd on a 2-level-alias struct and the caller's + * skip-path emitted NO DATA for a registered global — undefined + * reference where pre-G1 it was a silent frame-local read. */ + Type *u = type_chase_named(t); if (u == NULL || u->kind != TY_STRUCT) return 0; u64 pos = base; for (Tfield *f = u->fields; f != NULL; f = f->next) { @@ -14354,7 +14363,7 @@ static int emit_struct_data(FILE *out, Cg *c, const char *directive, const char *name, const char *module, Type *t, Node *rhs) { - Type *u = (t && t->kind == TY_NAMED) ? t->under : t; + Type *u = type_chase_named(t); if (u == NULL || u->kind != TY_STRUCT) return 0; fprintf(out, "%s %s(SB),\"", directive, mod_mangle_value(c, name, module)); @@ -14391,7 +14400,7 @@ emit_struct_data(FILE *out, Cg *c, const char *directive, static int emit_array_lit_bytes(FILE *out, Cg *c, Type *t, Node *rhs, int emit_phase) { - Type *u = type_unwrap(t); + Type *u = type_chase_named(t); if (u == NULL || u->kind != TY_ARRAY) return 0; Type *etype = u->sub; Type *eu = (etype && etype->kind == TY_NAMED) ? etype->under : etype; @@ -14609,7 +14618,7 @@ static int emit_strarray_data(FILE *out, Cg *c, const char *directive, const char *name, const char *module, Type *t, Node *rhs) { - Type *u = type_unwrap(t); + Type *u = type_chase_named(t); if (u == NULL || u->kind != TY_ARRAY) return 0; Type *etype = u->sub; Type *eu = (etype && etype->kind == TY_NAMED) ? etype->under : etype; @@ -14783,7 +14792,7 @@ static int emit_array_data(FILE *out, Cg *c, const char *directive, const char *name, const char *module, Type *t, Node *rhs) { - Type *u = type_unwrap(t); + Type *u = type_chase_named(t); if (u == NULL || u->kind != TY_ARRAY) return 0; /* str-element arrays carry per-element ptr relocations — handled * by the dedicated DATAW+DATAR helper (#18). */ @@ -14818,7 +14827,7 @@ static int emit_slice_data(FILE *out, Cg *c, const char *directive, const char *name, const char *module, Type *t, Node *rhs) { - Type *u = type_unwrap(t); + Type *u = type_chase_named(t); if (u == NULL || u->kind != TY_SLICE) return 0; if (rhs == NULL || rhs->kind != N_ARRLIT) return 0; if (strcmp(directive, "DATAW") != 0) @@ -15118,8 +15127,11 @@ let_pre_intern(Cg *c, Node *file) /* #18: `let xs: [N]str = […];` — pre-intern each element's * strlit in element order (then repeat-fill) so emit_strarray_ * data's DATAR rows find an _S_ rodata row. Must match that - * helper's interning order exactly to keep labels stable. */ - Type *u = type_unwrap(d->type); + * helper's interning order exactly to keep labels stable. + * Chase transitively (#77/#78 g-fold): emit_strarray_data now + * reaches 2-level-alias [N]str globals; a single peel here + * would intern their labels in emit order, not decl order. */ + Type *u = type_chase_named(d->type); if (u != NULL && u->kind == TY_ARRAY && r != NULL && r->kind == N_ARRLIT) { Type *eu = (u->sub && u->sub->kind == TY_NAMED)