w6c+w6c_ww: emit module-level slice-literal static-init (header+backing+reloc) (fix #10 part a)

`let g: []T = [v0, v1, …];` at module scope had no cgen arm: emit_lets /
emitletdataw handled str-lit and array-lit but not slice-lit, so NO
`DATAW main.g` was emitted and BOTH stages failed to link ("undefined
reference to main.g"). byte-id-blind — only the link step exposed it.

emit_slice_data / emitslicedata (parallel to the #18 str-array reloc
helper, generalized to a 24B header + array-backed data):
  1. writable backing DATAW "<mangled g>.d" holding the k element bytes,
     routed through the emit_array_lit_bytes / emitarraylitbytes choke-
     point via a synthesized [k]T (int/float element kinds reduce exactly
     as a [N]T global's do);
  2. 24B header { ptr-placeholder, LE len, LE cap } (len = cap = k), word
     sizes from the type table (ty_uintptr/ty_size, primtypesize) per
     rule-13;
  3. DATAR g+0 -> backing patches the ptr word.
The backing label's second '.' can't collide with a user global (source
identifiers carry no '.').

New emit_lets / slice arm gated on N_ARRLIT + slice-typed; rides on #18,
which keeps the module-level initializer as N_ARRLIT in both stages.

Aliased-slice spelling (`type S = []T; let g: S = [...]`): cstage
let_isslice already resolves the alias via type_unwrap, but wwstage
letvarisslice keyed only on the syntactic N_TSLICE node — unlike its
siblings letvarisstr/letvarisstruct/letvarisfloat, which all walk the
N_TNAME alias chain. So an aliased-slice global misrouted to the str arm
and never reached emitslicedata, link-failing on wwstage while cstage
emitted correctly (a cs≠ww divergence this fix would otherwise introduce).
letvarisslice now walks the alias chain exactly as letvarisstr does
(align wwstage UP to runtime-correct cstage, the #211 pattern); an alias
of a slice IS a slice. emitslicedata gains the nil/non-slice guard cstage
emit_slice_data already had (rule-10 symmetry; unreachable behind the
gate, guards the su.sub deref).

rule-7 loud-stops, symmetric both stages: read-only `def` slice-literal
(DATAR holder must be DATAW, w6a asm.c:362), `...` repeat (a slice
literal has no target length), and slice-of-{str,slice,tagged} elements
(per-element relocs / #17) — never silent no-emit.

Deferred (filed): struct-element module-level slice-literal surfaces a
separate checker cs!=ww ("let: not assignable" on wwstage, wrong runtime
on cstage) — out of #10's data-emission scope.

Test 687 (table-driven): []u8/[]i64/[]i32 element read-back + len + cap +
1-element edge + aliased-slice-type, dual-stage runtime + asm byte-id,
plus 3 build-fail rows for the loud-stops. selfhost combined.ww
regenerated.
This commit is contained in:
2026-06-03 21:25:09 +09:00
parent ad00114c7f
commit d40224755a
6 changed files with 894 additions and 144 deletions

View File

@@ -244,6 +244,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_arr_tagged_elem \
$(BIN)/test_arr_infer_len \
$(BIN)/test_slice_str_global_zero \
$(BIN)/test_slice_literal_global \
$(BIN)/test_dot_str_chained_arg \
$(BIN)/test_dot_slice_arg \
$(BIN)/test_dot_tagged_source \
@@ -582,6 +583,12 @@ $(BIN)/test_slice_str_global_zero: test/wcc/686_slice_str_global_zero.c $(BIN)/w
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_slice_literal_global: test/wcc/687_slice_literal_global.c $(BIN)/ww \
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
$(BIN)/test_dot_str_chained_arg: test/wcc/692_dot_str_chained_arg.c $(BIN)/ww \
$(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \