From a376ec89ebed7901f6907ba57ad439a27e1e9c25 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Wed, 20 May 2026 22:11:34 +0900 Subject: [PATCH] =?UTF-8?q?lib/rt:=20rename=20rt=5Falloc=20=E2=86=92=20rt?= =?UTF-8?q?=5Fmalloc;=20rt.alloc=20=E2=86=92=20rt.malloc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hare's canonical runtime allocator is rt::malloc with linker symbol rt.malloc (ref/hare/rt/malloc.ha:27,78). ww kept the dot→underscore Plan 9 convention (CLAUDE.md rule 4) so the linker symbol becomes rt_malloc; the lib/rt exported function name becomes malloc; ww callers say rt.malloc(...). The language builtin keyword stays `alloc(T)!` — unchanged from Hare (ref/hare/hare/lex/token.ha:21 ltok::ALLOC, parse/expr.ha:398 builtin()). The rename only touches the lowered linker symbol and the exported function name behind it; the user-facing syntax for heap-allocation is identical to Hare. Surface: - rt/alloc.s: TEXT rt_alloc → TEXT rt_malloc, labels updated - lib/rt/malloc.ww: @symbol("rt_malloc") fn malloc(...) (was rt_alloc/alloc) - rt/ensure.ww: local FFI decl + call site updated to malloc; `!` dropped on the direct FFI call (rt_malloc returns *void, not a tagged union) - 18 .ww callers: rt.alloc(...) → rt.malloc(...) - cstage cmd/wcc/check.c + wwstage selfhost/cmd/wcc/check.ww alloc-builtin suppression gate routes through ffi_resolve("malloc") for the lowering; the user-shadow check still keys on the BUILTIN KEYWORD "alloc" since that is what `alloc(...)` parses as. Adding "malloc" to the user-shadow check was unnecessary and was reverted during pre-commit review. - cstage cmd/w6c/cgen.c: 2× ffi_resolve("alloc") → ffi_resolve("malloc") - wwstage cgenexpr/cgenstmt: 2× ffiresolve(c, "alloc") → ffiresolve(c, "malloc") - Test fixtures (700_e2e, 758_cgalloc_str_field, 990_selfhost, 992_w6l_ww, selfhost/test/tagged_ptr_ret.ww): updated inline ww sources to the new decl + call form This is commit 2 of 3 in the lib/rt extraction (#38). Commit 3 closes the OOM contract — return type becomes nullable *void and the builtin lowering null-checks + propagates nomem. Verified 132/132 + 995_self_rebuild byte-identity (5 wwstage tools round-trip identical) + make clean cold rebuild. --- cmd/w6c/cgen.c | 6 +- cmd/wcc/check.c | 21 +++---- examples/cmatrix/cmatrix.ww | 12 ++-- examples/lisp/lispcore.ww | 16 +++--- lib/fmt/fmt.ww | 2 +- lib/memio/memio.ww | 2 +- lib/os/os.ww | 2 +- lib/os/ostest.ww | 2 +- lib/path/path.ww | 8 +-- lib/rt/malloc.ww | 8 +-- lib/shlex/shlex.ww | 2 +- lib/strings/strings.ww | 12 ++-- rt/alloc.s | 8 +-- rt/ensure.ww | 13 ++--- rt/start.s | 2 +- selfhost/cmd/w6a/asm.ww | 4 +- selfhost/cmd/w6a/main.combined.ww | 26 ++++----- selfhost/cmd/w6a/main.ww | 2 +- selfhost/cmd/w6c/main.combined.ww | 46 +++++++-------- selfhost/cmd/w6c/main.ww | 2 +- selfhost/cmd/w6l/dyn.ww | 2 +- selfhost/cmd/w6l/dynout.ww | 2 +- selfhost/cmd/w6l/main.combined.ww | 46 +++++++-------- selfhost/cmd/w6l/main.ww | 14 ++--- selfhost/cmd/w6l/obj.ww | 6 +- selfhost/cmd/w6l/out.ww | 2 +- selfhost/cmd/wcc/cgenexpr.ww | 8 +-- selfhost/cmd/wcc/cgenstmt.ww | 4 +- selfhost/cmd/wcc/mem.ww | 10 ++-- selfhost/cmd/ww/main.combined.ww | 84 ++++++++++++++-------------- selfhost/cmd/ww/main.ww | 64 ++++++++++----------- selfhost/cmd/wwdump/main.combined.ww | 44 +++++++-------- selfhost/test/smoke.combined.ww | 22 ++++---- selfhost/test/tagged_ptr_ret.ww | 4 +- test/wcc/700_e2e.c | 4 +- test/wcc/758_cgalloc_str_field.c | 40 ++++++------- test/wcc/990_selfhost.c | 6 +- test/wcc/992_w6l_ww.c | 2 +- 38 files changed, 277 insertions(+), 283 deletions(-) diff --git a/cmd/w6c/cgen.c b/cmd/w6c/cgen.c index 5d03920d..f9af7d23 100644 --- a/cmd/w6c/cgen.c +++ b/cmd/w6c/cgen.c @@ -4132,7 +4132,7 @@ cgexpr(Cg *c, Node *n, Local *locals) * `alloc` shadows the builtin (task #23). * * Result is the graduated `(*T | nomem)` tagged-pointer - * ABI (AX=tag, DX=ptr) — task #30. rt_alloc returns 0 + * ABI (AX=tag, DX=ptr) — task #30. rt_malloc returns 0 * on OOM (rt/alloc.s); we branch on AX, building tag=1 * (nomem, DX=0) on null and tag=0 (success, DX=ptr) * after the value-init stores complete. Callers wrap @@ -4146,7 +4146,7 @@ cgexpr(Cg *c, Node *n, Local *locals) char *alloc_ok = mklabel(c, "alloc_ok"); char *alloc_done = mklabel(c, "alloc_done"); ins2(c, A_MOVQ, aimm(sz), areg(D_DI)); - ins1(c, A_CALL, asym(ffi_resolve("alloc"))); + ins1(c, A_CALL, asym(ffi_resolve("malloc"))); ins2(c, A_CMPQ, aimm(0), areg(D_AX)); ins1(c, A_JNE, abranch(alloc_ok)); ins2(c, A_MOVQ, aimm(1), areg(D_AX)); @@ -6403,7 +6403,7 @@ cgstmt(Cg *c, Node *n, Local **locals, int *frame) ins2(c, A_IMULQ, areg(D_BX), areg(D_AX)); } ins2(c, A_MOVQ, areg(D_AX), areg(D_DI)); - ins1(c, A_CALL, asym(ffi_resolve("alloc"))); + ins1(c, A_CALL, asym(ffi_resolve("malloc"))); if (via_tryunw) { char *ok = mklabel(c, "tryunw_ok"); ins2(c, A_CMPQ, aimm(0), areg(D_AX)); diff --git a/cmd/wcc/check.c b/cmd/wcc/check.c index dac9e892..3c4fb06a 100644 --- a/cmd/wcc/check.c +++ b/cmd/wcc/check.c @@ -968,16 +968,13 @@ cexpr(Checker *c, Node *n) return n->type; } /* `alloc(value)` Hare-style builtin — suppressed when the - * current module declares its own `alloc` (lib/os/os.ww, - * rt/ensure.ww). Without the gate, the bare same-module call - * lands in the typed-builtin path and silently allocates - * sizeof(arg-type) bytes against rt_alloc, shadowing the - * user decl. Strict same-module check (not scope_lookup_prefer): - * `use os;` in a primary brings os.alloc into the flat scope - * as a fallback match — that's what the `abort` precedent - * sidesteps by leaving os.abort un-exported, but os.alloc IS - * exported. c->cur_mod==NULL is the primary unit; gate only - * fires when a same-module decl is registered. Task #23. */ + * current module declares its own `alloc` (user shadow, task + * #23). Strict same-module check (not scope_lookup_prefer): + * `import rt;` brings rt.malloc into a separate qualified + * scope, not flat — only a same-module `fn alloc` registers + * here. The Hare builtin name is `alloc` (ref/hare/hare/lex/ + * token.ha:21, ltok::ALLOC); a hypothetical user `fn malloc` + * does not shadow it. Task #23. */ if (n->lhs && n->lhs->kind == N_IDENT && n->lhs->str && strcmp(n->lhs->str, "alloc") == 0 && n->list != NULL && n->list->next == NULL && @@ -987,7 +984,7 @@ cexpr(Checker *c, Node *n) Type *def = type_default(t); Type *pt = type_ptr(c->a, def ? def : ty_void); /* Task #30 — graduate to Hare's `(*T | nomem)` shape; - * the cgen branches on rt_alloc's null return to emit + * the cgen branches on rt_malloc's null return to emit * the nomem variant. Two-variant union with TY_PTR + * TY_NAMED(nomem) does not trip the nullable-pointer * fold (#25), so the result rides the general AX=tag, @@ -1053,7 +1050,7 @@ cexpr(Checker *c, Node *n) /* alloc([], n) — Hare-style fresh slice with cap n. We pin * the element type to u8 by default; the caller's declared * slice type drives the actual element size at codegen. - * Same scope_lookup_in_module gate as the value-form (#23). */ + * Same single-key `alloc` gate as the value-form above. */ if (n->lhs && n->lhs->kind == N_IDENT && n->lhs->str && strcmp(n->lhs->str, "alloc") == 0 && n->list && n->list->kind == N_ARRLIT && diff --git a/examples/cmatrix/cmatrix.ww b/examples/cmatrix/cmatrix.ww index 5ce9bd07..49051c66 100644 --- a/examples/cmatrix/cmatrix.ww +++ b/examples/cmatrix/cmatrix.ww @@ -201,18 +201,18 @@ fn now_ns() u64 = { // ---- cmat allocate / free --------------------------------------------- fn cmat_alloc(w: i32, h: i32, r: *rng) *cmat = { - let m = rt.alloc(CMAT_SZ): *cmat; + let m = rt.malloc(CMAT_SZ): *cmat; m.w = w; m.h = h; m.gspeed = -1; m.gtheme = theme.GREEN: i32; m.flash = 0; let n4 = (w: u64) * 4u64; - m.head = rt.alloc(n4): *i32; - m.length = rt.alloc(n4): *i32; - m.speed = rt.alloc(n4): *i32; - m.counter = rt.alloc(n4): *i32; - m.glyphs = rt.alloc((w: u64) * (MAX_TRAIL: u64)): *u8; + m.head = rt.malloc(n4): *i32; + m.length = rt.malloc(n4): *i32; + m.speed = rt.malloc(n4): *i32; + m.counter = rt.malloc(n4): *i32; + m.glyphs = rt.malloc((w: u64) * (MAX_TRAIL: u64)): *u8; let c = 0; for (c < w) { m.head[c] = -rng_range(r, 0, h); diff --git a/examples/lisp/lispcore.ww b/examples/lisp/lispcore.ww index 53ec9aec..c97b9763 100644 --- a/examples/lisp/lispcore.ww +++ b/examples/lisp/lispcore.ww @@ -124,7 +124,7 @@ def ENV_SZ: u64 = 32u64; // result). repl() resets the trans arena between top-level forms. // // Pre-arena every cell paid the 4 KiB page-per-call cost of -// rt_alloc; test_huge.lisp peaked at ~525 MB under massif +// rt_malloc; test_huge.lisp peaked at ~525 MB under massif // --pages-as-heap=yes. With chunking alone Pass A brought that to // ~253 MB; per-form trans reset (this pass) drops it further by // reclaiming the trans high-water mark after each form. @@ -159,7 +159,7 @@ let perm_arena: arena; let trans_arena: arena; fn arena_new_chunk(prev: *chunk) *chunk = { - let raw: *u8 = rt.alloc(ARENA_CHUNK): *u8; + let raw: *u8 = rt.malloc(ARENA_CHUNK): *u8; let c: *chunk = raw: *chunk; c.next = prev; c.cur = 0u64; @@ -240,7 +240,7 @@ export type eof = !void; // parser: end of input — distinct from a parse // // Every v* constructor allocates one VALUE_SZ slab from the arena and // initialises the fields the kind needs. The cgen's -// `alloc(value{...})` struct-literal sugar lowers to rt_alloc directly +// `alloc(value{...})` struct-literal sugar lowers to rt_malloc directly // (one mmap per cell), so the constructors hand-roll the alloc + per- // field stores instead. Same shape as `new T(...)` in other languages. @@ -343,7 +343,7 @@ def SYM_BLOBSZ: i32 = 8192; // a top-level `[N]T` global, because the wwstage cgen still mis-lowers // `globalarr[i] = …` (variable index) to `LEAQ (BP), BX` — it treats // the global address as if it were on the stack. Pointers indexed -// through `[i]` go through the cmatrix path (LEAQ from rt_alloc result) +// through `[i]` go through the cmatrix path (LEAQ from rt_malloc result) // which works. let sym_off: *i32 = nil; let sym_len: *i32 = nil; @@ -1566,10 +1566,10 @@ fn bind_one(e: **env, name: str, id: i32) void = { export fn initsyms() void = { arena_init(); - sym_off = rt.alloc((SYM_CAP: u64) * 4u64): *i32; - sym_len = rt.alloc((SYM_CAP: u64) * 4u64): *i32; - sym_blob = rt.alloc(SYM_BLOBSZ: u64): *u8; - obuf = rt.alloc(OBUF_SZ: u64): *u8; + sym_off = rt.malloc((SYM_CAP: u64) * 4u64): *i32; + sym_len = rt.malloc((SYM_CAP: u64) * 4u64): *i32; + sym_blob = rt.malloc(SYM_BLOBSZ: u64): *u8; + obuf = rt.malloc(OBUF_SZ: u64): *u8; // Stash the special-form ids so classify_sform sees them. SID_QUOTE = intern("quote"); diff --git a/lib/fmt/fmt.ww b/lib/fmt/fmt.ww index 1162c676..d7af7130 100644 --- a/lib/fmt/fmt.ww +++ b/lib/fmt/fmt.ww @@ -886,7 +886,7 @@ export fn asprintf(fmt: str, args: field...) str = { match (cres) { case void => {}; case io.closed => {}; }; return out; }; - let tight: *u8 = rt.alloc(view.len: u64): *u8; + let tight: *u8 = rt.malloc(view.len: u64): *u8; let i: i32 = 0; for (i < view.len) { tight[i] = view.ptr[i]; diff --git a/lib/memio/memio.ww b/lib/memio/memio.ww index 720619fe..79f3ef21 100644 --- a/lib/memio/memio.ww +++ b/lib/memio/memio.ww @@ -197,7 +197,7 @@ fn grow(m: *state, need: i32) void = { let newcap: i32 = m.cap; if (newcap < 8) { newcap = 8; }; for (newcap < need) { newcap *= 2; }; - let nbuf: *u8 = rt.alloc(newcap: u64): *u8; + let nbuf: *u8 = rt.malloc(newcap: u64): *u8; let i: i32 = 0; for (i < m.len) { nbuf[i] = m.ptr[i]; diff --git a/lib/os/os.ww b/lib/os/os.ww index 49fab36d..8e42e1a3 100644 --- a/lib/os/os.ww +++ b/lib/os/os.ww @@ -340,7 +340,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. diff --git a/lib/os/ostest.ww b/lib/os/ostest.ww index 977d4f8a..a79b2891 100644 --- a/lib/os/ostest.ww +++ b/lib/os/ostest.ww @@ -103,7 +103,7 @@ fn streq(a: str, b: str) bool = { // dereferenceable, not just non-nil). @test fn test_alloc_free_roundtrip() void = { - let p: *u8 = rt.alloc(4096u64): *u8; + let p: *u8 = rt.malloc(4096u64): *u8; if (p == nil: *u8) { fail(); }; // Write a sentinel at the head and tail of the page, read it // back. A miscompiled binding (wrong arg order, wrong ABI, etc.) diff --git a/lib/path/path.ww b/lib/path/path.ww index 40fbfb61..abb3a368 100644 --- a/lib/path/path.ww +++ b/lib/path/path.ww @@ -95,7 +95,7 @@ export fn extension(p: str) str = { // two-arg join (no variadic). export fn join(a: str, b: str) str = { if (abs(b)) { - let buf: *u8 = rt.alloc(b.len: u64): *u8; + let buf: *u8 = rt.malloc(b.len: u64): *u8; let i: i32 = 0; for (i < b.len) { buf[i] = b[i]; i += 1; }; let r: str; @@ -104,7 +104,7 @@ export fn join(a: str, b: str) str = { return r; }; if (a.len == 0) { - let buf: *u8 = rt.alloc(b.len: u64): *u8; + let buf: *u8 = rt.malloc(b.len: u64): *u8; let i: i32 = 0; for (i < b.len) { buf[i] = b[i]; i += 1; }; let r: str; @@ -113,7 +113,7 @@ export fn join(a: str, b: str) str = { return r; }; if (b.len == 0) { - let buf: *u8 = rt.alloc(a.len: u64): *u8; + let buf: *u8 = rt.malloc(a.len: u64): *u8; let i: i32 = 0; for (i < a.len) { buf[i] = a[i]; i += 1; }; let r: str; @@ -129,7 +129,7 @@ export fn join(a: str, b: str) str = { an -= 1; }; let total: i32 = an + 1 + b.len; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let i: i32 = 0; for (i < an) { buf[i] = a[i]; i += 1; }; buf[an] = SEP; diff --git a/lib/rt/malloc.ww b/lib/rt/malloc.ww index fdee8a6e..9d10913b 100644 --- a/lib/rt/malloc.ww +++ b/lib/rt/malloc.ww @@ -3,7 +3,7 @@ package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -11,12 +11,12 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; diff --git a/lib/shlex/shlex.ww b/lib/shlex/shlex.ww index c452ce96..71264b08 100644 --- a/lib/shlex/shlex.ww +++ b/lib/shlex/shlex.ww @@ -126,7 +126,7 @@ fn dupstr(s: str) str = { r.ptr = nil; r.len = 0; if (s.len == 0) { return r; }; - let buf: *u8 = rt.alloc(s.len: u64): *u8; + let buf: *u8 = rt.malloc(s.len: u64): *u8; let i: i32 = 0; for (i < s.len) { buf[i] = s[i]; i += 1; }; r.ptr = buf; diff --git a/lib/strings/strings.ww b/lib/strings/strings.ww index 5df40a8a..1c306dba 100644 --- a/lib/strings/strings.ww +++ b/lib/strings/strings.ww @@ -99,7 +99,7 @@ export fn dup(s: str) str = { r.ptr = nil; r.len = 0; if (s.len == 0) { return r; }; - let buf: *u8 = rt.alloc(s.len: u64): *u8; + let buf: *u8 = rt.malloc(s.len: u64): *u8; let i: i32 = 0; for (i < s.len) { buf[i] = s[i]; i += 1; }; r.ptr = buf; @@ -121,7 +121,7 @@ export fn dup(s: str) str = { // (#46). The pre-allocated slice has `cap == s.len`, so appendstr's // rt_ensure call never reaches the grow branch. // -// Empty input bypasses the alloc: rt_alloc(0) is an mmap of 0 bytes +// Empty input bypasses the alloc: rt_malloc(0) is an mmap of 0 bytes // which returns -EINVAL, and the alloc-slice `?` shortcut routes // that through nomem — Hare's heap allocator hands back a sentinel // instead (#47). Return `{nil, 0, 0}` directly so callers get the @@ -177,7 +177,7 @@ export fn concat(strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -210,7 +210,7 @@ export fn join(delim: str, strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -887,7 +887,7 @@ export fn lpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let padwrite: i32 = (maxlen - s.len) * pad.len; if (padwrite > maxlen) { padwrite = maxlen; }; let off: i32 = 0; @@ -970,7 +970,7 @@ export fn rpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let k: i32 = 0; for (k < s.len) { buf[k] = s[k]; diff --git a/rt/alloc.s b/rt/alloc.s index 290e1dfa..ad0dc01f 100644 --- a/rt/alloc.s +++ b/rt/alloc.s @@ -1,6 +1,6 @@ // rt/alloc.s — page allocator via the mmap syscall. // -// rt_alloc(n: u64) returns a *void aligned at a page boundary, sized +// rt_malloc(n: u64) returns a *void aligned at a page boundary, sized // to the next page multiple. Pair with rt_free(p, n). // // We pin to PROT_READ|PROT_WRITE and MAP_PRIVATE|MAP_ANONYMOUS so @@ -12,7 +12,7 @@ // the failure path here returns 0 instead of a poisoned pointer. The // builtin's caller is expected to `!`/`?` the result. -TEXT rt_alloc,$0 +TEXT rt_malloc,$0 MOVQ DI, SI // arg 1: length = caller's n MOVQ $0, DI // arg 0: addr = NULL (kernel chooses) MOVQ $3, DX // arg 2: prot = R|W @@ -22,9 +22,9 @@ TEXT rt_alloc,$0 MOVQ $9, AX // syscall: mmap SYSCALL CMPQ $0, AX - JGE rt_alloc_ok + JGE rt_malloc_ok XORQ AX, AX -rt_alloc_ok: +rt_malloc_ok: RET TEXT rt_free,$0 diff --git a/rt/ensure.ww b/rt/ensure.ww index 5b2409b9..ef19140b 100644 --- a/rt/ensure.ww +++ b/rt/ensure.ww @@ -14,12 +14,12 @@ // no per-type wrapper functions (appendu8 / appendi64) needed. // // User code never `use`s this — the symbol is resolved at link time -// from libwwrt.a, like rt_alloc and rt_streq. No `module` declaration: +// from libwwrt.a, like rt_malloc and rt_streq. No `module` declaration: // rt/ensure.ww is compiled standalone via `w6c rt/ensure.ww` (not // through the driver), and its `export fn rt_ensure` must keep its // bare symbol name so the linker resolves it. -@symbol("rt_alloc") fn alloc(n: u64) *void; +@symbol("rt_malloc") fn malloc(n: u64) *void; @symbol("rt_free") fn free(p: *void, n: u64) void; // Mirrors ww's []T header layout: 24 bytes with 8-byte slots. @@ -37,12 +37,9 @@ export fn rt_ensure(s: *slice, membsz: u64) void = { let nc: i64 = s.cap * 2i64; if (nc < 8i64) { nc = 8i64; }; for (nc < s.len) { nc *= 2i64; }; - // Task #30: the alloc builtin returns `(*T | nomem)`; `!` aborts - // on OOM. The longstanding sizeof-only allocation bug (task #27) - // stays unfixed here — rt_ensure presumes a same-module `fn - // alloc(n)` resolution that the bare cur_mod=NULL gate at - // cmd/wcc/check.c:984 doesn't honour. - let np: *u8 = alloc((nc: u64) * membsz)!: *u8; + // Task #30 (commit 3) upgrades to nullable *void + null-check. + // For now, rt_malloc returns plain *void; OOM faults on deref. + let np: *u8 = malloc((nc: u64) * membsz): *u8; let n: u64 = (s.cap: u64) * membsz; let i: u64 = 0u64; for (i < n) { diff --git a/rt/start.s b/rt/start.s index e95d3425..6eb58c4b 100644 --- a/rt/start.s +++ b/rt/start.s @@ -32,7 +32,7 @@ TEXT _start,$0 // rt_envp — getter that returns the envp pointer captured at process // entry. Bound from lib/os via `@symbol("rt_envp") fn rtenvp() **u8;`, -// matching the rt_syscall / rt_alloc / rt_abort pattern. Read-only +// matching the rt_syscall / rt_malloc / rt_abort pattern. Read-only // view of the kernel-supplied table; the bytes live for the process // lifetime. A future setenv that grows the table re-points the slot // (separate task). diff --git a/selfhost/cmd/w6a/asm.ww b/selfhost/cmd/w6a/asm.ww index 05fa9133..cf933042 100644 --- a/selfhost/cmd/w6a/asm.ww +++ b/selfhost/cmd/w6a/asm.ww @@ -23,7 +23,7 @@ export fn emitbyte(a: *asm_, b: u8) void = { let nc: u64 = a.textcap; if (nc == 0u64) { nc = 4096u64; }; nc = nc * 2u64; - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < a.textlen) { nb[i] = a.text[i]; i += 1u64; }; a.text = nb; @@ -60,7 +60,7 @@ export fn emitdatabyte(a: *asm_, b: u8) void = { let nc: u64 = a.datacap; if (nc == 0u64) { nc = 256u64; }; nc = nc * 2u64; - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < a.datalen) { nb[i] = a.data[i]; i += 1u64; }; a.data = nb; diff --git a/selfhost/cmd/w6a/main.combined.ww b/selfhost/cmd/w6a/main.combined.ww index 783cfccb..5a1a4efc 100644 --- a/selfhost/cmd/w6a/main.combined.ww +++ b/selfhost/cmd/w6a/main.combined.ww @@ -438,7 +438,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. @@ -732,7 +732,7 @@ export fn exists(path: str) bool = { package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -740,20 +740,20 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; // selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. // // Bump arena allocator. Backed by the runtime page allocator -// (rt_alloc / rt_free), no libc. Each chunk is mmap'd; when the +// (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. // @@ -783,8 +783,8 @@ fn roundup(n: u64, a: u64) u64 = { }; export fn newarena() *arena = { - let a: *arena = rt.alloc(ARENA_SZ): *arena; - a.buf = rt.alloc(INIT_CHUNK): *u8; + 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; @@ -801,14 +801,14 @@ fn grow(a: *arena, need: u64) bool = { if (want > MAX_CHUNK) { want = MAX_CHUNK; }; if (want < need) { return false; }; // single allocation too big - let old: *arena = rt.alloc(ARENA_SZ): *arena; + 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.alloc(want): *u8; + a.buf = rt.malloc(want): *u8; a.off = 0u64; a.cap = want; a.next = old; @@ -1760,7 +1760,7 @@ export fn emitbyte(a: *asm_, b: u8) void = { let nc: u64 = a.textcap; if (nc == 0u64) { nc = 4096u64; }; nc = nc * 2u64; - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < a.textlen) { nb[i] = a.text[i]; i += 1u64; }; a.text = nb; @@ -1797,7 +1797,7 @@ export fn emitdatabyte(a: *asm_, b: u8) void = { let nc: u64 = a.datacap; if (nc == 0u64) { nc = 256u64; }; nc = nc * 2u64; - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < a.datalen) { nb[i] = a.data[i]; i += 1u64; }; a.data = nb; @@ -3058,7 +3058,7 @@ fn slurp(path: *u8) (*u8, u64) = { case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; let nz: u64 = n: u64; - let buf: *u8 = rt.alloc(nz + 1u64): *u8; + let buf: *u8 = rt.malloc(nz + 1u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, nz); os.close(fd); let got: i64 = 0i64; diff --git a/selfhost/cmd/w6a/main.ww b/selfhost/cmd/w6a/main.ww index e9a4eda6..0f2eff31 100644 --- a/selfhost/cmd/w6a/main.ww +++ b/selfhost/cmd/w6a/main.ww @@ -53,7 +53,7 @@ fn slurp(path: *u8) (*u8, u64) = { case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; let nz: u64 = n: u64; - let buf: *u8 = rt.alloc(nz + 1u64): *u8; + let buf: *u8 = rt.malloc(nz + 1u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, nz); os.close(fd); let got: i64 = 0i64; diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index ac6c39a4..e3ace8a2 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -438,7 +438,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. @@ -732,7 +732,7 @@ export fn exists(path: str) bool = { package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -740,20 +740,20 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; // selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. // // Bump arena allocator. Backed by the runtime page allocator -// (rt_alloc / rt_free), no libc. Each chunk is mmap'd; when the +// (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. // @@ -783,8 +783,8 @@ fn roundup(n: u64, a: u64) u64 = { }; export fn newarena() *arena = { - let a: *arena = rt.alloc(ARENA_SZ): *arena; - a.buf = rt.alloc(INIT_CHUNK): *u8; + 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; @@ -801,14 +801,14 @@ fn grow(a: *arena, need: u64) bool = { if (want > MAX_CHUNK) { want = MAX_CHUNK; }; if (want < need) { return false; }; // single allocation too big - let old: *arena = rt.alloc(ARENA_SZ): *arena; + 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.alloc(want): *u8; + a.buf = rt.malloc(want): *u8; a.off = 0u64; a.cap = want; a.next = old; @@ -1938,7 +1938,7 @@ export fn dup(s: str) str = { r.ptr = nil; r.len = 0; if (s.len == 0) { return r; }; - let buf: *u8 = rt.alloc(s.len: u64): *u8; + let buf: *u8 = rt.malloc(s.len: u64): *u8; let i: i32 = 0; for (i < s.len) { buf[i] = s[i]; i += 1; }; r.ptr = buf; @@ -1960,7 +1960,7 @@ export fn dup(s: str) str = { // (#46). The pre-allocated slice has `cap == s.len`, so appendstr's // rt_ensure call never reaches the grow branch. // -// Empty input bypasses the alloc: rt_alloc(0) is an mmap of 0 bytes +// Empty input bypasses the alloc: rt_malloc(0) is an mmap of 0 bytes // which returns -EINVAL, and the alloc-slice `?` shortcut routes // that through nomem — Hare's heap allocator hands back a sentinel // instead (#47). Return `{nil, 0, 0}` directly so callers get the @@ -2016,7 +2016,7 @@ export fn concat(strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -2049,7 +2049,7 @@ export fn join(delim: str, strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -2726,7 +2726,7 @@ export fn lpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let padwrite: i32 = (maxlen - s.len) * pad.len; if (padwrite > maxlen) { padwrite = maxlen; }; let off: i32 = 0; @@ -2809,7 +2809,7 @@ export fn rpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let k: i32 = 0; for (k < s.len) { buf[k] = s[k]; @@ -15924,14 +15924,14 @@ fn cgbin(c: *cgen, n: *node) void = { }; // cgalloc — `alloc(value)` builtin lowering. Allocate sizeof(value) -// bytes via rt_alloc, then write the value's bytes into the new +// bytes via rt_malloc, then write the value's bytes into the new // region. For an N_STRUCTLIT arg, allocate the struct's totsize and // emit per-field stores at each field's offset. For a scalar/ptr, // allocate 8 bytes and store one word. Mirrors cmd/w6c/cgen.c's // alloc-special branch in N_CALL. // // Task #30: result is the graduated `(*T | nomem)` tagged-pointer -// pair (AX=tag, DX=ptr). rt_alloc now returns 0 on OOM +// pair (AX=tag, DX=ptr). rt_malloc now returns 0 on OOM // (rt/alloc.s); branch on AX to emit the nomem variant (tag=1, // DX=0) or the success variant (tag=0, DX=ptr) after the // value-init stores complete. Callers wrap with `!` / `?` to @@ -15957,7 +15957,7 @@ fn cgalloc(c: *cgen, n: *node) void = { emitint(sz: i64); emitline(", DI\n"); emitline("\tCALL\t"); - emitline(ffiresolve(c, "alloc")); + emitline(ffiresolve(c, "malloc")); emitline("(SB)\n"); emitline("\tCMPQ\t$0, AX\n"); emitline("\tJNE\t"); emitline(okl); emitline("\n"); @@ -16184,7 +16184,7 @@ fn cgcall(c: *cgen, n: *node) void = { }; }; // `alloc(value)` builtin: heap-init a fresh *T with the - // value's bytes. For struct literals, lower to rt_alloc + // value's bytes. For struct literals, lower to rt_malloc // + per-field stores. Mirrors cmd/w6c/cgen.c's N_CALL // alloc path. // @@ -19588,7 +19588,7 @@ fn cglet(c: *cgen, n: *node) void = { let rhs: *node = n.rhs; // `let s: []T = alloc([], n)!;` / `?` shortcut (#32, #45). // Mirror of cstage cgen.c N_LET arrlit-empty branch: allocate - // n*esz bytes via rt_alloc, then build the {ptr, 0, n} slice + // n*esz bytes via rt_malloc, then build the {ptr, 0, n} slice // header in the let slot. The `!`/`?` wraps the builtin's // `([]T | nomem)` return; walk into the N_TRYUNW / N_TRYPROP // to keep the direct-store fast path rather than falling @@ -19657,7 +19657,7 @@ fn cglet(c: *cgen, n: *node) void = { }; emitline("\tMOVQ\tAX, DI\n"); emitline("\tCALL\t"); - emitline(ffiresolve(c, "alloc")); + emitline(ffiresolve(c, "malloc")); emitline("(SB)\n"); if (viatryunw) { let okl: str = mklabel(c, "tryunw_ok"); @@ -23217,7 +23217,7 @@ fn slurp(path: *u8) (*u8, u64) = { case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; let nz: u64 = n: u64; - let buf: *u8 = rt.alloc(nz + 1u64): *u8; + let buf: *u8 = rt.malloc(nz + 1u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, nz); os.close(fd); let got: i64 = 0i64; diff --git a/selfhost/cmd/w6c/main.ww b/selfhost/cmd/w6c/main.ww index e4a33ab0..bc4840d9 100644 --- a/selfhost/cmd/w6c/main.ww +++ b/selfhost/cmd/w6c/main.ww @@ -62,7 +62,7 @@ fn slurp(path: *u8) (*u8, u64) = { case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; let nz: u64 = n: u64; - let buf: *u8 = rt.alloc(nz + 1u64): *u8; + let buf: *u8 = rt.malloc(nz + 1u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, nz); os.close(fd); let got: i64 = 0i64; diff --git a/selfhost/cmd/w6l/dyn.ww b/selfhost/cmd/w6l/dyn.ww index 778651d8..e5c9d6cc 100644 --- a/selfhost/cmd/w6l/dyn.ww +++ b/selfhost/cmd/w6l/dyn.ww @@ -135,7 +135,7 @@ fn slurpso(path: *u8) (*u8, u64) = { case let v: i64 => n = v; case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; - let buf: *u8 = rt.alloc(n: u64): *u8; + let buf: *u8 = rt.malloc(n: u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, n: u64); os.close(fd); let got: i64 = 0i64; diff --git a/selfhost/cmd/w6l/dynout.ww b/selfhost/cmd/w6l/dynout.ww index 5574a1da..a421edf4 100644 --- a/selfhost/cmd/w6l/dynout.ww +++ b/selfhost/cmd/w6l/dynout.ww @@ -658,7 +658,7 @@ export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { }; // ---- assemble file buffer ---- - let filebuf: *u8 = rt.alloc(fileend): *u8; + let filebuf: *u8 = rt.malloc(fileend): *u8; if (filebuf == nil) { os.write(2, "w6l: out of memory\n".ptr, 18u64); return 1; diff --git a/selfhost/cmd/w6l/main.combined.ww b/selfhost/cmd/w6l/main.combined.ww index 3d3774af..ea5eafd7 100644 --- a/selfhost/cmd/w6l/main.combined.ww +++ b/selfhost/cmd/w6l/main.combined.ww @@ -438,7 +438,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. @@ -732,7 +732,7 @@ export fn exists(path: str) bool = { package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -740,20 +740,20 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; // selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. // // Bump arena allocator. Backed by the runtime page allocator -// (rt_alloc / rt_free), no libc. Each chunk is mmap'd; when the +// (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. // @@ -783,8 +783,8 @@ fn roundup(n: u64, a: u64) u64 = { }; export fn newarena() *arena = { - let a: *arena = rt.alloc(ARENA_SZ): *arena; - a.buf = rt.alloc(INIT_CHUNK): *u8; + 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; @@ -801,14 +801,14 @@ fn grow(a: *arena, need: u64) bool = { if (want > MAX_CHUNK) { want = MAX_CHUNK; }; if (want < need) { return false; }; // single allocation too big - let old: *arena = rt.alloc(ARENA_SZ): *arena; + 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.alloc(want): *u8; + a.buf = rt.malloc(want): *u8; a.off = 0u64; a.cap = want; a.next = old; @@ -1061,7 +1061,7 @@ fn slurp(path: *u8) (*u8, u64) = { case let v: i64 => n = v; case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; - let buf: *u8 = rt.alloc(n: u64): *u8; + let buf: *u8 = rt.malloc(n: u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, n: u64); os.close(fd); let got: i64 = 0i64; @@ -1083,7 +1083,7 @@ fn emittext(l: *lnk, src: *u8, n: u64) void = { // Grow by mmap'ing a fresh region and copying. The old buffer // is leaked into the page allocator; for a linker run this is // trivial waste. - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < l.textlen) { nb[i] = l.text[i]; @@ -1105,7 +1105,7 @@ fn emitdata(l: *lnk, src: *u8, n: u64) void = { let nc: u64 = l.datacap; if (nc == 0u64) { nc = 256u64; }; for (nc < l.datalen + n) { nc = nc * 2u64; }; - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < l.datalen) { nb[i] = l.data[i]; @@ -1721,7 +1721,7 @@ fn slurpso(path: *u8) (*u8, u64) = { case let v: i64 => n = v; case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; - let buf: *u8 = rt.alloc(n: u64): *u8; + let buf: *u8 = rt.malloc(n: u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, n: u64); os.close(fd); let got: i64 = 0i64; @@ -2782,7 +2782,7 @@ export fn emitdynelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { }; // ---- assemble file buffer ---- - let filebuf: *u8 = rt.alloc(fileend): *u8; + let filebuf: *u8 = rt.malloc(fileend): *u8; if (filebuf == nil) { os.write(2, "w6l: out of memory\n".ptr, 18u64); return 1; @@ -2973,7 +2973,7 @@ export fn emitelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let datafilelen: u64 = l.datalen - bsslen; // One contiguous header buffer covering [0..0x1000), then .text. - let hdr: *u8 = rt.alloc(TEXT_OFF): *u8; // zero-initialised by mmap + let hdr: *u8 = rt.malloc(TEXT_OFF): *u8; // zero-initialised by mmap // --- Ehdr (64 bytes) --- hdr[0u64] = 127u8; // 0x7f @@ -3128,7 +3128,7 @@ fn appenddec(dst: *u8, i: u64, n: u64) u64 = { dst[i] = 48u8; return i + 1u64; }; - let buf: *u8 = rt.alloc(16u64): *u8; + let buf: *u8 = rt.malloc(16u64): *u8; let k: u64 = 0u64; let v: u64 = n; for (v > 0u64) { @@ -3167,7 +3167,7 @@ fn buildpathv(dst: *u8, dir: *u8, name: *u8, v: u64) u64 = { fn islinkable(path: *u8) bool = { let fd: i32 = os.open(pathstr(path), os.flag.RDONLY, 0i32); if (fd < 0) { return false; }; - let mp: *u8 = rt.alloc(8u64): *u8; + let mp: *u8 = rt.malloc(8u64): *u8; let n: i64 = os.read(fd, mp, 8u64); os.close(fd); if (n < 4i64) { return false; }; @@ -3195,7 +3195,7 @@ fn islinkable(path: *u8) bool = { // then lib.a. Return arena-owned NUL-terminated path on success, // nil on miss. fn resolvelib(a: *arena, name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = { - let bufp: *u8 = rt.alloc(1024u64): *u8; + let bufp: *u8 = rt.malloc(1024u64): *u8; let i: i32 = 0; for (i < nlibdirs) { let dir: *u8 = libdirs[i]; @@ -3236,7 +3236,7 @@ fn resolvelib(a: *arena, name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = { fn isso(path: *u8) i32 = { let fd: i32 = os.open(pathstr(path), os.flag.RDONLY, 0i32); if (fd < 0) { return 0; }; - let mp: *u8 = rt.alloc(20u64): *u8; + let mp: *u8 = rt.malloc(20u64): *u8; let n: i64 = os.read(fd, mp, 20u64); os.close(fd); if (n < 20i64) { return 0; }; @@ -3253,11 +3253,11 @@ fn isso(path: *u8) i32 = { export fn main(argc: i32, argv: **u8) i32 = { let outpath: *u8 = nil; let maxinputs: i32 = 64; - let inputs: **u8 = rt.alloc((maxinputs: u64) * 8u64): **u8; + let inputs: **u8 = rt.malloc((maxinputs: u64) * 8u64): **u8; let ninputs: i32 = 0; - let libdirs: **u8 = rt.alloc((maxinputs: u64) * 8u64): **u8; + let libdirs: **u8 = rt.malloc((maxinputs: u64) * 8u64): **u8; let nlibdirs: i32 = 0; - let lflags: **u8 = rt.alloc((maxinputs: u64) * 8u64): **u8; + let lflags: **u8 = rt.malloc((maxinputs: u64) * 8u64): **u8; let nlflags: i32 = 0; let i: i32 = 1; diff --git a/selfhost/cmd/w6l/main.ww b/selfhost/cmd/w6l/main.ww index 301d9a5f..433dc9f1 100644 --- a/selfhost/cmd/w6l/main.ww +++ b/selfhost/cmd/w6l/main.ww @@ -64,7 +64,7 @@ fn appenddec(dst: *u8, i: u64, n: u64) u64 = { dst[i] = 48u8; return i + 1u64; }; - let buf: *u8 = rt.alloc(16u64): *u8; + let buf: *u8 = rt.malloc(16u64): *u8; let k: u64 = 0u64; let v: u64 = n; for (v > 0u64) { @@ -103,7 +103,7 @@ fn buildpathv(dst: *u8, dir: *u8, name: *u8, v: u64) u64 = { fn islinkable(path: *u8) bool = { let fd: i32 = os.open(pathstr(path), os.flag.RDONLY, 0i32); if (fd < 0) { return false; }; - let mp: *u8 = rt.alloc(8u64): *u8; + let mp: *u8 = rt.malloc(8u64): *u8; let n: i64 = os.read(fd, mp, 8u64); os.close(fd); if (n < 4i64) { return false; }; @@ -131,7 +131,7 @@ fn islinkable(path: *u8) bool = { // then lib.a. Return arena-owned NUL-terminated path on success, // nil on miss. fn resolvelib(a: *arena, name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = { - let bufp: *u8 = rt.alloc(1024u64): *u8; + let bufp: *u8 = rt.malloc(1024u64): *u8; let i: i32 = 0; for (i < nlibdirs) { let dir: *u8 = libdirs[i]; @@ -172,7 +172,7 @@ fn resolvelib(a: *arena, name: *u8, libdirs: **u8, nlibdirs: i32) *u8 = { fn isso(path: *u8) i32 = { let fd: i32 = os.open(pathstr(path), os.flag.RDONLY, 0i32); if (fd < 0) { return 0; }; - let mp: *u8 = rt.alloc(20u64): *u8; + let mp: *u8 = rt.malloc(20u64): *u8; let n: i64 = os.read(fd, mp, 20u64); os.close(fd); if (n < 20i64) { return 0; }; @@ -189,11 +189,11 @@ fn isso(path: *u8) i32 = { export fn main(argc: i32, argv: **u8) i32 = { let outpath: *u8 = nil; let maxinputs: i32 = 64; - let inputs: **u8 = rt.alloc((maxinputs: u64) * 8u64): **u8; + let inputs: **u8 = rt.malloc((maxinputs: u64) * 8u64): **u8; let ninputs: i32 = 0; - let libdirs: **u8 = rt.alloc((maxinputs: u64) * 8u64): **u8; + let libdirs: **u8 = rt.malloc((maxinputs: u64) * 8u64): **u8; let nlibdirs: i32 = 0; - let lflags: **u8 = rt.alloc((maxinputs: u64) * 8u64): **u8; + let lflags: **u8 = rt.malloc((maxinputs: u64) * 8u64): **u8; let nlflags: i32 = 0; let i: i32 = 1; diff --git a/selfhost/cmd/w6l/obj.ww b/selfhost/cmd/w6l/obj.ww index 1022116b..fa19cffc 100644 --- a/selfhost/cmd/w6l/obj.ww +++ b/selfhost/cmd/w6l/obj.ww @@ -87,7 +87,7 @@ fn slurp(path: *u8) (*u8, u64) = { case let v: i64 => n = v; case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; - let buf: *u8 = rt.alloc(n: u64): *u8; + let buf: *u8 = rt.malloc(n: u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, n: u64); os.close(fd); let got: i64 = 0i64; @@ -109,7 +109,7 @@ fn emittext(l: *lnk, src: *u8, n: u64) void = { // Grow by mmap'ing a fresh region and copying. The old buffer // is leaked into the page allocator; for a linker run this is // trivial waste. - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < l.textlen) { nb[i] = l.text[i]; @@ -131,7 +131,7 @@ fn emitdata(l: *lnk, src: *u8, n: u64) void = { let nc: u64 = l.datacap; if (nc == 0u64) { nc = 256u64; }; for (nc < l.datalen + n) { nc = nc * 2u64; }; - let nb: *u8 = rt.alloc(nc): *u8; + let nb: *u8 = rt.malloc(nc): *u8; let i: u64 = 0u64; for (i < l.datalen) { nb[i] = l.data[i]; diff --git a/selfhost/cmd/w6l/out.ww b/selfhost/cmd/w6l/out.ww index 98693a28..c43504d6 100644 --- a/selfhost/cmd/w6l/out.ww +++ b/selfhost/cmd/w6l/out.ww @@ -89,7 +89,7 @@ export fn emitelf(l: *lnk, fd: i32, base: u64, entry: u64) i32 = { let datafilelen: u64 = l.datalen - bsslen; // One contiguous header buffer covering [0..0x1000), then .text. - let hdr: *u8 = rt.alloc(TEXT_OFF): *u8; // zero-initialised by mmap + let hdr: *u8 = rt.malloc(TEXT_OFF): *u8; // zero-initialised by mmap // --- Ehdr (64 bytes) --- hdr[0u64] = 127u8; // 0x7f diff --git a/selfhost/cmd/wcc/cgenexpr.ww b/selfhost/cmd/wcc/cgenexpr.ww index 0c31c537..ffb3089b 100644 --- a/selfhost/cmd/wcc/cgenexpr.ww +++ b/selfhost/cmd/wcc/cgenexpr.ww @@ -2712,14 +2712,14 @@ fn cgbin(c: *cgen, n: *node) void = { }; // cgalloc — `alloc(value)` builtin lowering. Allocate sizeof(value) -// bytes via rt_alloc, then write the value's bytes into the new +// bytes via rt_malloc, then write the value's bytes into the new // region. For an N_STRUCTLIT arg, allocate the struct's totsize and // emit per-field stores at each field's offset. For a scalar/ptr, // allocate 8 bytes and store one word. Mirrors cmd/w6c/cgen.c's // alloc-special branch in N_CALL. // // Task #30: result is the graduated `(*T | nomem)` tagged-pointer -// pair (AX=tag, DX=ptr). rt_alloc now returns 0 on OOM +// pair (AX=tag, DX=ptr). rt_malloc now returns 0 on OOM // (rt/alloc.s); branch on AX to emit the nomem variant (tag=1, // DX=0) or the success variant (tag=0, DX=ptr) after the // value-init stores complete. Callers wrap with `!` / `?` to @@ -2745,7 +2745,7 @@ fn cgalloc(c: *cgen, n: *node) void = { emitint(sz: i64); emitline(", DI\n"); emitline("\tCALL\t"); - emitline(ffiresolve(c, "alloc")); + emitline(ffiresolve(c, "malloc")); emitline("(SB)\n"); emitline("\tCMPQ\t$0, AX\n"); emitline("\tJNE\t"); emitline(okl); emitline("\n"); @@ -2972,7 +2972,7 @@ fn cgcall(c: *cgen, n: *node) void = { }; }; // `alloc(value)` builtin: heap-init a fresh *T with the - // value's bytes. For struct literals, lower to rt_alloc + // value's bytes. For struct literals, lower to rt_malloc // + per-field stores. Mirrors cmd/w6c/cgen.c's N_CALL // alloc path. // diff --git a/selfhost/cmd/wcc/cgenstmt.ww b/selfhost/cmd/wcc/cgenstmt.ww index f1ed4ad6..6eac818d 100644 --- a/selfhost/cmd/wcc/cgenstmt.ww +++ b/selfhost/cmd/wcc/cgenstmt.ww @@ -576,7 +576,7 @@ fn cglet(c: *cgen, n: *node) void = { let rhs: *node = n.rhs; // `let s: []T = alloc([], n)!;` / `?` shortcut (#32, #45). // Mirror of cstage cgen.c N_LET arrlit-empty branch: allocate - // n*esz bytes via rt_alloc, then build the {ptr, 0, n} slice + // n*esz bytes via rt_malloc, then build the {ptr, 0, n} slice // header in the let slot. The `!`/`?` wraps the builtin's // `([]T | nomem)` return; walk into the N_TRYUNW / N_TRYPROP // to keep the direct-store fast path rather than falling @@ -645,7 +645,7 @@ fn cglet(c: *cgen, n: *node) void = { }; emitline("\tMOVQ\tAX, DI\n"); emitline("\tCALL\t"); - emitline(ffiresolve(c, "alloc")); + emitline(ffiresolve(c, "malloc")); emitline("(SB)\n"); if (viatryunw) { let okl: str = mklabel(c, "tryunw_ok"); diff --git a/selfhost/cmd/wcc/mem.ww b/selfhost/cmd/wcc/mem.ww index b37fa14f..12510d26 100644 --- a/selfhost/cmd/wcc/mem.ww +++ b/selfhost/cmd/wcc/mem.ww @@ -1,7 +1,7 @@ // selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. // // Bump arena allocator. Backed by the runtime page allocator -// (rt_alloc / rt_free), no libc. Each chunk is mmap'd; when the +// (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. // @@ -31,8 +31,8 @@ fn roundup(n: u64, a: u64) u64 = { }; export fn newarena() *arena = { - let a: *arena = rt.alloc(ARENA_SZ): *arena; - a.buf = rt.alloc(INIT_CHUNK): *u8; + 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; @@ -49,14 +49,14 @@ fn grow(a: *arena, need: u64) bool = { if (want > MAX_CHUNK) { want = MAX_CHUNK; }; if (want < need) { return false; }; // single allocation too big - let old: *arena = rt.alloc(ARENA_SZ): *arena; + 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.alloc(want): *u8; + a.buf = rt.malloc(want): *u8; a.off = 0u64; a.cap = want; a.next = old; diff --git a/selfhost/cmd/ww/main.combined.ww b/selfhost/cmd/ww/main.combined.ww index 9e3bb6e0..84a727f1 100644 --- a/selfhost/cmd/ww/main.combined.ww +++ b/selfhost/cmd/ww/main.combined.ww @@ -438,7 +438,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. @@ -732,7 +732,7 @@ export fn exists(path: str) bool = { package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -740,20 +740,20 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; // selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. // // Bump arena allocator. Backed by the runtime page allocator -// (rt_alloc / rt_free), no libc. Each chunk is mmap'd; when the +// (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. // @@ -783,8 +783,8 @@ fn roundup(n: u64, a: u64) u64 = { }; export fn newarena() *arena = { - let a: *arena = rt.alloc(ARENA_SZ): *arena; - a.buf = rt.alloc(INIT_CHUNK): *u8; + 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; @@ -801,14 +801,14 @@ fn grow(a: *arena, need: u64) bool = { if (want > MAX_CHUNK) { want = MAX_CHUNK; }; if (want < need) { return false; }; // single allocation too big - let old: *arena = rt.alloc(ARENA_SZ): *arena; + 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.alloc(want): *u8; + a.buf = rt.malloc(want): *u8; a.off = 0u64; a.cap = want; a.next = old; @@ -1001,7 +1001,7 @@ fn selfdirinto(dst: *u8, dstsz: u64, argv0: *u8) void = { // Build "$dir/$name" (NUL-terminated) into a fresh page-sized buffer. fn joinpath(dir: *u8, name: *u8) *u8 = { - let buf: *u8 = rt.alloc(PATH_MAX): *u8; + let buf: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = cstrinto(buf, 0u64, dir); off = byteinto(buf, off, 47u8); off = cstrinto(buf, off, name); @@ -1011,7 +1011,7 @@ fn joinpath(dir: *u8, name: *u8) *u8 = { // Same, but the second component is a ww `str` literal. fn joinpathlit(dir: *u8, name: str) *u8 = { - let buf: *u8 = rt.alloc(PATH_MAX): *u8; + let buf: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = cstrinto(buf, 0u64, dir); off = byteinto(buf, off, 47u8); off = strinto(buf, off, name); @@ -1262,7 +1262,7 @@ fn enumeratedir(a: *arena, dirpath: *u8) (**u8, i32) = { let names: **u8 = amalloc(a, (maxnames: u64) * 8u64): **u8; let nlens: *u64 = amalloc(a, (maxnames: u64) * 8u64): *u64; let n: i32 = 0; - let buf: *u8 = rt.alloc(8192u64): *u8; + let buf: *u8 = rt.malloc(8192u64): *u8; let r: i64 = os.getdents64(fd, buf, 8192u64); for (r > 0i64) { let off: u64 = 0u64; @@ -1324,7 +1324,7 @@ fn slurp(pathcs: *u8) (*u8, u64) = { case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; let nu: u64 = n: u64; - let buf: *u8 = rt.alloc(nu + 1u64): *u8; + let buf: *u8 = rt.malloc(nu + 1u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, nu); os.close(fd); let got: i64 = 0i64; @@ -1431,7 +1431,7 @@ fn expand(c: *expctx, pathcs: *u8) void = { fn peekpackage(a: *arena, pathcs: *u8) *u8 = { let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32); if (fd < 0) { return nil; }; - let buf: *u8 = rt.alloc(2048u64): *u8; + let buf: *u8 = rt.malloc(2048u64): *u8; let n: i64 = os.read(fd, buf, 2048u64); os.close(fd); if (n <= 0i64) { return nil; }; @@ -1578,7 +1578,7 @@ fn makestem(stem: *u8, src: *u8) void = { // Append a literal suffix to `stem` (which already lives in a buffer). fn appendlit(stem: *u8, suffix: str) *u8 = { - let buf: *u8 = rt.alloc(PATH_MAX): *u8; + let buf: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = cstrinto(buf, 0u64, stem); off = strinto(buf, off, suffix); cstrseal(buf, off); @@ -1616,7 +1616,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l let l6: *u8 = joinpathlit(selfdir, "w6l_ww"); // Default lib search path: /../../lib - let dotdotlib: *u8 = rt.alloc(PATH_MAX): *u8; + let dotdotlib: *u8 = rt.malloc(PATH_MAX): *u8; { let off: u64 = cstrinto(dotdotlib, 0u64, selfdir); off = strinto(dotdotlib, off, "/../../lib"); @@ -1629,7 +1629,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // convention assumes you're running from the module dir; our // wrappers don't cd, so dirname(src) stands in as the closest // analog. Source-dir wins ties over the system path (cc -I.). - let srcd: *u8 = rt.alloc(PATH_MAX): *u8; + let srcd: *u8 = rt.malloc(PATH_MAX): *u8; if (entryisdir != 0) { let slen: u64 = cstrlen(src); let k: u64 = 0u64; @@ -1663,7 +1663,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l }; // Compose searchpath: srcd + ':' + incs + ':' + dotdotlib. - let searchpath: *u8 = rt.alloc(PATH_MAX * 3u64): *u8; + let searchpath: *u8 = rt.malloc(PATH_MAX * 3u64): *u8; { let off: u64 = cstrinto(searchpath, 0u64, srcd); off = byteinto(searchpath, off, 58u8); // ':' @@ -1677,7 +1677,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // Stem for .s/.o/.combined.ww side files. Dir entry: /; // file entry: src stripped of .ww. - let stem: *u8 = rt.alloc(PATH_MAX): *u8; + let stem: *u8 = rt.malloc(PATH_MAX): *u8; if (entryisdir != 0) { let dlen: u64 = cstrlen(srcd); let bo: u64 = basenameoff(srcd, dlen); @@ -1694,7 +1694,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l let combined: *u8 = appendlit(stem, ".combined.ww"); // libwwrt.a path: /../lib/libwwrt.a - let libwwrt: *u8 = rt.alloc(PATH_MAX): *u8; + let libwwrt: *u8 = rt.malloc(PATH_MAX): *u8; { let off: u64 = cstrinto(libwwrt, 0u64, selfdir); off = strinto(libwwrt, off, "/../lib/libwwrt.a"); @@ -1721,7 +1721,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // Step 2: w6c -o .s .combined.ww { - let argv: **u8 = rt.alloc(40u64): **u8; + let argv: **u8 = rt.malloc(40u64): **u8; argv[0] = "w6c\0".ptr; argv[1] = "-o\0".ptr; argv[2] = asmf; @@ -1735,7 +1735,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // Step 3: w6a -o .o .s { - let argv: **u8 = rt.alloc(40u64): **u8; + let argv: **u8 = rt.malloc(40u64): **u8; argv[0] = "w6a\0".ptr; argv[1] = "-o\0".ptr; argv[2] = objf; @@ -1764,7 +1764,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // + 2 * nlibs (-l, name) // + 1 nil terminator. let total: i32 = 5 + 2 * nldirs + 2 * nllibs + 1; - let argv: **u8 = rt.alloc((total: u64) * 8u64): **u8; + let argv: **u8 = rt.malloc((total: u64) * 8u64): **u8; argv[0] = "w6l\0".ptr; argv[1] = "-o\0".ptr; argv[2] = out; @@ -1936,7 +1936,7 @@ fn defaultoutpath(src: *u8) *u8 = { if (src[i] == 47u8) { start = i + 1u64; }; // '/' i += 1u64; }; - let out: *u8 = rt.alloc(PATH_MAX): *u8; + let out: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = 0u64; let j: u64 = start; for (j < n) { @@ -1961,14 +1961,14 @@ fn defaultoutpath(src: *u8) *u8 = { fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { let a: *arena = newarena(); let src: *u8 = nil; - let incs: *u8 = rt.alloc(PATH_MAX * 2u64): *u8; + let incs: *u8 = rt.malloc(PATH_MAX * 2u64): *u8; let incoff: u64 = 0u64; cstrseal(incs, 0u64); let maxlflags: i32 = 32; - let libdirs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libdirs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibdirs: i32 = 0; - let libs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibs: i32 = 0; let i: i32 = start; @@ -2058,7 +2058,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { rlen -= 1u64; }; let bo: u64 = basenameoff(resolved, rlen); - out = rt.alloc(PATH_MAX): *u8; + out = rt.malloc(PATH_MAX): *u8; let i: u64 = bo; let off: u64 = 0u64; for (i < rlen) { out[off] = resolved[i]; off += 1u64; i += 1u64; }; @@ -2108,14 +2108,14 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { let a: *arena = newarena(); let src: *u8 = nil; let passstart: i32 = -1; // first argv idx to pass through to program - let incs: *u8 = rt.alloc(PATH_MAX * 2u64): *u8; + let incs: *u8 = rt.malloc(PATH_MAX * 2u64): *u8; let incoff: u64 = 0u64; cstrseal(incs, 0u64); let maxlflags: i32 = 32; - let libdirs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libdirs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibdirs: i32 = 0; - let libs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibs: i32 = 0; let i: i32 = start; @@ -2205,7 +2205,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { return 1; }; - let tmp: *u8 = rt.alloc(PATH_MAX): *u8; + let tmp: *u8 = rt.malloc(PATH_MAX): *u8; makeruntmp(tmp); let lf: lflags; lf.libdirs = libdirs; @@ -2221,7 +2221,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { let nextra: i32 = 0; if (passstart >= 0) { nextra = argc - passstart; }; let total: i32 = nextra + 2; - let execargv: **u8 = rt.alloc((total: u64) * 8u64): **u8; + let execargv: **u8 = rt.malloc((total: u64) * 8u64): **u8; execargv[0] = tmp; let k: i32 = 0; for (k < nextra) { @@ -2242,13 +2242,13 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { // report ok/FAIL per file, return 0 iff all pass. fn runsingletest(selfdir: *u8, src: *u8) i32 = { - let tmp: *u8 = rt.alloc(PATH_MAX): *u8; + let tmp: *u8 = rt.malloc(PATH_MAX): *u8; makeruntmp(tmp); if (buildone(selfdir, src, 0, tmp, "\0".ptr, nil) != 0) { os.remove(pathstr(tmp)); return 1; }; - let execargv: **u8 = rt.alloc(16u64): **u8; + let execargv: **u8 = rt.malloc(16u64): **u8; execargv[0] = tmp; execargv[1] = nil; let rc: i32 = procrun(tmp, execargv); @@ -2265,7 +2265,7 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { let pass: i32 = 0; let fail: i32 = 0; - let buf: *u8 = rt.alloc(8192u64): *u8; + let buf: *u8 = rt.malloc(8192u64): *u8; let dirlen: u64 = cstrlen(dir); let n: i64 = os.getdents64(fd, buf, 8192u64); @@ -2281,7 +2281,7 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { if (cstrendswithlit(name, "_test.ww")) { let nlen: u64 = cstrlen(name); // path = / - let path: *u8 = rt.alloc(PATH_MAX): *u8; + let path: *u8 = rt.malloc(PATH_MAX): *u8; let poff: u64 = cstrinto(path, 0u64, dir); path[poff] = 47u8; poff += 1u64; let i: u64 = 0u64; @@ -2289,10 +2289,10 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { poff += nlen; cstrseal(path, poff); // incs = so test files can `use ` siblings - let tincs: *u8 = rt.alloc(PATH_MAX): *u8; + let tincs: *u8 = rt.malloc(PATH_MAX): *u8; let ic: u64 = cstrinto(tincs, 0u64, dir); cstrseal(tincs, ic); - let tmp: *u8 = rt.alloc(PATH_MAX): *u8; + let tmp: *u8 = rt.malloc(PATH_MAX): *u8; makeruntmp(tmp); let bres: i32 = buildone(selfdir, path, 0, tmp, tincs, nil); if (bres != 0) { @@ -2301,7 +2301,7 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { os.write(2, name, nlen); os.write(2, " (build)\n".ptr, 9u64); } else { - let execargv: **u8 = rt.alloc(16u64): **u8; + let execargv: **u8 = rt.malloc(16u64): **u8; execargv[0] = tmp; execargv[1] = nil; let rc: i32 = procrun(tmp, execargv); @@ -2358,7 +2358,7 @@ export fn main(argc: i32, argv: **u8) i32 = { }; // selfdir = dirname(argv[0]) - let selfdir: *u8 = rt.alloc(PATH_MAX): *u8; + let selfdir: *u8 = rt.malloc(PATH_MAX): *u8; selfdirinto(selfdir, PATH_MAX, argv[0]); if (argc < 2) { diff --git a/selfhost/cmd/ww/main.ww b/selfhost/cmd/ww/main.ww index bada56a5..fd9dd027 100644 --- a/selfhost/cmd/ww/main.ww +++ b/selfhost/cmd/ww/main.ww @@ -139,7 +139,7 @@ fn selfdirinto(dst: *u8, dstsz: u64, argv0: *u8) void = { // Build "$dir/$name" (NUL-terminated) into a fresh page-sized buffer. fn joinpath(dir: *u8, name: *u8) *u8 = { - let buf: *u8 = rt.alloc(PATH_MAX): *u8; + let buf: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = cstrinto(buf, 0u64, dir); off = byteinto(buf, off, 47u8); off = cstrinto(buf, off, name); @@ -149,7 +149,7 @@ fn joinpath(dir: *u8, name: *u8) *u8 = { // Same, but the second component is a ww `str` literal. fn joinpathlit(dir: *u8, name: str) *u8 = { - let buf: *u8 = rt.alloc(PATH_MAX): *u8; + let buf: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = cstrinto(buf, 0u64, dir); off = byteinto(buf, off, 47u8); off = strinto(buf, off, name); @@ -400,7 +400,7 @@ fn enumeratedir(a: *arena, dirpath: *u8) (**u8, i32) = { let names: **u8 = amalloc(a, (maxnames: u64) * 8u64): **u8; let nlens: *u64 = amalloc(a, (maxnames: u64) * 8u64): *u64; let n: i32 = 0; - let buf: *u8 = rt.alloc(8192u64): *u8; + let buf: *u8 = rt.malloc(8192u64): *u8; let r: i64 = os.getdents64(fd, buf, 8192u64); for (r > 0i64) { let off: u64 = 0u64; @@ -462,7 +462,7 @@ fn slurp(pathcs: *u8) (*u8, u64) = { case let e: os.oserror => { os.close(fd); return nil, 0u64; }; }; let nu: u64 = n: u64; - let buf: *u8 = rt.alloc(nu + 1u64): *u8; + let buf: *u8 = rt.malloc(nu + 1u64): *u8; let rr: (i64 | os.oserror) = os.readall(fd, buf, nu); os.close(fd); let got: i64 = 0i64; @@ -569,7 +569,7 @@ fn expand(c: *expctx, pathcs: *u8) void = { fn peekpackage(a: *arena, pathcs: *u8) *u8 = { let fd: i32 = os.open(pathstr(pathcs), os.flag.RDONLY, 0i32); if (fd < 0) { return nil; }; - let buf: *u8 = rt.alloc(2048u64): *u8; + let buf: *u8 = rt.malloc(2048u64): *u8; let n: i64 = os.read(fd, buf, 2048u64); os.close(fd); if (n <= 0i64) { return nil; }; @@ -716,7 +716,7 @@ fn makestem(stem: *u8, src: *u8) void = { // Append a literal suffix to `stem` (which already lives in a buffer). fn appendlit(stem: *u8, suffix: str) *u8 = { - let buf: *u8 = rt.alloc(PATH_MAX): *u8; + let buf: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = cstrinto(buf, 0u64, stem); off = strinto(buf, off, suffix); cstrseal(buf, off); @@ -754,7 +754,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l let l6: *u8 = joinpathlit(selfdir, "w6l_ww"); // Default lib search path: /../../lib - let dotdotlib: *u8 = rt.alloc(PATH_MAX): *u8; + let dotdotlib: *u8 = rt.malloc(PATH_MAX): *u8; { let off: u64 = cstrinto(dotdotlib, 0u64, selfdir); off = strinto(dotdotlib, off, "/../../lib"); @@ -767,7 +767,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // convention assumes you're running from the module dir; our // wrappers don't cd, so dirname(src) stands in as the closest // analog. Source-dir wins ties over the system path (cc -I.). - let srcd: *u8 = rt.alloc(PATH_MAX): *u8; + let srcd: *u8 = rt.malloc(PATH_MAX): *u8; if (entryisdir != 0) { let slen: u64 = cstrlen(src); let k: u64 = 0u64; @@ -801,7 +801,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l }; // Compose searchpath: srcd + ':' + incs + ':' + dotdotlib. - let searchpath: *u8 = rt.alloc(PATH_MAX * 3u64): *u8; + let searchpath: *u8 = rt.malloc(PATH_MAX * 3u64): *u8; { let off: u64 = cstrinto(searchpath, 0u64, srcd); off = byteinto(searchpath, off, 58u8); // ':' @@ -815,7 +815,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // Stem for .s/.o/.combined.ww side files. Dir entry: /; // file entry: src stripped of .ww. - let stem: *u8 = rt.alloc(PATH_MAX): *u8; + let stem: *u8 = rt.malloc(PATH_MAX): *u8; if (entryisdir != 0) { let dlen: u64 = cstrlen(srcd); let bo: u64 = basenameoff(srcd, dlen); @@ -832,7 +832,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l let combined: *u8 = appendlit(stem, ".combined.ww"); // libwwrt.a path: /../lib/libwwrt.a - let libwwrt: *u8 = rt.alloc(PATH_MAX): *u8; + let libwwrt: *u8 = rt.malloc(PATH_MAX): *u8; { let off: u64 = cstrinto(libwwrt, 0u64, selfdir); off = strinto(libwwrt, off, "/../lib/libwwrt.a"); @@ -859,7 +859,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // Step 2: w6c -o .s .combined.ww { - let argv: **u8 = rt.alloc(40u64): **u8; + let argv: **u8 = rt.malloc(40u64): **u8; argv[0] = "w6c\0".ptr; argv[1] = "-o\0".ptr; argv[2] = asmf; @@ -873,7 +873,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // Step 3: w6a -o .o .s { - let argv: **u8 = rt.alloc(40u64): **u8; + let argv: **u8 = rt.malloc(40u64): **u8; argv[0] = "w6a\0".ptr; argv[1] = "-o\0".ptr; argv[2] = objf; @@ -902,7 +902,7 @@ fn buildone(selfdir: *u8, src: *u8, entryisdir: i32, out: *u8, incs: *u8, lf: *l // + 2 * nlibs (-l, name) // + 1 nil terminator. let total: i32 = 5 + 2 * nldirs + 2 * nllibs + 1; - let argv: **u8 = rt.alloc((total: u64) * 8u64): **u8; + let argv: **u8 = rt.malloc((total: u64) * 8u64): **u8; argv[0] = "w6l\0".ptr; argv[1] = "-o\0".ptr; argv[2] = out; @@ -1074,7 +1074,7 @@ fn defaultoutpath(src: *u8) *u8 = { if (src[i] == 47u8) { start = i + 1u64; }; // '/' i += 1u64; }; - let out: *u8 = rt.alloc(PATH_MAX): *u8; + let out: *u8 = rt.malloc(PATH_MAX): *u8; let off: u64 = 0u64; let j: u64 = start; for (j < n) { @@ -1099,14 +1099,14 @@ fn defaultoutpath(src: *u8) *u8 = { fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { let a: *arena = newarena(); let src: *u8 = nil; - let incs: *u8 = rt.alloc(PATH_MAX * 2u64): *u8; + let incs: *u8 = rt.malloc(PATH_MAX * 2u64): *u8; let incoff: u64 = 0u64; cstrseal(incs, 0u64); let maxlflags: i32 = 32; - let libdirs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libdirs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibdirs: i32 = 0; - let libs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibs: i32 = 0; let i: i32 = start; @@ -1196,7 +1196,7 @@ fn dobuild(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { rlen -= 1u64; }; let bo: u64 = basenameoff(resolved, rlen); - out = rt.alloc(PATH_MAX): *u8; + out = rt.malloc(PATH_MAX): *u8; let i: u64 = bo; let off: u64 = 0u64; for (i < rlen) { out[off] = resolved[i]; off += 1u64; i += 1u64; }; @@ -1246,14 +1246,14 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { let a: *arena = newarena(); let src: *u8 = nil; let passstart: i32 = -1; // first argv idx to pass through to program - let incs: *u8 = rt.alloc(PATH_MAX * 2u64): *u8; + let incs: *u8 = rt.malloc(PATH_MAX * 2u64): *u8; let incoff: u64 = 0u64; cstrseal(incs, 0u64); let maxlflags: i32 = 32; - let libdirs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libdirs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibdirs: i32 = 0; - let libs: **u8 = rt.alloc((maxlflags: u64) * 8u64): **u8; + let libs: **u8 = rt.malloc((maxlflags: u64) * 8u64): **u8; let nlibs: i32 = 0; let i: i32 = start; @@ -1343,7 +1343,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { return 1; }; - let tmp: *u8 = rt.alloc(PATH_MAX): *u8; + let tmp: *u8 = rt.malloc(PATH_MAX): *u8; makeruntmp(tmp); let lf: lflags; lf.libdirs = libdirs; @@ -1359,7 +1359,7 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { let nextra: i32 = 0; if (passstart >= 0) { nextra = argc - passstart; }; let total: i32 = nextra + 2; - let execargv: **u8 = rt.alloc((total: u64) * 8u64): **u8; + let execargv: **u8 = rt.malloc((total: u64) * 8u64): **u8; execargv[0] = tmp; let k: i32 = 0; for (k < nextra) { @@ -1380,13 +1380,13 @@ fn dorun(selfdir: *u8, argv: **u8, argc: i32, start: i32) i32 = { // report ok/FAIL per file, return 0 iff all pass. fn runsingletest(selfdir: *u8, src: *u8) i32 = { - let tmp: *u8 = rt.alloc(PATH_MAX): *u8; + let tmp: *u8 = rt.malloc(PATH_MAX): *u8; makeruntmp(tmp); if (buildone(selfdir, src, 0, tmp, "\0".ptr, nil) != 0) { os.remove(pathstr(tmp)); return 1; }; - let execargv: **u8 = rt.alloc(16u64): **u8; + let execargv: **u8 = rt.malloc(16u64): **u8; execargv[0] = tmp; execargv[1] = nil; let rc: i32 = procrun(tmp, execargv); @@ -1403,7 +1403,7 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { let pass: i32 = 0; let fail: i32 = 0; - let buf: *u8 = rt.alloc(8192u64): *u8; + let buf: *u8 = rt.malloc(8192u64): *u8; let dirlen: u64 = cstrlen(dir); let n: i64 = os.getdents64(fd, buf, 8192u64); @@ -1419,7 +1419,7 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { if (cstrendswithlit(name, "_test.ww")) { let nlen: u64 = cstrlen(name); // path = / - let path: *u8 = rt.alloc(PATH_MAX): *u8; + let path: *u8 = rt.malloc(PATH_MAX): *u8; let poff: u64 = cstrinto(path, 0u64, dir); path[poff] = 47u8; poff += 1u64; let i: u64 = 0u64; @@ -1427,10 +1427,10 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { poff += nlen; cstrseal(path, poff); // incs = so test files can `use ` siblings - let tincs: *u8 = rt.alloc(PATH_MAX): *u8; + let tincs: *u8 = rt.malloc(PATH_MAX): *u8; let ic: u64 = cstrinto(tincs, 0u64, dir); cstrseal(tincs, ic); - let tmp: *u8 = rt.alloc(PATH_MAX): *u8; + let tmp: *u8 = rt.malloc(PATH_MAX): *u8; makeruntmp(tmp); let bres: i32 = buildone(selfdir, path, 0, tmp, tincs, nil); if (bres != 0) { @@ -1439,7 +1439,7 @@ fn rundirtests(selfdir: *u8, dir: *u8) i32 = { os.write(2, name, nlen); os.write(2, " (build)\n".ptr, 9u64); } else { - let execargv: **u8 = rt.alloc(16u64): **u8; + let execargv: **u8 = rt.malloc(16u64): **u8; execargv[0] = tmp; execargv[1] = nil; let rc: i32 = procrun(tmp, execargv); @@ -1496,7 +1496,7 @@ export fn main(argc: i32, argv: **u8) i32 = { }; // selfdir = dirname(argv[0]) - let selfdir: *u8 = rt.alloc(PATH_MAX): *u8; + let selfdir: *u8 = rt.malloc(PATH_MAX): *u8; selfdirinto(selfdir, PATH_MAX, argv[0]); if (argc < 2) { diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index c09f341c..d1334983 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -438,7 +438,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. @@ -732,7 +732,7 @@ export fn exists(path: str) bool = { package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -740,20 +740,20 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; // selfhost/cmd/wcc/mem.ww — port of cmd/wcc/mem.c. // // Bump arena allocator. Backed by the runtime page allocator -// (rt_alloc / rt_free), no libc. Each chunk is mmap'd; when the +// (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. // @@ -783,8 +783,8 @@ fn roundup(n: u64, a: u64) u64 = { }; export fn newarena() *arena = { - let a: *arena = rt.alloc(ARENA_SZ): *arena; - a.buf = rt.alloc(INIT_CHUNK): *u8; + 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; @@ -801,14 +801,14 @@ fn grow(a: *arena, need: u64) bool = { if (want > MAX_CHUNK) { want = MAX_CHUNK; }; if (want < need) { return false; }; // single allocation too big - let old: *arena = rt.alloc(ARENA_SZ): *arena; + 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.alloc(want): *u8; + a.buf = rt.malloc(want): *u8; a.off = 0u64; a.cap = want; a.next = old; @@ -1938,7 +1938,7 @@ export fn dup(s: str) str = { r.ptr = nil; r.len = 0; if (s.len == 0) { return r; }; - let buf: *u8 = rt.alloc(s.len: u64): *u8; + let buf: *u8 = rt.malloc(s.len: u64): *u8; let i: i32 = 0; for (i < s.len) { buf[i] = s[i]; i += 1; }; r.ptr = buf; @@ -1960,7 +1960,7 @@ export fn dup(s: str) str = { // (#46). The pre-allocated slice has `cap == s.len`, so appendstr's // rt_ensure call never reaches the grow branch. // -// Empty input bypasses the alloc: rt_alloc(0) is an mmap of 0 bytes +// Empty input bypasses the alloc: rt_malloc(0) is an mmap of 0 bytes // which returns -EINVAL, and the alloc-slice `?` shortcut routes // that through nomem — Hare's heap allocator hands back a sentinel // instead (#47). Return `{nil, 0, 0}` directly so callers get the @@ -2016,7 +2016,7 @@ export fn concat(strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -2049,7 +2049,7 @@ export fn join(delim: str, strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -2726,7 +2726,7 @@ export fn lpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let padwrite: i32 = (maxlen - s.len) * pad.len; if (padwrite > maxlen) { padwrite = maxlen; }; let off: i32 = 0; @@ -2809,7 +2809,7 @@ export fn rpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let k: i32 = 0; for (k < s.len) { buf[k] = s[k]; @@ -15924,14 +15924,14 @@ fn cgbin(c: *cgen, n: *node) void = { }; // cgalloc — `alloc(value)` builtin lowering. Allocate sizeof(value) -// bytes via rt_alloc, then write the value's bytes into the new +// bytes via rt_malloc, then write the value's bytes into the new // region. For an N_STRUCTLIT arg, allocate the struct's totsize and // emit per-field stores at each field's offset. For a scalar/ptr, // allocate 8 bytes and store one word. Mirrors cmd/w6c/cgen.c's // alloc-special branch in N_CALL. // // Task #30: result is the graduated `(*T | nomem)` tagged-pointer -// pair (AX=tag, DX=ptr). rt_alloc now returns 0 on OOM +// pair (AX=tag, DX=ptr). rt_malloc now returns 0 on OOM // (rt/alloc.s); branch on AX to emit the nomem variant (tag=1, // DX=0) or the success variant (tag=0, DX=ptr) after the // value-init stores complete. Callers wrap with `!` / `?` to @@ -15957,7 +15957,7 @@ fn cgalloc(c: *cgen, n: *node) void = { emitint(sz: i64); emitline(", DI\n"); emitline("\tCALL\t"); - emitline(ffiresolve(c, "alloc")); + emitline(ffiresolve(c, "malloc")); emitline("(SB)\n"); emitline("\tCMPQ\t$0, AX\n"); emitline("\tJNE\t"); emitline(okl); emitline("\n"); @@ -16184,7 +16184,7 @@ fn cgcall(c: *cgen, n: *node) void = { }; }; // `alloc(value)` builtin: heap-init a fresh *T with the - // value's bytes. For struct literals, lower to rt_alloc + // value's bytes. For struct literals, lower to rt_malloc // + per-field stores. Mirrors cmd/w6c/cgen.c's N_CALL // alloc path. // @@ -19588,7 +19588,7 @@ fn cglet(c: *cgen, n: *node) void = { let rhs: *node = n.rhs; // `let s: []T = alloc([], n)!;` / `?` shortcut (#32, #45). // Mirror of cstage cgen.c N_LET arrlit-empty branch: allocate - // n*esz bytes via rt_alloc, then build the {ptr, 0, n} slice + // n*esz bytes via rt_malloc, then build the {ptr, 0, n} slice // header in the let slot. The `!`/`?` wraps the builtin's // `([]T | nomem)` return; walk into the N_TRYUNW / N_TRYPROP // to keep the direct-store fast path rather than falling @@ -19657,7 +19657,7 @@ fn cglet(c: *cgen, n: *node) void = { }; emitline("\tMOVQ\tAX, DI\n"); emitline("\tCALL\t"); - emitline(ffiresolve(c, "alloc")); + emitline(ffiresolve(c, "malloc")); emitline("(SB)\n"); if (viatryunw) { let okl: str = mklabel(c, "tryunw_ok"); diff --git a/selfhost/test/smoke.combined.ww b/selfhost/test/smoke.combined.ww index 1a2934b7..3339fda9 100644 --- a/selfhost/test/smoke.combined.ww +++ b/selfhost/test/smoke.combined.ww @@ -438,7 +438,7 @@ export fn getdents64(fd: i32, buf: *u8, n: u64) i64 = { // rt_envp — runtime-side getter. rt/start.s captures envp into a DATAW // slot before calling main; this binding lifts the captured pointer -// into ww. Same FFI shape as rt_syscall / rt_alloc / rt_abort: a TEXT +// into ww. Same FFI shape as rt_syscall / rt_malloc / rt_abort: a TEXT // symbol the linker resolves. The returned `**u8` is a NUL-terminated // table of `*u8` entries, each pointing at a NUL-terminated // "NAME=VALUE" byte sequence. @@ -1709,7 +1709,7 @@ export fn position(d: *decoder) i32 = { package rt; -// alloc — mmap-backed page allocator. Untyped: `alloc(n)` returns a +// malloc — mmap-backed page allocator. Untyped: `malloc(n)` returns a // `*void`; callers cast to the target type. Diverges from Hare: Hare // exposes `alloc` / `free` as typed language builtins that the // compiler lowers to rt::malloc/rt::free; ww has no such builtins, @@ -1717,15 +1717,15 @@ package rt; // need a typed allocation pattern wrap this with a cast plus a stored // capacity (see [[strings.dup]], [[memio.dynamic]]). // -// OOM: rt_alloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no +// OOM: rt_malloc is a bare mmap(MAP_ANON|MAP_PRIVATE) wrapper with no // error path. The raw Linux mmap syscall returns a negative errno cast // to `*void` on failure (e.g. `(void*)-12` for ENOMEM); the // `MAP_FAILED` (`(void*)-1`) value is a libc-wrapper convention that -// rt_alloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches +// rt_malloc doesn't apply. Neither `== nil` nor `== (void*)-1` catches // it; any deref of such a return faults. Today the stdlib does not // check; OOM faults on first dereference. A typed fallible variant is // a future task (task #39). ref/hare/rt/malloc.ha:27. -@symbol("rt_alloc") export fn alloc(n: u64) *void; +@symbol("rt_malloc") export fn malloc(n: u64) *void; // strings — operations over str ({ptr,len}). Hare port; see // ref/hare/strings/. @@ -1828,7 +1828,7 @@ export fn dup(s: str) str = { r.ptr = nil; r.len = 0; if (s.len == 0) { return r; }; - let buf: *u8 = rt.alloc(s.len: u64): *u8; + let buf: *u8 = rt.malloc(s.len: u64): *u8; let i: i32 = 0; for (i < s.len) { buf[i] = s[i]; i += 1; }; r.ptr = buf; @@ -1850,7 +1850,7 @@ export fn dup(s: str) str = { // (#46). The pre-allocated slice has `cap == s.len`, so appendstr's // rt_ensure call never reaches the grow branch. // -// Empty input bypasses the alloc: rt_alloc(0) is an mmap of 0 bytes +// Empty input bypasses the alloc: rt_malloc(0) is an mmap of 0 bytes // which returns -EINVAL, and the alloc-slice `?` shortcut routes // that through nomem — Hare's heap allocator hands back a sentinel // instead (#47). Return `{nil, 0, 0}` directly so callers get the @@ -1906,7 +1906,7 @@ export fn concat(strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -1939,7 +1939,7 @@ export fn join(delim: str, strs: str...) str = { r.ptr = nil; r.len = 0; if (total == 0) { return r; }; - let buf: *u8 = rt.alloc(total: u64): *u8; + let buf: *u8 = rt.malloc(total: u64): *u8; let off: i32 = 0; i = 0; for (i < strs.len) { @@ -2616,7 +2616,7 @@ export fn lpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let padwrite: i32 = (maxlen - s.len) * pad.len; if (padwrite > maxlen) { padwrite = maxlen; }; let off: i32 = 0; @@ -2699,7 +2699,7 @@ export fn rpad(s: str, p: rune, maxlen: i32) str = { if (s.len >= maxlen) { return dup(s); }; let scratch: [4]u8; let pad: []u8 = runebytes(scratch[0:4], p); - let buf: *u8 = rt.alloc(maxlen: u64): *u8; + let buf: *u8 = rt.malloc(maxlen: u64): *u8; let k: i32 = 0; for (k < s.len) { buf[k] = s[k]; diff --git a/selfhost/test/tagged_ptr_ret.ww b/selfhost/test/tagged_ptr_ret.ww index 8ca42ef9..c05d59a1 100644 --- a/selfhost/test/tagged_ptr_ret.ww +++ b/selfhost/test/tagged_ptr_ret.ww @@ -44,12 +44,12 @@ fn allocbox() (*point | nomem) = { }; // Task #32: slice-form `let s: []T = alloc([], n)!;` shortcut. Both -// stages must lower to `n*esz` bytes via rt_alloc, abort on null, and +// stages must lower to `n*esz` bytes via rt_malloc, abort on null, and // build a {ptr, 0, n} header in the let slot. Pre-#32 wwstage fell // through to cgalloc, allocating 8B and dropping the slice header // entirely — silent miscompile. Cap-only would pass on a junk header // pointing to dead memory; write-then-read on s[0]/s[cap-1] proves -// the ptr field is a real rt_alloc'd region (would SIGSEGV otherwise). +// the ptr field is a real rt_malloc'd region (would SIGSEGV otherwise). // IMULQ esz path is currently unreachable from user code — check.c // pins the alloc shape to []u8 (cstage check.c:1052-1082) — so this // row only exercises esz=1; the cgen elemsizeofc resolution stays diff --git a/test/wcc/700_e2e.c b/test/wcc/700_e2e.c index 2a368375..e5f65862 100644 --- a/test/wcc/700_e2e.c +++ b/test/wcc/700_e2e.c @@ -154,7 +154,7 @@ static const struct row rows[] = { { "import os;\n" "import rt;\n" "fn main() i32 = {\n" - " let p: *void = rt.alloc(4096u64);\n" + " let p: *void = rt.malloc(4096u64);\n" " if (p == nil) { return 1; };\n" " let bp: *u8 = p: *u8;\n" " bp[0] = 65u8;\n" @@ -341,7 +341,7 @@ static const struct row rows[] = { * must suppress the builtin and dispatch to the user fn so the * call returns n+100. Pre-gate this site lands in the typed-builtin * path: arg is i64 → returns *i64 → init-type fails against the - * declared i64 (and would over-allocate against rt_alloc anyway). + * declared i64 (and would over-allocate against rt_malloc anyway). * Inline multi-`package` mirrors driver-concatenated layout; the * `import myos;` directive is silently skipped by locate_import * (no external module by that name). */ diff --git a/test/wcc/758_cgalloc_str_field.c b/test/wcc/758_cgalloc_str_field.c index 2470fe3a..ee343c5c 100644 --- a/test/wcc/758_cgalloc_str_field.c +++ b/test/wcc/758_cgalloc_str_field.c @@ -5,7 +5,7 @@ * Pre-fix (#22): wwstage cgalloc's per-field walk routed str-typed * fields through the generic `MOVQ (SP), BX ; MOVQ AX, foff(BX)` path, * which landed only AX (str.ptr) and clobbered BX (str.len) with the - * heap base. str.len silently stayed zero (rt_alloc is MAP_ANON-backed, + * heap base. str.len silently stayed zero (rt_malloc is MAP_ANON-backed, * so the slot was zero-init rather than garbage — but still wrong). * 990 and 995 byte-identity didn't catch this because nothing in the * bootstrapped selfhost source uses `alloc(T { strfield = "..." })!`. @@ -16,15 +16,15 @@ * multi-word fields) is the broader follow-up; this row pins str. * * Pre-fix (#25): wwstage's cgalloc emitted a hardcoded `CALL - * rt_alloc(SB)` while cstage routed the same site through + * rt_malloc(SB)` while cstage routed the same site through * ffi_resolve("alloc"), so direct `w6c` vs `w6c_ww` on a fixture * without the @symbol decl in scope diverged (cstage: `CALL - * alloc(SB)`; wwstage: `CALL rt_alloc(SB)`). The fix swaps both + * alloc(SB)`; wwstage: `CALL rt_malloc(SB)`). The fix swaps both * cgenexpr.ww and cgenstmt.ww cgalloc CALL sites to - * `ffiresolve(c, "alloc")`, aligning wwstage down to the leaner + * `ffiresolve(c, "malloc")`, aligning wwstage down to the leaner * cstage shape (CLAUDE.md rule 10). The `asm_rows` table below pins * the CALL line via single-file `w6c -o` / `w6c_ww -o`; `ww build` - * combines lib/os/os.ww into the fixture and would always supply + * combines lib/rt/malloc.ww into the fixture and would always supply * the @symbol decl, masking the regression. * * The runtime `rows` below run the generated binary under cstage and @@ -177,20 +177,20 @@ run_driver(const char *driver, const struct row *r, int i) * both stages' .s output. Single-file `w6c` compile (no `ww build` * combine), so the @symbol decl is only in scope when the fixture * writes one — that's how `noscope_*` rows pin the pre-fix wwstage - * hardcoded-`rt_alloc` divergence and `withsym_*` rows pin that + * hardcoded-`rt_malloc` divergence and `withsym_*` rows pin that * ffiresolve actually hits when the decl is present. */ struct asm_row { const char *label; const char *src; const char *want_sym; }; static const struct asm_row asm_rows[] = { - /* Int-field, no @symbol in scope. ffiresolve("alloc") misses the - * ffi table and returns "alloc" unchanged on both stages. Pre-fix - * wwstage hardcoded `CALL rt_alloc(SB)` → diverged from cstage's - * ffi_resolve-mediated `CALL alloc(SB)`. */ + /* Int-field, no @symbol in scope. ffiresolve("malloc") misses the + * ffi table and returns "malloc" unchanged on both stages. Pre-fix + * wwstage hardcoded `CALL rt_malloc(SB)` → diverged from cstage's + * ffi_resolve-mediated `CALL malloc(SB)`. */ { "noscope_intfield", "package main;\n" "type holder = struct { n: i32 };\n" "fn dummy() *holder = { return alloc(holder { n = 42 })!; };\n", - "alloc" }, + "malloc" }, /* Str-field, no @symbol in scope. Confirms the str-field branch * (the #22 fix) still routes its CALL through ffiresolve, not a * stray hardcoded literal copied alongside the #22 emit. */ @@ -198,7 +198,7 @@ static const struct asm_row asm_rows[] = { "package main;\n" "type holder = struct { s: str };\n" "fn dummy() *holder = { return alloc(holder { s = \"hi\" })!; };\n", - "alloc" }, + "malloc" }, /* Two-step let-then-assign. cglet's CALL site (cgenstmt.ww:647) * is the second cgalloc emit point; this row covers it. */ { "noscope_let_then_assign", @@ -209,16 +209,16 @@ static const struct asm_row asm_rows[] = { " p.n = 7;\n" " return p;\n" "};\n", - "alloc" }, - /* Explicit @symbol decl in scope. ffiresolve("alloc") → "rt_alloc" - * so both stages emit `CALL rt_alloc(SB)` — positive confirmation + "malloc" }, + /* Explicit @symbol decl in scope. ffiresolve("malloc") → "rt_malloc" + * so both stages emit `CALL rt_malloc(SB)` — positive confirmation * that the ffi table lookup hits, complementing the noscope rows. */ { "withsym_intfield", "package main;\n" - "@symbol(\"rt_alloc\") export fn alloc(n: u64) *void;\n" + "@symbol(\"rt_malloc\") export fn malloc(n: u64) *void;\n" "type holder = struct { n: i32 };\n" "fn dummy() *holder = { return alloc(holder { n = 42 })!; };\n", - "rt_alloc" }, + "rt_malloc" }, }; /* asm_disp_row — pins the foff=0 displacement formatting (#24 part B). @@ -268,7 +268,7 @@ static const struct asm_disp_row asm_disp_rows[] = { }; /* asm_call_check — compile via direct w6c / w6c_ww (no `ww build`), - * extract the `CALL\t(SB)` line referencing alloc/rt_alloc from + * extract the `CALL\t(SB)` line referencing alloc/rt_malloc from * each .s file, and verify (a) both stages emit the same line and * (b) the symbol matches r->want_sym. Returns 0 on success. */ static int @@ -313,7 +313,7 @@ asm_call_check(const char *bin, const struct asm_row *r, int i) while (fgets(buf, sizeof buf, fc)) { if (strstr(buf, "\tCALL\t") && (strstr(buf, "alloc(SB)") - || strstr(buf, "rt_alloc(SB)"))) { + || strstr(buf, "rt_malloc(SB)"))) { strncpy(cline, buf, sizeof cline - 1); break; } @@ -321,7 +321,7 @@ asm_call_check(const char *bin, const struct asm_row *r, int i) while (fgets(buf, sizeof buf, fw)) { if (strstr(buf, "\tCALL\t") && (strstr(buf, "alloc(SB)") - || strstr(buf, "rt_alloc(SB)"))) { + || strstr(buf, "rt_malloc(SB)"))) { strncpy(wline, buf, sizeof wline - 1); break; } diff --git a/test/wcc/990_selfhost.c b/test/wcc/990_selfhost.c index cd0fc7cb..6fb72585 100644 --- a/test/wcc/990_selfhost.c +++ b/test/wcc/990_selfhost.c @@ -437,13 +437,13 @@ probe_ww_compile(const char *bin) * pointer-to-struct field). Pre-fix the cgen fell through * silently and returned the inner pointer instead of the * dereferenced field. Surfaced porting w6l/pass.ww. */ - { "@symbol(\"rt_alloc\") fn rt_alloc(n: u64) *void;\n" + { "@symbol(\"rt_malloc\") fn rt_malloc(n: u64) *void;\n" "type inner = struct { val: u64 };\n" "type outer = struct { p: *inner };\n" "fn main() i32 = {\n" - " let in_: *inner = rt_alloc(8u64): *inner;\n" + " let in_: *inner = rt_malloc(8u64): *inner;\n" " in_.val = 42u64;\n" - " let o: *outer = rt_alloc(8u64): *outer;\n" + " let o: *outer = rt_malloc(8u64): *outer;\n" " o.p = in_;\n" " return o.p.val: i32;\n" "};", 42 }, diff --git a/test/wcc/992_w6l_ww.c b/test/wcc/992_w6l_ww.c index 8d5b0d3f..e96b1418 100644 --- a/test/wcc/992_w6l_ww.c +++ b/test/wcc/992_w6l_ww.c @@ -108,7 +108,7 @@ main(void) } cases[] = { /* Real bootstrap-style links: every selfhost main.o paired * with libwwrt.a. Exercises both the .o code path and the - * archive two-pass loader (rt_alloc / rt_syscall / rt_abort + * archive two-pass loader (rt_malloc / rt_syscall / rt_abort * are pulled from libwwrt.a as undefs are encountered). */ { "wwdump+libwwrt", "%s/selfhost/cmd/wwdump/main.o %s/out/lib/libwwrt.a" },