diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index d8ad8c56..317fcca7 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -11313,35 +11313,25 @@ fn loadopsz(sigd: bool, sz: i32) str = { }; // localloadop — read instruction for a scalar local/let load. Same -// dispatch as fieldloadop, but keyed on the value's own tnode. Lets -// the caller emit MOVSXD/MOVSWQ/MOVSBQ on a signed-narrow slot instead -// of a raw MOVQ, so a slot that was last written by a narrow deref- -// store (`*p: *i32 = v` lowers to MOVL, only 4B) reads back as a -// properly-sign-extended i64. The natural N_ASSIGN / N_LET paths +// dispatch as fieldloadop, but keyed on the value's own tnode.type_. +// Lets the caller emit MOVSXD/MOVSWQ/MOVSBQ on a signed-narrow slot +// instead of a raw MOVQ, so a slot that was last written by a narrow +// deref-store (`*p: *i32 = v` lowers to MOVL, only 4B) reads back as +// a properly-sign-extended i64. The natural N_ASSIGN / N_LET paths // store the rhs as a sign-extended 8B word, so MOVQ accidentally // works; deref-stores are the only path that touches fewer bytes -// than MOVQ reads. Mirror of cstage's localloadop in cmd/w6c/cgen.c. -// Resolves TBANG / TENUM / TNAME-alias chains so `type err = !i32` -// picks up size 4 the same way the cstage checker pre-computes -// t->size — without this, aliased narrows fall through to MOVQ. +// than MOVQ reads. Mirror of cstage's localloadop in cmd/w6c/cgen.c +// — tinfo.size carries the same numeric width cstage's `t->size` +// reports, with TBANG / TENUM / TNAME-alias chains pre-folded by +// tinfofornode (check.ww:1102-1153 TNAME, 1154-1161 TBANG, +// 1196-1208 TENUM). export fn localloadop(c: *cgen, tnode: *node) str = { - let t: *node = tnode; - for (t != nil) { - let k: nkind = t.kind; - if (k == nkind.N_TBANG) { t = t.lhs; } - else { if (k == nkind.N_TENUM) { t = t.lhs; } - else { if (k == nkind.N_TNAME) { - let nm: str = t.str; - if (primsize(nm) > 0) { break; }; - let al: *node = aliaslookup(c, nm); - if (al == nil) { break; }; - t = al; - } - else { break; }; }; }; - }; - let sz: i32 = fieldsize(c, t); + if (tnode == nil) { return "MOVQ"; }; + let ti: *tinfo = tnode.type_: *tinfo; + if (ti == nil) { return "MOVQ"; }; + let sz: i32 = ti.size: i32; if (sz != 1) { if (sz != 2) { if (sz != 4) { return "MOVQ"; }; }; }; - let sigd: bool = fieldissignedc(c, tnode); + let sigd: bool = typeissigned(ti); return loadopsz(sigd, sz); }; diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index ec169e98..648f6954 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -941,35 +941,25 @@ fn loadopsz(sigd: bool, sz: i32) str = { }; // localloadop — read instruction for a scalar local/let load. Same -// dispatch as fieldloadop, but keyed on the value's own tnode. Lets -// the caller emit MOVSXD/MOVSWQ/MOVSBQ on a signed-narrow slot instead -// of a raw MOVQ, so a slot that was last written by a narrow deref- -// store (`*p: *i32 = v` lowers to MOVL, only 4B) reads back as a -// properly-sign-extended i64. The natural N_ASSIGN / N_LET paths +// dispatch as fieldloadop, but keyed on the value's own tnode.type_. +// Lets the caller emit MOVSXD/MOVSWQ/MOVSBQ on a signed-narrow slot +// instead of a raw MOVQ, so a slot that was last written by a narrow +// deref-store (`*p: *i32 = v` lowers to MOVL, only 4B) reads back as +// a properly-sign-extended i64. The natural N_ASSIGN / N_LET paths // store the rhs as a sign-extended 8B word, so MOVQ accidentally // works; deref-stores are the only path that touches fewer bytes -// than MOVQ reads. Mirror of cstage's localloadop in cmd/w6c/cgen.c. -// Resolves TBANG / TENUM / TNAME-alias chains so `type err = !i32` -// picks up size 4 the same way the cstage checker pre-computes -// t->size — without this, aliased narrows fall through to MOVQ. +// than MOVQ reads. Mirror of cstage's localloadop in cmd/w6c/cgen.c +// — tinfo.size carries the same numeric width cstage's `t->size` +// reports, with TBANG / TENUM / TNAME-alias chains pre-folded by +// tinfofornode (check.ww:1102-1153 TNAME, 1154-1161 TBANG, +// 1196-1208 TENUM). export fn localloadop(c: *cgen, tnode: *node) str = { - let t: *node = tnode; - for (t != nil) { - let k: nkind = t.kind; - if (k == nkind.N_TBANG) { t = t.lhs; } - else { if (k == nkind.N_TENUM) { t = t.lhs; } - else { if (k == nkind.N_TNAME) { - let nm: str = t.str; - if (primsize(nm) > 0) { break; }; - let al: *node = aliaslookup(c, nm); - if (al == nil) { break; }; - t = al; - } - else { break; }; }; }; - }; - let sz: i32 = fieldsize(c, t); + if (tnode == nil) { return "MOVQ"; }; + let ti: *tinfo = tnode.type_: *tinfo; + if (ti == nil) { return "MOVQ"; }; + let sz: i32 = ti.size: i32; if (sz != 1) { if (sz != 2) { if (sz != 4) { return "MOVQ"; }; }; }; - let sigd: bool = fieldissignedc(c, tnode); + let sigd: bool = typeissigned(ti); return loadopsz(sigd, sz); }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 69b84bb6..725536ff 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -11313,35 +11313,25 @@ fn loadopsz(sigd: bool, sz: i32) str = { }; // localloadop — read instruction for a scalar local/let load. Same -// dispatch as fieldloadop, but keyed on the value's own tnode. Lets -// the caller emit MOVSXD/MOVSWQ/MOVSBQ on a signed-narrow slot instead -// of a raw MOVQ, so a slot that was last written by a narrow deref- -// store (`*p: *i32 = v` lowers to MOVL, only 4B) reads back as a -// properly-sign-extended i64. The natural N_ASSIGN / N_LET paths +// dispatch as fieldloadop, but keyed on the value's own tnode.type_. +// Lets the caller emit MOVSXD/MOVSWQ/MOVSBQ on a signed-narrow slot +// instead of a raw MOVQ, so a slot that was last written by a narrow +// deref-store (`*p: *i32 = v` lowers to MOVL, only 4B) reads back as +// a properly-sign-extended i64. The natural N_ASSIGN / N_LET paths // store the rhs as a sign-extended 8B word, so MOVQ accidentally // works; deref-stores are the only path that touches fewer bytes -// than MOVQ reads. Mirror of cstage's localloadop in cmd/w6c/cgen.c. -// Resolves TBANG / TENUM / TNAME-alias chains so `type err = !i32` -// picks up size 4 the same way the cstage checker pre-computes -// t->size — without this, aliased narrows fall through to MOVQ. +// than MOVQ reads. Mirror of cstage's localloadop in cmd/w6c/cgen.c +// — tinfo.size carries the same numeric width cstage's `t->size` +// reports, with TBANG / TENUM / TNAME-alias chains pre-folded by +// tinfofornode (check.ww:1102-1153 TNAME, 1154-1161 TBANG, +// 1196-1208 TENUM). export fn localloadop(c: *cgen, tnode: *node) str = { - let t: *node = tnode; - for (t != nil) { - let k: nkind = t.kind; - if (k == nkind.N_TBANG) { t = t.lhs; } - else { if (k == nkind.N_TENUM) { t = t.lhs; } - else { if (k == nkind.N_TNAME) { - let nm: str = t.str; - if (primsize(nm) > 0) { break; }; - let al: *node = aliaslookup(c, nm); - if (al == nil) { break; }; - t = al; - } - else { break; }; }; }; - }; - let sz: i32 = fieldsize(c, t); + if (tnode == nil) { return "MOVQ"; }; + let ti: *tinfo = tnode.type_: *tinfo; + if (ti == nil) { return "MOVQ"; }; + let sz: i32 = ti.size: i32; if (sz != 1) { if (sz != 2) { if (sz != 4) { return "MOVQ"; }; }; }; - let sigd: bool = fieldissignedc(c, tnode); + let sigd: bool = typeissigned(ti); return loadopsz(sigd, sz); };