selfhost: fix 4B array load/store width + 8B uninit zero-init
This commit is contained in:
@@ -504,13 +504,11 @@ fn cglet(c: *cgen, n: *node) void = {
|
||||
};
|
||||
} else {
|
||||
// Bare `let x: T;` with no initializer. C cgen
|
||||
// (cmd/w6c/cgen.c:2181-2183) zero-inits only when
|
||||
// the underlying type's natural size is 8 — pointers,
|
||||
// i64/u64, function pointers, ints. Structs/arrays/
|
||||
// slices/strings/tagged/tuples are left for per-field
|
||||
// writes. ww's slotsize pads struct slots up to 8,
|
||||
// so we can't just check sz == 8: walk the type AST
|
||||
// directly to make the same call.
|
||||
// (cmd/w6c/cgen.c:3317) zero-inits whenever the raw type size
|
||||
// is 8: scalar primitives, pointers, fn/chan handles, plus 8B
|
||||
// composites like `[8]bool`, `[2]i32`, `[4]i16`, `[1]i64`.
|
||||
// Larger composites and `[N]T` with size != 8 are left for
|
||||
// per-field writes.
|
||||
if (typeis8byteprimitive(c, n.lhs)) {
|
||||
emitline("\tMOVQ\t$0, ");
|
||||
emitoff(off: i64);
|
||||
@@ -799,15 +797,12 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
let ioff: i32 = localalloc(c, iname, 8, nil);
|
||||
let loff: i32 = localalloc(c, lname, 8, nil);
|
||||
|
||||
// Per-binding (up to 8 — matches the C array). Parallel i64 arrays
|
||||
// keep every elem at 8B so the indexed-store hits the working MOVQ
|
||||
// path (selfhost cgen doesn't yet emit MOVL for i32-array writes,
|
||||
// and doesn't zero-init `[8]bool` uninit slots — both byte-diverge
|
||||
// from C w6c on the wwstage rebuild).
|
||||
let bind_off: [8]i64;
|
||||
let bind_sz: [8]i64;
|
||||
let bind_foff: [8]i64;
|
||||
let bind_signed: [8]i64; // 0 / 1
|
||||
// Per-binding (up to 8 — matches the C array). Parallel arrays so
|
||||
// we don't depend on local-struct cgen.
|
||||
let bind_off: [8]i32;
|
||||
let bind_sz: [8]i32;
|
||||
let bind_foff: [8]i32;
|
||||
let bind_signed: [8]bool;
|
||||
let nbinds: i32 = 0;
|
||||
|
||||
if (destruct) {
|
||||
@@ -828,15 +823,14 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
};
|
||||
let slot_sz: i32 = fsz;
|
||||
if (slot_sz < 8) { slot_sz = 8; };
|
||||
bind_sz[nbinds] = fsz: i64;
|
||||
bind_foff[nbinds] = field_off: i64;
|
||||
if (signf) { bind_signed[nbinds] = 1i64; }
|
||||
else { bind_signed[nbinds] = 0i64; };
|
||||
bind_sz[nbinds] = fsz;
|
||||
bind_foff[nbinds] = field_off;
|
||||
bind_signed[nbinds] = signf;
|
||||
let bnm: str = m.str;
|
||||
if (bnm.len > 0) {
|
||||
bind_off[nbinds] = localadd(c, bnm, slot_sz, nil): i64;
|
||||
bind_off[nbinds] = localadd(c, bnm, slot_sz, nil);
|
||||
} else {
|
||||
bind_off[nbinds] = localalloc(c, mkscratchname(c, "fr"), slot_sz, nil): i64;
|
||||
bind_off[nbinds] = localalloc(c, mkscratchname(c, "fr"), slot_sz, nil);
|
||||
};
|
||||
field_off += fsz;
|
||||
nbinds += 1;
|
||||
@@ -847,18 +841,18 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
} else {
|
||||
let slot_sz: i32 = esz;
|
||||
if (slot_sz < 8) { slot_sz = 8; };
|
||||
bind_sz[0] = esz: i64;
|
||||
bind_foff[0] = 0i64;
|
||||
bind_sz[0] = esz;
|
||||
bind_foff[0] = 0;
|
||||
// Single-binding signed-narrow detection: mirror C which
|
||||
// reads `u->sub->kind` for the elem type.
|
||||
let signf0: bool = false;
|
||||
if (elemt != nil) { signf0 = paramissigned(elemt); };
|
||||
if (signf0) { bind_signed[0] = 1i64; }
|
||||
else { bind_signed[0] = 0i64; };
|
||||
bind_signed[0] = false;
|
||||
if (elemt != nil) {
|
||||
bind_signed[0] = paramissigned(elemt);
|
||||
};
|
||||
if (n.str.len > 0) {
|
||||
bind_off[0] = localadd(c, n.str, slot_sz, nil): i64;
|
||||
bind_off[0] = localadd(c, n.str, slot_sz, nil);
|
||||
} else {
|
||||
bind_off[0] = localalloc(c, mkscratchname(c, "fr"), slot_sz, nil): i64;
|
||||
bind_off[0] = localalloc(c, mkscratchname(c, "fr"), slot_sz, nil);
|
||||
};
|
||||
nbinds = 1;
|
||||
};
|
||||
@@ -952,18 +946,18 @@ fn cgforrange(c: *cgen, n: *node) void = {
|
||||
let b: i32 = 0;
|
||||
for (b < nbinds) {
|
||||
let op: str = "MOVQ";
|
||||
if (bind_sz[b] == 1i64) { op = "MOVZBQ"; }
|
||||
else { if (bind_sz[b] == 4i64) {
|
||||
if (bind_signed[b] != 0i64) { op = "MOVSXD"; }
|
||||
else { op = "MOVL"; };
|
||||
if (bind_sz[b] == 1) { op = "MOVZBQ"; }
|
||||
else { if (bind_sz[b] == 4) {
|
||||
if (bind_signed[b]) { op = "MOVSXD"; }
|
||||
else { op = "MOVL"; };
|
||||
};};
|
||||
emitline("\t");
|
||||
emitline(op);
|
||||
emitline("\t");
|
||||
emitoff(bind_foff[b]);
|
||||
emitoff(bind_foff[b]: i64);
|
||||
emitline("(BX), AX\n");
|
||||
emitline("\tMOVQ\tAX, ");
|
||||
emitoff(bind_off[b]);
|
||||
emitoff(bind_off[b]: i64);
|
||||
emitline("(BP)\n");
|
||||
b += 1;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user