w6c+w6c_ww: append() stores the full element width per element kind (fix #34)
Both stages lowered the append element store as one sized mov from AX — correct only for scalars <= 8B. A str/slice element kept only .ptr (byte-id-blind), a tagged element got its raw payload written into the tag slot (the #12 pathology, no boxing), a struct element kept only its first qword. wwstage additionally fed rt_ensure membsz from bare elemsizeof, whose 8-sentinel under-allocated and mis-strided named tagged/struct elements (the #8 family; cs!=ww on the SI imm + stride). Fix, keyed on the DECLARED slice local's element type (cstage su->sub->size as before; wwstage elemsizeofc off the stamped tnode — never the value node, the #25/#31 esz=0 trap), applied to both the single-value and spread bodies (2 arms x 2 stages): - scalar 1/2/4/8: untouched (u8 asm byte-identical to pre-fix). - str/slice: AX/BX/CX pushed across rt_ensure, dst in DX (BX holds the element .len after the pops — the #24 register discipline), 3-word store. - tagged: grow first, dst -> BX, box via the #12 widen choke-point (cg_widen_tagged_store / cgwidentaggedstore via_outer). - struct: grow first; literal -> dst spilled to per-fn @appendscr (cached on cstage to mirror wwstage's @-prefix localadd dedup) + structlit fill DST_PTR_LOCAL; local ident -> word-copy; any other source shape is a rule-7 loud-stop, never a silent scalar fall-through. struct-from-call deferred. - spread: the source element is already a fully-formed T (tag included), so the wide arm grows first and whole-width word-copies &items[i] -> dst, recomputing both addresses from the slice headers after the possibly-reallocating rt_ensure. The elemsizeofc swap also corrects the named-scalar-alias membsz (wwstage fed SI=$8 where cstage fed $4); no in-tree consumer appended to such a slice, so nothing was riding the wrong 8 (lib/selfhost append sites are all u8). Test 800_append_wide_elem: 13 rows (runtime readback per kind, 2-append realloc survival, spread str+tagged, @appendscr dedup, enum-alias esz, loud-stop build-fail) + per-row cs==ww byte-id, which subsumes the frame canary.
This commit is contained in:
12
Makefile
12
Makefile
@@ -382,6 +382,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
|
||||
$(BIN)/test_globalidx_run \
|
||||
$(BIN)/test_tuple_sret_callee \
|
||||
$(BIN)/test_tuple_sret_receive_run \
|
||||
$(BIN)/test_append_wide_elem \
|
||||
$(BIN)/test_struct_tuple_field_slot \
|
||||
$(BIN)/test_widen_pad_zero_run \
|
||||
$(BIN)/test_named_ptr_alias_variant_widen \
|
||||
@@ -983,6 +984,17 @@ $(BIN)/test_tuple_sret_receive_run: test/wcc/799_tuple_sret_receive_run.c \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
# #34: append() stores the full element width per element kind — runtime
|
||||
# readback (tagged box / str+slice 3-word header / struct fill / spread
|
||||
# word-copy / 2-append realloc survival) + per-row cs==ww byte-id (which
|
||||
# pins the wwstage elemsizeofc membsz, scratch order, and frame canary)
|
||||
# + the rule-7 loud-stop for the deferred struct-from-call source shape.
|
||||
$(BIN)/test_append_wide_elem: test/wcc/800_append_wide_elem.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6c_ww $(BIN)/w6a $(BIN)/w6l \
|
||||
$(BIN)/ww_ww \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
# #237: a tuple-typed struct field must contribute its real slot width to
|
||||
# the enclosing struct's slotsize — pure cs==ww .s byte-id (frame size).
|
||||
$(BIN)/test_struct_tuple_field_slot: test/wcc/930_struct_tuple_field_slot.c \
|
||||
|
||||
Reference in New Issue
Block a user