wcc/ww: try-unwrap str success reads the stamped operand type

The ?/! success-is-str decision was name-keyed off the FIRST variant
and only handled call operands — an ident operand with junk registers
unwrapped garbage, and error-first unions picked the wrong variant.
Key on the stamped success variant (successvariant + typeisstr,
mirror cgen.c:10459-10466/10595-10602). Review item #16.
This commit is contained in:
2026-06-13 01:44:27 +09:00
parent 75c1b278e6
commit 36e17b58f2
5 changed files with 204 additions and 204 deletions

View File

@@ -23738,42 +23738,13 @@ fn cgtryprop(c: *cgen, n: *node) void = {
// the codegen expects the success value in AX (and BX for str).
// AX=tag, DX=val0, CX=val1 from the call ABI. For str success,
// shuffle (DX,CX) → (AX,BX); else move DX → AX.
// #16: read the STAMPED operand's success-variant type (any source
// shape, any variant order), not a name-keyed call-only lookup of
// the first variant. Mirrors cstage cgen.c:10459-10466
// (success_is_str = type_isstr(succ_t at cg_tagged_success_tag)).
let succisstr: bool = false;
if (n.lhs != nil) {
if (n.lhs.kind == nkind.N_CALL) {
let callee: *node = n.lhs.lhs;
if (callee != nil) {
let cname: str;
cname.ptr = nil; cname.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
cname = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
cname = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (cname.len > 0) {
let rtyp: *node = fnretlookupmod(c, cname, cmod);
if (rtyp != nil) {
if (rtyp.kind == nkind.N_TTAGGED) {
let first: *node = rtyp.list;
if (first != nil) {
if (isstrtype(c, first)) {
succisstr = true;
};
};
};
};
};
};
};
succisstr = typeisstr(successvariant(n.lhs.type_: *tinfo));
};
if (succisstr) {
// str IS []u8: success arrives DX=ptr, CX=len, R8=cap
@@ -23836,42 +23807,11 @@ fn cgtryunw(c: *cgen, n: *node) void = {
if (cgtrytupleshift(c, n)) { return; };
if (cgtrytaggedshift(c, n)) { return; };
// Unwrap success value. (Same shuffle pattern as cgtryprop.)
// #16: stamped success-variant type, any source/order (twin of
// cgtryprop; cstage cgen.c:10595-10602).
let succisstr: bool = false;
if (n.lhs != nil) {
if (n.lhs.kind == nkind.N_CALL) {
let callee: *node = n.lhs.lhs;
if (callee != nil) {
let cname: str;
cname.ptr = nil; cname.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
cname = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
cname = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (cname.len > 0) {
let rtyp: *node = fnretlookupmod(c, cname, cmod);
if (rtyp != nil) {
if (rtyp.kind == nkind.N_TTAGGED) {
let first: *node = rtyp.list;
if (first != nil) {
if (isstrtype(c, first)) {
succisstr = true;
};
};
};
};
};
};
};
succisstr = typeisstr(successvariant(n.lhs.type_: *tinfo));
};
if (succisstr) {
// str IS []u8: success arrives DX=ptr, CX=len, R8=cap

View File

@@ -518,42 +518,13 @@ fn cgtryprop(c: *cgen, n: *node) void = {
// the codegen expects the success value in AX (and BX for str).
// AX=tag, DX=val0, CX=val1 from the call ABI. For str success,
// shuffle (DX,CX) → (AX,BX); else move DX → AX.
// #16: read the STAMPED operand's success-variant type (any source
// shape, any variant order), not a name-keyed call-only lookup of
// the first variant. Mirrors cstage cgen.c:10459-10466
// (success_is_str = type_isstr(succ_t at cg_tagged_success_tag)).
let succisstr: bool = false;
if (n.lhs != nil) {
if (n.lhs.kind == nkind.N_CALL) {
let callee: *node = n.lhs.lhs;
if (callee != nil) {
let cname: str;
cname.ptr = nil; cname.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
cname = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
cname = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (cname.len > 0) {
let rtyp: *node = fnretlookupmod(c, cname, cmod);
if (rtyp != nil) {
if (rtyp.kind == nkind.N_TTAGGED) {
let first: *node = rtyp.list;
if (first != nil) {
if (isstrtype(c, first)) {
succisstr = true;
};
};
};
};
};
};
};
succisstr = typeisstr(successvariant(n.lhs.type_: *tinfo));
};
if (succisstr) {
// str IS []u8: success arrives DX=ptr, CX=len, R8=cap
@@ -616,42 +587,11 @@ fn cgtryunw(c: *cgen, n: *node) void = {
if (cgtrytupleshift(c, n)) { return; };
if (cgtrytaggedshift(c, n)) { return; };
// Unwrap success value. (Same shuffle pattern as cgtryprop.)
// #16: stamped success-variant type, any source/order (twin of
// cgtryprop; cstage cgen.c:10595-10602).
let succisstr: bool = false;
if (n.lhs != nil) {
if (n.lhs.kind == nkind.N_CALL) {
let callee: *node = n.lhs.lhs;
if (callee != nil) {
let cname: str;
cname.ptr = nil; cname.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
cname = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
cname = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (cname.len > 0) {
let rtyp: *node = fnretlookupmod(c, cname, cmod);
if (rtyp != nil) {
if (rtyp.kind == nkind.N_TTAGGED) {
let first: *node = rtyp.list;
if (first != nil) {
if (isstrtype(c, first)) {
succisstr = true;
};
};
};
};
};
};
};
succisstr = typeisstr(successvariant(n.lhs.type_: *tinfo));
};
if (succisstr) {
// str IS []u8: success arrives DX=ptr, CX=len, R8=cap

View File

@@ -23738,42 +23738,13 @@ fn cgtryprop(c: *cgen, n: *node) void = {
// the codegen expects the success value in AX (and BX for str).
// AX=tag, DX=val0, CX=val1 from the call ABI. For str success,
// shuffle (DX,CX) → (AX,BX); else move DX → AX.
// #16: read the STAMPED operand's success-variant type (any source
// shape, any variant order), not a name-keyed call-only lookup of
// the first variant. Mirrors cstage cgen.c:10459-10466
// (success_is_str = type_isstr(succ_t at cg_tagged_success_tag)).
let succisstr: bool = false;
if (n.lhs != nil) {
if (n.lhs.kind == nkind.N_CALL) {
let callee: *node = n.lhs.lhs;
if (callee != nil) {
let cname: str;
cname.ptr = nil; cname.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
cname = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
cname = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (cname.len > 0) {
let rtyp: *node = fnretlookupmod(c, cname, cmod);
if (rtyp != nil) {
if (rtyp.kind == nkind.N_TTAGGED) {
let first: *node = rtyp.list;
if (first != nil) {
if (isstrtype(c, first)) {
succisstr = true;
};
};
};
};
};
};
};
succisstr = typeisstr(successvariant(n.lhs.type_: *tinfo));
};
if (succisstr) {
// str IS []u8: success arrives DX=ptr, CX=len, R8=cap
@@ -23836,42 +23807,11 @@ fn cgtryunw(c: *cgen, n: *node) void = {
if (cgtrytupleshift(c, n)) { return; };
if (cgtrytaggedshift(c, n)) { return; };
// Unwrap success value. (Same shuffle pattern as cgtryprop.)
// #16: stamped success-variant type, any source/order (twin of
// cgtryprop; cstage cgen.c:10595-10602).
let succisstr: bool = false;
if (n.lhs != nil) {
if (n.lhs.kind == nkind.N_CALL) {
let callee: *node = n.lhs.lhs;
if (callee != nil) {
let cname: str;
cname.ptr = nil; cname.len = 0;
let cmod: str;
cmod.ptr = nil; cmod.len = 0;
if (callee.kind == nkind.N_IDENT) {
cname = callee.str;
cmod = c.curmod;
};
if (callee.kind == nkind.N_DOT) {
cname = callee.str;
if (callee.lhs != nil) {
if (callee.lhs.kind == nkind.N_IDENT) {
cmod = callee.lhs.str;
};
};
};
if (cname.len > 0) {
let rtyp: *node = fnretlookupmod(c, cname, cmod);
if (rtyp != nil) {
if (rtyp.kind == nkind.N_TTAGGED) {
let first: *node = rtyp.list;
if (first != nil) {
if (isstrtype(c, first)) {
succisstr = true;
};
};
};
};
};
};
};
succisstr = typeisstr(successvariant(n.lhs.type_: *tinfo));
};
if (succisstr) {
// str IS []u8: success arrives DX=ptr, CX=len, R8=cap