selfhost/cmd/wcc/cgenstmt+test: emit slice-form alloc let-init shortcut
Cstage's cmd/w6c/cgen.c:6363-6411 special-cases `let s: []T = alloc([], n)!;` to inline rt_alloc + null-check + exit(1) + slice header build, avoiding a generic call-then-store path. Wwstage's cglet had no mirror — pre-#31 the path was rejected at check, but once #31 made the check side accept it, the cgen side would have silently miscompiled. Mirror added at cgenstmt.ww cglet rhs head, emitting byte-identical asm. Element size goes through elemsizeofc so str (16), structs, and tagged aliases all match cstage's lu->sub->size uniformly — the defensive path matters because check today only allows []u8, but relaxing that is its own task. Test exercises the path: writes to s[0] and s[15], reads back. Would SIGSEGV on a junk header. 994 + 995 byte-identity green.
This commit is contained in:
@@ -43,6 +43,25 @@ fn allocbox() (*point | nomem) = {
|
||||
return p;
|
||||
};
|
||||
|
||||
// Task #32: slice-form `let s: []T = alloc([], n)!;` shortcut. Both
|
||||
// stages must lower to `n*esz` bytes via rt_alloc, abort on null, and
|
||||
// build a {ptr, 0, n} header in the let slot. Pre-#32 wwstage fell
|
||||
// through to cgalloc, allocating 8B and dropping the slice header
|
||||
// entirely — silent miscompile. Cap-only would pass on a junk header
|
||||
// pointing to dead memory; write-then-read on s[0]/s[cap-1] proves
|
||||
// the ptr field is a real rt_alloc'd region (would SIGSEGV otherwise).
|
||||
// IMULQ esz path is currently unreachable from user code — check.c
|
||||
// pins the alloc shape to []u8 (cstage check.c:1052-1082) — so this
|
||||
// row only exercises esz=1; the cgen elemsizeofc resolution stays
|
||||
// defensive against a future check.c relaxation.
|
||||
fn sliceshort() i32 = {
|
||||
let s: []u8 = alloc([], 16)!;
|
||||
if (s.cap != 16) { return -1i32; };
|
||||
s[0] = 42u8;
|
||||
s[15] = 99u8;
|
||||
return (s[0]: i32) + (s[15]: i32);
|
||||
};
|
||||
|
||||
export fn main() i32 = {
|
||||
let rc: i32 = 0;
|
||||
match (caller(0i64)) {
|
||||
@@ -74,5 +93,7 @@ export fn main() i32 = {
|
||||
rc = 5;
|
||||
};
|
||||
};
|
||||
if (sliceshort() != 141i32) { rc = 6; }
|
||||
else { fmt.println("sliceshort ok"); };
|
||||
return rc;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user