lib/rt: rename rt_alloc → rt_malloc; rt.alloc → rt.malloc
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.
This commit is contained in:
@@ -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
|
||||
|
||||
13
rt/ensure.ww
13
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) {
|
||||
|
||||
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user