w6c_ww/cgen: size [N]enum element from tinfo not slotsize (fix #8)
wwstage sized a named-enum array element (`[N]tk`, tk = enum i32) as a
raw 8-byte slot instead of its i32 backing (4), via two sibling code
paths that both derived the element width structurally and missed the
enum's underlying size:
- elemsizeofc (cgenutil.ww) was the odd-one-out among the elem*c
helpers: elemissignedc/elemisfloatc already read the checker-stamped
tinfo (t.type_.sub), but elemsizeofc went elemsizeof->primsize->
slotsize, and primsize("tk")=0 fell through to 8. This drove the
cgindex READ: `a[i]` strode by 8 (MOVQ) where cstage strode by 4
(MOVSXD), reading the wrong/out-of-bounds element for i>=1.
- the array-literal init STORE (cgenstmt.ww) computed its own esz the
same way (primsize=0 -> stayed at the 8 sentinel, enum is not an
aggregate), so a local `[N]enum` literal stored at stride 8 into a
stride-4 frame slot, overrunning it and smashing the saved BP /
return addr -> wwstage-built binary SEGFAULTED.
Both align UP to cstage, which reads the stamped element size uniformly
(N_INDEX idx_eff(bt)->sub->size; N_LET array-init lu->sub->size,
cgen.c:6387). The read fix brings all four elem*c helpers onto the same
tinfo SSoT; the store fix takes the stamped element size for a narrow
scalar. Closing both close-by-construction at the size source.
No in-tree [N]enum / aliased-narrow element existed before kwtab, so
this was byte-id-gate-blind until now. test/wcc/682_arr_enum_elem.c
pins it table-driven: global+local reads, local init-store, signed
sign-extend, and a frame-smash row, each run through both stages with
exit-code and cstage==wwstage asm-byte-id checks.
This commit is contained in:
@@ -1166,6 +1166,26 @@ fn elemsizeofc(c: *cgen, t: *node) i32 = {
|
||||
};
|
||||
let direct: i32 = elemsizeof(t);
|
||||
if (direct != 8) { return direct; };
|
||||
// #8: direct==8 is elemsizeof's "unresolved alias/aggregate" sentinel.
|
||||
// Read the element width off the checker-stamped tinfo, mirroring the
|
||||
// sibling elem*c helpers (elemissignedc :915, elemisfloatc :939, which
|
||||
// already read t.type_.sub) and cstage idx_eff(bt)->sub->size
|
||||
// (cmd/w6c/cgen.c N_INDEX). elemsizeofc was the odd-one-out among the
|
||||
// elem*c family — it derived size purely structurally, so a named-narrow
|
||||
// element (`[N]tkind`, tkind = enum i32) slipped through to a raw 8B slot
|
||||
// instead of its i32 backing (4), wrong-striding both the cgindex READ
|
||||
// and the local-array-init STORE (frame-smash). Peel TY_NAMED on the
|
||||
// indexable and on its element, matching the #270-2 nested-array block
|
||||
// above. Structural slotsize fallback stays for the t.type_==nil case.
|
||||
let ti: *tinfo = t.type_: *tinfo;
|
||||
if (ti != nil) {
|
||||
for (ti != nil && ti.kind == tykind.TY_NAMED) { ti = ti.under; };
|
||||
if (ti != nil) {
|
||||
let esub: *tinfo = ti.sub;
|
||||
for (esub != nil && esub.kind == tykind.TY_NAMED) { esub = esub.under; };
|
||||
if (esub != nil) { return esub.size: i32; };
|
||||
};
|
||||
};
|
||||
let k: nkind = t.kind;
|
||||
let elem: *node = nil;
|
||||
if (k == nkind.N_TPTR) { elem = t.lhs; };
|
||||
|
||||
Reference in New Issue
Block a user