cgen: default the hi bound of a slice/str-field slice, both stages

x.slicefield[:] / x.strfield[2:] emitted MOVQ $0 for the omitted hi
bound on BOTH stages (N_IDENT-gated dispatch; symmetric, so byte
identity never caught it) in all four sites: cgexpr N_SLICE + pushargs
(cstage), cgslice + pushargsrev (wwstage). The new arm re-evaluates
the pure field read for its {ptr,len,cap} header and takes .len,
covering local, viaptr, dot-chain, (*p), arr[i], and global inners.
Call inners still loud-reject upstream. Sibling of the #252/#257
array-field arms.
This commit is contained in:
2026-08-08 00:29:51 +09:00
parent cc22abfc04
commit 66251cc52b
7 changed files with 190 additions and 6 deletions

View File

@@ -0,0 +1,49 @@
//ww:run
// Default-hi slice of a slice/str FIELD (`x.f[:]`, `x.f[2:]`) —
// expression position. The pre-fix default-hi dispatch was
// N_IDENT-gated on BOTH stages, so an N_DOT base fell to MOVQ $0
// (len 0 / negative, byteid-blind). Covers local, viaptr, dot-chain,
// (*p) spelling, and struct-array-element inners.
package main;
type inner = struct {
buf: []i32,
name: str,
};
type outer = struct {
pad: i64,
in: inner,
};
export fn main() int = {
let arr: [4]i32 = [10, 20, 30, 40];
let v: inner = inner{ buf = arr[:], name = "hello" };
let b1: []i32 = v.buf[:];
if (len(b1) != 4) { return 1; };
let b2: []i32 = v.buf[1:];
if (len(b2) != 3) { return 2; };
if (b2[0] != 20) { return 3; };
let s1: str = v.name[2:];
if (len(s1) != 3) { return 4; };
let p: *inner = &v;
let b3: []i32 = p.buf[:];
if (len(b3) != 4) { return 5; };
let s2: str = p.name[1:];
if (len(s2) != 4) { return 6; };
let o: outer = outer{ pad = 7, in = inner{ buf = arr[:], name = "world" } };
let b4: []i32 = o.in.buf[:];
if (len(b4) != 4) { return 7; };
let b5: []i32 = o.in.buf[2:];
if (len(b5) != 2) { return 8; };
if (b5[1] != 40) { return 9; };
let s3: str = o.in.name[3:];
if (len(s3) != 2) { return 10; };
let b6: []i32 = (*p).buf[:];
if (len(b6) != 4) { return 11; };
let xs: [2]inner = [v, v];
let b7: []i32 = xs[1].buf[:];
if (len(b7) != 4) { return 12; };
if (b7[3] != 40) { return 13; };
return 0;
};

View File

@@ -0,0 +1,46 @@
//ww:run
// Default-hi slice of a slice/str FIELD in call-ARG position — the
// pushargs twin of dotfield_slice_defhi. Pre-fix the pushargs
// N_SLICE default-hi arm was N_IDENT-gated on BOTH stages, so
// callees received a 0-length slice.
package main;
type inner = struct {
buf: []i32,
name: str,
};
type outer = struct {
pad: i64,
in: inner,
};
fn sum(xs: []i32) i32 = {
let t: i32 = 0;
let i: i32 = 0;
for (i < len(xs)) {
t += xs[i];
i += 1;
};
return t;
};
fn slen(s: str) i32 = {
return len(s);
};
export fn main() int = {
let arr: [4]i32 = [10, 20, 30, 40];
let v: inner = inner{ buf = arr[:], name = "hello" };
if (sum(v.buf[:]) != 100) { return 1; };
if (sum(v.buf[2:]) != 70) { return 2; };
if (slen(v.name[1:]) != 4) { return 3; };
let p: *inner = &v;
if (sum(p.buf[:]) != 100) { return 4; };
if (slen(p.name[2:]) != 3) { return 5; };
let o: outer = outer{ pad = 7, in = inner{ buf = arr[:], name = "world" } };
if (sum(o.in.buf[:]) != 100) { return 6; };
if (sum(o.in.buf[1:]) != 90) { return 7; };
if (slen(o.in.name[4:]) != 1) { return 8; };
return 0;
};

View File

@@ -0,0 +1,51 @@
//ww:run
// Default-hi slice of a slice/str FIELD on module-GLOBAL struct
// bases (single dot and chain), expression + arg positions — the
// global leg of dotfield_slice_defhi.
package main;
type inner = struct {
buf: []i32,
name: str,
};
type outer = struct {
pad: i64,
in: inner,
};
let g: inner = inner{};
let go: outer = outer{};
fn sum(xs: []i32) i32 = {
let t: i32 = 0;
let i: i32 = 0;
for (i < len(xs)) {
t += xs[i];
i += 1;
};
return t;
};
export fn main() int = {
let arr: [4]i32 = [10, 20, 30, 40];
g.buf = arr[:];
g.name = "globals";
let b1: []i32 = g.buf[:];
if (len(b1) != 4) { return 1; };
let b2: []i32 = g.buf[2:];
if (len(b2) != 2) { return 2; };
if (b2[0] != 30) { return 3; };
let s1: str = g.name[3:];
if (len(s1) != 4) { return 4; };
if (sum(g.buf[:]) != 100) { return 5; };
if (sum(g.buf[1:]) != 90) { return 6; };
go.in.buf = arr[:];
go.in.name = "chain";
let b3: []i32 = go.in.buf[:];
if (len(b3) != 4) { return 7; };
if (sum(go.in.buf[2:]) != 70) { return 8; };
let s2: str = go.in.name[1:];
if (len(s2) != 4) { return 9; };
return 0;
};