Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 9 additions & 17 deletions .dev/checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,6 @@ Prefix: W## (to distinguish from CW's F## items).

## Open Items

- [ ] W46: Un-link libc — migrate WASI I/O / cache / platform off `std.c.*` onto
`std.Io` (or `std.posix.system` direct syscalls). Scope: `src/wasi.zig`
(fd_read / fd_write / fd_pread / fd_pwrite / fd_seek / fd_tell / fstatat),
`src/cache.zig` (fsync), `src/platform.zig` (statx helpers), test helpers.
Why this is a priority, not cosmetic:
1. **Zig 0.16 philosophy** — release notes explicitly say "go higher
(std.Io) or go lower (std.posix.system)"; `std.c.*` is neither direction.
2. **Windows correctness** — `std.c.fd_t` = `windows.HANDLE` (pointer),
but `std.c.write` binds to MSVCRT `_write(int fd, …)`. The ABI
mismatch is what broke Windows real-world compat in v1.10.0.
3. **Binary size** — Linux ELF pays ~290 KB for libc linkage; returning
to no-libc lets us restore the 1.50 MB guard.
4. **Performance** — 2025-02 Andrew Kelley devlog: "No-Libc Zig Now
Outperforms Glibc Zig" — no-libc is the fast path.
Non-goal for v1.10.x: rewriting all I/O atomically. Plan is phase-by-phase
(phase 1 = WASI stdio Windows fix, phase 2 = fd_read/fd_write, …).

- [ ] W45: SIMD loop persistence — Skip Q-cache eviction at loop headers.
Requires back-edge detection in scanBranchTargets.

Expand Down Expand Up @@ -54,5 +37,14 @@ W43: SIMD v128 base addr cache (SIMD_BASE_REG x17). Phase A of D132.
W44: SIMD register class — Q16-Q31 (ARM64) + XMM6-XMM15 (x86) cache.
Phase B of D132. Merged 2026-03-26. Q-cache with LRU eviction + lazy
writeback. Benefit limited by loop-header eviction (diagnosed same day).
W46: Un-link libc — Phase 1 complete (delib 1a–1f, merged 2026-04-24/25).
link_libc=false across lib / cli / tests / examples / e2e / bench / fuzz;
C API targets (shared-lib, static-lib, c-test) keep link_libc=true because
`src/c_api.zig` uses `std.heap.c_allocator`. Platform helpers added:
pfdWrite, pfdRead, pfdClose, pfdDup, pfdDup2, pfdPipe, pfdSleepNs, pfdErrno,
pfdFsync, pfdReadlinkAt (Linux=direct syscalls, Mac=libSystem auto-link,
Windows=kernel32/Win32). Payoff measured: Mac 1.38 MB, Linux 1.65 MB
stripped (vs 1.80 MB ceiling). The 1.50 MB target is deferred to the
std.Io migration (tracked separately if it resurfaces).

W2-W36: See git history. All resolved through Stages 0-47 and Phases 1-19.
63 changes: 36 additions & 27 deletions .dev/memo.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,46 @@ Session handover document. Read at session start.

## Current State

- **Zig toolchain**: 0.16.0 (migrated from 0.15.2, 2026-04-24).
- Stages 0-46 + Phase 1, 3, 5, 8, 10, 11, 13, 15, 19, **20** complete.
- **Zig toolchain**: 0.16.0 (migrated 2026-04-24).
- Stages 0-46 + Phase 1, 3, 5, 8, 10, 11, 13, 15, 19, 20 complete.
- Spec: 62,263/62,263 Mac+Ubuntu (100.0%, 0 skip).
- E2E: 796/796 Mac+Ubuntu, 0 fail.
- Real-world: Mac 50/50, Ubuntu 50/50, 0 crash.
- Real-world: Mac 50/50, Ubuntu 50/50, Windows 46/46, 0 crash.
- FFI: 80/80 Mac+Ubuntu.
- JIT: Register IR + ARM64/x86_64 + SIMD (NEON 253/256, SSE 244/256).
- HOT_THRESHOLD=3 (lowered from 10 in W38).
- Binary: 1.29MB stripped. Memory: ~3.5MB RSS.
- Binary stripped: Mac 1.38 MB, Linux 1.65 MB (ceiling 1.80 MB). Memory: ~3.5 MB RSS.
- Platforms: macOS ARM64, Linux x86_64/ARM64, Windows x86_64.
- **main = stable** (currently v1.9.1). v1.10.0 on `develop/zig-0.16.0`, awaiting PR.
- **main = stable**. v1.10.0 released; post-release work on delib / W46 merged
via PRs #47 (1a/1b pre-cursor), #48 (1b), #49 (1c/1d/1e/1f + C-API libc fix).
- link_libc = false across lib / cli / tests / examples / e2e / bench / fuzz.
C-API targets (shared-lib, static-lib, c-test) keep link_libc = true because
`src/c_api.zig` uses `std.heap.c_allocator`.

