lib/io: empty() stream; wcc/cgen: #129 sretretsize + #130 global tagged-field store

io.empty (discard+EOF stream, ref/hare/io/empty.ha:4-17) — needed by getopt's
two-pass printusage width measurement. Diverges from Hare's `const empty: *stream`:
a `let _empty_vt` + `fn empty()` that wires the fn-ptr slots per call, because
const-init of a vtable struct with fn-ptr fields is blocked (#118, ruled accept).

Co-discovered while making empty() byte-identical across stages: three
wwstage-only cgen fixes (cstage was already correct; wwstage aligned down):
- #129 sretretsize: consult the same-module pointer-alias before structlookup's
  any-module struct fallback (io.stream = *vtable was mis-sized as memio's 56B
  struct -> spurious sret save).
- #129 callsretsize: swap curmod to the callee's module before sret-size
  classification (cross-module callee context).
- #130 cgassign global-struct tagged-union field store: add the missing arm
  (was a 1-word store) mirroring cstage cgen.c:4893-4912.

The three are inseparable from io.empty here — splitting them out leaves a
divergent-asm intermediate (993/995 red), so they ride one commit per the
one-class gate-repair carve-out (#133-expanded precedent). Regenerates the
embedded combined.ww; 989_lib_byteid pins bufio + fmt graduated to M_ID.
(cgenexpr.ww fix-3 inline comment cites the #129 cluster; narrow to #130 on
next touch to avoid a regen for a comment.)
This commit is contained in:
2026-06-07 06:19:13 +09:00
parent 3ae24c22b8
commit f3750ae3ce
7 changed files with 251 additions and 28 deletions

View File

@@ -95,6 +95,15 @@ static const struct ent ents[] = {
{ .fixture = "lib/strings/stringstest.ww", .mode = M_ID },
{ .fixture = "lib/temp/temptest.ww", .mode = M_ID },
{ .fixture = "lib/time/timetest.ww", .mode = M_ID },
/* graduated from #59.2 DIVERGE by the #129 sretretsize fixes
* (same-module alias priority + callsretsize callee-context swap;
* bufio imports io so cross-module io.stream returns were spuriously
* sret-classified, producing divergent caller prologues) */
{ .fixture = "lib/bufio/bufiotest.ww", .mode = M_ID },
/* graduated from #59.6 DIVERGE by the #129 same fix (fmt imports
* io transitively through bufio; sretretsize curmod swap closed
* the getopt.printusage spurious LEAQ DI caller divergence) */
{ .fixture = "lib/fmt/fmttest.ww", .mode = M_ID },
/* fixtureless modules, import-probe shape */
{ .probe = "package main;\nimport sort;\nfn main() i32 = { return 0; };\n",
.mode = M_ID, .sentinel = "package sort;", .moddir = "lib/sort" },
@@ -119,15 +128,13 @@ static const struct ent ents[] = {
/* -------- documented-allowed cs≠ww (task #59) ------------ */
{ .fixture = "lib/ascii/asciitest.ww",
.mode = M_DIVERGE, .cite = "#59.1" },
{ .fixture = "lib/bufio/bufiotest.ww",
.mode = M_DIVERGE, .cite = "#59.2" },
/* #59.2 bufio graduated to M_ID above (#129 fix) */
{ .fixture = "lib/encoding/base64/base64_test.ww",
.mode = M_DIVERGE, .cite = "#59.3" },
/* #59.4 hextest graduated to M_ID above (#22a reviewer fixes) */
{ .fixture = "lib/errors/errnotest.ww",
.mode = M_DIVERGE, .cite = "#59.5" },
{ .fixture = "lib/fmt/fmttest.ww",
.mode = M_DIVERGE, .cite = "#59.6" },
/* #59.6 fmt graduated to M_ID above (#129 fix) */
/* #59.7 siphash graduated to M_ID above (#61 fix) */
{ .fixture = "lib/log/logtest.ww",
.mode = M_DIVERGE, .cite = "#59.8" },