wwstage: resolve deref-store width through type aliases so *(!i32-alias) narrows (#11)
The deref-store *p=v integer arm computed width by name-keying the pointee node (primsize(pe.str)), so a pointer to a !-flagged or otherwise non-primitive-named alias (os.errno = !i32) fell to the MOVQ default where cstage type-resolves to MOVL (cgen.c:4647-4652) -- cs!=ww and a latent 4-byte over-write. Add a primsize-first fallback to the existing typenodeprimresolved (peels N_TBANG/N_TENUM/N_TNAME alias chains to the underlying primitive) so *(!i32-alias) narrows to MOVL. primsize-first preserves *bool/*i32/*u8 byte-id (typenodeprimresolved excludes bool). Adds test/wcc/786 (store through *(!i32-alias) then read an adjacent field -- over-write guard -- plus a plain-*i32 control). The residual name-blind cases (non-ident pointers, str/float/bool aliases, size-2 i16/u16) are routed to #10/#12. Unblocks errno's opaque_ tail store. rule-10 fix-up: wwstage aligned up to cstage.
This commit is contained in:
@@ -22571,6 +22571,20 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
||||
else {
|
||||
let ps: i32 = primsize(pe.str);
|
||||
// #11: primsize is name-keyed and
|
||||
// misses a `!`/enum/name alias
|
||||
// (`type errno = !i32`); peel it to
|
||||
// the underlying primitive width so
|
||||
// the store narrows, as cstage's
|
||||
// type-resolved pointee does
|
||||
// (cgen.c:4647-4652). Residual:
|
||||
// non-ident pointers + str/float-alias
|
||||
// deref-store widths stay name-blind
|
||||
// (#10 wwstage->tinfo SSoT).
|
||||
if (ps == 0) {
|
||||
let uns: bool = false;
|
||||
typenodeprimresolved(c, pe, &ps, &uns);
|
||||
};
|
||||
if (ps == 1) { storeop = "MOVB"; }
|
||||
else { if (ps == 4) { storeop = "MOVL"; }; };
|
||||
}; }; };
|
||||
|
||||
@@ -4427,6 +4427,20 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
||||
else {
|
||||
let ps: i32 = primsize(pe.str);
|
||||
// #11: primsize is name-keyed and
|
||||
// misses a `!`/enum/name alias
|
||||
// (`type errno = !i32`); peel it to
|
||||
// the underlying primitive width so
|
||||
// the store narrows, as cstage's
|
||||
// type-resolved pointee does
|
||||
// (cgen.c:4647-4652). Residual:
|
||||
// non-ident pointers + str/float-alias
|
||||
// deref-store widths stay name-blind
|
||||
// (#10 wwstage->tinfo SSoT).
|
||||
if (ps == 0) {
|
||||
let uns: bool = false;
|
||||
typenodeprimresolved(c, pe, &ps, &uns);
|
||||
};
|
||||
if (ps == 1) { storeop = "MOVB"; }
|
||||
else { if (ps == 4) { storeop = "MOVL"; }; };
|
||||
}; }; };
|
||||
|
||||
@@ -22571,6 +22571,20 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
else { if (streq(pe.str, "f32")) { elemfloat = true; elemf32 = true; }
|
||||
else {
|
||||
let ps: i32 = primsize(pe.str);
|
||||
// #11: primsize is name-keyed and
|
||||
// misses a `!`/enum/name alias
|
||||
// (`type errno = !i32`); peel it to
|
||||
// the underlying primitive width so
|
||||
// the store narrows, as cstage's
|
||||
// type-resolved pointee does
|
||||
// (cgen.c:4647-4652). Residual:
|
||||
// non-ident pointers + str/float-alias
|
||||
// deref-store widths stay name-blind
|
||||
// (#10 wwstage->tinfo SSoT).
|
||||
if (ps == 0) {
|
||||
let uns: bool = false;
|
||||
typenodeprimresolved(c, pe, &ps, &uns);
|
||||
};
|
||||
if (ps == 1) { storeop = "MOVB"; }
|
||||
else { if (ps == 4) { storeop = "MOVL"; }; };
|
||||
}; }; };
|
||||
|
||||
Reference in New Issue
Block a user