From b416e7114e2781b23563eeb8139d189280d95bab Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sun, 24 May 2026 09:00:53 +0900 Subject: [PATCH] cgen: fold str tagged-variant payload store onto slice arm (both stages) Phase 2 step 4. The str and slice tagged-union payload stores were byte-identical adjacent arms (3-word ptr/len/cap @ slot+8/+16/+24 + tag) since #1 made str a 24B {ptr,len,cap}. Delete the dedicated str arm and widen the slice arm's gate to accept str (cstage type_isstr, wwstage nodeisstr). One site, both stages. Byte-id-neutral: str now flows the identical slice arm; full test incl 990-997 green. --- cmd/w6c/cgen.c | 24 ++++++--------------- selfhost/cmd/w6c/main.combined.ww | 31 +++++----------------------- selfhost/cmd/wcc/cgenutil.ww | 31 +++++----------------------- selfhost/cmd/wwdump/main.combined.ww | 31 +++++----------------------- 4 files changed, 21 insertions(+), 96 deletions(-) diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index 266b660e..40e0fe72 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -1421,24 +1421,12 @@ cg_widen_tagged_store(Cg *c, Local **locals_p, Type *dst, Node *src, if (via_outer) goto copy_out; return; } - /* str IS []u8: AX=ptr, BX=len, CX=cap from cgexpr. Slot layout - * tag@+0, ptr@+8, len@+16, cap@+24 — same 32B shape as the slice - * payload below (#1/Phase 3). */ - if (type_isstr(st) || (su && su->kind == TY_STR)) { - cgexpr(c, src, *locals_p); - ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, write_off + 8)); - ins2(c, A_MOVQ, areg(D_BX), amem(D_BP, write_off + 16)); - ins2(c, A_MOVQ, areg(D_CX), amem(D_BP, write_off + 24)); - int tag = cg_tag_for_variant(du, st); - ins2(c, A_MOVQ, aimm(tag < 0 ? 0 : tag), - amem(D_BP, write_off + 0)); - if (via_outer) goto copy_out; - return; - } - /* Slice payload: cgexpr leaves (AX=ptr, BX=len, CX=cap). The - * slot layout is tag@+0, ptr@+8, len@+16, cap@+24 — requires the - * destination tagged-union slot be at least 32B. */ - if (type_isslice(st) || (su && su->kind == TY_SLICE)) { + /* str IS []u8 — same 32B payload as a slice: cgexpr leaves + * (AX=ptr, BX=len, CX=cap); slot layout tag@+0, ptr@+8, len@+16, + * cap@+24, destination slot >= 32B. str folds onto the slice arm + * (#1/Phase 3 collapse). */ + if (type_isslice(st) || (su && su->kind == TY_SLICE) || + type_isstr(st) || (su && su->kind == TY_STR)) { cgexpr(c, src, *locals_p); ins2(c, A_MOVQ, areg(D_AX), amem(D_BP, write_off + 8)); ins2(c, A_MOVQ, areg(D_BX), amem(D_BP, write_off + 16)); diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index 8cb708d6..23723cd3 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -13176,32 +13176,11 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s return; }; }; - // str IS []u8: AX=ptr, BX=len, CX=cap from cgexpr. Slot layout - // tag@+0, ptr@+8, len@+16, cap@+24 — same 32B shape as the slice - // payload below (#1/Phase 3). - if (nodeisstr(c, src)) { - cgexpr(c, src); - emitline("\tMOVQ\tAX, "); - emitoff((slot_off + 8): i64); - emitline("(BP)\n"); - emitline("\tMOVQ\tBX, "); - emitoff((slot_off + 16): i64); - emitline("(BP)\n"); - emitline("\tMOVQ\tCX, "); - emitoff((slot_off + 24): i64); - emitline("(BP)\n"); - let tag: i32 = taggedvariantindext(c, dt, src); - if (tag < 0) { tag = 0; }; - emitline("\tMOVQ\t$"); - emitint(tag: i64); - emitline(", "); - emitoff(slot_off: i64); - emitline("(BP)\n"); - return; - }; - // Slice payload (24B): cgexpr leaves (AX=ptr, BX=len, CX=cap). - // Slot layout: [+0]=tag, [+8]=ptr, [+16]=len, [+24]=cap. - if (nodeisslice(c, src)) { + // str IS []u8 — same 32B payload as a slice: cgexpr leaves + // (AX=ptr, BX=len, CX=cap); slot layout [+0]=tag, [+8]=ptr, + // [+16]=len, [+24]=cap. str folds onto the slice arm (#1/Phase 3 + // collapse; cite cstage cg_widen_tagged_store). + if (nodeisslice(c, src) || nodeisstr(c, src)) { cgexpr(c, src); emitline("\tMOVQ\tAX, "); emitoff((slot_off + 8): i64); diff --git a/selfhost/cmd/wcc/cgenutil.ww b/selfhost/cmd/wcc/cgenutil.ww index c1270f66..5d69602d 100644 --- a/selfhost/cmd/wcc/cgenutil.ww +++ b/selfhost/cmd/wcc/cgenutil.ww @@ -2616,32 +2616,11 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s return; }; }; - // str IS []u8: AX=ptr, BX=len, CX=cap from cgexpr. Slot layout - // tag@+0, ptr@+8, len@+16, cap@+24 — same 32B shape as the slice - // payload below (#1/Phase 3). - if (nodeisstr(c, src)) { - cgexpr(c, src); - emitline("\tMOVQ\tAX, "); - emitoff((slot_off + 8): i64); - emitline("(BP)\n"); - emitline("\tMOVQ\tBX, "); - emitoff((slot_off + 16): i64); - emitline("(BP)\n"); - emitline("\tMOVQ\tCX, "); - emitoff((slot_off + 24): i64); - emitline("(BP)\n"); - let tag: i32 = taggedvariantindext(c, dt, src); - if (tag < 0) { tag = 0; }; - emitline("\tMOVQ\t$"); - emitint(tag: i64); - emitline(", "); - emitoff(slot_off: i64); - emitline("(BP)\n"); - return; - }; - // Slice payload (24B): cgexpr leaves (AX=ptr, BX=len, CX=cap). - // Slot layout: [+0]=tag, [+8]=ptr, [+16]=len, [+24]=cap. - if (nodeisslice(c, src)) { + // str IS []u8 — same 32B payload as a slice: cgexpr leaves + // (AX=ptr, BX=len, CX=cap); slot layout [+0]=tag, [+8]=ptr, + // [+16]=len, [+24]=cap. str folds onto the slice arm (#1/Phase 3 + // collapse; cite cstage cg_widen_tagged_store). + if (nodeisslice(c, src) || nodeisstr(c, src)) { cgexpr(c, src); emitline("\tMOVQ\tAX, "); emitoff((slot_off + 8): i64); diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 18dfd561..e067c071 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -13176,32 +13176,11 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *tinfo, src: *node, slot_off: i32, slot_s return; }; }; - // str IS []u8: AX=ptr, BX=len, CX=cap from cgexpr. Slot layout - // tag@+0, ptr@+8, len@+16, cap@+24 — same 32B shape as the slice - // payload below (#1/Phase 3). - if (nodeisstr(c, src)) { - cgexpr(c, src); - emitline("\tMOVQ\tAX, "); - emitoff((slot_off + 8): i64); - emitline("(BP)\n"); - emitline("\tMOVQ\tBX, "); - emitoff((slot_off + 16): i64); - emitline("(BP)\n"); - emitline("\tMOVQ\tCX, "); - emitoff((slot_off + 24): i64); - emitline("(BP)\n"); - let tag: i32 = taggedvariantindext(c, dt, src); - if (tag < 0) { tag = 0; }; - emitline("\tMOVQ\t$"); - emitint(tag: i64); - emitline(", "); - emitoff(slot_off: i64); - emitline("(BP)\n"); - return; - }; - // Slice payload (24B): cgexpr leaves (AX=ptr, BX=len, CX=cap). - // Slot layout: [+0]=tag, [+8]=ptr, [+16]=len, [+24]=cap. - if (nodeisslice(c, src)) { + // str IS []u8 — same 32B payload as a slice: cgexpr leaves + // (AX=ptr, BX=len, CX=cap); slot layout [+0]=tag, [+8]=ptr, + // [+16]=len, [+24]=cap. str folds onto the slice arm (#1/Phase 3 + // collapse; cite cstage cg_widen_tagged_store). + if (nodeisslice(c, src) || nodeisstr(c, src)) { cgexpr(c, src); emitline("\tMOVQ\tAX, "); emitoff((slot_off + 8): i64);