From 17765942f9562b4b0bc3bb26336f6cfd5b81bdae Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Thu, 21 May 2026 13:24:27 +0900 Subject: [PATCH] =?UTF-8?q?selfhost/cmd/wcc:=20delete=20mem.ww=20(=CE=B3-7?= =?UTF-8?q?,=20Phase=200=20close)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mem.ww has 0 callers post-γ-6 — newarena/amalloc/grow/freearena/ roundup all unreferenced after the *arena cascade strip. Drop the 91-line module. Makefile: remove mem.ww from 5 dep lists (wwdump_ww, w6c_ww, w6a_ww, w6l_ww, ww_ww); drop `-I selfhost/cmd/wcc` from w6a_ww/ w6l_ww/ww_ww build invocations (wwdump_ww + w6c_ww still need it for check.ww/cgen*.ww). test/wcc/990_selfhost.c: drop 6 mem.ww entries from probe_codegen, probe_dump_diff (×2), probe_resolve, probe_dump_stable, and probe_cgen_match file lists. lib/memio/memio.ww: dynamicgrow doc comment reframed as historical context (collision source is gone, but task #9 keeps the module-prefixed name conservative against future collisions). Two dead `import mem;` lines remain in selfhost/cmd/w6a/asm.ww and selfhost/test/uses.ww; tolerated silently by ww build, swept in task #8. main.combined.ww auto-regenerated for w6a/w6c/wwdump. Verified 132/132 incl. 994_w6c_ww + 995_self_rebuild byte-identity. Phase 0 closes. --- Makefile | 22 +++---- lib/memio/memio.ww | 10 +-- selfhost/cmd/w6a/main.combined.ww | 92 ---------------------------- selfhost/cmd/w6c/main.combined.ww | 10 +-- selfhost/cmd/wcc/mem.ww | 91 --------------------------- selfhost/cmd/wwdump/main.combined.ww | 10 +-- test/wcc/990_selfhost.c | 6 -- 7 files changed, 24 insertions(+), 217 deletions(-) delete mode 100644 selfhost/cmd/wcc/mem.ww diff --git a/Makefile b/Makefile index 36264f54..b5695881 100644 --- a/Makefile +++ b/Makefile @@ -104,12 +104,12 @@ $(OBJ)/w6l/%.o: cmd/w6l/%.c cmd/w6l/l.h | $(OBJ)/w6l # ---- ww-side wwdump (the lexer port, exercised by 990_selfhost) -------- # Built via the user-facing ww driver. The introspection ports (lex, # tok, ast, parse, typ, sym) live in lib/ww/; the compiler-only bits -# (mem, check, cgen*) stay in selfhost/cmd/wcc/. Output named wwdump_ww +# (check, cgen*) stay in selfhost/cmd/wcc/. Output named wwdump_ww # to avoid colliding with the C-side wwdump in $(BIN). $(BIN)/wwdump_ww: selfhost/cmd/wwdump/main.ww \ lib/ww/lex/lex.ww lib/ww/lex/tok.ww lib/ww/ast.ww \ lib/ww/parse/parse.ww lib/ww/parse/expr.ww lib/ww/parse/stmt.ww lib/ww/parse/decl.ww lib/ww/typ.ww lib/ww/sym.ww \ - selfhost/cmd/wcc/mem.ww selfhost/cmd/wcc/check.ww \ + selfhost/cmd/wcc/check.ww \ selfhost/cmd/wcc/cgen.ww selfhost/cmd/wcc/cgenexpr.ww \ selfhost/cmd/wcc/cgenstmt.ww selfhost/cmd/wcc/cgenutil.ww \ selfhost/cmd/wcc/cgendecl.ww \ @@ -131,7 +131,7 @@ $(BIN)/wwdump_ww: selfhost/cmd/wwdump/main.ww \ $(BIN)/w6c_ww: selfhost/cmd/w6c/main.ww \ lib/ww/lex/lex.ww lib/ww/lex/tok.ww lib/ww/ast.ww \ lib/ww/parse/parse.ww lib/ww/parse/expr.ww lib/ww/parse/stmt.ww lib/ww/parse/decl.ww lib/ww/typ.ww lib/ww/sym.ww \ - selfhost/cmd/wcc/mem.ww selfhost/cmd/wcc/check.ww \ + selfhost/cmd/wcc/check.ww \ selfhost/cmd/wcc/cgen.ww selfhost/cmd/wcc/cgenexpr.ww \ selfhost/cmd/wcc/cgenstmt.ww selfhost/cmd/wcc/cgenutil.ww \ selfhost/cmd/wcc/cgendecl.ww \ @@ -149,48 +149,44 @@ $(BIN)/w6c_ww: selfhost/cmd/w6c/main.ww \ # ---- ww-side w6a (assembler port, exercised by 991_w6a_ww) ------------ # Built like wwdump_ww. Needs -I selfhost/cmd/w6a for the local types/lex/ -# parse/asm/obj modules and -I selfhost/cmd/wcc to find `mem`. +# parse/asm/obj modules. $(BIN)/w6a_ww: selfhost/cmd/w6a/main.ww selfhost/cmd/w6a/opcodes.ww \ selfhost/cmd/w6a/lex.ww selfhost/cmd/w6a/parse.ww \ selfhost/cmd/w6a/asm.ww selfhost/cmd/w6a/obj.ww \ - selfhost/cmd/wcc/mem.ww \ lib/os/os.ww lib/rt/malloc.ww lib/time/time.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) @mkdir -p $(BIN)/w6a_ww.d cd $(BIN)/w6a_ww.d && $(CURDIR)/$(BIN)/ww build \ -I $(CURDIR)/selfhost/cmd/w6a \ - -I $(CURDIR)/selfhost/cmd/wcc \ $(CURDIR)/selfhost/cmd/w6a/main.ww mv $(BIN)/w6a_ww.d/main $@ # ---- ww-side w6l (linker port, exercised by 992_w6l_ww) --------------- # Built like 6a_ww. Needs -I selfhost/cmd/w6l for the local sym/obj/pass/ -# out modules and -I selfhost/cmd/wcc to find `mem`. +# out modules. $(BIN)/w6l_ww: selfhost/cmd/w6l/main.ww selfhost/cmd/w6l/sym.ww \ selfhost/cmd/w6l/obj.ww selfhost/cmd/w6l/dyn.ww \ selfhost/cmd/w6l/pass.ww selfhost/cmd/w6l/dynout.ww \ - selfhost/cmd/w6l/out.ww selfhost/cmd/wcc/mem.ww \ + selfhost/cmd/w6l/out.ww \ lib/os/os.ww lib/rt/malloc.ww lib/time/time.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) @mkdir -p $(BIN)/w6l_ww.d cd $(BIN)/w6l_ww.d && $(CURDIR)/$(BIN)/ww build \ -I $(CURDIR)/selfhost/cmd/w6l \ - -I $(CURDIR)/selfhost/cmd/wcc \ $(CURDIR)/selfhost/cmd/w6l/main.ww mv $(BIN)/w6l_ww.d/main $@ # ---- ww-side ww driver (exercised by 993_ww_ww) ------------------------ -# The driver pulls in lib/os (default search path) and selfhost/cmd/wcc -# (for the bump arena). It then orchestrates w6c/w6a/w6l like the C driver. -$(BIN)/ww_ww: selfhost/cmd/ww/main.ww selfhost/cmd/wcc/mem.ww lib/os/os.ww lib/rt/malloc.ww \ +# The driver pulls in lib/os (default search path) and orchestrates +# w6c/w6a/w6l like the C driver. +$(BIN)/ww_ww: selfhost/cmd/ww/main.ww lib/os/os.ww lib/rt/malloc.ww \ lib/time/time.ww lib/strconv/strconv.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) @mkdir -p $(BIN)/ww_ww.d cd $(BIN)/ww_ww.d && $(CURDIR)/$(BIN)/ww build \ - -I $(CURDIR)/selfhost/cmd/wcc \ $(CURDIR)/selfhost/cmd/ww/main.ww mv $(BIN)/ww_ww.d/main $@ diff --git a/lib/memio/memio.ww b/lib/memio/memio.ww index af081c26..88690a8f 100644 --- a/lib/memio/memio.ww +++ b/lib/memio/memio.ww @@ -195,11 +195,11 @@ fn closenoop(s: *io.stream) (void | io.closed) = { // small write bursts without a tail of reallocs. // // `dynamicgrow`, not Hare's bare `grow`: cstage bundles all imported -// modules into a flat TU and resolves private fns by unqualified -// name, so two `fn grow` decls (here + selfhost/cmd/wcc/mem.ww's -// arena `grow`) collide. Module-prefixed name keeps the symmetry -// with `dynamicwrite`/`dynamicclose` until task #9 (module-aware -// private-fn scoping in cstage) lands. +// modules into a flat TU and resolves private fns by unqualified name, +// so historically two `fn grow` decls (here + the now-deleted bump +// arena's `grow`) would have collided. Module-prefixed name kept the +// symmetry with `dynamicwrite`/`dynamicclose`; retained pending task +// #9 (module-aware private-fn scoping in cstage). fn dynamicgrow(m: *state, need: i32) void = { let newcap: i32 = m.cap; if (newcap < 8) { newcap = 8; }; diff --git a/selfhost/cmd/w6a/main.combined.ww b/selfhost/cmd/w6a/main.combined.ww index 4ba02ea3..ea2bfed7 100644 --- a/selfhost/cmd/w6a/main.combined.ww +++ b/selfhost/cmd/w6a/main.combined.ww @@ -3555,98 +3555,6 @@ export fn parse(a: *asm_) i32 = { return a.errs; }; -// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. -// -// Bump arena allocator. Backed by the runtime page allocator -// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the -// current chunk runs out we link a fresh one. Freeing the arena -// unmaps the chain. -// -// Memory handed out is 16-byte aligned. The C version under -// cmd/wcc/ is retained until the three-stage bootstrap diffs clean. - -package wcc; - -import os; -import rt; - -def ALIGN: u64 = 16u64; -def INIT_CHUNK: u64 = 65536u64; -def MAX_CHUNK: u64 = 4194304u64; -def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below - -type arena = struct { - buf: *u8, - off: u64, - cap: u64, - next: *arena, - total: u64, -}; - -fn roundup(n: u64, a: u64) u64 = { - return (n + a - 1u64) & ~(a - 1u64); -}; - -export fn newarena() *arena = { - let a: *arena = rt.malloc(ARENA_SZ): *arena; - a.buf = rt.malloc(INIT_CHUNK): *u8; - a.off = 0u64; - a.cap = INIT_CHUNK; - a.next = nil; - a.total = 0u64; - return a; -}; - -// Grow: link a fresh chunk in front of the head. We push the old -// chunk into `next` so the head always describes the current bump -// region. Chunk size doubles up to MAX_CHUNK. -fn grow(a: *arena, need: u64) bool = { - let want: u64 = a.cap * 2u64; - if (want < need) { want = need; }; - if (want > MAX_CHUNK) { want = MAX_CHUNK; }; - if (want < need) { return false; }; // single allocation too big - - let old: *arena = rt.malloc(ARENA_SZ): *arena; - old.buf = a.buf; - old.off = a.off; - old.cap = a.cap; - old.next = a.next; - old.total = 0u64; - - a.buf = rt.malloc(want): *u8; - a.off = 0u64; - a.cap = want; - a.next = old; - return true; -}; - -export fn amalloc(a: *arena, n: u64) *void = { - let need: u64 = roundup(n, ALIGN); - if (need > a.cap - a.off) { - if (!grow(a, need)) { return nil; }; - }; - let p: *u8 = a.buf + a.off; - a.off += need; - a.total += need; - // Zero the region. Plan 9 amalloc zeroes; we mirror that here so - // the checker can assume freshly allocated nodes start at 0. - let i: u64 = 0u64; - for (i < need) { - p[i] = 0u8; - i += 1u64; - }; - return p: *void; -}; - -export fn freearena(a: *arena) void = { - for (a != nil) { - let next: *arena = a.next; - os.free(a.buf: *void, a.cap); - os.free(a: *void, ARENA_SZ); - a = next; - }; -}; - // selfhost/cmd/w6a/asm.ww — port of cmd/w6a/asm.c. // // Encode the parsed aprog list into amd64 machine bytes, appending to diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index f0cfb906..29393408 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -9291,11 +9291,11 @@ fn closenoop(s: *io.stream) (void | io.closed) = { // small write bursts without a tail of reallocs. // // `dynamicgrow`, not Hare's bare `grow`: cstage bundles all imported -// modules into a flat TU and resolves private fns by unqualified -// name, so two `fn grow` decls (here + selfhost/cmd/wcc/mem.ww's -// arena `grow`) collide. Module-prefixed name keeps the symmetry -// with `dynamicwrite`/`dynamicclose` until task #9 (module-aware -// private-fn scoping in cstage) lands. +// modules into a flat TU and resolves private fns by unqualified name, +// so historically two `fn grow` decls (here + the now-deleted bump +// arena's `grow`) would have collided. Module-prefixed name kept the +// symmetry with `dynamicwrite`/`dynamicclose`; retained pending task +// #9 (module-aware private-fn scoping in cstage). fn dynamicgrow(m: *state, need: i32) void = { let newcap: i32 = m.cap; if (newcap < 8) { newcap = 8; }; diff --git a/selfhost/cmd/wcc/mem.ww b/selfhost/cmd/wcc/mem.ww deleted file mode 100644 index e40f469e..00000000 --- a/selfhost/cmd/wcc/mem.ww +++ /dev/null @@ -1,91 +0,0 @@ -// selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. -// -// Bump arena allocator. Backed by the runtime page allocator -// (rt_malloc / rt_free), no libc. Each chunk is mmap'd; when the -// current chunk runs out we link a fresh one. Freeing the arena -// unmaps the chain. -// -// Memory handed out is 16-byte aligned. The C version under -// cmd/wcc/ is retained until the three-stage bootstrap diffs clean. - -package wcc; - -import os; -import rt; - -def ALIGN: u64 = 16u64; -def INIT_CHUNK: u64 = 65536u64; -def MAX_CHUNK: u64 = 4194304u64; -def ARENA_SZ: u64 = 48u64; // sizeof(arena), kept in sync below - -type arena = struct { - buf: *u8, - off: u64, - cap: u64, - next: *arena, - total: u64, -}; - -fn roundup(n: u64, a: u64) u64 = { - return (n + a - 1u64) & ~(a - 1u64); -}; - -export fn newarena() *arena = { - let a: *arena = rt.malloc(ARENA_SZ): *arena; - a.buf = rt.malloc(INIT_CHUNK): *u8; - a.off = 0u64; - a.cap = INIT_CHUNK; - a.next = nil; - a.total = 0u64; - return a; -}; - -// Grow: link a fresh chunk in front of the head. We push the old -// chunk into `next` so the head always describes the current bump -// region. Chunk size doubles up to MAX_CHUNK. -fn grow(a: *arena, need: u64) bool = { - let want: u64 = a.cap * 2u64; - if (want < need) { want = need; }; - if (want > MAX_CHUNK) { want = MAX_CHUNK; }; - if (want < need) { return false; }; // single allocation too big - - let old: *arena = rt.malloc(ARENA_SZ): *arena; - old.buf = a.buf; - old.off = a.off; - old.cap = a.cap; - old.next = a.next; - old.total = 0u64; - - a.buf = rt.malloc(want): *u8; - a.off = 0u64; - a.cap = want; - a.next = old; - return true; -}; - -export fn amalloc(a: *arena, n: u64) *void = { - let need: u64 = roundup(n, ALIGN); - if (need > a.cap - a.off) { - if (!grow(a, need)) { return nil; }; - }; - let p: *u8 = a.buf + a.off; - a.off += need; - a.total += need; - // Zero the region. Plan 9 amalloc zeroes; we mirror that here so - // the checker can assume freshly allocated nodes start at 0. - let i: u64 = 0u64; - for (i < need) { - p[i] = 0u8; - i += 1u64; - }; - return p: *void; -}; - -export fn freearena(a: *arena) void = { - for (a != nil) { - let next: *arena = a.next; - os.free(a.buf: *void, a.cap); - os.free(a: *void, ARENA_SZ); - a = next; - }; -}; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 045d8779..dd01c864 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -9291,11 +9291,11 @@ fn closenoop(s: *io.stream) (void | io.closed) = { // small write bursts without a tail of reallocs. // // `dynamicgrow`, not Hare's bare `grow`: cstage bundles all imported -// modules into a flat TU and resolves private fns by unqualified -// name, so two `fn grow` decls (here + selfhost/cmd/wcc/mem.ww's -// arena `grow`) collide. Module-prefixed name keeps the symmetry -// with `dynamicwrite`/`dynamicclose` until task #9 (module-aware -// private-fn scoping in cstage) lands. +// modules into a flat TU and resolves private fns by unqualified name, +// so historically two `fn grow` decls (here + the now-deleted bump +// arena's `grow`) would have collided. Module-prefixed name kept the +// symmetry with `dynamicwrite`/`dynamicclose`; retained pending task +// #9 (module-aware private-fn scoping in cstage). fn dynamicgrow(m: *state, need: i32) void = { let newcap: i32 = m.cap; if (newcap < 8) { newcap = 8; }; diff --git a/test/wcc/990_selfhost.c b/test/wcc/990_selfhost.c index 6fb72585..bcf2c3e1 100644 --- a/test/wcc/990_selfhost.c +++ b/test/wcc/990_selfhost.c @@ -70,7 +70,6 @@ static int probe_codegen(const char *bin) { static const char *files[] = { - "selfhost/cmd/wcc/mem.ww", "selfhost/cmd/wcc/err.ww", NULL, }; @@ -169,7 +168,6 @@ static int probe_dump_diff(const char *bin) { const char *tok_inputs[] = { - "selfhost/cmd/wcc/mem.ww", "selfhost/cmd/wcc/err.ww", "lib/ww/lex/lex.ww", "lib/ww/lex/tok.ww", @@ -187,7 +185,6 @@ probe_dump_diff(const char *bin) const char *ast_inputs[] = { "selfhost/test/uses.ww", "selfhost/cmd/wcc/err.ww", - "selfhost/cmd/wcc/mem.ww", "lib/ww/lex/lex.ww", "lib/ww/lex/tok.ww", "lib/ww/ast.ww", @@ -531,7 +528,6 @@ probe_resolve(const char *bin) if (getcwd(cwd, sizeof cwd) == NULL) return -1; const char *complete[] = { "selfhost/cmd/wcc/err.ww", - "selfhost/cmd/wcc/mem.ww", "lib/ww/lex/tok.ww", "selfhost/test/smoke.ww", NULL, @@ -560,7 +556,6 @@ probe_dump_stable(const char *bin) char cwd[1024]; if (getcwd(cwd, sizeof cwd) == NULL) return -1; const char *inputs[] = { - "selfhost/cmd/wcc/mem.ww", "selfhost/cmd/wcc/err.ww", "selfhost/test/smoke.ww", NULL, @@ -812,7 +807,6 @@ static int probe_cgen_match(const char *bin) { const char *files[] = { - "selfhost/cmd/wcc/mem.ww", "selfhost/cmd/wcc/err.ww", "lib/ww/lex/tok.ww", "selfhost/test/smoke.ww",