w6c: fix global-ptr field-store SEGV via decline-to-resolver (#6)

A module-global pointer's field store/compound (`let gp:*S=nil; gp.f += 5`,
`gp.in = Inner{...}`) SEGV'd in cstage: the enumerated N_DOT-lhs arms load
the base pointer with `MOVQ boff(BP),BX`, valid only for a LOCAL ptr slot,
but a module-global ptr has no local slot (localfind=0) so it dereferenced
the saved BP. wwstage was correct -- it routes these through its F6
cgplaceaddr resolver (its dedicated arm is scalar-`=`-only by design,
#60/#61). The byte-id gate was blind (no global-ptr compound in the
bootstrap corpus) and the deferral note was stale: this is a live cs!=ww
divergence with wwstage as the oracle.

cstage already has an equivalent assign-resolver (cgen.c ~7488) that emits
byte-identically to wwstage's F6 route, but the enumerated arms intercepted
the global case first. Fix (align cstage UP, cstage-only): two precondition
entry-guards decline a module-global `*struct` base for the compound +
non-scalar-field cases so they fall through to the resolver. Plain-scalar
`=` stays in the enumerated arm (its #47 fix already matches wwstage). The
decline and resolver accept-sets exactly partition the global-base
N_DOT-lhs space (no gap, no overlap); tagged/float field stores now both
loud-stop symmetrically (were SEGV'ing). The discriminant keys on
localfind-presence + let_islet, so a param at offset 0 stays local.

New both-stage + byte-id test 689_globptr_field_store_run covers offset-0/8,
compound, struct/str field, chained gp.x.y, indexed gp.a[i].f, with local +
offset-0-param controls. The field-READ path is independently broken in
both stages (filed #15). make clean && make test: all 403 passed, byte-id
990-996 green.
This commit is contained in:
2026-06-23 01:12:27 +09:00
parent 30a4920ccf
commit 02967e04ce
3 changed files with 309 additions and 2 deletions

View File

@@ -325,6 +325,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
$(BIN)/test_global_arr_elem_field \
$(BIN)/test_structlit_slice_field \
$(BIN)/test_arrglob_nodup_run \
$(BIN)/test_globptr_field_store_run \
$(BIN)/test_dot_str_chained_arg \
$(BIN)/test_dot_slice_arg \
$(BIN)/test_dot_tagged_source \
@@ -1448,6 +1449,15 @@ $(BIN)/test_arrglob_nodup_run: test/wcc/689_arrglob_nodup_run.c $(BIN)/ww \
$(LIB)/libwwrt.a | $(BIN)
$(CC) $(CFLAGS) -o $@ $<
# 689_globptr_field_store_run (#6): a module-global *struct ptr base field
# store (compound / non-scalar / chained / indexed) no longer SEGVs in cstage
# and is byte-identical to wwstage (cstage aligned UP via decline-to-resolver).
$(BIN)/test_globptr_field_store_run: test/wcc/689_globptr_field_store_run.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 \