6c: ww-side compiler binary, dup2 syscall, test 994

selfhost/cmd/6c/main.ww is a thin packaging of the wwc cgen — slurp
a .ww file, run lex+parse+cgen, write Plan 9 amd64 asm to the path
given by -o. The cgen routines in selfhost/cmd/wwc/cgen.ww write
directly to fd 1, so we use dup2 to redirect stdout into the
output file rather than thread an fd through every emit helper.
Adds the SYS_DUP2=33 wrapper in lib/os.

Makefile wires $(BIN)/6c_ww alongside the other wwstage tools and
adds $(BIN)/test_6c_ww to the TESTS list.

test/wwc/994_6c_ww.c diffs 6c_ww byte-for-byte against
`wwdump_ww -c` on five in-source programs plus the four selfhost
main.combined.ww files: same cgen reached through two binaries, so
any divergence is a packaging bug in selfhost/cmd/6c.

We deliberately don't diff against C-side 6c here — 990 probe 5
already covers that on the subset the ww cgen handles today.
This commit is contained in:
2026-05-11 11:20:06 +09:00
parent 607cc8d330
commit 218d8469ff
4 changed files with 347 additions and 3 deletions

View File

@@ -24,6 +24,7 @@ def SYS_OPEN: i64 = 2;
def SYS_CLOSE: i64 = 3;
def SYS_LSEEK: i64 = 8;
def SYS_ACCESS: i64 = 21;
def SYS_DUP2: i64 = 33;
def SYS_GETPID: i64 = 39;
def SYS_FORK: i64 = 57;
def SYS_EXECVE: i64 = 59;
@@ -62,6 +63,14 @@ export fn close(fd: i32) i32 = {
return syscall1(SYS_CLOSE, fd: i64): i32;
};
// dup2(2): make `newfd` refer to the same description as `oldfd`,
// closing `newfd` first if open. Returns `newfd` on success or a
// negative errno. Used by 6c_ww to redirect stdout into an output
// file without changing the cgen emit path.
export fn dup2(oldfd: i32, newfd: i32) i32 = {
return syscall2(SYS_DUP2, oldfd: i64, newfd: i64): i32;
};
// Fallible wrappers. The error variant is a plain str (Plan 9 errstr
// model, see lib/errors); the sum type makes success/failure explicit
// without overloading length-zero.