diff --git a/internal/wwfixture/types.ww b/internal/wwfixture/types.ww index 1b2b39b7..6f663be6 100644 --- a/internal/wwfixture/types.ww +++ b/internal/wwfixture/types.ww @@ -1,13 +1,13 @@ package wwfixture; def protocolversion: i32 = 1; -def corpuscount: i32 = 1229; +def corpuscount: i32 = 1230; def errorcount: i32 = 314; def compilecount: i32 = 12; -def runcount: i32 = 137; +def runcount: i32 = 138; def runexitcount: i32 = 766; -def nativecount: i32 = 2458; -def corpushash: str = "9d1db4b4bdde1b7e2b1f2e2ae5ca6c6b91b0162df585fd877021d27ec6863d89"; +def nativecount: i32 = 2460; +def corpushash: str = "fd04059b05a19ae63f1bec3edaefedf1d8ce9a505302a153434457d0fb9b9eca"; type directive = enum i32 { ERROR = 0, diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index 0a55c570..0ae5fe2f 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -4242,7 +4242,12 @@ fn cgdot(c: *cgen, n: *syntax.node) void = { cgloadtaggedfield(c, "CX", foff, tsz, true); return; }; - if (syntax.typeisstr(ftraw)) { + // slice joins the str header load (#263: cstage + // N_DOT chain arm keys TY_STR||TY_SLICE — the + // same 24B {ptr,len,cap}); the scalar tail below + // pulled ONLY .ptr, so len(g.buf) read garbage. + if (syntax.typeisstr(ftraw) + || syntax.typeisslice(ftraw)) { emitline("\tMOVQ\t"); emitdispreg(foff: i64, "CX"); emitline(", AX\n"); diff --git a/test/wcc/data/globaldot_slicefield_hdr/case.ww b/test/wcc/data/globaldot_slicefield_hdr/case.ww new file mode 100644 index 00000000..e468a80c --- /dev/null +++ b/test/wcc/data/globaldot_slicefield_hdr/case.ww @@ -0,0 +1,25 @@ +//ww:run +// A module-global struct's slice field read BY VALUE must load the +// full 24B {ptr,len,cap} header. The pre-fix wwstage global-dot arm +// dispatched only str fields to the header load; a []T field fell to +// the scalar tail (ptr word only) and len(x) read stale registers. +package main; + +type box = struct { + buf: []i32, + name: str, +}; + +let g: box = box{}; + +export fn main() int = { + let arr: [4]i32 = [10, 20, 30, 40]; + g.buf = arr[:]; + g.name = "globals"; + let x: []i32 = g.buf; + if (len(x) != 4) { return 1; }; + if (x[2] != 30) { return 2; }; + let s: str = g.name; + if (len(s) != 7) { return 3; }; + return 0; +};