Files
ww/rt/alloc.s
Hojun-Cho a376ec89eb 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.
2026-05-20 22:11:34 +09:00

35 lines
1.1 KiB
ArmAsm

// rt/alloc.s page allocator via the mmap syscall.
//
// 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
// callers never have to plumb file descriptors through.
//
// On mmap failure the raw syscall returns -errno (negative). Task #30
// graduated the `alloc` builtin to a fallible `(*T | nomem)` /
// `([]T | nomem)` signature whose cgen branches on a null return, so
// the failure path here returns 0 instead of a poisoned pointer. The
// builtin's caller is expected to `!`/`?` the result.
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
MOVQ $34, R10 // arg 3: flags = MAP_PRIVATE|MAP_ANON
MOVQ $-1, R8 // arg 4: fd = -1
MOVQ $0, R9 // arg 5: offset = 0
MOVQ $9, AX // syscall: mmap
SYSCALL
CMPQ $0, AX
JGE rt_malloc_ok
XORQ AX, AX
rt_malloc_ok:
RET
TEXT rt_free,$0
// DI already holds ptr, SI already holds length
MOVQ $11, AX // syscall: munmap
SYSCALL
RET