ww: rename toolchain to w-prefix + hare-style build/run/test driver

Plan 9-style w-prefix on the per-arch tools, disambiguating from the
real Plan 9 6c/6a/6l in ref/plan9front/:

    cmd/wwc/      → cmd/wcc/        libwwc.a → libwcc.a
    cmd/6{c,a,l}  → cmd/w6{c,a,l}   binary names too
    test/wwc/     → test/wcc/       6 test files w/ w6 prefix
    selfhost/cmd  mirror in lockstep
    bootstrap/amd64/{w6c,w6a,w6l}   snapshot binaries (gitignored)
    WW_6{C,A,L}   → WW_W6{C,A,L}    env-var overrides

Plan 9 source-tree refs ("Plan 9 6c shape", ref/plan9front/, etc.)
preserved. Hare-style driver, both C and ww sides:

    ww test [path]   discover *_test.ww in a directory module, run
                     each; single-file mode for `ww test foo.ww`
    Module-by-name   `ww build foo` resolves to foo.ww or foo/foo.ww
                     via search path (cwd : -I dirs : $WW_LIB)
    Default-to-cwd   `ww build` / `ww test` build the cwd module
    Run pass-through `ww run path arg1 arg2` reaches the program

lib/os: getcwd (79) and getdents64 (217) syscalls power `.` resolution
and directory enumeration on the ww side.

