Per Hare convention, alloc is a typed builtin that returns a tagged
union carrying nomem as the OOM variant. Callers spell their policy:
`alloc(T)!` aborts on OOM (the old behavior), `alloc(T)?` propagates
when the enclosing fn already returns nomem.
cstage: check builds TY_TAGGED{*T | nomem} (or {[]T | nomem}); cgen
emits AX=tag, DX=ptr per the general tagged-return ABI (the (*T|!void)
nullable-ptr fold gated in ea76ee4 keeps this clean). wwstage cgalloc
mirrors. rt/alloc.s zeroes AX on syscall error so the builtin's null
check sees a clean 0 instead of mmap's -errno leaking through as a
poisoned pointer.
Migration: 3 `!` sites in test/wcc/700_e2e.c, 1 `!` site in
rt/ensure.ww (preserves the pre-existing sizeof bug tracked by #27),
1 `?` site in selfhost/test/tagged_ptr_ret.ww (allocbox exercises
real `?` propagation against a (*T | nomem) return).
130/130 tests green, 994_w6c_ww + 995_self_rebuild stage byte-identity
preserved. Follow-ups #31 (wwstage checkletassign leniency), #32
(wwstage slice-form gap), #33 (tagged_ptr_ret.ww make-test wiring).
35 lines
1.1 KiB
ArmAsm
35 lines
1.1 KiB
ArmAsm
// rt/alloc.s — page allocator via the mmap syscall.
|
|
//
|
|
// rt_alloc(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_alloc,$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_alloc_ok
|
|
XORQ AX, AX
|
|
rt_alloc_ok:
|
|
RET
|
|
|
|
TEXT rt_free,$0
|
|
// DI already holds ptr, SI already holds length
|
|
MOVQ $11, AX // syscall: munmap
|
|
SYSCALL
|
|
RET
|