From 1aece29d533f8f5749ac0700bc747dd4d8225cdc Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sat, 16 May 2026 03:09:49 +0900 Subject: [PATCH] lib/os: revert `at` enum to three top-level defs (post-#24) cf24af8 fixed the negative-literal def DATA-emit gap that forced the `at` enum bundle. Revert to Hare's shape: three export def AT_FDCWD / AT_SYMLINK_NOFOLLOW / AT_EMPTY_PATH at i32, mirroring ref/hare/sys/+linux/types.ha:45-51. Values from : -100 / 256 / 4096. Four call sites (stat / lstat / fstat / exists) updated. --- lib/os/os.ww | 26 +++++++++++--------------- selfhost/cmd/w6a/main.combined.ww | 26 +++++++++++--------------- selfhost/cmd/w6c/main.combined.ww | 26 +++++++++++--------------- selfhost/cmd/w6l/main.combined.ww | 26 +++++++++++--------------- selfhost/cmd/ww/main.combined.ww | 26 +++++++++++--------------- selfhost/cmd/wwdump/main.combined.ww | 26 +++++++++++--------------- selfhost/test/smoke.combined.ww | 26 +++++++++++--------------- 7 files changed, 77 insertions(+), 105 deletions(-) diff --git a/lib/os/os.ww b/lib/os/os.ww index 9cce6c6f..1aa65eb9 100644 --- a/lib/os/os.ww +++ b/lib/os/os.ww @@ -390,16 +390,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -558,7 +554,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -568,8 +564,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -581,7 +577,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -605,6 +601,6 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; }; diff --git a/selfhost/cmd/w6a/main.combined.ww b/selfhost/cmd/w6a/main.combined.ww index 06a650ca..2c906dc6 100644 --- a/selfhost/cmd/w6a/main.combined.ww +++ b/selfhost/cmd/w6a/main.combined.ww @@ -391,16 +391,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -559,7 +555,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -569,8 +565,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -582,7 +578,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -606,7 +602,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; }; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index d5028b1e..058043c3 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -391,16 +391,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -559,7 +555,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -569,8 +565,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -582,7 +578,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -606,7 +602,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; }; diff --git a/selfhost/cmd/w6l/main.combined.ww b/selfhost/cmd/w6l/main.combined.ww index 67d778d6..ddb65297 100644 --- a/selfhost/cmd/w6l/main.combined.ww +++ b/selfhost/cmd/w6l/main.combined.ww @@ -391,16 +391,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -559,7 +555,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -569,8 +565,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -582,7 +578,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -606,7 +602,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; }; diff --git a/selfhost/cmd/ww/main.combined.ww b/selfhost/cmd/ww/main.combined.ww index 750ef7c7..303a3b6e 100644 --- a/selfhost/cmd/ww/main.combined.ww +++ b/selfhost/cmd/ww/main.combined.ww @@ -391,16 +391,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -559,7 +555,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -569,8 +565,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -582,7 +578,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -606,7 +602,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; }; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 60fb7012..1549bbc7 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -391,16 +391,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -559,7 +555,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -569,8 +565,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -582,7 +578,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -606,7 +602,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; }; diff --git a/selfhost/test/smoke.combined.ww b/selfhost/test/smoke.combined.ww index 7a153dfe..73416fe7 100644 --- a/selfhost/test/smoke.combined.ww +++ b/selfhost/test/smoke.combined.ww @@ -391,16 +391,12 @@ export fn getenv(name: str) (str | void) = { // but Hare's filestat doesn't expose btime either, so we stay on // the simpler 144B kernel struct. -// at — flags for fstatat(2). Numeric values match . -// Bundled as an enum because top-level `def` of a negative literal -// (FDCWD = -100) doesn't get a DATA slot emitted by cstage cgen — -// linker surfaces as "undefined reference". Tracked as task #24; -// enum-member resolution sidesteps it cleanly. -type at = enum i64 { - FDCWD = -100, - SYMLINK_NOFOLLOW = 256, // 0x100 - EMPTY_PATH = 4096, // 0x1000 -}; +// fstatat(2) flag values. Linux constants from . +// Names mirror Hare's ref/hare/sys/+linux/types.ha:45-51 (capital- +// AT_ prefix, top-level `def`s). +export def AT_FDCWD: i32 = -100; +export def AT_SYMLINK_NOFOLLOW: i32 = 256; // 0x100 +export def AT_EMPTY_PATH: i32 = 4096; // 0x1000 // mode — file-mode bits. Mirrors Hare's fs::mode (ref/hare/fs/ // types.ha:63). Permission bits are the standard Unix octal subset; @@ -559,7 +555,7 @@ fn fillfilestat(out: *filestat, k: *kstat) void = { export fn stat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -569,8 +565,8 @@ export fn stat(out: *filestat, path: *u8) (void | oserror) = { export fn lstat(out: *filestat, path: *u8) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, - at.SYMLINK_NOFOLLOW: i64); + AT_FDCWD: i64, path: i64, (&k): i64, + AT_SYMLINK_NOFOLLOW: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -582,7 +578,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, fd: i64, (&emptypath[0]): i64, (&k): i64, - at.EMPTY_PATH: i64); + AT_EMPTY_PATH: i64); if (r < 0) { return r: oserror; }; fillfilestat(out, &k); }; @@ -606,7 +602,7 @@ export fn fstat(out: *filestat, fd: i32) (void | oserror) = { export fn exists(path: *u8) bool = { let k: kstat; let r: i64 = syscall4(nr.NEWFSTATAT, - at.FDCWD: i64, path: i64, (&k): i64, 0i64); + AT_FDCWD: i64, path: i64, (&k): i64, 0i64); return r >= 0i64; };