Makefile: wwstage tool deps now include lib/os/os.ww (+ lib/strconv
for wwdump_ww) so lib/* edits force their rebuild instead of leaving
stale binaries — surfaced when test 995 first failed against a stale
w6c_ww built before the lib/os additions.

Test 993 byte-identical parity gate (C-side ww vs ww-side ww_ww on a
build corpus) stays green; all 19 tests pass.
This commit is contained in:
2026-05-11 13:49:27 +09:00
parent e217cd32d1
commit 2c33228b7e
96 changed files with 2129 additions and 973 deletions

View File

@@ -13,17 +13,17 @@ This file is the contract for the work. Read PLAN.md for the schedule.
- Toolchain: Plan 9-organized. One library + one binary per role
per target architecture. Plan 9 uses a single digit per arch
(8=386, 6=amd64, 5=arm, 7=arm64, 9=power); we adopt that.
- `cmd/wwc/` — frontend library (lex, parse, check). Builds
`libwwc.a`. Not a binary.
- `cmd/6c/` — amd64 compiler. Reads `.ww`, writes `.s`
- `cmd/wcc/` — frontend library (lex, parse, check). Builds
`libwcc.a`. Not a binary.
- `cmd/w6c/` — amd64 compiler. Reads `.ww`, writes `.s`
(Plan 9 amd64 asm).
- `cmd/6a/` — amd64 assembler. Reads `.s`, writes `.o`
- `cmd/w6a/` — amd64 assembler. Reads `.s`, writes `.o`
(ELF, for C interop).
- `cmd/6l/` — amd64 linker. Reads `.o` and `.a`, writes a
- `cmd/w6l/` — amd64 linker. Reads `.o` and `.a`, writes a
static ELF binary.
- `cmd/ww/` — user-facing driver (Hare's `hare(1)` /
Plan 9's `cc(1)` analogue). Orchestrates `6c → 6a → 6l`.
Adding a new target later means a new triple (e.g. `7c`/`7a`/`7l`
Plan 9's `cc(1)` analogue). Orchestrates `w6c → w6a → w6l`.
Adding a new target later means a new triple (e.g. `w7c`/`w7a`/`w7l`
for arm64). The frontend library `wwc` is shared.
## Hard rules (do not violate)
@@ -48,12 +48,12 @@ This file is the contract for the work. Read PLAN.md for the schedule.
`extern "c"` marker is needed.
6. **Plan 9 toolchain. No LLVM, no QBE, no external IR.** We do not
invent a portable SSA IR. We follow Plan 9: the per-target
compiler (`6c` for amd64) reads `.ww` and writes Plan 9-style
target assembly (`.s`); the per-target assembler (`6a`) writes
ELF objects; the per-target linker (`6l`) produces a static
compiler (`w6c` for amd64) reads `.ww` and writes Plan 9-style
target assembly (`.s`); the per-target assembler (`w6a`) writes
ELF objects; the per-target linker (`w6l`) produces a static
binary. Each tool uses Plan 9 cc's in-memory `Prog`/`Adr`
shapes — read `ref/plan9front/sys/src/cmd/cc/`, `cmd/6c/`,
`cmd/6a/`, `cmd/6l/` before writing your own.
shapes — read `ref/plan9front/sys/src/cmd/cc/`, `cmd/w6c/`,
`cmd/w6a/`, `cmd/w6l/` before writing your own.
7. **No generics, no interfaces, no closures, no lambdas.** Four forms
of bloat we refuse. Polymorphism, when genuinely needed, is a
struct of function pointers plus a `ctx: *void` (Plan 9 `Bio`,
@@ -74,7 +74,7 @@ This file is the contract for the work. Read PLAN.md for the schedule.
8. **Tests run after every change.** `make test` is the truth. A
change without a green `make test` is not a change.
9. **Prototype in C, then self-host.** The C bootstrap toolchain
(`libwwc`, `6c`, `6a`, `6l`, `ww`) is throwaway scaffolding.
(`libwcc`, `w6c`, `w6a`, `w6l`, `ww`) is throwaway scaffolding.
Its job is to compile enough of `ww` to compile the ww
reimplementations of itself. Do not over-engineer the C side.
@@ -300,7 +300,7 @@ ergonomics live in a sibling pure-`ww` package.
POSIX `make`, no autotools, no cmake.
```
make # builds libwwc, 6c, 6a, 6l, ww, stdlib
make # builds libwcc, w6c, w6a, w6l, ww, stdlib
make test # runs all tests (toolchain + stdlib)
make install # installs to $PREFIX (default /usr/local)
make clean
@@ -312,11 +312,11 @@ Target layout under `out/`:
out/
bin/
ww user-facing driver
6c amd64 compiler
6a amd64 assembler
6l amd64 linker
w6c amd64 compiler
w6a amd64 assembler
w6l amd64 linker
lib/
libwwc.a frontend library (linked into 6c)
libwcc.a frontend library (linked into w6c)
libwwrt.a runtime archive (linked into final binaries)
<pkg>.a precompiled stdlib modules
obj/... intermediate .s, .o per package
@@ -329,7 +329,7 @@ ELF. Dynamic is `ww build -shared` or per-library `-l`.
Three tiers, all driven by `make test`:
1. **Compiler unit tests** (`test/wwc/`): C, table-driven. Lex, parse,
1. **Compiler unit tests** (`test/wcc/`): C, table-driven. Lex, parse,
typecheck, IR-gen, codegen each have their own table.
2. **Language tests** (`test/lang/*.ww`): each file is a single ww
program with a comment header declaring expected exit code and
@@ -355,7 +355,7 @@ Every change must:
Applied to this project:
- `6c` is a single-pass-ish recursive-descent parser into a typed
- `w6c` is a single-pass-ish recursive-descent parser into a typed
AST, walked into a `Prog` list, then printed as text. No parser
generator, no LLVM, no SSA pass pipeline.
- Optimizer is intentionally absent at first. Constant fold + dead
@@ -370,7 +370,7 @@ Applied to this project:
- `ref/hare/` — the Hare distribution. Read for syntax, FFI
(`@symbol`), stdlib layout, type names, error idioms.
- `ref/plan9front/` — 9front. Read `sys/src/cmd/cc/` (the shared
frontend library), `sys/src/cmd/8c/` and `sys/src/cmd/6c/` (per-
frontend library), `sys/src/cmd/8c/` and `sys/src/cmd/w6c/` (per-
target compilers), `sys/src/cmd/8a/` (assembler), `sys/src/cmd/8l/`
(linker) for toolchain organization, `Prog`/`Adr` data shapes,
mkfile style, and naming.
@@ -404,7 +404,7 @@ When making changes:
writing code.
- Keep diffs small. One concern per change.
- Commits: Plan 9 style. Subject is one short lowercase line,
prefixed with the affected area: `6c: fix const fold for i64`,
prefixed with the affected area: `w6c: fix const fold for i64`,
`lib/fmt: handle %v for slices`, `cc: typo`. Body only when the
why is not obvious from the diff. No `Co-Authored-By` trailer,
no "Generated with" footer, no emoji.