w6c+w6c_ww: struct-lit store into indexed/deref/field place fills via resolver (#20)
A struct-LITERAL rhs aimed at an N_INDEX element (a[i] = pt{...},
(*ts)[i].caps[k] = capture{...}), an N_UN deref place (*p = pt{...}),
or an indexed-base FIELD place (a[i].f = pt{...}, reviewer-20 sibling)
fell to a scalar store tail in BOTH stages: cgexpr on a struct
literal emits nothing (AX=0) and one MOVQ zeroed the place's first
word — every field silently dropped, a str-leading element's
content.ptr nulled (downstream SEGFAULT). Byte-identically wrong, so
every byte-id gate was blind; runtime pins added.
Fix: divert struct-lit-rhs INDEX/UN-STAR/DOT-over-INDEX places past
the legacy arms and widen the F6 assign-resolver gate
(N_DOT -> N_DOT|N_INDEX|N_UN); the existing C1.25 aggregate arm
materialises the literal into a fresh per-use @placescr slot and
word-copies to the cgplaceaddr-resolved address. No new path;
@placescr alloc site stays single per stage. Rider (task #32): an
array-LITERAL rhs at assignment — unwired for EVERY place kind, same
silent zero-word tail — now dies loud at one choke-point until the
fill lands; build-fail rows pin it.
Gates regex fold-5a (run_thread groupstart capture store,
regex.ha:643-651). Residual adjacent gaps (deref ident-rhs truncation,
>24B ident reassign cs!=ww, struct compound acceptance, value-global
DATAW, tuple-lit deref truncation, CALL-rhs RAX-only store) probed
pre-existing and filed as tasks #31 A-G / #32.
This commit is contained in:
@@ -27248,6 +27248,42 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
|
||||
fn cgassign(c: *cgen, n: *node) void = {
|
||||
let lhs: *node = n.lhs;
|
||||
// #20 (task): struct-lit rhs into an INDEXED struct element —
|
||||
// `a[i] = pt{...}`, `(*ts)[i].caps[k] = capture{...}` — a
|
||||
// DEREF place (`*p = pt{...}`) or an indexed-base FIELD place
|
||||
// (`a[i].f = pt{...}`, same class) skips the legacy arms and
|
||||
// routes to the resolver aggregate arm below (the single
|
||||
// @placescr funnel). The legacy arms' rhs handling (#270-1b
|
||||
// ident/dot/deref gate; deref scalar store; the a[i].f
|
||||
// fldstoreop tail) let the lit fall to a scalar tail:
|
||||
// cgexpr(N_STRUCTLIT) emits nothing (AX=0) and one MOVQ zeroed
|
||||
// the place's first word — every field silently dropped, a
|
||||
// leading str header trashed.
|
||||
let placeslit: bool = false;
|
||||
let placedotidx: bool = false;
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil) {
|
||||
if (lhs.lhs.kind == nkind.N_INDEX) {
|
||||
placedotidx = true;
|
||||
};
|
||||
};
|
||||
if ((lhs.kind == nkind.N_INDEX
|
||||
|| (lhs.kind == nkind.N_UN && lhs.op == tkind.TK_STAR)
|
||||
|| placedotidx)
|
||||
&& n.op == tkind.TK_ASSIGN && n.rhs != nil) {
|
||||
if (n.rhs.kind == nkind.N_STRUCTLIT) {
|
||||
let iet: *tinfo = lhs.type_: *tinfo;
|
||||
for (iet != nil && iet.kind == tykind.TY_NAMED) {
|
||||
iet = iet.under;
|
||||
};
|
||||
if (iet != nil) {
|
||||
if (iet.kind == tykind.TY_STRUCT) {
|
||||
placeslit = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Discard lvalue `_ = expr;` — evaluate rhs for side effects,
|
||||
// write nothing. Detected by lhs being an nkind.N_IDENT with empty str
|
||||
// (planted by parseprimary on the tkind.TK_UNDER token).
|
||||
@@ -27261,6 +27297,26 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// Task #32: an array-LITERAL rhs at assignment is unwired for
|
||||
// EVERY place kind (ident reassign, index, deref, dot) — only
|
||||
// decl-init fills. Pre-#32 the same scalar tail zeroed one
|
||||
// word silently; die loud until the fill lands. Slice-typed
|
||||
// places are already loud in the checker.
|
||||
if (n.op == tkind.TK_ASSIGN && lhs != nil && n.rhs != nil) {
|
||||
if (n.rhs.kind == nkind.N_ARRLIT) {
|
||||
let alt: *tinfo = lhs.type_: *tinfo;
|
||||
for (alt != nil && alt.kind == tykind.TY_NAMED) {
|
||||
alt = alt.under;
|
||||
};
|
||||
if (alt != nil) {
|
||||
if (alt.kind == tykind.TY_ARRAY) {
|
||||
let mal: str = "array-literal store at assignment unwired (task #32)\n";
|
||||
os.write(2, mal.ptr, mal.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Tagged-union local reassignment: `r = expr;` where r has a
|
||||
// tagged-union type. Delegate to cgwidentaggedstore (same path
|
||||
// as cglet's tagged-init). Covers nullable fold, tagged source,
|
||||
@@ -27341,10 +27397,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// and BX if str), push, eval pointer, pop value, store.
|
||||
// We default to MOVQ (8B) since most fixtures use it; for
|
||||
// `*bool` / `*u8` / `*i32` we narrow via the local's tnode.
|
||||
// Retained gap: an aggregate >8B rhs (ident, tuple-lit, call)
|
||||
// truncates to one word here — task #31 A/E/G; struct-lit
|
||||
// diverts at the placeslit gate, array-lit dies loud (#32).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_UN) {
|
||||
if (lhs.op == tkind.TK_STAR) {
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
if (n.op == tkind.TK_ASSIGN && !placeslit) {
|
||||
let inner: *node = lhs.lhs;
|
||||
let elemstr: bool = false;
|
||||
let elemfloat: bool = false;
|
||||
@@ -27552,7 +27611,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// Array/slice/ptr index store: `arr[i] = v;`. Element size
|
||||
// from base.tnode picks MOVB vs MOVQ.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_INDEX) {
|
||||
if (lhs.kind == nkind.N_INDEX && !placeslit) {
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
let base: *node = lhs.lhs;
|
||||
let idx: *node = lhs.rhs;
|
||||
@@ -27771,8 +27830,10 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// address, then word-copy esz bytes: the WRITE-twin of
|
||||
// the #268 let-init copy loop. Source shapes mirror that
|
||||
// loop (ident, N_DOT field via dotchainaddr, `*p`
|
||||
// deref); a by-value call result is the deferred #271, so
|
||||
// N_CALL/literal sources fall through unchanged. esz>8
|
||||
// deref); struct-lit sources divert at the placeslit
|
||||
// gate above (#20), array-lit dies loud (task #32), and
|
||||
// a by-value call result still falls to the scalar tail
|
||||
// — RAX-only store, task #31-G. esz>8
|
||||
// non-str/non-slice IS a struct/array/tuple here (the
|
||||
// tagged element already returned above; floats are ≤8).
|
||||
let aggsrc: bool = (n.rhs.kind == nkind.N_IDENT)
|
||||
@@ -28196,7 +28257,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// field write).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil
|
||||
&& lhs.lhs.kind == nkind.N_INDEX) {
|
||||
&& lhs.lhs.kind == nkind.N_INDEX && !placeslit) {
|
||||
let idxbase: *node = lhs.lhs.lhs;
|
||||
let idx: *node = lhs.lhs.rhs;
|
||||
let fld2: str = lhs.str;
|
||||
@@ -30569,8 +30630,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// N_DOT shape the resolver can't address dies LOUD below: the
|
||||
// pre-C1 fall-off-the-function tail silently emitted NOTHING
|
||||
// (rhs unevaluated). Mirror of the cstage cgen.c N_ASSIGN arm.
|
||||
// #20 (task): N_INDEX and N_UN(STAR) lvalues enroll too — only
|
||||
// the struct-lit-rhs diversion above reaches here (every other
|
||||
// indexed/deref shape returned from its legacy arm), and the
|
||||
// C1.25 aggregate branch fills via @placescr.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT) {
|
||||
if (lhs.kind == nkind.N_DOT || lhs.kind == nkind.N_INDEX
|
||||
|| (lhs.kind == nkind.N_UN && lhs.op == tkind.TK_STAR)) {
|
||||
let ft: *tinfo = lhs.type_: *tinfo;
|
||||
let fu: *tinfo = ft;
|
||||
for (fu != nil && fu.kind == tykind.TY_NAMED) {
|
||||
|
||||
@@ -6814,6 +6814,42 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
|
||||
fn cgassign(c: *cgen, n: *node) void = {
|
||||
let lhs: *node = n.lhs;
|
||||
// #20 (task): struct-lit rhs into an INDEXED struct element —
|
||||
// `a[i] = pt{...}`, `(*ts)[i].caps[k] = capture{...}` — a
|
||||
// DEREF place (`*p = pt{...}`) or an indexed-base FIELD place
|
||||
// (`a[i].f = pt{...}`, same class) skips the legacy arms and
|
||||
// routes to the resolver aggregate arm below (the single
|
||||
// @placescr funnel). The legacy arms' rhs handling (#270-1b
|
||||
// ident/dot/deref gate; deref scalar store; the a[i].f
|
||||
// fldstoreop tail) let the lit fall to a scalar tail:
|
||||
// cgexpr(N_STRUCTLIT) emits nothing (AX=0) and one MOVQ zeroed
|
||||
// the place's first word — every field silently dropped, a
|
||||
// leading str header trashed.
|
||||
let placeslit: bool = false;
|
||||
let placedotidx: bool = false;
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil) {
|
||||
if (lhs.lhs.kind == nkind.N_INDEX) {
|
||||
placedotidx = true;
|
||||
};
|
||||
};
|
||||
if ((lhs.kind == nkind.N_INDEX
|
||||
|| (lhs.kind == nkind.N_UN && lhs.op == tkind.TK_STAR)
|
||||
|| placedotidx)
|
||||
&& n.op == tkind.TK_ASSIGN && n.rhs != nil) {
|
||||
if (n.rhs.kind == nkind.N_STRUCTLIT) {
|
||||
let iet: *tinfo = lhs.type_: *tinfo;
|
||||
for (iet != nil && iet.kind == tykind.TY_NAMED) {
|
||||
iet = iet.under;
|
||||
};
|
||||
if (iet != nil) {
|
||||
if (iet.kind == tykind.TY_STRUCT) {
|
||||
placeslit = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Discard lvalue `_ = expr;` — evaluate rhs for side effects,
|
||||
// write nothing. Detected by lhs being an nkind.N_IDENT with empty str
|
||||
// (planted by parseprimary on the tkind.TK_UNDER token).
|
||||
@@ -6827,6 +6863,26 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// Task #32: an array-LITERAL rhs at assignment is unwired for
|
||||
// EVERY place kind (ident reassign, index, deref, dot) — only
|
||||
// decl-init fills. Pre-#32 the same scalar tail zeroed one
|
||||
// word silently; die loud until the fill lands. Slice-typed
|
||||
// places are already loud in the checker.
|
||||
if (n.op == tkind.TK_ASSIGN && lhs != nil && n.rhs != nil) {
|
||||
if (n.rhs.kind == nkind.N_ARRLIT) {
|
||||
let alt: *tinfo = lhs.type_: *tinfo;
|
||||
for (alt != nil && alt.kind == tykind.TY_NAMED) {
|
||||
alt = alt.under;
|
||||
};
|
||||
if (alt != nil) {
|
||||
if (alt.kind == tykind.TY_ARRAY) {
|
||||
let mal: str = "array-literal store at assignment unwired (task #32)\n";
|
||||
os.write(2, mal.ptr, mal.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Tagged-union local reassignment: `r = expr;` where r has a
|
||||
// tagged-union type. Delegate to cgwidentaggedstore (same path
|
||||
// as cglet's tagged-init). Covers nullable fold, tagged source,
|
||||
@@ -6907,10 +6963,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// and BX if str), push, eval pointer, pop value, store.
|
||||
// We default to MOVQ (8B) since most fixtures use it; for
|
||||
// `*bool` / `*u8` / `*i32` we narrow via the local's tnode.
|
||||
// Retained gap: an aggregate >8B rhs (ident, tuple-lit, call)
|
||||
// truncates to one word here — task #31 A/E/G; struct-lit
|
||||
// diverts at the placeslit gate, array-lit dies loud (#32).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_UN) {
|
||||
if (lhs.op == tkind.TK_STAR) {
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
if (n.op == tkind.TK_ASSIGN && !placeslit) {
|
||||
let inner: *node = lhs.lhs;
|
||||
let elemstr: bool = false;
|
||||
let elemfloat: bool = false;
|
||||
@@ -7118,7 +7177,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// Array/slice/ptr index store: `arr[i] = v;`. Element size
|
||||
// from base.tnode picks MOVB vs MOVQ.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_INDEX) {
|
||||
if (lhs.kind == nkind.N_INDEX && !placeslit) {
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
let base: *node = lhs.lhs;
|
||||
let idx: *node = lhs.rhs;
|
||||
@@ -7337,8 +7396,10 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// address, then word-copy esz bytes: the WRITE-twin of
|
||||
// the #268 let-init copy loop. Source shapes mirror that
|
||||
// loop (ident, N_DOT field via dotchainaddr, `*p`
|
||||
// deref); a by-value call result is the deferred #271, so
|
||||
// N_CALL/literal sources fall through unchanged. esz>8
|
||||
// deref); struct-lit sources divert at the placeslit
|
||||
// gate above (#20), array-lit dies loud (task #32), and
|
||||
// a by-value call result still falls to the scalar tail
|
||||
// — RAX-only store, task #31-G. esz>8
|
||||
// non-str/non-slice IS a struct/array/tuple here (the
|
||||
// tagged element already returned above; floats are ≤8).
|
||||
let aggsrc: bool = (n.rhs.kind == nkind.N_IDENT)
|
||||
@@ -7762,7 +7823,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// field write).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil
|
||||
&& lhs.lhs.kind == nkind.N_INDEX) {
|
||||
&& lhs.lhs.kind == nkind.N_INDEX && !placeslit) {
|
||||
let idxbase: *node = lhs.lhs.lhs;
|
||||
let idx: *node = lhs.lhs.rhs;
|
||||
let fld2: str = lhs.str;
|
||||
@@ -10135,8 +10196,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// N_DOT shape the resolver can't address dies LOUD below: the
|
||||
// pre-C1 fall-off-the-function tail silently emitted NOTHING
|
||||
// (rhs unevaluated). Mirror of the cstage cgen.c N_ASSIGN arm.
|
||||
// #20 (task): N_INDEX and N_UN(STAR) lvalues enroll too — only
|
||||
// the struct-lit-rhs diversion above reaches here (every other
|
||||
// indexed/deref shape returned from its legacy arm), and the
|
||||
// C1.25 aggregate branch fills via @placescr.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT) {
|
||||
if (lhs.kind == nkind.N_DOT || lhs.kind == nkind.N_INDEX
|
||||
|| (lhs.kind == nkind.N_UN && lhs.op == tkind.TK_STAR)) {
|
||||
let ft: *tinfo = lhs.type_: *tinfo;
|
||||
let fu: *tinfo = ft;
|
||||
for (fu != nil && fu.kind == tykind.TY_NAMED) {
|
||||
|
||||
@@ -27248,6 +27248,42 @@ fn cgcall(c: *cgen, n: *node) void = {
|
||||
|
||||
fn cgassign(c: *cgen, n: *node) void = {
|
||||
let lhs: *node = n.lhs;
|
||||
// #20 (task): struct-lit rhs into an INDEXED struct element —
|
||||
// `a[i] = pt{...}`, `(*ts)[i].caps[k] = capture{...}` — a
|
||||
// DEREF place (`*p = pt{...}`) or an indexed-base FIELD place
|
||||
// (`a[i].f = pt{...}`, same class) skips the legacy arms and
|
||||
// routes to the resolver aggregate arm below (the single
|
||||
// @placescr funnel). The legacy arms' rhs handling (#270-1b
|
||||
// ident/dot/deref gate; deref scalar store; the a[i].f
|
||||
// fldstoreop tail) let the lit fall to a scalar tail:
|
||||
// cgexpr(N_STRUCTLIT) emits nothing (AX=0) and one MOVQ zeroed
|
||||
// the place's first word — every field silently dropped, a
|
||||
// leading str header trashed.
|
||||
let placeslit: bool = false;
|
||||
let placedotidx: bool = false;
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil) {
|
||||
if (lhs.lhs.kind == nkind.N_INDEX) {
|
||||
placedotidx = true;
|
||||
};
|
||||
};
|
||||
if ((lhs.kind == nkind.N_INDEX
|
||||
|| (lhs.kind == nkind.N_UN && lhs.op == tkind.TK_STAR)
|
||||
|| placedotidx)
|
||||
&& n.op == tkind.TK_ASSIGN && n.rhs != nil) {
|
||||
if (n.rhs.kind == nkind.N_STRUCTLIT) {
|
||||
let iet: *tinfo = lhs.type_: *tinfo;
|
||||
for (iet != nil && iet.kind == tykind.TY_NAMED) {
|
||||
iet = iet.under;
|
||||
};
|
||||
if (iet != nil) {
|
||||
if (iet.kind == tykind.TY_STRUCT) {
|
||||
placeslit = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Discard lvalue `_ = expr;` — evaluate rhs for side effects,
|
||||
// write nothing. Detected by lhs being an nkind.N_IDENT with empty str
|
||||
// (planted by parseprimary on the tkind.TK_UNDER token).
|
||||
@@ -27261,6 +27297,26 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
};
|
||||
};
|
||||
};
|
||||
// Task #32: an array-LITERAL rhs at assignment is unwired for
|
||||
// EVERY place kind (ident reassign, index, deref, dot) — only
|
||||
// decl-init fills. Pre-#32 the same scalar tail zeroed one
|
||||
// word silently; die loud until the fill lands. Slice-typed
|
||||
// places are already loud in the checker.
|
||||
if (n.op == tkind.TK_ASSIGN && lhs != nil && n.rhs != nil) {
|
||||
if (n.rhs.kind == nkind.N_ARRLIT) {
|
||||
let alt: *tinfo = lhs.type_: *tinfo;
|
||||
for (alt != nil && alt.kind == tykind.TY_NAMED) {
|
||||
alt = alt.under;
|
||||
};
|
||||
if (alt != nil) {
|
||||
if (alt.kind == tykind.TY_ARRAY) {
|
||||
let mal: str = "array-literal store at assignment unwired (task #32)\n";
|
||||
os.write(2, mal.ptr, mal.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
// Tagged-union local reassignment: `r = expr;` where r has a
|
||||
// tagged-union type. Delegate to cgwidentaggedstore (same path
|
||||
// as cglet's tagged-init). Covers nullable fold, tagged source,
|
||||
@@ -27341,10 +27397,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// and BX if str), push, eval pointer, pop value, store.
|
||||
// We default to MOVQ (8B) since most fixtures use it; for
|
||||
// `*bool` / `*u8` / `*i32` we narrow via the local's tnode.
|
||||
// Retained gap: an aggregate >8B rhs (ident, tuple-lit, call)
|
||||
// truncates to one word here — task #31 A/E/G; struct-lit
|
||||
// diverts at the placeslit gate, array-lit dies loud (#32).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_UN) {
|
||||
if (lhs.op == tkind.TK_STAR) {
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
if (n.op == tkind.TK_ASSIGN && !placeslit) {
|
||||
let inner: *node = lhs.lhs;
|
||||
let elemstr: bool = false;
|
||||
let elemfloat: bool = false;
|
||||
@@ -27552,7 +27611,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// Array/slice/ptr index store: `arr[i] = v;`. Element size
|
||||
// from base.tnode picks MOVB vs MOVQ.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_INDEX) {
|
||||
if (lhs.kind == nkind.N_INDEX && !placeslit) {
|
||||
if (n.op == tkind.TK_ASSIGN) {
|
||||
let base: *node = lhs.lhs;
|
||||
let idx: *node = lhs.rhs;
|
||||
@@ -27771,8 +27830,10 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// address, then word-copy esz bytes: the WRITE-twin of
|
||||
// the #268 let-init copy loop. Source shapes mirror that
|
||||
// loop (ident, N_DOT field via dotchainaddr, `*p`
|
||||
// deref); a by-value call result is the deferred #271, so
|
||||
// N_CALL/literal sources fall through unchanged. esz>8
|
||||
// deref); struct-lit sources divert at the placeslit
|
||||
// gate above (#20), array-lit dies loud (task #32), and
|
||||
// a by-value call result still falls to the scalar tail
|
||||
// — RAX-only store, task #31-G. esz>8
|
||||
// non-str/non-slice IS a struct/array/tuple here (the
|
||||
// tagged element already returned above; floats are ≤8).
|
||||
let aggsrc: bool = (n.rhs.kind == nkind.N_IDENT)
|
||||
@@ -28196,7 +28257,7 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// field write).
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT && lhs.lhs != nil
|
||||
&& lhs.lhs.kind == nkind.N_INDEX) {
|
||||
&& lhs.lhs.kind == nkind.N_INDEX && !placeslit) {
|
||||
let idxbase: *node = lhs.lhs.lhs;
|
||||
let idx: *node = lhs.lhs.rhs;
|
||||
let fld2: str = lhs.str;
|
||||
@@ -30569,8 +30630,13 @@ fn cgassign(c: *cgen, n: *node) void = {
|
||||
// N_DOT shape the resolver can't address dies LOUD below: the
|
||||
// pre-C1 fall-off-the-function tail silently emitted NOTHING
|
||||
// (rhs unevaluated). Mirror of the cstage cgen.c N_ASSIGN arm.
|
||||
// #20 (task): N_INDEX and N_UN(STAR) lvalues enroll too — only
|
||||
// the struct-lit-rhs diversion above reaches here (every other
|
||||
// indexed/deref shape returned from its legacy arm), and the
|
||||
// C1.25 aggregate branch fills via @placescr.
|
||||
if (lhs != nil) {
|
||||
if (lhs.kind == nkind.N_DOT) {
|
||||
if (lhs.kind == nkind.N_DOT || lhs.kind == nkind.N_INDEX
|
||||
|| (lhs.kind == nkind.N_UN && lhs.op == tkind.TK_STAR)) {
|
||||
let ft: *tinfo = lhs.type_: *tinfo;
|
||||
let fu: *tinfo = ft;
|
||||
for (fu != nil && fu.kind == tykind.TY_NAMED) {
|
||||
|
||||
Reference in New Issue
Block a user