## Current Task

**v1.10.0: Zig 0.16.0 migration — DONE on both platforms (2026-04-24)**
**W46 Phase 1 — DONE (2026-04-25).** PR #49 merged (`30a3680`). See
`.dev/checklist.md` Resolved section for details. Next candidate work:

Full rundown in `@./.dev/archive/zig-0.16-migration.md` (archived work log + D135 Io strategy).
- **W47**: `tgo_strops_cached` +24% regression investigation (single-benchmark,
low priority). See checklist.
- **W45**: SIMD loop persistence — skip Q-cache eviction at loop headers
(requires back-edge detection in `scanBranchTargets`).
- **W46 Phase 2 (optional)**: migrate `fd_read`/`fd_write` onto `std.Io`.
Not blocking. Would help return binary size to 1.50 MB target and improve
Windows I/O correctness further; pick up when `std.Io` stdlib APIs stabilize.

- **Mac aarch64 gates**: 399/399 unit, 62263/62263 spec (0 skip), 796/796 e2e,
50/50 realworld, 80/80 FFI, minimal build OK, `0.16.0-baseline` bench
recorded (no >10% regression vs v1.9.1).
- **Ubuntu x86_64 gates** (OrbStack): 408/411 unit (3 WAT/JIT-guarded skips),
62263/62263 spec, 796/796 e2e, 50/50 realworld, 80/80 FFI, minimal build OK.
- **Branch**: `develop/zig-0.16.0` — 22 commits, ready for PR.
- **Remaining**: PR open, CI green, close notxorand's #41, tag + CW bump.
## Previous Task

### 0.16 highlights we had to adapt to
**W46 Phase 1c/1d/1e/1f — DONE (2026-04-25 via PR #49).**

- `std.process.Init` param on `main()` (args/gpa/arena/io/env from start.zig)
- `std.Io` threading — Vm gets an `io` field, stdlib methods take it as 1st arg
- `std.leb` gone → inline port of 0.15's `@shlWithOverflow` algorithm
(`std.Io.Reader.takeLeb128` is NOT spec-equivalent; misses the "integer too
large" overshoot check — see `binary-leb128.77.wasm`)
- `std.posix.*` attrition (fsync/mkdirat/dup/pread/etc.) — swap to `std.c.*`
- `std.c.*Stat` empty on Linux — fstatat replaced by `statx` via
`fstatatToFileStat()`; fstat-for-size replaced by `lseek(SEEK_END)`
- `@Vector` runtime indexing rejected → use `[N]T` arrays + `@bitCast`
- Decisions.md D135 covers the Io threading architecture.
Routed test-site and trace-site `std.c.*` calls through new platform helpers
(`pfdDup2`, `pfdPipe`, `pfdSleepNs` added alongside existing `pfd*` family),
then flipped `.link_libc = false` across every module in `build.zig` except
the three C-API targets. CI-green on all four runners (Mac/Ubuntu/Windows/
size-matrix). Fix commit `c11a947` routed `std.c.{pipe,dup,dup2,read,
nanosleep}` in wasi.zig+vm.zig tests; `04ac19d` kept link_libc=true on
C-API targets after the first push revealed `std.heap.c_allocator` needs libc.

### Hard-won nuggets (reuse later)

Expand All @@ -52,8 +54,15 @@ Full rundown in `@./.dev/archive/zig-0.16-migration.md` (archived work log + D13
- **e2e_runner uses `init.io`, NOT a locally constructed Threaded io**.
A fresh `std.Io.Threaded.init(allocator, .{}).io()` inside user main
crashes with `0xaa…` in `Io.Timestamp.now` when iterating many files.

## Previous Task
- **C-API targets must keep `link_libc = true`.** `src/c_api.zig` uses
`std.heap.c_allocator`. Mac masks this via libSystem auto-link; Linux and
Windows fail with "C allocator is only available when linking against libc".
- **Cross-compile sanity trick.** `zig build test -Dtarget=x86_64-linux-gnu`
and `-Dtarget=x86_64-windows-gnu` compile cleanly on Mac even though the
test binaries can't execute — the compile success alone catches link-time
symbol-resolution issues before pushing to CI.

## Previous Task (older)

**W45: SIMD Loop Persistence — DONE (2026-03-26)**

Expand Down
Loading