w6c+w6c_ww: (*p)[i] deref base materializes the array ADDRESS (#61 C)
Both stages SEGV'd identically (byte-id-blind): cgun's TK_STAR emitted a scalar MOVQ (AX),AX for an array pointee, so the index consumed a[0]'s VALUE as its base — a wild deref. An array value IS its address everywhere in this cgen (#270-1a), so the ARRAY pointee now takes the same skip as the #185 *fn deref in both stages: `*p` leaves AX = p's value, and every consumer that materializes a complex index base via cgexpr(base) — N_INDEX read fallback, cgassign store/compound, TK_AMP, N_SLICE — gets the array address from the one deref choke-point. wwstage additionally joins the N_UN-TK_STAR base to the stamped-tinfo esz arms (cgindex / cgassign store + compound / TK_AMP &(*p)[i]) where cstage reads base->type uniformly: without it, esz fell to the 8B default and a narrow element would mis-stride the moment the base started materializing (cs!=ww only reachable post-choke-point-fix, which is why it rides this commit). 949_ptrarr_index_run grows the deref_* rows: read (8B/4B/param-base), write (8B / 1B+neighbor-guards), compound — runtime + byte-id, the only nets that can see a both-stages-identical miscompile.
This commit is contained in:
@@ -21930,7 +21930,8 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT) {
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN && base.op == tkind.TK_STAR)) {
|
||||
// `s.ptr[i]` / struct-field index: stride is the
|
||||
// checker-stamped element tinfo's natural size, the
|
||||
// same idiom as the N_INDEX-base arm below (#60/#72).
|
||||
@@ -21939,6 +21940,10 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
// so a signed-narrow field element sign-extends on load
|
||||
// (loadopsz keys on (signed,sz)); cstage's fldloadop reads
|
||||
// it from the element type — align ww up (#255).
|
||||
// N_UN deref base (`(*p)[i]`, #61 C): same stamped-tinfo
|
||||
// source — cstage reads base->type uniformly; without
|
||||
// this arm esz fell to the 8B default (wrong stride for
|
||||
// narrow elements once the deref base materializes).
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; signed_elem = typeissigned(dt); elemisstr = typeisstr(dt); elemisslice = typeisslice(dt); float_elem = typeisfloat(dt); f32_elem = typeisf32(dt); };
|
||||
elem_isarray = tinfoisarray(dt);
|
||||
@@ -21997,7 +22002,9 @@ fn cgindex(c: *cgen, n: *node) void = {
|
||||
// cstage's fallback `MOVQ AX,BX; MOVQ (BX),AX`). #261: without
|
||||
// this an N_DOT-base tagged element fell to the scalar
|
||||
// loadopsz path and silently dropped the tag/payload-high word.
|
||||
if (base.kind == nkind.N_DOT || base.kind == nkind.N_INDEX) {
|
||||
// N_UN deref base joins for the same reason (#61 C).
|
||||
if (base.kind == nkind.N_DOT || base.kind == nkind.N_INDEX
|
||||
|| (base.kind == nkind.N_UN && base.op == tkind.TK_STAR)) {
|
||||
let dt: *tinfo = n.type_: *tinfo;
|
||||
if (dt != nil) {
|
||||
if (typeistagged(dt)) {
|
||||
@@ -24489,12 +24496,17 @@ fn cgun(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT) {
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN
|
||||
&& base.op == tkind.TK_STAR)) {
|
||||
// `&p.ptr[i]`: stride is the checker-stamped
|
||||
// element tinfo's natural size, mirroring
|
||||
// cgindex's N_DOT arm so &p.ptr[i] and
|
||||
// p.ptr[i] agree. cstage idx_eff(base->type)
|
||||
// ->sub->size (cmd/w6c/cgen.c:3517-18). #72.
|
||||
// N_UN deref base (`&(*p)[i]`, #61 C): same
|
||||
// stamped source; cstage reads base->type
|
||||
// uniformly.
|
||||
let dt: *tinfo = opnd.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; };
|
||||
};};
|
||||
@@ -24583,9 +24595,15 @@ fn cgun(c: *cgen, n: *node) void = {
|
||||
// would load the first instruction word and a subsequent
|
||||
// CALL would segfault. Mirror ref/harec/src/check.c
|
||||
// expr_call's STORAGE_POINTER→STORAGE_FUNCTION skip.
|
||||
// #61 C: same skip for an ARRAY pointee — an array value IS
|
||||
// its address everywhere in this cgen (#270-1a), so `*p` on
|
||||
// `*[N]T` leaves AX = p's value. The scalar load below
|
||||
// pulled a[0]'s VALUE and `(*p)[i]` then dereferenced it as
|
||||
// the index base — a wild pointer, SIGSEGV on both stages.
|
||||
let rti: *tinfo = n.type_: *tinfo;
|
||||
for (rti != nil && rti.kind == tykind.TY_NAMED) { rti = rti.under; };
|
||||
if (rti != nil && rti.kind == tykind.TY_FN) { return; };
|
||||
if (rti != nil && rti.kind == tykind.TY_ARRAY) { return; };
|
||||
// f64/f32 result rides X0 (SSE), not AX — an integer MOVQ
|
||||
// strands the value off the float ABI and the caller's
|
||||
// MOVSD X0 reads stale bits (#96). Mirrors the float
|
||||
@@ -27232,13 +27250,16 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT) {
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN
|
||||
&& base.op == tkind.TK_STAR)) {
|
||||
// lhs.type_ is the checker-stamped element tinfo
|
||||
// of the N_INDEX: esz is its natural size and the
|
||||
// tagged-element gate (below) reads the same
|
||||
// .type_ — same idiom as cgindex's n.type_ read
|
||||
// (#60/#72). cstage idx_eff(base->type)->sub->size
|
||||
// (cmd/w6c/cgen.c:3517-18).
|
||||
// (cmd/w6c/cgen.c:3517-18). N_UN deref base
|
||||
// (`(*p)[i] = v`, #61 C): same stamped source.
|
||||
let dt: *tinfo = lhs.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; elemtn = lhs; };
|
||||
} else { if (base.kind == nkind.N_INDEX) {
|
||||
@@ -27677,7 +27698,11 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
} else { if (base.kind == nkind.N_DOT) {
|
||||
} else { if (base.kind == nkind.N_DOT
|
||||
|| (base.kind == nkind.N_UN
|
||||
&& base.op == tkind.TK_STAR)) {
|
||||
// N_UN deref base (`(*p)[i] OP= v`, #61 C):
|
||||
// same stamped source as the store arm.
|
||||
let dt: *tinfo = lhs.type_: *tinfo;
|
||||
if (dt != nil) { esz = dt.size: i32; elemtn = lhs; };
|
||||
} else { if (base.kind == nkind.N_INDEX) {
|
||||
|
||||
Reference in New Issue
Block a user