wcc/cgen: GAP-A.ptr global-array base — LEAQ name(SB) not (BP) (#11, both stages)
A global fixed array's .ptr (= &A[0]) must take the SB base, but cstage emitted frame-relative LEAQ off(BP) for BOTH let- and def-global arrays -> *A.ptr read frame garbage (0 instead of the element). cstage-SILENT; wwstage def-global was a loud link-error. The .ptr read arm now gates off==0 && (let_islet || def_isarraydef) -> LEAQ name(SB), reusing the def-array index base predicate (cgen.c:4367, the #94/#231/#48 class). Locals (off != 0) stay BP-relative -- the 14 toolchain backing-ptr sites unaffected. wwstage let-global was already correct; this adds the missing def-global arm (cgenexpr.ww), converging cstage/wwstage byte-identical across all three flavors (local / let-global / def-global) and closing a latent cstage-only let-global cs!=ww divergence. Byte-id 990-997 8/8 (corpus has no global .ptr); w6c/w6c_ww binaries move (cgen changed). test/wcc/818 table-driven, build+run+byte-id per flavor.
This commit is contained in:
@@ -24981,11 +24981,24 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// SB fallback → MOVQ len(SB) (w6l: undefined 'len'). cstage cgen.c
|
||||
// emits MOVQ $alen here. defvartnode is the def-side mirror of
|
||||
// letvartnode (returns dtnode = the N_TARRAY whose .rhs length child
|
||||
// is #11-stamped). `.ptr`/`.cap` are NOT mirrored: cstage's def .ptr
|
||||
// is itself buggy (LEAQ (BP), task GAP-A.ptr) and arrays have no
|
||||
// .cap (cstage rejects, task GAP-A.cap).
|
||||
// is #11-stamped). `.ptr` mirrors the let-global arm above: the
|
||||
// array's backing pointer ≡ &A[0] = LEAQ name(SB) (drew #13,
|
||||
// .ai/drew-gapa-ptr-ruling.md; GAP-A.ptr now fixed cstage-side too,
|
||||
// so both stages byte-id). `.cap` stays unmirrored — arrays have no
|
||||
// .cap (both checkers reject, task GAP-A.cap).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_IDENT) {
|
||||
if (streq(fld, "ptr")) {
|
||||
let dtn: *node = defvartnode(c, lhs.str);
|
||||
if (dtn != nil) {
|
||||
if (dtn.kind == nkind.N_TARRAY) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, lhs.str);
|
||||
emitline("(SB), AX\n");
|
||||
return;
|
||||
};
|
||||
};
|
||||
};
|
||||
if (streq(fld, "len")) {
|
||||
let dtn: *node = defvartnode(c, lhs.str);
|
||||
if (dtn != nil) {
|
||||
|
||||
@@ -3461,11 +3461,24 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// SB fallback → MOVQ len(SB) (w6l: undefined 'len'). cstage cgen.c
|
||||
// emits MOVQ $alen here. defvartnode is the def-side mirror of
|
||||
// letvartnode (returns dtnode = the N_TARRAY whose .rhs length child
|
||||
// is #11-stamped). `.ptr`/`.cap` are NOT mirrored: cstage's def .ptr
|
||||
// is itself buggy (LEAQ (BP), task GAP-A.ptr) and arrays have no
|
||||
// .cap (cstage rejects, task GAP-A.cap).
|
||||
// is #11-stamped). `.ptr` mirrors the let-global arm above: the
|
||||
// array's backing pointer ≡ &A[0] = LEAQ name(SB) (drew #13,
|
||||
// .ai/drew-gapa-ptr-ruling.md; GAP-A.ptr now fixed cstage-side too,
|
||||
// so both stages byte-id). `.cap` stays unmirrored — arrays have no
|
||||
// .cap (both checkers reject, task GAP-A.cap).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_IDENT) {
|
||||
if (streq(fld, "ptr")) {
|
||||
let dtn: *node = defvartnode(c, lhs.str);
|
||||
if (dtn != nil) {
|
||||
if (dtn.kind == nkind.N_TARRAY) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, lhs.str);
|
||||
emitline("(SB), AX\n");
|
||||
return;
|
||||
};
|
||||
};
|
||||
};
|
||||
if (streq(fld, "len")) {
|
||||
let dtn: *node = defvartnode(c, lhs.str);
|
||||
if (dtn != nil) {
|
||||
|
||||
@@ -24981,11 +24981,24 @@ fn cgdot(c: *cgen, n: *node) void = {
|
||||
// SB fallback → MOVQ len(SB) (w6l: undefined 'len'). cstage cgen.c
|
||||
// emits MOVQ $alen here. defvartnode is the def-side mirror of
|
||||
// letvartnode (returns dtnode = the N_TARRAY whose .rhs length child
|
||||
// is #11-stamped). `.ptr`/`.cap` are NOT mirrored: cstage's def .ptr
|
||||
// is itself buggy (LEAQ (BP), task GAP-A.ptr) and arrays have no
|
||||
// .cap (cstage rejects, task GAP-A.cap).
|
||||
// is #11-stamped). `.ptr` mirrors the let-global arm above: the
|
||||
// array's backing pointer ≡ &A[0] = LEAQ name(SB) (drew #13,
|
||||
// .ai/drew-gapa-ptr-ruling.md; GAP-A.ptr now fixed cstage-side too,
|
||||
// so both stages byte-id). `.cap` stays unmirrored — arrays have no
|
||||
// .cap (both checkers reject, task GAP-A.cap).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_IDENT) {
|
||||
if (streq(fld, "ptr")) {
|
||||
let dtn: *node = defvartnode(c, lhs.str);
|
||||
if (dtn != nil) {
|
||||
if (dtn.kind == nkind.N_TARRAY) {
|
||||
emitline("\tLEAQ\t");
|
||||
emitsymname(c, lhs.str);
|
||||
emitline("(SB), AX\n");
|
||||
return;
|
||||
};
|
||||
};
|
||||
};
|
||||
if (streq(fld, "len")) {
|
||||
let dtn: *node = defvartnode(c, lhs.str);
|
||||
if (dtn != nil) {
|
||||
|
||||
Reference in New Issue
Block a user