commit 0b61df9e1743dabbe4d1912d22c97edbebd95d9b
parent 1c28efab79a61a5ce7f7191f55dd4fca7357a597
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 26 Apr 2026 16:31:07 -0700
P1pp: add %fn2 / %stl / %ldl + init_arenas; adopt in scheme1
Function definitions with locals previously required an out-of-line
%struct NAME_LOCALS and a hand-rolled %st(reg, sp, %NAME_LOCALS.field).
%fn2(name, {a b c}, body) synthesizes the struct, opens an m1pp frame,
and sizes %enter from it; %stl/%ldl take the slot name directly.
Move the BSS arena pointer-init walk (formerly scheme1's local
bss_init) into libp1pp as init_arenas + %arena_entry. The new layout
threads a running offset, so each arena_table row is (slot, size)
rather than (slot, precomputed offset).
Convert all 53 scheme1 functions with locals to %fn2; swap bss_init
for init_arenas at startup.
Diffstat:
| M | P1/P1pp.P1pp | | | 178 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
| M | scheme1/scheme1.P1pp | | | 1713 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
2 files changed, 953 insertions(+), 938 deletions(-)
diff --git a/P1/P1pp.P1pp b/P1/P1pp.P1pp
@@ -469,6 +469,44 @@
%endm
# =========================================================================
+# %fn2 -- function with named locals
+# =========================================================================
+#
+# Like %fn, but the second argument is a braced list of local names
+# instead of a byte frame size. Synthesizes a `name_FRAME` %struct
+# (one 8-byte slot per local), opens both an m1pp scope and an m1pp
+# frame named after the function, and sizes the stack frame from
+# %name_FRAME.SIZE.
+#
+# Inside the body these helpers resolve against the enclosing frame:
+# %local(slot) byte offset of local `slot`
+# %stl(reg, slot) store reg into local `slot`
+# %ldl(reg, slot) load local `slot` into reg
+#
+# Because m1pp tracks frames in a single slot independent of the
+# %scope stack, %local / %stl / %ldl keep resolving against the
+# function even when the body opens nested %scope blocks (e.g. from
+# a control-flow macro).
+#
+# Locals follow the same braces convention as `body`: a multi-local
+# list must be braced (`{a, b, c}`); a zero-local function uses `{}`.
+
+%macro fn2(name, locals, body)
+ %struct name ## _FRAME { locals }
+ : ## name
+ %scope name
+ %frame name
+ %enter(% ## name ## _FRAME.SIZE)
+ body
+ %eret
+ %endframe
+ %endscope
+%endm
+
+%macro stl(reg, slot) %st(reg, sp, %local(slot)) %endm
+%macro ldl(reg, slot) %ld(reg, sp, %local(slot)) %endm
+
+# =========================================================================
# %assert_<cc> macros
# =========================================================================
#
@@ -946,39 +984,39 @@
# sys_read(fd=a0, buf=a1, len=a2) -> n (a0)
:sys_read
-%mov(a3, a2)
-%mov(a2, a1)
-%mov(a1, a0)
-%li(a0, %p1_sys_read)
-%syscall
-%ret
+ %mov(a3, a2)
+ %mov(a2, a1)
+ %mov(a1, a0)
+ %li(a0, %p1_sys_read)
+ %syscall
+ %ret
# sys_write(fd=a0, buf=a1, len=a2) -> n (a0)
:sys_write
-%mov(a3, a2)
-%mov(a2, a1)
-%mov(a1, a0)
-%li(a0, %p1_sys_write)
-%syscall
-%ret
+ %mov(a3, a2)
+ %mov(a2, a1)
+ %mov(a1, a0)
+ %li(a0, %p1_sys_write)
+ %syscall
+ %ret
# sys_open(path=a0, flags=a1, mode=a2) -> fd (a0)
# Implemented as openat(AT_FDCWD, path, flags, mode). AT_FDCWD = -100.
:sys_open
-%mov(t0, a2)
-%mov(a3, a1)
-%mov(a2, a0)
-%li(a1, -100)
-%li(a0, %p1_sys_openat)
-%syscall
-%ret
+ %mov(t0, a2)
+ %mov(a3, a1)
+ %mov(a2, a0)
+ %li(a1, -100)
+ %li(a0, %p1_sys_openat)
+ %syscall
+ %ret
# sys_close(fd=a0) -> r (a0)
:sys_close
-%mov(a1, a0)
-%li(a0, %p1_sys_close)
-%syscall
-%ret
+ %mov(a1, a0)
+ %li(a0, %p1_sys_close)
+ %syscall
+ %ret
# sys_exit(code=a0) -> never returns
:sys_exit
@@ -1244,6 +1282,43 @@
})
# =========================================================================
+# BSS arena pointer-init table
+# =========================================================================
+#
+# Pattern: a program reserves a stretch of memory past :ELF_end (or any
+# base) and wants to carve it into N fixed-size arenas, each anchored
+# by a pointer slot in the data section. The table emits one
+# (slot, size) row per arena via %arena_entry; init_arenas walks the
+# table once at startup and writes base + sum of prior sizes into each
+# slot, so arena[k] starts where arena[k-1] ended.
+
+# %arena_entry(slot, size) -- one 16-byte row: 4-byte label ref + 4
+# bytes zero pad + 8-byte size. `slot` is passed as a label ref (`&foo`).
+%macro arena_entry(slot, size) slot %(0) $(size) %endm
+
+# init_arenas(base=a0, tbl=a1, tbl_end=a2) -> 0
+#
+# Walks (slot, size) pairs from `tbl` to `tbl_end`, threading a running
+# offset starting at 0. For each entry: *slot = base + offset, then
+# offset += size. Leaf.
+:init_arenas
+%scope init_arenas
+ %li(t0, 0)
+ ::loop
+ %beq(a1, a2, &::done)
+ %ld(t1, a1, 0)
+ %ld(t2, a1, 8)
+ %add(a3, a0, t0)
+ %st(a3, t1, 0)
+ %add(t0, t0, t2)
+ %addi(a1, a1, 16)
+ %b(&::loop)
+ ::done
+ %li(a0, 0)
+ %ret
+%endscope
+
+# =========================================================================
# Bump allocator
# =========================================================================
#
@@ -1252,14 +1327,14 @@
# bump_init(base=a0, cap=a1) -> 0
:bump_init
-%la(t0, &libp1pp__bump_base)
-%st(a0, t0, 0)
-%la(t0, &libp1pp__bump_cursor)
-%st(a0, t0, 0)
-%la(t0, &libp1pp__bump_cap)
-%st(a1, t0, 0)
-%li(a0, 0)
-%ret
+ %la(t0, &libp1pp__bump_base)
+ %st(a0, t0, 0)
+ %la(t0, &libp1pp__bump_cursor)
+ %st(a0, t0, 0)
+ %la(t0, &libp1pp__bump_cap)
+ %st(a1, t0, 0)
+ %li(a0, 0)
+ %ret
# bump_alloc(n=a0) -> ptr (0 on exhaustion)
#
@@ -1290,25 +1365,25 @@
# bump_mark() -> saved
:bump_mark
-%la(t0, &libp1pp__bump_cursor)
-%ld(a0, t0, 0)
-%ret
+ %la(t0, &libp1pp__bump_cursor)
+ %ld(a0, t0, 0)
+ %ret
# bump_release(saved=a0) -> 0
:bump_release
-%la(t0, &libp1pp__bump_cursor)
-%st(a0, t0, 0)
-%li(a0, 0)
-%ret
+ %la(t0, &libp1pp__bump_cursor)
+ %st(a0, t0, 0)
+ %li(a0, 0)
+ %ret
# bump_reset() -> 0
:bump_reset
-%la(t0, &libp1pp__bump_base)
-%ld(t1, t0, 0)
-%la(t0, &libp1pp__bump_cursor)
-%st(t1, t0, 0)
-%li(a0, 0)
-%ret
+ %la(t0, &libp1pp__bump_base)
+ %ld(t1, t0, 0)
+ %la(t0, &libp1pp__bump_cursor)
+ %st(t1, t0, 0)
+ %li(a0, 0)
+ %ret
# =========================================================================
# Panic
@@ -1334,20 +1409,15 @@
# 8-byte word (0x0A in the low byte, zeros above) so the following
# buffers and the user source that comes after libp1pp stay 8-byte
# aligned. sys_write reads only the one byte callers request.
-:libp1pp__newline
-$(10)
+:libp1pp__newline $(10)
# Scratch buffer used by print_int / print_hex. fmt_dec writes at most
# 20 bytes, fmt_hex at most 16, so 32 bytes with word alignment is
# comfortably above both.
-:libp1pp__num_buf
-$(0) $(0) $(0) $(0)
+:libp1pp__num_buf $(0) $(0) $(0) $(0)
# Bump-allocator state. Zero-initialized so bump_alloc returns 0 until
# bump_init installs an arena.
-:libp1pp__bump_base
-$(0)
-:libp1pp__bump_cursor
-$(0)
-:libp1pp__bump_cap
-$(0)
+:libp1pp__bump_base $(0)
+:libp1pp__bump_cursor $(0)
+:libp1pp__bump_cap $(0)
diff --git a/scheme1/scheme1.P1pp b/scheme1/scheme1.P1pp
@@ -30,13 +30,13 @@
%struct REC { hdr td } # .SIZE = 16 (header)
# Records are variable width: header + td slot + N field slots.
-# BSS arena offsets from :ELF_end. readbuf is 256 KiB (sized to fit
+# BSS arenas anchored past :ELF_end. readbuf is 256 KiB (sized to fit
# the catm'd cc compiler source incl. prelude — see READBUF_CAP_BYTES),
# then the heap (HEAP_CAP_BYTES, currently 16 MiB), then symtab. The three are packed
# back-to-back; everything lives within the ELF p_memsz reservation
-# (currently 32 MiB) declared in vendor/seed/<arch>/ELF.hex2. p1_main's
-# startup loop materializes &ELF_end + OFF_X into the matching pointer
-# slot. The offsets are emitted directly in bss_init_tbl via $().
+# (currently 32 MiB) declared in vendor/seed/<arch>/ELF.hex2. p1_main
+# calls libp1pp's init_arenas, which walks arena_table and writes
+# &ELF_end + sum of prior sizes into each pointer slot.
%macro SYMTAB_CAP_SLOTS() 8192 %endm
%macro READBUF_CAP_BYTES() 262144 %endm
@@ -209,7 +209,10 @@
%bltu(a0, t0, &::usage)
# Initialize
- %call(&bss_init)
+ %la(a0, &ELF_end)
+ %la(a1, &arena_table)
+ %la(a2, &arena_table_end)
+ %call(&init_arenas)
%call(&heap_init)
%call(&intern_special_forms)
%call(®ister_primitives)
@@ -457,14 +460,13 @@
# parse_list() -> tagged list value in a0. Cursor sits past '(' on entry;
# returns once ')' is consumed.
#
-# Frame: 16 bytes
-# +0 head (NIL until first item)
-# +8 tail (most recent cons; set-cdr! target)
-%struct PARSE_LIST_LOCALS { head tail } # .SIZE = 16
-%fn(parse_list, %PARSE_LIST_LOCALS.SIZE, {
+# Locals:
+# head NIL until first item
+# tail most recent cons (set-cdr! target)
+%fn2(parse_list, {head tail}, {
%li(t0, %imm_val(%IMM.NIL))
- %st(t0, sp, %PARSE_LIST_LOCALS.head)
- %st(t0, sp, %PARSE_LIST_LOCALS.tail)
+ %stl(t0, head)
+ %stl(t0, tail)
::loop
%call(&skip_ws)
@@ -496,18 +498,18 @@
%call(&cons)
# If head is NIL, both head and tail = new cons; else set-cdr! tail = new.
- %ld(t0, sp, %PARSE_LIST_LOCALS.head)
+ %ldl(t0, head)
%li(t1, %imm_val(%IMM.NIL))
%bne(t0, t1, &::link)
- %st(a0, sp, %PARSE_LIST_LOCALS.head)
- %st(a0, sp, %PARSE_LIST_LOCALS.tail)
+ %stl(a0, head)
+ %stl(a0, tail)
%b(&::loop)
::link
- %ld(t0, sp, %PARSE_LIST_LOCALS.tail)
+ %ldl(t0, tail)
# set-cdr! tail = a0 -> store a0 at [tail + 7] (raw + 8)
%set_cdr(a0, t0)
- %st(a0, sp, %PARSE_LIST_LOCALS.tail)
+ %stl(a0, tail)
%b(&::loop)
::do_dot
@@ -517,7 +519,7 @@
%addi(t0, t0, 1)
%st(t0, t1, 0)
%call(&parse_one)
- %ld(t0, sp, %PARSE_LIST_LOCALS.tail)
+ %ldl(t0, tail)
%set_cdr(a0, t0)
%call(&skip_ws)
%bnez(a0, &::eof)
@@ -527,7 +529,7 @@
%bnez(a1, &::eof)
%addi(t0, t0, 1)
%st(t0, t1, 0)
- %ld(a0, sp, %PARSE_LIST_LOCALS.head)
+ %ldl(a0, head)
%eret
::close
@@ -535,7 +537,7 @@
%lda_global(t1, t0, &readbuf_pos)
%addi(t1, t1, 1)
%st(t1, t0, 0)
- %ld(a0, sp, %PARSE_LIST_LOCALS.head)
+ %ldl(a0, head)
%eret
::eof
@@ -547,20 +549,19 @@
# range is unchecked, matching make-bytevector's lax stance) and packs
# them into a fresh bytevector.
#
-# Frame: 16 bytes
-# +0 list head (cursor during fill pass)
-# +8 result bv
-%struct PARSE_U8_BODY_LOCALS { list result } # .SIZE = 16
-%fn(parse_u8_body, %PARSE_U8_BODY_LOCALS.SIZE, {
+# Locals:
+# list parsed element list (cursor during fill pass)
+# result freshly allocated bv
+%fn2(parse_u8_body, {list result}, {
%call(&parse_list)
- %st(a0, sp, %PARSE_U8_BODY_LOCALS.list)
+ %stl(a0, list)
%call(&list_length) ; clobbers a0 -> count
%call(&bv_alloc) ; a0 = bv
- %st(a0, sp, %PARSE_U8_BODY_LOCALS.result)
+ %stl(a0, result)
%heap_ld(t0, a0, %BV.data)
- %ld(a0, sp, %PARSE_U8_BODY_LOCALS.list) ; list cursor
+ %ldl(a0, list) ; list cursor
::loop
%if_nil(t1, a0, &::done)
@@ -571,7 +572,7 @@
%cdr(a0, a0)
%b(&::loop)
::done
- %ld(a0, sp, %PARSE_U8_BODY_LOCALS.result)
+ %ldl(a0, result)
})
# is_ident_byte(c=a0) -> a1 (1 if c is a valid identifier byte, else 0).
@@ -637,14 +638,13 @@
# parse_dec and any non-numeric byte aborts; otherwise the token is a
# symbol and every byte is checked against is_ident_byte before intern.
#
-# Frame: 24 bytes
-# +0 start cursor (byte offset)
-# +8 end cursor (byte offset)
-# +16 cursor (scratch slot for the symbol-validation loop)
-%struct PARSE_ATOM_LOCALS { start end cursor } # .SIZE = 24
-%fn(parse_atom, %PARSE_ATOM_LOCALS.SIZE, {
+# Locals:
+# start cursor (byte offset)
+# end cursor (byte offset)
+# cursor (scratch slot for the symbol-validation loop)
+%fn2(parse_atom, {start end cursor}, {
%lda_global(t1, t0, &readbuf_pos)
- %st(t1, sp, %PARSE_ATOM_LOCALS.start)
+ %stl(t1, start)
%ld_global(t2, &readbuf_len)
@@ -663,11 +663,11 @@
%b(&::scan)
::end
- %st(t1, sp, %PARSE_ATOM_LOCALS.end)
+ %stl(t1, end)
%st(t1, t0, 0)
# Dispatch on the first byte.
- %ld(t0, sp, %PARSE_ATOM_LOCALS.start)
+ %ldl(t0, start)
%ld_global(a0, &readbuf_buf_ptr)
%add(a0, a0, t0)
%lb(t1, a0, 0)
@@ -684,7 +684,7 @@
%beqz(a1, &::sign)
%b(&::is_sym)
::sign
- %ld(t2, sp, %PARSE_ATOM_LOCALS.end)
+ %ldl(t2, end)
%addi(t0, t0, 1)
%beq(t0, t2, &::is_sym)
%readbuf_byte(a0, t0)
@@ -694,35 +694,35 @@
::is_sym
# Validate every byte; abort on the first non-ident byte.
- %ld(t0, sp, %PARSE_ATOM_LOCALS.start)
- %st(t0, sp, %PARSE_ATOM_LOCALS.cursor)
+ %ldl(t0, start)
+ %stl(t0, cursor)
::sym_loop
- %ld(t0, sp, %PARSE_ATOM_LOCALS.cursor)
- %ld(t1, sp, %PARSE_ATOM_LOCALS.end)
+ %ldl(t0, cursor)
+ %ldl(t1, end)
%beq(t0, t1, &::sym_intern)
%readbuf_byte(a0, t0)
%call(&is_ident_byte)
%beqz(a1, &::sym_bad)
- %ld(t0, sp, %PARSE_ATOM_LOCALS.cursor)
+ %ldl(t0, cursor)
%addi(t0, t0, 1)
- %st(t0, sp, %PARSE_ATOM_LOCALS.cursor)
+ %stl(t0, cursor)
%b(&::sym_loop)
::sym_bad
%die(msg_bad_ident)
::sym_intern
- %ld(a0, sp, %PARSE_ATOM_LOCALS.start)
+ %ldl(a0, start)
%ld_global(t0, &readbuf_buf_ptr)
%add(a0, t0, a0)
- %ld(t1, sp, %PARSE_ATOM_LOCALS.end)
- %ld(t2, sp, %PARSE_ATOM_LOCALS.start)
+ %ldl(t1, end)
+ %ldl(t2, start)
%sub(a1, t1, t2)
%tail(&intern)
::is_int
- %ld(t0, sp, %PARSE_ATOM_LOCALS.start) ; start_off
- %ld(t1, sp, %PARSE_ATOM_LOCALS.end) ; end_off
+ %ldl(t0, start) ; start_off
+ %ldl(t1, end) ; end_off
%ld_global(a0, &readbuf_buf_ptr)
%add(a0, a0, t0) ; ptr = base + start_off
%sub(a1, t1, t0) ; len = end_off - start_off
@@ -740,15 +740,14 @@
# (\n \t \r \\ \") yields one byte; an inline-hex escape \xHEX; (1+
# hex digits, value 0..255, terminated by ';') also yields one byte.
#
-# Frame: 32 bytes
-# +0 start cursor (first content byte)
-# +8 end cursor (closing '"' position)
-# +16 bv wrapper (saved across the data fill loop)
-# +24 spill slot (write ptr saved across parse_hex in \x escape)
-%struct PARSE_STRING_LOCALS { start end bv spill } # .SIZE = 32
-%fn(parse_string, %PARSE_STRING_LOCALS.SIZE, {
+# Locals:
+# start cursor (first content byte)
+# end cursor (closing '"' position)
+# bv wrapper (saved across the data fill loop)
+# spill slot (write ptr saved across parse_hex in \x escape)
+%fn2(parse_string, {start end bv spill}, {
%ld_global(t1, &readbuf_pos)
- %st(t1, sp, %PARSE_STRING_LOCALS.start)
+ %stl(t1, start)
%ld_global(t2, &readbuf_len)
@@ -795,13 +794,13 @@
%b(&::scan)
::scan_done
- %st(t1, sp, %PARSE_STRING_LOCALS.end)
+ %stl(t1, end)
%call(&bv_alloc)
- %st(a0, sp, %PARSE_STRING_LOCALS.bv)
+ %stl(a0, bv)
# Pass 2: decode into the freshly allocated data buffer.
- %ld(t1, sp, %PARSE_STRING_LOCALS.start) ; start
- %ld(t2, sp, %PARSE_STRING_LOCALS.end) ; end
+ %ldl(t1, start) ; start
+ %ldl(t2, end) ; end
%heap_ld(a3, a0, %BV.data)
::fill
@@ -851,8 +850,8 @@
# t0/t1/t2 and a2/a3, so spill the cursor (t1) and write ptr (a3)
# across the call. sp+0 is free once pass 1 finishes.
%addi(t1, t1, 1) ; t1 -> first hex digit
- %st(t1, sp, %PARSE_STRING_LOCALS.start)
- %st(a3, sp, %PARSE_STRING_LOCALS.spill)
+ %stl(t1, start)
+ %stl(a3, spill)
%ld_global(t0, &readbuf_buf_ptr)
%add(a0, t0, t1) ; ptr to first hex digit
%sub(a1, t2, t1) ; max len (bytes left in body)
@@ -860,15 +859,15 @@
%beqz(a1, &::hex_bad)
%li(t0, 255)
%bltu(t0, a0, &::hex_bad)
- %ld(t1, sp, %PARSE_STRING_LOCALS.start)
+ %ldl(t1, start)
%add(t1, t1, a1) ; t1 = position of expected ';'
- %ld(t2, sp, %PARSE_STRING_LOCALS.end)
+ %ldl(t2, end)
%beq(t1, t2, &::hex_bad)
%readbuf_byte(t0, t1)
%addi(t0, t0, -59) ; ';'
%bnez(t0, &::hex_bad)
%addi(t1, t1, 1) ; consume ';'
- %ld(a3, sp, %PARSE_STRING_LOCALS.spill)
+ %ldl(a3, spill)
%sb(a0, a3, 0)
%addi(a3, a3, 1)
%b(&::fill)
@@ -879,7 +878,7 @@
::fill_done
%addi(t1, t1, 1) ; consume closing '"'
%st_global(t1, &readbuf_pos, t0)
- %ld(a0, sp, %PARSE_STRING_LOCALS.bv)
+ %ldl(a0, bv)
%eret
::eof
@@ -892,13 +891,12 @@
# bodies yield that byte; multi-byte bodies dispatch to hex (#\xNN) or
# named (#\space, #\newline, #\tab, #\return, #\null) forms.
#
-# Frame: 16 bytes
-# +0 start cursor
-# +8 end cursor
-%struct PARSE_CHAR_LOCALS { start end } # .SIZE = 16
-%fn(parse_char, %PARSE_CHAR_LOCALS.SIZE, {
+# Locals:
+# start cursor
+# end cursor
+%fn2(parse_char, {start end}, {
%lda_global(t1, t0, &readbuf_pos)
- %st(t1, sp, %PARSE_CHAR_LOCALS.start)
+ %stl(t1, start)
%ld_global(t2, &readbuf_len)
@@ -920,11 +918,11 @@
%b(&::scan)
::scan_done
- %st(t1, sp, %PARSE_CHAR_LOCALS.end)
+ %stl(t1, end)
%st(t1, t0, 0)
- %ld(t0, sp, %PARSE_CHAR_LOCALS.start)
- %ld(t1, sp, %PARSE_CHAR_LOCALS.end)
+ %ldl(t0, start)
+ %ldl(t1, end)
%sub(a2, t1, t0) ; length
%li(a3, 1)
@@ -1103,14 +1101,14 @@
# eval(expr=a0, env=a1) -> value (a0)
#
-# Frame: 32 bytes
-# +0 expr
-# +8 env
-# +16 fn (head value, while args are being evaluated)
-%struct EVAL_LOCALS { expr env fn pad } # .SIZE = 32
-%fn(eval, %EVAL_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_LOCALS.expr)
- %st(a1, sp, %EVAL_LOCALS.env)
+# Locals:
+# expr
+# env
+# fn (head value, while args are being evaluated)
+# pad
+%fn2(eval, {expr env fn pad}, {
+ %stl(a0, expr)
+ %stl(a1, env)
%tagof(t0, a0)
%li(t1, %TAG.PAIR)
@@ -1150,7 +1148,7 @@
# Special-form dispatch: pointer-compare head against the cached
# special-form symbol values. SYM is a distinct tag, so a head that
# isn't a symbol cannot collide with any sym_* slot.
- %ld(t0, sp, %EVAL_LOCALS.expr)
+ %ldl(t0, expr)
%car(t0, t0) ; t0 = head
%dispatch_form(&sym_quote, &::do_quote)
%dispatch_form(&sym_if, &::do_if)
@@ -1168,26 +1166,26 @@
%dispatch_form(&sym_pmatch, &::do_pmatch)
# head = eval(car(expr), env)
- %ld(a0, sp, %EVAL_LOCALS.expr)
+ %ldl(a0, expr)
%car(a0, a0)
- %ld(a1, sp, %EVAL_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
- %st(a0, sp, %EVAL_LOCALS.fn)
+ %stl(a0, fn)
# args = eval_args(cdr(expr), env)
- %ld(a0, sp, %EVAL_LOCALS.expr)
+ %ldl(a0, expr)
%cdr(a0, a0)
- %ld(a1, sp, %EVAL_LOCALS.env)
+ %ldl(a1, env)
%call(&eval_args)
# apply(fn, args) -- tail call
%mov(a1, a0)
- %ld(a0, sp, %EVAL_LOCALS.fn)
+ %ldl(a0, fn)
%tail(&apply)
::do_quote
# (quote datum) -> car(cdr(expr))
- %ld(a0, sp, %EVAL_LOCALS.expr)
+ %ldl(a0, expr)
%cdr(a0, a0)
%car(a0, a0)
%eret
@@ -1226,59 +1224,57 @@
# previous tail. Host stack stays O(1) regardless of arg-list length;
# eval order is left-to-right.
#
-# Frame: 32 bytes
-# +0 args (advances)
-# +8 env
-# +16 head (NIL until first val is appended)
-# +24 tail (most recent cell; set-cdr! target)
-%struct EVAL_ARGS_LOCALS { args env head tail } # .SIZE = 32
-%fn(eval_args, %EVAL_ARGS_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_ARGS_LOCALS.args)
- %st(a1, sp, %EVAL_ARGS_LOCALS.env)
+# Locals:
+# args (advances)
+# env
+# head (NIL until first val is appended)
+# tail (most recent cell; set-cdr! target)
+%fn2(eval_args, {args env head tail}, {
+ %stl(a0, args)
+ %stl(a1, env)
%li(t0, %imm_val(%IMM.NIL))
- %st(t0, sp, %EVAL_ARGS_LOCALS.head)
- %st(t0, sp, %EVAL_ARGS_LOCALS.tail)
+ %stl(t0, head)
+ %stl(t0, tail)
::loop
- %ld(t0, sp, %EVAL_ARGS_LOCALS.args)
+ %ldl(t0, args)
%if_nil(t1, t0, &::done)
# val = eval(car(args), env)
%car(a0, t0)
- %ld(a1, sp, %EVAL_ARGS_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
# cell = cons(val, NIL); append to head/tail.
%li(a1, %imm_val(%IMM.NIL))
%call(&cons)
- %ld(t0, sp, %EVAL_ARGS_LOCALS.head)
+ %ldl(t0, head)
%if_nil(t1, t0, &::first)
- %ld(t0, sp, %EVAL_ARGS_LOCALS.tail)
+ %ldl(t0, tail)
%set_cdr(a0, t0)
- %st(a0, sp, %EVAL_ARGS_LOCALS.tail)
+ %stl(a0, tail)
%b(&::advance)
::first
- %st(a0, sp, %EVAL_ARGS_LOCALS.head)
- %st(a0, sp, %EVAL_ARGS_LOCALS.tail)
+ %stl(a0, head)
+ %stl(a0, tail)
::advance
%advance_walk(0)
%b(&::loop)
::done
- %ld(a0, sp, %EVAL_ARGS_LOCALS.head)
+ %ldl(a0, head)
})
# apply(fn=a0, args=a1) -> result (a0)
#
-# Frame: 16 bytes
-# +0 args
-# +8 body (saved across bind_params for the closure path)
-%struct APPLY_LOCALS { args body } # .SIZE = 16
-%fn(apply, %APPLY_LOCALS.SIZE, {
- %st(a1, sp, %APPLY_LOCALS.args)
+# Locals:
+# args
+# body (saved across bind_params for the closure path)
+%fn2(apply, {args body}, {
+ %stl(a1, args)
# Only HEAP-tagged values can be applicable.
%tagof(t0, a0)
@@ -1307,25 +1303,25 @@
# tail-calls back into apply.
%mov(a1, a0)
%heap_ld(t0, a0, %PRIM.entry_w)
- %ld(a0, sp, %APPLY_LOCALS.args)
+ %ldl(a0, args)
%tailr(t0)
::closure
# Closure layout (HEAP-tagged): [hdr][params][body][env]
# field offsets from tagged ptr: params=5, body=13, env=21.
%heap_ld(t1, a0, %CLOSURE.body) ; must survive bind_params
- %st(t1, sp, %APPLY_LOCALS.body)
+ %stl(t1, body)
%heap_ld(t2, a0, %CLOSURE.env)
%heap_ld(t0, a0, %CLOSURE.params)
%mov(a0, t0) ; bind_params(params, args, env)
- %ld(a1, sp, %APPLY_LOCALS.args)
+ %ldl(a1, args)
%mov(a2, t2)
%call(&bind_params)
# eval_body(body, new_env) -- tail call
%mov(a1, a0)
- %ld(a0, sp, %APPLY_LOCALS.body)
+ %ldl(a0, body)
%tail(&eval_body)
})
@@ -1364,13 +1360,12 @@
# eval_if(rest=a0, env=a1) -> value (a0). `rest` is (test then else).
# No arity check here -- spec policy: malformed special forms are UB.
#
-# Frame: 16 bytes
-# +0 rest
-# +8 env
-%struct EVAL_IF_LOCALS { rest env } # .SIZE = 16
-%fn(eval_if, %EVAL_IF_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_IF_LOCALS.rest)
- %st(a1, sp, %EVAL_IF_LOCALS.env)
+# Locals:
+# rest
+# env
+%fn2(eval_if, {rest env}, {
+ %stl(a0, rest)
+ %stl(a1, env)
# val = eval(car(rest), env)
%car(a0, a0)
@@ -1380,19 +1375,19 @@
%beq(a0, t0, &::else_branch)
# then-branch: tail-eval(cadr(rest), env)
- %ld(a0, sp, %EVAL_IF_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
%car(a0, a0)
- %ld(a1, sp, %EVAL_IF_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval)
::else_branch
# else-branch: tail-eval(caddr(rest), env)
- %ld(a0, sp, %EVAL_IF_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
%cdr(a0, a0)
%car(a0, a0)
- %ld(a1, sp, %EVAL_IF_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval)
})
@@ -1400,36 +1395,35 @@
# rest is (params . body). Allocates a 32-byte CLOSURE on the heap
# and stores params, body, and the captured env directly.
#
-# Frame: 24 bytes
-# +0 rest
-# +8 env
-# +16 closure ptr (HEAP-tagged)
-%struct EVAL_LAMBDA_LOCALS { rest env closure } # .SIZE = 24
-%fn(eval_lambda, %EVAL_LAMBDA_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_LAMBDA_LOCALS.rest)
- %st(a1, sp, %EVAL_LAMBDA_LOCALS.env)
+# Locals:
+# rest
+# env
+# closure ptr (HEAP-tagged)
+%fn2(eval_lambda, {rest env closure}, {
+ %stl(a0, rest)
+ %stl(a1, env)
%li(a0, 32)
%li(a1, %HDR.CLOSURE)
%call(&alloc_hdr)
- %st(a0, sp, %EVAL_LAMBDA_LOCALS.closure)
+ %stl(a0, closure)
# closure[params] = car(rest)
- %ld(t0, sp, %EVAL_LAMBDA_LOCALS.rest)
+ %ldl(t0, rest)
%car(t1, t0)
- %ld(t0, sp, %EVAL_LAMBDA_LOCALS.closure)
+ %ldl(t0, closure)
%heap_st(t1, t0, %CLOSURE.params)
# closure[body] = cdr(rest)
- %ld(t1, sp, %EVAL_LAMBDA_LOCALS.rest)
+ %ldl(t1, rest)
%cdr(t1, t1)
%heap_st(t1, t0, %CLOSURE.body)
# closure[env] = captured env
- %ld(t1, sp, %EVAL_LAMBDA_LOCALS.env)
+ %ldl(t1, env)
%heap_st(t1, t0, %CLOSURE.env)
- %ld(a0, sp, %EVAL_LAMBDA_LOCALS.closure)
+ %ldl(a0, closure)
})
# eval_define(rest=a0, env=a1) -> UNSPEC (a0).
@@ -1441,13 +1435,12 @@
# (every internal body context routes through eval_body); see the check
# at the head of eval_body's loop.
#
-# Frame: 16 bytes
-# +0 rest
-# +8 env
-%struct EVAL_DEFINE_LOCALS { rest env } # .SIZE = 16
-%fn(eval_define, %EVAL_DEFINE_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_DEFINE_LOCALS.rest)
- %st(a1, sp, %EVAL_DEFINE_LOCALS.env)
+# Locals:
+# rest
+# env
+%fn2(eval_define, {rest env}, {
+ %stl(a0, rest)
+ %stl(a1, env)
# If car(rest) is a pair, this is the lambda-sugar form.
%car(t0, a0)
@@ -1456,13 +1449,13 @@
%beq(t1, t2, &::sugar)
# Plain define: value = eval(car(cdr(rest)), env)
- %ld(t0, sp, %EVAL_DEFINE_LOCALS.rest)
+ %ldl(t0, rest)
%cdr(a0, t0)
%car(a0, a0)
- %ld(a1, sp, %EVAL_DEFINE_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
- %ld(t0, sp, %EVAL_DEFINE_LOCALS.rest)
+ %ldl(t0, rest)
%car(t0, t0)
%bind_global_from_t0()
%li(a0, %imm_val(%IMM.UNSPEC))
@@ -1470,16 +1463,16 @@
::sugar
# rest = ((name . params) . body); build (params . body) for eval_lambda.
- %ld(t0, sp, %EVAL_DEFINE_LOCALS.rest)
+ %ldl(t0, rest)
%car(t0, t0)
%cdr(a0, t0) ; params
- %ld(t0, sp, %EVAL_DEFINE_LOCALS.rest)
+ %ldl(t0, rest)
%cdr(a1, t0) ; body
%call(&cons)
- %ld(a1, sp, %EVAL_DEFINE_LOCALS.env)
+ %ldl(a1, env)
%call(&eval_lambda)
- %ld(t0, sp, %EVAL_DEFINE_LOCALS.rest)
+ %ldl(t0, rest)
%car(t0, t0)
%car(t0, t0) ; name
%bind_global_from_t0()
@@ -1494,48 +1487,47 @@
# by define for top-level rebind. Spec: behavior on a truly unbound
# name follows the primitive-failure policy.
#
-# Frame: 24 bytes
-# +0 rest (sym . (value-expr . ()))
-# +8 env
-# +16 saved value (eval'd value-expr)
-%struct EVAL_SETBANG_LOCALS { rest env saved } # .SIZE = 24
-%fn(eval_setbang, %EVAL_SETBANG_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_SETBANG_LOCALS.rest)
- %st(a1, sp, %EVAL_SETBANG_LOCALS.env)
+# Locals:
+# rest (sym . (value-expr . ()))
+# env
+# saved value (eval'd value-expr)
+%fn2(eval_setbang, {rest env saved}, {
+ %stl(a0, rest)
+ %stl(a1, env)
# value = eval(cadr(rest), env)
%cdr(a0, a0)
%car(a0, a0)
- %ld(a1, sp, %EVAL_SETBANG_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
- %st(a0, sp, %EVAL_SETBANG_LOCALS.saved)
+ %stl(a0, saved)
# Walk env looking for a binding cell whose car == target sym.
# Only t0..t2 are available: t0 scratch, t1 target sym, t2 env cursor.
- %ld(t1, sp, %EVAL_SETBANG_LOCALS.rest)
+ %ldl(t1, rest)
%car(t1, t1) ; target sym
::lp
- %ld(t2, sp, %EVAL_SETBANG_LOCALS.env)
+ %ldl(t2, env)
%if_nil(t0, t2, &::ms)
%car(t0, t2)
%car(t0, t0) ; cell sym
%beq(t0, t1, &::ht)
%cdr(t2, t2)
- %st(t2, sp, %EVAL_SETBANG_LOCALS.env)
+ %stl(t2, env)
%b(&::lp)
::ht
%car(t0, t2) ; re-fetch binding cell
- %ld(a0, sp, %EVAL_SETBANG_LOCALS.saved)
+ %ldl(a0, saved)
%set_cdr(a0, t0) ; mutate cell's cdr
%li(a0, %imm_val(%IMM.UNSPEC))
%eret
::ms
# Miss: rebind global.
- %ld(a0, sp, %EVAL_SETBANG_LOCALS.saved)
- %ld(t0, sp, %EVAL_SETBANG_LOCALS.rest)
+ %ldl(a0, saved)
+ %ldl(t0, rest)
%car(t0, t0)
%bind_global_from_t0()
%li(a0, %imm_val(%IMM.UNSPEC))
@@ -1547,18 +1539,17 @@
# arrow is only recognized in non-else clauses; an empty body after a
# truthy test returns UNSPEC (spec policy: malformed-form UB).
#
-# Frame: 32 bytes
-# +0 clauses (advances)
-# +8 env
-# +16 test value (live across the => eval/cons calls)
-# +24 proc (live across the => cons call)
-%struct EVAL_COND_LOCALS { clauses env test proc } # .SIZE = 32
-%fn(eval_cond, %EVAL_COND_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_COND_LOCALS.clauses)
- %st(a1, sp, %EVAL_COND_LOCALS.env)
+# Locals:
+# clauses (advances)
+# env
+# test value (live across the => eval/cons calls)
+# proc (live across the => cons call)
+%fn2(eval_cond, {clauses env test proc}, {
+ %stl(a0, clauses)
+ %stl(a1, env)
::loop
- %ld(t0, sp, %EVAL_COND_LOCALS.clauses)
+ %ldl(t0, clauses)
%if_nil(t1, t0, &::nm)
%car(t1, t0) ; clause
@@ -1568,15 +1559,15 @@
%beq(t2, a0, &::dm)
%mov(a0, t2)
- %ld(a1, sp, %EVAL_COND_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
%li(t0, %imm_val(%IMM.FALSE))
%beq(a0, t0, &::nx)
# Truthy. Spill test value and inspect cdr(clause): empty -> UNSPEC,
# car == => -> arrow path, else regular body.
- %st(a0, sp, %EVAL_COND_LOCALS.test)
- %ld(t0, sp, %EVAL_COND_LOCALS.clauses)
+ %stl(a0, test)
+ %ldl(t0, clauses)
%car(t0, t0)
%cdr(t0, t0)
%if_nil(t1, t0, &::nm)
@@ -1585,27 +1576,27 @@
%beq(t1, t2, &::ar)
%mov(a0, t0) ; regular body
- %ld(a1, sp, %EVAL_COND_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval_body)
::ar
%cdr(t0, t0)
%car(a0, t0) ; proc-expr
- %ld(a1, sp, %EVAL_COND_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
- %st(a0, sp, %EVAL_COND_LOCALS.proc)
- %ld(a0, sp, %EVAL_COND_LOCALS.test)
+ %stl(a0, proc)
+ %ldl(a0, test)
%li(a1, %imm_val(%IMM.NIL))
%call(&cons)
%mov(a1, a0)
- %ld(a0, sp, %EVAL_COND_LOCALS.proc)
+ %ldl(a0, proc)
%tail(&apply)
::dm
- %ld(t0, sp, %EVAL_COND_LOCALS.clauses)
+ %ldl(t0, clauses)
%car(t0, t0)
%cdr(a0, t0)
- %ld(a1, sp, %EVAL_COND_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval_body)
::nx
@@ -1623,15 +1614,14 @@
# Standard `let` evaluates every init in `env`, then extends env with all
# bindings simultaneously and tail-evaluates the body.
#
-# Frame: 32 bytes
-# +0 rest
-# +8 env (original)
-# +16 walk (bindings, advances)
-# +24 new_env (built up)
-%struct EVAL_LET_LOCALS { rest env walk new_env } # .SIZE = 32
-%fn(eval_let, %EVAL_LET_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_LET_LOCALS.rest)
- %st(a1, sp, %EVAL_LET_LOCALS.env)
+# Locals:
+# rest
+# env (original)
+# walk (bindings, advances)
+# new_env (built up)
+%fn2(eval_let, {rest env walk new_env}, {
+ %stl(a0, rest)
+ %stl(a1, env)
# Named let?
%car(t0, a0)
@@ -1639,14 +1629,14 @@
%li(t2, %TAG.SYM)
%beq(t1, t2, &::named)
- %ld(t0, sp, %EVAL_LET_LOCALS.rest)
+ %ldl(t0, rest)
%car(t0, t0) ; bindings
- %st(t0, sp, %EVAL_LET_LOCALS.walk)
- %ld(t0, sp, %EVAL_LET_LOCALS.env)
- %st(t0, sp, %EVAL_LET_LOCALS.new_env) ; new_env = env
+ %stl(t0, walk)
+ %ldl(t0, env)
+ %stl(t0, new_env) ; new_env = env
::loop
- %ld(t0, sp, %EVAL_LET_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::done)
%car(t1, t0) ; pair = (name init)
@@ -1655,11 +1645,11 @@
# val = eval(init, env_orig)
%mov(a0, t2)
- %ld(a1, sp, %EVAL_LET_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
# binding = cons(name, val)
- %ld(t0, sp, %EVAL_LET_LOCALS.walk)
+ %ldl(t0, walk)
%car(t1, t0)
%car(t2, t1)
%mov(a1, a0)
@@ -1667,22 +1657,22 @@
%call(&cons)
# new_env = cons(binding, new_env)
- %ld(a1, sp, %EVAL_LET_LOCALS.new_env)
+ %ldl(a1, new_env)
%call(&cons)
- %st(a0, sp, %EVAL_LET_LOCALS.new_env)
+ %stl(a0, new_env)
%advance_walk(16)
%b(&::loop)
::done
- %ld(a0, sp, %EVAL_LET_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0) ; body
- %ld(a1, sp, %EVAL_LET_LOCALS.new_env)
+ %ldl(a1, new_env)
%tail(&eval_body)
::named
- %ld(a0, sp, %EVAL_LET_LOCALS.rest)
- %ld(a1, sp, %EVAL_LET_LOCALS.env)
+ %ldl(a0, rest)
+ %ldl(a1, env)
%tail(&eval_let_named)
})
@@ -1690,20 +1680,23 @@
# Like let, but each init is evaluated in the env extended by all prior
# bindings of the same let* form (left-to-right shadowing).
#
-# Frame: 32 bytes (same layout as eval_let)
-%struct EVAL_LETSTAR_LOCALS { rest env walk new_env } # .SIZE = 32
-%fn(eval_letstar, %EVAL_LETSTAR_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_LETSTAR_LOCALS.rest)
- %st(a1, sp, %EVAL_LETSTAR_LOCALS.env)
-
- %ld(t0, sp, %EVAL_LETSTAR_LOCALS.rest)
+# Locals:
+# rest
+# env
+# walk
+# new_env
+%fn2(eval_letstar, {rest env walk new_env}, {
+ %stl(a0, rest)
+ %stl(a1, env)
+
+ %ldl(t0, rest)
%car(t0, t0)
- %st(t0, sp, %EVAL_LETSTAR_LOCALS.walk)
- %ld(t0, sp, %EVAL_LETSTAR_LOCALS.env)
- %st(t0, sp, %EVAL_LETSTAR_LOCALS.new_env)
+ %stl(t0, walk)
+ %ldl(t0, env)
+ %stl(t0, new_env)
::loop
- %ld(t0, sp, %EVAL_LETSTAR_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::done)
%car(t1, t0)
@@ -1712,27 +1705,27 @@
# val = eval(init, new_env)
%mov(a0, t2)
- %ld(a1, sp, %EVAL_LETSTAR_LOCALS.new_env)
+ %ldl(a1, new_env)
%call(&eval)
- %ld(t0, sp, %EVAL_LETSTAR_LOCALS.walk)
+ %ldl(t0, walk)
%car(t1, t0)
%car(t2, t1)
%mov(a1, a0)
%mov(a0, t2)
%call(&cons)
- %ld(a1, sp, %EVAL_LETSTAR_LOCALS.new_env)
+ %ldl(a1, new_env)
%call(&cons)
- %st(a0, sp, %EVAL_LETSTAR_LOCALS.new_env)
+ %stl(a0, new_env)
%advance_walk(16)
%b(&::loop)
::done
- %ld(a0, sp, %EVAL_LETSTAR_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
- %ld(a1, sp, %EVAL_LETSTAR_LOCALS.new_env)
+ %ldl(a1, new_env)
%tail(&eval_body)
})
@@ -1742,24 +1735,23 @@
# env and patch the matching binding's cdr (linear-scan lookup is fine
# here -- bindings are typically ≤ a handful).
#
-# Frame: 32 bytes
-# +0 rest
-# +8 env_orig
-# +16 walk
-# +24 new_env
-%struct EVAL_LETREC_LOCALS { rest env_orig walk new_env } # .SIZE = 32
-%fn(eval_letrec, %EVAL_LETREC_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_LETREC_LOCALS.rest)
- %st(a1, sp, %EVAL_LETREC_LOCALS.env_orig)
-
- %ld(t0, sp, %EVAL_LETREC_LOCALS.rest)
+# Locals:
+# rest
+# env_orig
+# walk
+# new_env
+%fn2(eval_letrec, {rest env_orig walk new_env}, {
+ %stl(a0, rest)
+ %stl(a1, env_orig)
+
+ %ldl(t0, rest)
%car(t0, t0)
- %st(t0, sp, %EVAL_LETREC_LOCALS.walk)
- %ld(t0, sp, %EVAL_LETREC_LOCALS.env_orig)
- %st(t0, sp, %EVAL_LETREC_LOCALS.new_env)
+ %stl(t0, walk)
+ %ldl(t0, env_orig)
+ %stl(t0, new_env)
::phase1
- %ld(t0, sp, %EVAL_LETREC_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::p1_done)
%car(t1, t0)
@@ -1767,34 +1759,34 @@
%mov(a0, t2)
%li(a1, %imm_val(%IMM.UNSPEC))
%call(&cons)
- %ld(a1, sp, %EVAL_LETREC_LOCALS.new_env)
+ %ldl(a1, new_env)
%call(&cons)
- %st(a0, sp, %EVAL_LETREC_LOCALS.new_env)
+ %stl(a0, new_env)
%advance_walk(16)
%b(&::phase1)
::p1_done
- %ld(t0, sp, %EVAL_LETREC_LOCALS.rest)
+ %ldl(t0, rest)
%car(t0, t0)
- %st(t0, sp, %EVAL_LETREC_LOCALS.walk) ; reset walk
+ %stl(t0, walk) ; reset walk
::phase2
- %ld(t0, sp, %EVAL_LETREC_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::p2_done)
%car(t1, t0)
%cdr(t2, t1)
%car(t2, t2) ; init
%mov(a0, t2)
- %ld(a1, sp, %EVAL_LETREC_LOCALS.new_env)
+ %ldl(a1, new_env)
%call(&eval) ; val in a0
- %ld(t0, sp, %EVAL_LETREC_LOCALS.walk)
+ %ldl(t0, walk)
%car(t1, t0)
%car(t2, t1) ; name (in t2)
- %ld(t1, sp, %EVAL_LETREC_LOCALS.new_env)
+ %ldl(t1, new_env)
::scan
%car(a1, t1)
%car(a2, a1)
@@ -1810,9 +1802,9 @@
%b(&::phase2)
::p2_done
- %ld(a0, sp, %EVAL_LETREC_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
- %ld(a1, sp, %EVAL_LETREC_LOCALS.new_env)
+ %ldl(a1, new_env)
%tail(&eval_body)
})
@@ -1821,17 +1813,16 @@
# the moment one yields #f. The last form is tail-evaluated so a tail call
# inside `and` doesn't grow the host stack.
#
-# Frame: 16 bytes
-# +0 rest
-# +8 env
-%struct EVAL_AND_LOCALS { rest env } # .SIZE = 16
-%fn(eval_and, %EVAL_AND_LOCALS.SIZE, {
+# Locals:
+# rest
+# env
+%fn2(eval_and, {rest env}, {
%li(t0, %imm_val(%IMM.TRUE))
%if_nil(t1, a0, &::done_imm)
::loop
- %st(a0, sp, %EVAL_AND_LOCALS.rest)
- %st(a1, sp, %EVAL_AND_LOCALS.env)
+ %stl(a0, rest)
+ %stl(a1, env)
# If cdr(rest) is NIL, the head is the last form -> tail-eval.
%cdr(t0, a0)
@@ -1842,15 +1833,15 @@
%call(&eval)
%li(t0, %imm_val(%IMM.FALSE))
%beq(a0, t0, &::done)
- %ld(a0, sp, %EVAL_AND_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
- %ld(a1, sp, %EVAL_AND_LOCALS.env)
+ %ldl(a1, env)
%b(&::loop)
::last
- %ld(a0, sp, %EVAL_AND_LOCALS.rest)
+ %ldl(a0, rest)
%car(a0, a0)
- %ld(a1, sp, %EVAL_AND_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval)
::done
@@ -1865,17 +1856,16 @@
# non-#f value; if every form was #f, return #f. The last form is
# tail-evaluated.
#
-# Frame: 16 bytes
-# +0 rest
-# +8 env
-%struct EVAL_OR_LOCALS { rest env } # .SIZE = 16
-%fn(eval_or, %EVAL_OR_LOCALS.SIZE, {
+# Locals:
+# rest
+# env
+%fn2(eval_or, {rest env}, {
%li(t0, %imm_val(%IMM.FALSE))
%if_nil(t1, a0, &::done_imm)
::loop
- %st(a0, sp, %EVAL_OR_LOCALS.rest)
- %st(a1, sp, %EVAL_OR_LOCALS.env)
+ %stl(a0, rest)
+ %stl(a1, env)
%cdr(t0, a0)
%if_nil(t1, t0, &::last)
@@ -1884,15 +1874,15 @@
%call(&eval)
%li(t0, %imm_val(%IMM.FALSE))
%bne(a0, t0, &::done)
- %ld(a0, sp, %EVAL_OR_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
- %ld(a1, sp, %EVAL_OR_LOCALS.env)
+ %ldl(a1, env)
%b(&::loop)
::last
- %ld(a0, sp, %EVAL_OR_LOCALS.rest)
+ %ldl(a0, rest)
%car(a0, a0)
- %ld(a1, sp, %EVAL_OR_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval)
::done
@@ -1914,28 +1904,27 @@
# clause's body is tail-evaluated via eval_body so the last form keeps
# tail position. No-match (and no else) dies via runtime_error.
#
-# Frame: 48 bytes
-# +0 subject
-# +8 env_outer (per-clause restart point)
-# +16 clauses (current cursor; advances on miss / failed guard)
-# +24 env_ext (env extended with the matched clause's bindings)
-# +32 guard cursor (advances during the guard AND-fold)
-# +40 body (saved across guard evals, tail-evaluated on success)
-%struct EVAL_PMATCH_LOCALS { subject env_outer clauses env_ext guard body } # .SIZE = 48
-%fn(eval_pmatch, %EVAL_PMATCH_LOCALS.SIZE, {
- %st(a1, sp, %EVAL_PMATCH_LOCALS.env_outer)
+# Locals:
+# subject
+# env_outer (per-clause restart point)
+# clauses (current cursor; advances on miss / failed guard)
+# env_ext (env extended with the matched clause's bindings)
+# guard cursor (advances during the guard AND-fold)
+# body (saved across guard evals, tail-evaluated on success)
+%fn2(eval_pmatch, {subject env_outer clauses env_ext guard body}, {
+ %stl(a1, env_outer)
# subject = eval(car(rest), env_outer); clauses = cdr(rest).
%mov(t0, a0)
%cdr(t1, t0)
- %st(t1, sp, %EVAL_PMATCH_LOCALS.clauses)
+ %stl(t1, clauses)
%car(a0, t0)
- %ld(a1, sp, %EVAL_PMATCH_LOCALS.env_outer)
+ %ldl(a1, env_outer)
%call(&eval)
- %st(a0, sp, %EVAL_PMATCH_LOCALS.subject)
+ %stl(a0, subject)
::loop
- %ld(t0, sp, %EVAL_PMATCH_LOCALS.clauses)
+ %ldl(t0, clauses)
%if_nil(t1, t0, &::no_match)
%car(t1, t0) ; clause
@@ -1946,15 +1935,15 @@
# pmatch_match(pat, subject, env_outer) -> (a0=env_ext, a1=ok)
%mov(a0, t2)
- %ld(a1, sp, %EVAL_PMATCH_LOCALS.subject)
- %ld(a2, sp, %EVAL_PMATCH_LOCALS.env_outer)
+ %ldl(a1, subject)
+ %ldl(a2, env_outer)
%call(&pmatch_match)
%beqz(a1, &::next)
- %st(a0, sp, %EVAL_PMATCH_LOCALS.env_ext) ; env_ext
+ %stl(a0, env_ext) ; env_ext
# tail = cdr(clause)
- %ld(t0, sp, %EVAL_PMATCH_LOCALS.clauses)
+ %ldl(t0, clauses)
%car(t0, t0)
%cdr(t0, t0) ; tail = (body...) or ((guard ...) body...)
@@ -1973,28 +1962,28 @@
# Guard clause. guards = cdr(car(tail)); body = cdr(tail).
%cdr(a0, t1)
- %st(a0, sp, %EVAL_PMATCH_LOCALS.guard)
+ %stl(a0, guard)
%cdr(t0, t0)
- %st(t0, sp, %EVAL_PMATCH_LOCALS.body)
+ %stl(t0, body)
::g_loop
- %ld(t0, sp, %EVAL_PMATCH_LOCALS.guard)
+ %ldl(t0, guard)
%if_nil(t1, t0, &::body_run)
%car(a0, t0) ; guard expr
- %ld(a1, sp, %EVAL_PMATCH_LOCALS.env_ext) ; env_ext
+ %ldl(a1, env_ext) ; env_ext
%call(&eval)
%li(t0, %imm_val(%IMM.FALSE))
%beq(a0, t0, &::next)
- %ld(t0, sp, %EVAL_PMATCH_LOCALS.guard)
+ %ldl(t0, guard)
%cdr(t0, t0)
- %st(t0, sp, %EVAL_PMATCH_LOCALS.guard)
+ %stl(t0, guard)
%b(&::g_loop)
::body_run
- %ld(a0, sp, %EVAL_PMATCH_LOCALS.body)
- %ld(a1, sp, %EVAL_PMATCH_LOCALS.env_ext)
+ %ldl(a0, body)
+ %ldl(a1, env_ext)
%tail(&eval_body)
::body_simple
@@ -2002,20 +1991,20 @@
# with the extended env; tail position of the matched clause's body
# is preserved.
%mov(a0, t0)
- %ld(a1, sp, %EVAL_PMATCH_LOCALS.env_ext)
+ %ldl(a1, env_ext)
%tail(&eval_body)
::do_else
- %ld(t0, sp, %EVAL_PMATCH_LOCALS.clauses)
+ %ldl(t0, clauses)
%car(t0, t0)
%cdr(a0, t0) ; body
- %ld(a1, sp, %EVAL_PMATCH_LOCALS.env_outer) ; env_outer (no bindings introduced)
+ %ldl(a1, env_outer) ; env_outer (no bindings introduced)
%tail(&eval_body)
::next
- %ld(t0, sp, %EVAL_PMATCH_LOCALS.clauses)
+ %ldl(t0, clauses)
%cdr(t0, t0)
- %st(t0, sp, %EVAL_PMATCH_LOCALS.clauses)
+ %stl(t0, clauses)
%b(&::loop)
::no_match
@@ -2039,15 +2028,14 @@
# - HEAP-tagged HDR.BV: structural byte-for-byte equality via
# bv_equal_check; only when both pat and subj are HDR.BV.
#
-# Frame: 24 bytes
-# +0 pat
-# +8 subj
-# +16 env
-%struct PMATCH_MATCH_LOCALS { pat subj env } # .SIZE = 24
-%fn(pmatch_match, %PMATCH_MATCH_LOCALS.SIZE, {
- %st(a0, sp, %PMATCH_MATCH_LOCALS.pat)
- %st(a1, sp, %PMATCH_MATCH_LOCALS.subj)
- %st(a2, sp, %PMATCH_MATCH_LOCALS.env)
+# Locals:
+# pat
+# subj
+# env
+%fn2(pmatch_match, {pat subj env}, {
+ %stl(a0, pat)
+ %stl(a1, subj)
+ %stl(a2, env)
%tagof(t0, a0)
%li(t1, %TAG.PAIR)
@@ -2085,25 +2073,25 @@
%bne(t0, t1, &::no)
# Recurse on the cars; on success, recurse on the cdrs as a tail call.
- %ld(t0, sp, %PMATCH_MATCH_LOCALS.pat)
+ %ldl(t0, pat)
%car(a0, t0)
- %ld(t0, sp, %PMATCH_MATCH_LOCALS.subj)
+ %ldl(t0, subj)
%car(a1, t0)
- %ld(a2, sp, %PMATCH_MATCH_LOCALS.env)
+ %ldl(a2, env)
%call(&pmatch_match)
%beqz(a1, &::no)
%mov(a2, a0) ; env_after_car
- %ld(t0, sp, %PMATCH_MATCH_LOCALS.pat)
+ %ldl(t0, pat)
%cdr(a0, t0)
- %ld(t0, sp, %PMATCH_MATCH_LOCALS.subj)
+ %ldl(t0, subj)
%cdr(a1, t0)
%tail(&pmatch_match)
::binder
# Validate (unquote <sym>): cdr(pat) is a pair, cdr(cdr(pat)) is NIL,
# car(cdr(pat)) is a symbol.
- %ld(t0, sp, %PMATCH_MATCH_LOCALS.pat)
+ %ldl(t0, pat)
%cdr(t1, t0) ; cdr(pat)
%tagof(t0, t1)
%li(t2, %TAG.PAIR)
@@ -2123,15 +2111,15 @@
# Bind: env' = cons(cons(pident, subj), env). pident lives in t0;
# cons clobbers t0..t2, so move it into a0 right away.
%mov(a0, t0)
- %ld(a1, sp, %PMATCH_MATCH_LOCALS.subj)
+ %ldl(a1, subj)
%call(&cons)
- %ld(a1, sp, %PMATCH_MATCH_LOCALS.env)
+ %ldl(a1, env)
%call(&cons)
%li(a1, 1)
%eret
::ok
- %ld(a0, sp, %PMATCH_MATCH_LOCALS.env)
+ %ldl(a0, env)
%li(a1, 1)
%eret
@@ -2150,41 +2138,40 @@
# pair). Inits are evaluated in the *original* env (matches let
# semantics), then we apply the closure.
#
-# Frame: 64 bytes
-# +0 rest
-# +8 env_orig
-# +16 self_binding (the (name . UNSPEC) placeholder, patched at the end)
-# +24 self_env (cons(self_binding, env_orig))
-# +32 walk (advances; reset between passes)
-# +40 head (current pass's list head — params, then args)
-# +48 tail (current pass's list tail)
-# +56 params (saved between passes)
-%struct EVAL_LET_NAMED_LOCALS { rest env_orig self_binding self_env walk head tail params } # .SIZE = 64
-%fn(eval_let_named, %EVAL_LET_NAMED_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.rest)
- %st(a1, sp, %EVAL_LET_NAMED_LOCALS.env_orig)
+# Locals:
+# rest
+# env_orig
+# self_binding (the (name . UNSPEC) placeholder, patched at the end)
+# self_env (cons(self_binding, env_orig))
+# walk (advances; reset between passes)
+# head (current pass's list head — params, then args)
+# tail (current pass's list tail)
+# params (saved between passes)
+%fn2(eval_let_named, {rest env_orig self_binding self_env walk head tail params}, {
+ %stl(a0, rest)
+ %stl(a1, env_orig)
# 1. self_binding = (name . UNSPEC); self_env = cons(self_binding, env)
%car(t0, a0)
%mov(a0, t0)
%li(a1, %imm_val(%IMM.UNSPEC))
%call(&cons)
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.self_binding)
- %ld(a1, sp, %EVAL_LET_NAMED_LOCALS.env_orig)
+ %stl(a0, self_binding)
+ %ldl(a1, env_orig)
%call(&cons)
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.self_env)
+ %stl(a0, self_env)
# 2. Pass 1: build params list (cdr-tail trick) by walking bindings.
%li(t0, %imm_val(%IMM.NIL))
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.head)
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.tail)
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.rest)
+ %stl(t0, head)
+ %stl(t0, tail)
+ %ldl(t0, rest)
%cdr(t0, t0)
%car(t0, t0) ; bindings
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.walk)
+ %stl(t0, walk)
::p1_loop
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::p1_done)
%car(t1, t0)
@@ -2193,58 +2180,58 @@
%li(a1, %imm_val(%IMM.NIL))
%call(&cons) ; cell = (name . NIL)
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.head)
+ %ldl(t0, head)
%if_nil(t1, t0, &::p1_first)
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.tail)
+ %ldl(t0, tail)
%set_cdr(a0, t0)
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.tail)
+ %stl(a0, tail)
%b(&::p1_advance)
::p1_first
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.head)
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.tail)
+ %stl(a0, head)
+ %stl(a0, tail)
::p1_advance
%advance_walk(32)
%b(&::p1_loop)
::p1_done
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.head)
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.params) ; save params
+ %ldl(t0, head)
+ %stl(t0, params) ; save params
# 3. Pass 2: build args list (eval inits in env_orig).
%li(t0, %imm_val(%IMM.NIL))
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.head)
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.tail)
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.rest)
+ %stl(t0, head)
+ %stl(t0, tail)
+ %ldl(t0, rest)
%cdr(t0, t0)
%car(t0, t0)
- %st(t0, sp, %EVAL_LET_NAMED_LOCALS.walk)
+ %stl(t0, walk)
::p2_loop
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::p2_done)
%car(t1, t0)
%cdr(t2, t1)
%car(t2, t2) ; init
%mov(a0, t2)
- %ld(a1, sp, %EVAL_LET_NAMED_LOCALS.env_orig)
+ %ldl(a1, env_orig)
%call(&eval) ; val
%li(a1, %imm_val(%IMM.NIL))
%call(&cons) ; cell = (val . NIL)
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.head)
+ %ldl(t0, head)
%if_nil(t1, t0, &::p2_first)
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.tail)
+ %ldl(t0, tail)
%set_cdr(a0, t0)
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.tail)
+ %stl(a0, tail)
%b(&::p2_advance)
::p2_first
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.head)
- %st(a0, sp, %EVAL_LET_NAMED_LOCALS.tail)
+ %stl(a0, head)
+ %stl(a0, tail)
::p2_advance
%advance_walk(32)
@@ -2252,20 +2239,20 @@
::p2_done
# 4. Closure: eval_lambda((params . body), self_env).
- %ld(a0, sp, %EVAL_LET_NAMED_LOCALS.params) ; params
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.rest)
+ %ldl(a0, params) ; params
+ %ldl(t0, rest)
%cdr(t0, t0)
%cdr(a1, t0) ; body
%call(&cons)
- %ld(a1, sp, %EVAL_LET_NAMED_LOCALS.self_env)
+ %ldl(a1, self_env)
%call(&eval_lambda)
# 5. Patch self_binding cdr to closure.
- %ld(t0, sp, %EVAL_LET_NAMED_LOCALS.self_binding)
+ %ldl(t0, self_binding)
%set_cdr(a0, t0)
# 6. apply(closure, args).
- %ld(a1, sp, %EVAL_LET_NAMED_LOCALS.head)
+ %ldl(a1, head)
%tail(&apply)
})
@@ -2274,18 +2261,17 @@
# Variadic `.`-tail: when params terminates with a SYM (rather than NIL),
# bind it to the remaining args list and stop.
#
-# Frame: 24 bytes
-# +0 params (advanced each iteration)
-# +8 args (advanced each iteration)
-# +16 env (extended each iteration)
-%struct BIND_PARAMS_LOCALS { params args env } # .SIZE = 24
-%fn(bind_params, %BIND_PARAMS_LOCALS.SIZE, {
- %st(a0, sp, %BIND_PARAMS_LOCALS.params)
- %st(a1, sp, %BIND_PARAMS_LOCALS.args)
- %st(a2, sp, %BIND_PARAMS_LOCALS.env)
+# Locals:
+# params (advanced each iteration)
+# args (advanced each iteration)
+# env (extended each iteration)
+%fn2(bind_params, {params args env}, {
+ %stl(a0, params)
+ %stl(a1, args)
+ %stl(a2, env)
::loop
- %ld(t0, sp, %BIND_PARAMS_LOCALS.params)
+ %ldl(t0, params)
%tagof(t1, t0)
%li(t2, %TAG.PAIR)
%beq(t1, t2, &::pair)
@@ -2295,16 +2281,16 @@
::pair
# binding = cons(car(params), car(args))
- %ld(t0, sp, %BIND_PARAMS_LOCALS.params)
+ %ldl(t0, params)
%car(a0, t0)
- %ld(t0, sp, %BIND_PARAMS_LOCALS.args)
+ %ldl(t0, args)
%car(a1, t0)
%call(&cons)
# env = cons(binding, env)
- %ld(a1, sp, %BIND_PARAMS_LOCALS.env)
+ %ldl(a1, env)
%call(&cons)
- %st(a0, sp, %BIND_PARAMS_LOCALS.env)
+ %stl(a0, env)
# advance params and args
%advance_walk(0)
@@ -2313,15 +2299,15 @@
::rest_bind
# binding = cons(params_sym, args_list); env = cons(binding, env)
- %ld(a0, sp, %BIND_PARAMS_LOCALS.params)
- %ld(a1, sp, %BIND_PARAMS_LOCALS.args)
+ %ldl(a0, params)
+ %ldl(a1, args)
%call(&cons)
- %ld(a1, sp, %BIND_PARAMS_LOCALS.env)
+ %ldl(a1, env)
%call(&cons)
- %st(a0, sp, %BIND_PARAMS_LOCALS.env)
+ %stl(a0, env)
::done
- %ld(a0, sp, %BIND_PARAMS_LOCALS.env)
+ %ldl(a0, env)
})
# eval_body(body=a0, env=a1) -> value of last form (a0).
@@ -2333,14 +2319,13 @@
# bodies, cond clause bodies, begin's body). Per-form check is one
# tagof + one symbol compare, regardless of body length.
#
-# Frame: 16 bytes
-# +0 body
-# +8 env
-%struct EVAL_BODY_LOCALS { body env } # .SIZE = 16
-%fn(eval_body, %EVAL_BODY_LOCALS.SIZE, {
+# Locals:
+# body
+# env
+%fn2(eval_body, {body env}, {
::loop
- %st(a0, sp, %EVAL_BODY_LOCALS.body)
- %st(a1, sp, %EVAL_BODY_LOCALS.env)
+ %stl(a0, body)
+ %stl(a1, env)
# Reject internal `define`. Detect (define ...) at the head of any
# form before dispatching it to eval.
@@ -2354,23 +2339,23 @@
::not_define
# If cdr(body) is NIL, body's car is the last form.
- %ld(a0, sp, %EVAL_BODY_LOCALS.body)
+ %ldl(a0, body)
%cdr(t0, a0)
%if_nil(t1, t0, &::last)
# Non-last form: eval and discard, advance.
%car(a0, a0)
- %ld(a1, sp, %EVAL_BODY_LOCALS.env)
+ %ldl(a1, env)
%call(&eval)
- %ld(a0, sp, %EVAL_BODY_LOCALS.body)
+ %ldl(a0, body)
%cdr(a0, a0)
- %ld(a1, sp, %EVAL_BODY_LOCALS.env)
+ %ldl(a1, env)
%b(&::loop)
::last
- %ld(a0, sp, %EVAL_BODY_LOCALS.body)
+ %ldl(a0, body)
%car(a0, a0)
- %ld(a1, sp, %EVAL_BODY_LOCALS.env)
+ %ldl(a1, env)
%tail(&eval)
::internal_define
@@ -2480,51 +2465,50 @@
# Symbol intern -- linear scan, append on miss
# =========================================================================
#
-# Frame: 32 bytes
-# +0 name_ptr (input)
-# +8 name_len (input)
-# +16 idx (loop counter / found index)
-# +24 entry_ptr (spilled across memcmp)
-%struct INTERN_LOCALS { name_ptr name_len idx entry_ptr } # .SIZE = 32
-%fn(intern, %INTERN_LOCALS.SIZE, {
- %st(a0, sp, %INTERN_LOCALS.name_ptr)
- %st(a1, sp, %INTERN_LOCALS.name_len)
+# Locals:
+# name_ptr (input)
+# name_len (input)
+# idx (loop counter / found index)
+# entry_ptr (spilled across memcmp)
+%fn2(intern, {name_ptr name_len idx entry_ptr}, {
+ %stl(a0, name_ptr)
+ %stl(a1, name_len)
%li(t0, 0)
- %st(t0, sp, %INTERN_LOCALS.idx)
+ %stl(t0, idx)
::scan
# idx >= count? -> append
- %ld(t0, sp, %INTERN_LOCALS.idx)
+ %ldl(t0, idx)
%ld_global(t1, &symtab_count)
%bltu(t0, t1, &::probe)
%b(&::append)
::probe
%symtab_entry(t1, t0, t2)
- %st(t1, sp, %INTERN_LOCALS.entry_ptr)
+ %stl(t1, entry_ptr)
# entry.name_len == name_len ?
%ld(t2, t1, %SYMENT.name_len)
- %ld(a2, sp, %INTERN_LOCALS.name_len)
+ %ldl(a2, name_len)
%bne(t2, a2, &::next)
# memcmp(entry.name_ptr, name_ptr, len)
%ld(a0, t1, %SYMENT.name_ptr)
- %ld(a1, sp, %INTERN_LOCALS.name_ptr)
- %ld(a2, sp, %INTERN_LOCALS.name_len)
+ %ldl(a1, name_ptr)
+ %ldl(a2, name_len)
%call(&memcmp)
%beqz(a0, &::found)
::next
- %ld(t0, sp, %INTERN_LOCALS.idx)
+ %ldl(t0, idx)
%addi(t0, t0, 1)
- %st(t0, sp, %INTERN_LOCALS.idx)
+ %stl(t0, idx)
%b(&::scan)
::append
# Bounds check; on overflow exit 5 with a message.
- %ld(t0, sp, %INTERN_LOCALS.idx)
+ %ldl(t0, idx)
%li(t1, %SYMTAB_CAP_SLOTS)
%bltu(t0, t1, &::append_ok)
%die(msg_symtab_full)
@@ -2533,16 +2517,16 @@
# Copy the name into a stable heap buffer. The caller-provided ptr
# may live in readbuf_buf (parse_atom), which gets overwritten when
# the next source is loaded; symtab entries must outlive that.
- %ld(a0, sp, %INTERN_LOCALS.name_len)
+ %ldl(a0, name_len)
%call(&alloc_bytes)
- %ld(a1, sp, %INTERN_LOCALS.name_ptr)
- %ld(a2, sp, %INTERN_LOCALS.name_len)
+ %ldl(a1, name_ptr)
+ %ldl(a2, name_len)
%call(&memcpy) ; returns dst in a0 = stable copy
- %ld(t0, sp, %INTERN_LOCALS.idx)
+ %ldl(t0, idx)
%symtab_entry(t1, t0, t2)
%st(a0, t1, %SYMENT.name_ptr) ; stable copy
- %ld(a0, sp, %INTERN_LOCALS.name_len)
+ %ldl(a0, name_len)
%st(a0, t1, %SYMENT.name_len)
%li(a0, %imm_val(%IMM.UNBOUND))
%st(a0, t1, %SYMENT.global_val)
@@ -2556,7 +2540,7 @@
# fall through with idx in t0 = sp[16]
::found
- %ld(t0, sp, %INTERN_LOCALS.idx)
+ %ldl(t0, idx)
%shli(a0, t0, 3)
%ori(a0, a0, %TAG.SYM)
})
@@ -2591,21 +2575,19 @@
# the surface name, and bind the symbol's global slot to the HEAP-tagged
# prim pointer.
#
-# Frame: 24 bytes
-# +0 prim ptr (HEAP-tagged; spilled across intern + sym_set_global)
-# +8 walk (current table cursor)
-# +16 end (table_end)
-
-%struct REGISTER_PRIMITIVES_LOCALS { prim walk end } # .SIZE = 24
-%fn(register_primitives, %REGISTER_PRIMITIVES_LOCALS.SIZE, {
+# Locals:
+# prim ptr (HEAP-tagged; spilled across intern + sym_set_global)
+# walk (current table cursor)
+# end (table_end)
+%fn2(register_primitives, {prim walk end}, {
%la(t0, &prim_table)
- %st(t0, sp, %REGISTER_PRIMITIVES_LOCALS.walk)
+ %stl(t0, walk)
%la(t0, &prim_table_end)
- %st(t0, sp, %REGISTER_PRIMITIVES_LOCALS.end)
+ %stl(t0, end)
::loop
- %ld(t0, sp, %REGISTER_PRIMITIVES_LOCALS.walk)
- %ld(t1, sp, %REGISTER_PRIMITIVES_LOCALS.end)
+ %ldl(t0, walk)
+ %ldl(t1, end)
%beq(t0, t1, &::done)
# alloc_hdr(24, HDR.PRIM) -> HEAP-tagged a0. The third slot (offset 13
@@ -2615,26 +2597,26 @@
%li(a0, 24)
%li(a1, %HDR.PRIM)
%call(&alloc_hdr)
- %st(a0, sp, %REGISTER_PRIMITIVES_LOCALS.prim)
+ %stl(a0, prim)
# Write entry-label into prim's entry slot.
- %ld(t0, sp, %REGISTER_PRIMITIVES_LOCALS.walk)
+ %ldl(t0, walk)
%ld(t1, t0, 16)
- %ld(t2, sp, %REGISTER_PRIMITIVES_LOCALS.prim)
+ %ldl(t2, prim)
%heap_st(t1, t2, %PRIM.entry_w)
# Intern surface name; bind global to prim ptr.
- %ld(t0, sp, %REGISTER_PRIMITIVES_LOCALS.walk)
+ %ldl(t0, walk)
%ld(a0, t0, 0)
%ld(a1, t0, 8)
%call(&intern)
%untag_sym(a0, a0)
- %ld(a1, sp, %REGISTER_PRIMITIVES_LOCALS.prim)
+ %ldl(a1, prim)
%call(&sym_set_global)
- %ld(t0, sp, %REGISTER_PRIMITIVES_LOCALS.walk)
+ %ldl(t0, walk)
%addi(t0, t0, 24)
- %st(t0, sp, %REGISTER_PRIMITIVES_LOCALS.walk)
+ %stl(t0, walk)
%b(&::loop)
::done
@@ -2768,14 +2750,13 @@
# t-regs, so the running write offset and remaining-args cursor live
# in the frame across each call.
#
-# Frame: 32 bytes
-# +0 args list head (re-read for pass 2; cursor during pass 2)
-# +8 total length (raw)
-# +16 result bv
-# +24 write offset (raw, into result.data)
-%struct PRIM_BV_APPEND_ENTRY_LOCALS { args total result write } # .SIZE = 32
-%fn(prim_bv_append_entry, %PRIM_BV_APPEND_ENTRY_LOCALS.SIZE, {
- %st(a0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.args)
+# Locals:
+# args list head (re-read for pass 2; cursor during pass 2)
+# total length (raw)
+# result bv
+# write offset (raw, into result.data)
+%fn2(prim_bv_append_entry, {args total result write}, {
+ %stl(a0, args)
%li(t0, 0)
%mov(t1, a0)
@@ -2788,39 +2769,39 @@
%cdr(t1, t1)
%b(&::sum_loop)
::sum_done
- %st(t0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.total)
+ %stl(t0, total)
%mov(a0, t0)
%call(&bv_alloc)
- %st(a0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.result)
+ %stl(a0, result)
%li(t0, 0)
- %st(t0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.write)
+ %stl(t0, write)
::copy_loop
- %ld(t0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%if_nil(t1, t0, &::copy_done)
%car(t1, t0) ; src bv
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8) ; src length
- %ld(a0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.result)
+ %ldl(a0, result)
%heap_ld(a0, a0, %BV.data) ; result.data
- %ld(a3, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.write)
+ %ldl(a3, write)
%add(a0, a0, a3) ; dst = result.data + offset
%heap_ld(a1, t1, %BV.data) ; src.data
%mov(a2, t2) ; count
%add(a3, a3, t2)
- %st(a3, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.write)
+ %stl(a3, write)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.args)
+ %stl(t0, args)
%call(&memcpy)
%b(&::copy_loop)
::copy_done
- %ld(a0, sp, %PRIM_BV_APPEND_ENTRY_LOCALS.result)
+ %ldl(a0, result)
})
# (string->symbol bv) -- intern the bytes and return the SYM-tagged
@@ -2837,22 +2818,22 @@
# returns (ptr, len); bv_alloc gives us a clean wrapper; memcpy fills
# the data. Frame holds the (ptr, len) pair across bv_alloc and the
# resulting bv across memcpy.
-%struct PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS { ptr len bv } # .SIZE = 24
-%fn(prim_symbol_to_string_entry, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.SIZE, {
+
+%fn2(prim_symbol_to_string_entry, {ptr len bv}, {
%car(a0, a0)
%sari(a0, a0, 3) ; raw sym idx
%call(&sym_name) ; -> ptr (a0), len (a1)
- %st(a0, sp, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.ptr)
- %st(a1, sp, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.len)
+ %stl(a0, ptr)
+ %stl(a1, len)
%mov(a0, a1)
%call(&bv_alloc) ; tagged bv in a0
- %st(a0, sp, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.bv)
- %ld(a1, sp, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.ptr) ; src ptr
- %ld(a2, sp, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.len) ; len
+ %stl(a0, bv)
+ %ldl(a1, ptr) ; src ptr
+ %ldl(a2, len) ; len
%heap_ld(t0, a0, %BV.data) ; dst = bv.data
%mov(a0, t0)
%call(&memcpy)
- %ld(a0, sp, %PRIM_SYMBOL_TO_STRING_ENTRY_LOCALS.bv)
+ %ldl(a0, bv)
})
# (number->string n [radix]) -- decimal repr in a fresh bv. The radix
@@ -2861,14 +2842,14 @@
# is silently ignored. bv_putint takes the raw value, so untag first;
# bv_alloc(0) gives an empty wrapper that bv_putint grows in place.
# +0 holds the raw value across bv_alloc.
-%struct PRIM_NUMBER_TO_STRING_ENTRY_LOCALS { value pad } # .SIZE = 16
-%fn(prim_number_to_string_entry, %PRIM_NUMBER_TO_STRING_ENTRY_LOCALS.SIZE, {
+
+%fn2(prim_number_to_string_entry, {value pad}, {
%car(t0, a0)
%sari(t0, t0, 3) ; raw value
- %st(t0, sp, %PRIM_NUMBER_TO_STRING_ENTRY_LOCALS.value)
+ %stl(t0, value)
%li(a0, 0)
%call(&bv_alloc)
- %ld(a1, sp, %PRIM_NUMBER_TO_STRING_ENTRY_LOCALS.value)
+ %ldl(a1, value)
%tail(&bv_putint)
})
@@ -3171,27 +3152,26 @@
# bv_capacity_for, data buffer uninitialized. data_ptr lives in a frame
# slot because alloc_hdr's alignup clobbers t-regs.
#
-# Frame: 24 bytes
-# +0 raw_len
-# +8 capacity
-# +16 data_ptr (raw)
-%struct BV_ALLOC_LOCALS { raw_len capacity data_ptr } # .SIZE = 24
-%fn(bv_alloc, %BV_ALLOC_LOCALS.SIZE, {
- %st(a0, sp, %BV_ALLOC_LOCALS.raw_len)
+# Locals:
+# raw_len
+# capacity
+# data_ptr (raw)
+%fn2(bv_alloc, {raw_len capacity data_ptr}, {
+ %stl(a0, raw_len)
%call(&bv_capacity_for)
- %st(a0, sp, %BV_ALLOC_LOCALS.capacity)
+ %stl(a0, capacity)
%call(&alloc_bytes)
- %st(a0, sp, %BV_ALLOC_LOCALS.data_ptr)
+ %stl(a0, data_ptr)
- %ld(a1, sp, %BV_ALLOC_LOCALS.raw_len)
+ %ldl(a1, raw_len)
%shli(a1, a1, 8) ; hdr = (raw_len << 8) | HDR.BV (BV == 0)
%li(a0, 24)
%call(&alloc_hdr)
- %ld(t0, sp, %BV_ALLOC_LOCALS.data_ptr)
+ %ldl(t0, data_ptr)
%heap_st(t0, a0, %BV.data)
- %ld(t1, sp, %BV_ALLOC_LOCALS.capacity)
+ %ldl(t1, capacity)
%st(t1, a0, 13) ; bv.cap (raw offset 16; not in BV struct)
})
@@ -3200,56 +3180,52 @@
# capacity), and patches the wrapper's data_ptr/capacity slots in place.
# A no-op when current capacity already satisfies min_cap.
#
-# Frame: 32 bytes
-# +0 bv
-# +8 min_cap (input) / new_cap (during loop)
-# +16 new_data_ptr
-# +24 raw length
-%struct BV_GROW_LOCALS { bv min_cap new_data_ptr raw } # .SIZE = 32
-%fn(bv_grow, %BV_GROW_LOCALS.SIZE, {
- %st(a0, sp, %BV_GROW_LOCALS.bv)
- %st(a1, sp, %BV_GROW_LOCALS.min_cap)
+# Locals:
+# bv
+# min_cap (input) / new_cap (during loop)
+# new_data_ptr
+# raw length
+%fn2(bv_grow, {bv min_cap new_data_ptr raw}, {
+ %stl(a0, bv)
+ %stl(a1, min_cap)
%ld(t0, a0, 13) ; bv.cap (raw offset 16; not in BV struct)
%bltu(t0, a1, &::need)
- %ld(a0, sp, %BV_GROW_LOCALS.bv)
+ %ldl(a0, bv)
%eret
::need
::loop
%shli(t0, t0, 1)
- %ld(t1, sp, %BV_GROW_LOCALS.min_cap)
+ %ldl(t1, min_cap)
%bltu(t0, t1, &::loop)
- %st(t0, sp, %BV_GROW_LOCALS.min_cap)
+ %stl(t0, min_cap)
%mov(a0, t0)
%call(&alloc_bytes)
- %st(a0, sp, %BV_GROW_LOCALS.new_data_ptr)
+ %stl(a0, new_data_ptr)
- %ld(t0, sp, %BV_GROW_LOCALS.bv)
+ %ldl(t0, bv)
%heap_ld(t1, t0, %BV.hdr)
%shri(t1, t1, 8) ; raw length
- %st(t1, sp, %BV_GROW_LOCALS.raw)
- %ld(a0, sp, %BV_GROW_LOCALS.new_data_ptr)
+ %stl(t1, raw)
+ %ldl(a0, new_data_ptr)
%heap_ld(a1, t0, %BV.data) ; old data ptr
- %ld(a2, sp, %BV_GROW_LOCALS.raw)
+ %ldl(a2, raw)
%call(&memcpy)
- %ld(t0, sp, %BV_GROW_LOCALS.bv)
- %ld(t1, sp, %BV_GROW_LOCALS.new_data_ptr)
+ %ldl(t0, bv)
+ %ldl(t1, new_data_ptr)
%heap_st(t1, t0, %BV.data)
- %ld(t1, sp, %BV_GROW_LOCALS.min_cap)
+ %ldl(t1, min_cap)
%st(t1, t0, 13) ; bv.cap (raw offset 16; not in BV struct)
- %ld(a0, sp, %BV_GROW_LOCALS.bv)
+ %ldl(a0, bv)
})
# (make-bytevector len) or (make-bytevector len fill)
-%struct PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS { args fill wrapper } # .SIZE = 24
-%fn(prim_make_bytevector_entry, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.SIZE, {
- # +0 args
- # +8 fill (raw byte)
- # +16 wrapper (saved across fill loop)
- %st(a0, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.args)
+
+%fn2(prim_make_bytevector_entry, {args fill wrapper}, {
+ %stl(a0, args)
%li(t2, 0)
%cdr(t0, a0)
@@ -3257,18 +3233,18 @@
%car(t0, t0)
%sari(t2, t0, 3)
::no_fill
- %st(t2, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.fill)
+ %stl(t2, fill)
- %ld(a0, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.args)
+ %ldl(a0, args)
%car_fix(a0, a0)
%bltz(a0, &::bad_len)
%call(&bv_alloc)
- %st(a0, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.wrapper)
+ %stl(a0, wrapper)
- %ld(t0, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%car_fix(t0, t0) ; raw_len
- %ld(t1, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.fill) ; fill
- %ld(a1, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.wrapper)
+ %ldl(t1, fill) ; fill
+ %ldl(a1, wrapper)
%heap_ld(t2, a1, %BV.data)
%li(a1, 0)
@@ -3280,7 +3256,7 @@
%b(&::fill_loop)
::fill_done
- %ld(a0, sp, %PRIM_MAKE_BYTEVECTOR_ENTRY_LOCALS.wrapper)
+ %ldl(a0, wrapper)
%eret
::bad_len
@@ -3333,16 +3309,15 @@
# (bytevector-copy src start end) -> fresh bv of length end-start.
# Bounds: 0 <= start <= end <= src.length.
#
-# Frame: 24 bytes
-# +0 args
-# +8 src tagged
-# +16 wrapper (saved after bv_alloc)
-%struct PRIM_BV_COPY_ENTRY_LOCALS { args src wrapper } # .SIZE = 24
-%fn(prim_bv_copy_entry, %PRIM_BV_COPY_ENTRY_LOCALS.SIZE, {
- %st(a0, sp, %PRIM_BV_COPY_ENTRY_LOCALS.args)
+# Locals:
+# args
+# src tagged
+# wrapper (saved after bv_alloc)
+%fn2(prim_bv_copy_entry, {args src wrapper}, {
+ %stl(a0, args)
%args3(t0, t2, t1, a0) ; src, start, end
- %st(t0, sp, %PRIM_BV_COPY_ENTRY_LOCALS.src)
+ %stl(t0, src)
%sari(t2, t2, 3) ; raw start
%sari(t1, t1, 3) ; raw end
@@ -3356,16 +3331,16 @@
%sub(a0, t1, t2) ; count
%call(&bv_alloc)
- %st(a0, sp, %PRIM_BV_COPY_ENTRY_LOCALS.wrapper)
+ %stl(a0, wrapper)
# Recompute src ptr at start; dst ptr at 0; count from new bv's hdr.
- %ld(t0, sp, %PRIM_BV_COPY_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%cdr(t0, t0)
%car_fix(t0, t0) ; raw start
- %ld(t1, sp, %PRIM_BV_COPY_ENTRY_LOCALS.src)
+ %ldl(t1, src)
%heap_ld(t2, t1, %BV.data)
%add(t2, t2, t0) ; src ptr
- %ld(a3, sp, %PRIM_BV_COPY_ENTRY_LOCALS.wrapper)
+ %ldl(a3, wrapper)
%heap_ld(a2, a3, %BV.data) ; dst ptr
%heap_ld(a1, a3, %BV.hdr)
%shri(a1, a1, 8) ; count
@@ -3380,7 +3355,7 @@
%b(&::copy_loop)
::copy_done
- %ld(a0, sp, %PRIM_BV_COPY_ENTRY_LOCALS.wrapper)
+ %ldl(a0, wrapper)
%eret
::oob
@@ -3391,65 +3366,64 @@
# 0 <= src-start <= src-end <= src.length and
# 0 <= dst-start && dst-start + (src-end-src-start) <= dst.length.
#
-# Frame: 40 bytes (five raw args parked across the bounds checks).
-# +0 dst (tagged)
-# +8 dst-start (raw)
-# +16 src (tagged)
-# +24 src-start (raw)
-# +32 src-end (raw)
-%struct PRIM_BV_COPY_BANG_ENTRY_LOCALS { dst dst_start src src_start src_end } # .SIZE = 40
-%fn(prim_bv_copy_bang_entry, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.SIZE, {
+# Locals:
+# dst -start (raw)
+# dst_start
+# src -end (raw)
+# src_start
+# src_end
+%fn2(prim_bv_copy_bang_entry, {dst dst_start src src_start src_end}, {
%car(t0, a0)
- %st(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.dst) ; dst
+ %stl(t0, dst) ; dst
%cdr(a0, a0)
%car(t0, a0)
%sari(t0, t0, 3)
- %st(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.dst_start) ; dst-start
+ %stl(t0, dst_start) ; dst-start
%cdr(a0, a0)
%car(t0, a0)
- %st(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src) ; src
+ %stl(t0, src) ; src
%cdr(a0, a0)
%car(t0, a0)
%sari(t0, t0, 3)
- %st(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src_start) ; src-start
+ %stl(t0, src_start) ; src-start
%cdr(a0, a0)
%car(t0, a0)
%sari(t0, t0, 3)
- %st(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src_end) ; src-end
+ %stl(t0, src_end) ; src-end
# src-start >= 0
- %ld(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src_start)
+ %ldl(t0, src_start)
%bltz(t0, &::oob)
# src-end >= src-start (signed catches negative src-end)
- %ld(t1, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src_end)
+ %ldl(t1, src_end)
%blt(t1, t0, &::oob)
# src-end <= src.length
- %ld(t2, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src)
+ %ldl(t2, src)
%heap_ld(a0, t2, %BV.hdr)
%shri(a0, a0, 8)
%blt(a0, t1, &::oob)
# dst-start >= 0
- %ld(t2, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.dst_start)
+ %ldl(t2, dst_start)
%bltz(t2, &::oob)
# dst-start + count <= dst.length
%sub(a0, t1, t0) ; count = src-end - src-start
%add(a0, a0, t2) ; dst-start + count
- %ld(t1, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.dst)
+ %ldl(t1, dst)
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8)
%blt(t2, a0, &::oob)
# Set up copy. dst ptr = dst.data + dst-start; src ptr = src.data +
# src-start; count = src-end - src-start.
- %ld(t0, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.dst)
+ %ldl(t0, dst)
%heap_ld(t0, t0, %BV.data)
- %ld(a1, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.dst_start)
+ %ldl(a1, dst_start)
%add(t0, t0, a1) ; dst ptr
- %ld(a1, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src)
+ %ldl(a1, src)
%heap_ld(a1, a1, %BV.data)
- %ld(a2, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src_start)
+ %ldl(a2, src_start)
%add(a1, a1, a2) ; src ptr
- %ld(a3, sp, %PRIM_BV_COPY_BANG_ENTRY_LOCALS.src_end)
+ %ldl(a3, src_end)
%sub(a3, a3, a2) ; count
::loop
@@ -3535,11 +3509,12 @@
# only when both are HDR.BV (closures, prims, records, and TDs are
# identity-only). Tail-calls the cdr-side recursion and the BV check.
#
-# Frame: 16 bytes (a, b spilled across each %call).
-%struct EQUAL_RECURSE_LOCALS { a b } # .SIZE = 16
-%fn(equal_recurse, %EQUAL_RECURSE_LOCALS.SIZE, {
- %st(a0, sp, %EQUAL_RECURSE_LOCALS.a)
- %st(a1, sp, %EQUAL_RECURSE_LOCALS.b)
+# Locals:
+# a
+# b
+%fn2(equal_recurse, {a b}, {
+ %stl(a0, a)
+ %stl(a1, b)
%beq(a0, a1, &::true)
@@ -3554,22 +3529,22 @@
%b(&::false)
::pair
- %ld(t0, sp, %EQUAL_RECURSE_LOCALS.a)
- %ld(t1, sp, %EQUAL_RECURSE_LOCALS.b)
+ %ldl(t0, a)
+ %ldl(t1, b)
%car(a0, t0)
%car(a1, t1)
%call(&equal_recurse)
%li(t0, %imm_val(%IMM.FALSE))
%beq(a0, t0, &::done)
- %ld(t0, sp, %EQUAL_RECURSE_LOCALS.a)
- %ld(t1, sp, %EQUAL_RECURSE_LOCALS.b)
+ %ldl(t0, a)
+ %ldl(t1, b)
%cdr(a0, t0)
%cdr(a1, t1)
%tail(&equal_recurse)
::heap
- %ld(t0, sp, %EQUAL_RECURSE_LOCALS.a)
- %ld(t1, sp, %EQUAL_RECURSE_LOCALS.b)
+ %ldl(t0, a)
+ %ldl(t1, b)
%hdr_type(t2, t0)
%hdr_type(a0, t1)
%bne(t2, a0, &::false) ; differing heap classes -> #f
@@ -3604,45 +3579,44 @@
# every field is equal? (recursing through equal_recurse). Field i sits
# at tagged + 13 + 8*i; nfields lives at the TD's offset 13 (raw).
#
-# Frame: 32 bytes
-# +0 a (rec, tagged)
-# +8 b (rec, tagged)
-# +16 i (raw counter)
-# +24 nfields (raw)
-%struct REC_EQUAL_CHECK_LOCALS { a b i nfields } # .SIZE = 32
-%fn(rec_equal_check, %REC_EQUAL_CHECK_LOCALS.SIZE, {
- %st(a0, sp, %REC_EQUAL_CHECK_LOCALS.a)
- %st(a1, sp, %REC_EQUAL_CHECK_LOCALS.b)
+# Locals:
+# a (rec, tagged)
+# b (rec, tagged)
+# i (raw counter)
+# nfields (raw)
+%fn2(rec_equal_check, {a b i nfields}, {
+ %stl(a0, a)
+ %stl(a1, b)
%heap_ld(t0, a0, %REC.td) ; td_a
%heap_ld(t1, a1, %REC.td) ; td_b
%bne(t0, t1, &::false)
%heap_ld(t1, t0, %TD.nfields)
- %st(t1, sp, %REC_EQUAL_CHECK_LOCALS.nfields)
+ %stl(t1, nfields)
%li(t0, 0)
- %st(t0, sp, %REC_EQUAL_CHECK_LOCALS.i) ; i = 0
+ %stl(t0, i) ; i = 0
::loop
- %ld(t0, sp, %REC_EQUAL_CHECK_LOCALS.i)
- %ld(t1, sp, %REC_EQUAL_CHECK_LOCALS.nfields)
+ %ldl(t0, i)
+ %ldl(t1, nfields)
%beq(t0, t1, &::true)
%shli(t2, t0, 3)
%addi(t2, t2, 13) ; field offset = 13 + 8*i
- %ld(t1, sp, %REC_EQUAL_CHECK_LOCALS.a)
+ %ldl(t1, a)
%add(t1, t1, t2)
%ld(a0, t1, 0) ; a's field i
- %ld(t1, sp, %REC_EQUAL_CHECK_LOCALS.b)
+ %ldl(t1, b)
%add(t1, t1, t2)
%ld(a1, t1, 0) ; b's field i
%call(&equal_recurse)
%li(t0, %imm_val(%IMM.FALSE))
%beq(a0, t0, &::done)
- %ld(t0, sp, %REC_EQUAL_CHECK_LOCALS.i)
+ %ldl(t0, i)
%addi(t0, t0, 1)
- %st(t0, sp, %REC_EQUAL_CHECK_LOCALS.i)
+ %stl(t0, i)
%b(&::loop)
::true
@@ -3674,13 +3648,13 @@
# clobber it freely while assembling args, then tail-call apply, which
# re-derives a1 from the callee fn it dispatches on. Outer convention
# stays intact end-to-end.
-%struct PRIM_APPLY_ENTRY_LOCALS { args pad } # .SIZE = 16
-%fn(prim_apply_entry, %PRIM_APPLY_ENTRY_LOCALS.SIZE, {
- %st(a0, sp, %PRIM_APPLY_ENTRY_LOCALS.args)
+
+%fn2(prim_apply_entry, {args pad}, {
+ %stl(a0, args)
%cdr(a0, a0)
%call(&apply_build_args)
%mov(t0, a0)
- %ld(a0, sp, %PRIM_APPLY_ENTRY_LOCALS.args)
+ %ldl(a0, args)
%car(a0, a0)
%mov(a1, t0)
%tail(&apply)
@@ -3693,19 +3667,18 @@
# (aₖ . NIL) cons; the final element (the trailing list) becomes the
# tail's cdr (or the result itself if there are no leading elements).
#
-# Frame: 24 bytes
-# +0 walk (advances; current cell of rest)
-# +8 head (NIL until first leading arg appended)
-# +16 tail (most recent cell; set-cdr! target)
-%struct APPLY_BUILD_ARGS_LOCALS { walk head tail } # .SIZE = 24
-%fn(apply_build_args, %APPLY_BUILD_ARGS_LOCALS.SIZE, {
- %st(a0, sp, %APPLY_BUILD_ARGS_LOCALS.walk)
+# Locals:
+# walk (advances; current cell of rest)
+# head (NIL until first leading arg appended)
+# tail (most recent cell; set-cdr! target)
+%fn2(apply_build_args, {walk head tail}, {
+ %stl(a0, walk)
%li(t0, %imm_val(%IMM.NIL))
- %st(t0, sp, %APPLY_BUILD_ARGS_LOCALS.head)
- %st(t0, sp, %APPLY_BUILD_ARGS_LOCALS.tail)
+ %stl(t0, head)
+ %stl(t0, tail)
::loop
- %ld(t0, sp, %APPLY_BUILD_ARGS_LOCALS.walk)
+ %ldl(t0, walk)
%cdr(t1, t0)
%if_nil(t2, t1, &::last)
@@ -3714,16 +3687,16 @@
%li(a1, %imm_val(%IMM.NIL))
%call(&cons)
- %ld(t0, sp, %APPLY_BUILD_ARGS_LOCALS.head)
+ %ldl(t0, head)
%if_nil(t1, t0, &::first)
- %ld(t0, sp, %APPLY_BUILD_ARGS_LOCALS.tail)
+ %ldl(t0, tail)
%set_cdr(a0, t0)
- %st(a0, sp, %APPLY_BUILD_ARGS_LOCALS.tail)
+ %stl(a0, tail)
%b(&::advance)
::first
- %st(a0, sp, %APPLY_BUILD_ARGS_LOCALS.head)
- %st(a0, sp, %APPLY_BUILD_ARGS_LOCALS.tail)
+ %stl(a0, head)
+ %stl(a0, tail)
::advance
%advance_walk(0)
@@ -3734,11 +3707,11 @@
# args -- return the trailing list directly. Otherwise splice it onto
# the tail and return head.
%car(a0, t0)
- %ld(t1, sp, %APPLY_BUILD_ARGS_LOCALS.head)
+ %ldl(t1, head)
%if_nil(t2, t1, &::done)
- %ld(t1, sp, %APPLY_BUILD_ARGS_LOCALS.tail)
+ %ldl(t1, tail)
%set_cdr(a0, t1)
- %ld(a0, sp, %APPLY_BUILD_ARGS_LOCALS.head)
+ %ldl(a0, head)
::done
})
@@ -3752,18 +3725,18 @@
# make_param_prim(entry=a0, data=a1) -> prim (a0). Allocates a 24-byte
# PRIM, sets the entry label and data word.
-%struct MAKE_PARAM_PRIM_LOCALS { entry data } # .SIZE = 16
-%fn(make_param_prim, %MAKE_PARAM_PRIM_LOCALS.SIZE, {
- %st(a0, sp, %MAKE_PARAM_PRIM_LOCALS.entry)
- %st(a1, sp, %MAKE_PARAM_PRIM_LOCALS.data)
+
+%fn2(make_param_prim, {entry data}, {
+ %stl(a0, entry)
+ %stl(a1, data)
%li(a0, 24)
%li(a1, %HDR.PRIM)
%call(&alloc_hdr)
- %ld(t0, sp, %MAKE_PARAM_PRIM_LOCALS.entry)
+ %ldl(t0, entry)
%heap_st(t0, a0, %PRIM.entry_w)
- %ld(t1, sp, %MAKE_PARAM_PRIM_LOCALS.data)
+ %ldl(t1, data)
%heap_st(t1, a0, %PRIM.data)
})
@@ -3778,14 +3751,11 @@
# ctor: prim.data = TD (HEAP); args = (f0 f1 ...). Inlines the
# %make-record body so we don't have to cons (TD . args) first.
-%struct PRIM_CTOR_ENTRY_LOCALS { args td record } # .SIZE = 24
-%fn(prim_ctor_entry, %PRIM_CTOR_ENTRY_LOCALS.SIZE, {
- # +0 args
- # +8 td (from prim.data)
- # +16 record
- %st(a0, sp, %PRIM_CTOR_ENTRY_LOCALS.args)
+
+%fn2(prim_ctor_entry, {args td record}, {
+ %stl(a0, args)
%heap_ld(t0, a1, %PRIM.data)
- %st(t0, sp, %PRIM_CTOR_ENTRY_LOCALS.td)
+ %stl(t0, td)
# Count = length(args).
%call(&list_length)
@@ -3793,12 +3763,12 @@
%addi(a0, a0, 16)
%li(a1, %HDR.REC)
%call(&alloc_hdr)
- %st(a0, sp, %PRIM_CTOR_ENTRY_LOCALS.record)
+ %stl(a0, record)
- %ld(t0, sp, %PRIM_CTOR_ENTRY_LOCALS.td)
+ %ldl(t0, td)
%heap_st(t0, a0, %REC.td)
- %ld(t0, sp, %PRIM_CTOR_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%addi(t1, a0, 13)
::fill_loop
@@ -3810,7 +3780,7 @@
%b(&::fill_loop)
::fill_done
- %ld(a0, sp, %PRIM_CTOR_ENTRY_LOCALS.record)
+ %ldl(a0, record)
})
# predicate: prim.data = TD; args = (rec).
@@ -3861,43 +3831,43 @@
# Allocates one TD + one parameterized PRIM per name introduced (ctor,
# predicate, accessor, mutator) and binds each to the symbol's global.
#
-# Frame: 56 bytes
-# +0 rest
-# +8 env (unused, but the dispatcher passes it)
-# +16 td
-# +24 walk (clauses, advancing)
-# +32 idx (raw counter)
-# +40 nfields
-%struct EVAL_DEFINE_RECORD_TYPE_LOCALS { rest env td walk idx nfields pad } # .SIZE = 56
-%fn(eval_define_record_type, %EVAL_DEFINE_RECORD_TYPE_LOCALS.SIZE, {
- %st(a0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.rest)
- %st(a1, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.env)
+# Locals:
+# rest
+# env (unused, but the dispatcher passes it)
+# td
+# walk (clauses, advancing)
+# idx (raw counter)
+# nfields
+# pad
+%fn2(eval_define_record_type, {rest env td walk idx nfields pad}, {
+ %stl(a0, rest)
+ %stl(a1, env)
# clauses = cdddr(rest); count them via list_length.
- %ld(a0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.rest)
+ %ldl(a0, rest)
%cdr(a0, a0)
%cdr(a0, a0)
%cdr(a0, a0)
- %st(a0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.walk)
+ %stl(a0, walk)
%call(&list_length)
- %st(a0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.nfields)
+ %stl(a0, nfields)
# td = alloc_hdr(24, HDR.TD); td.name = type-name; td.nfields = nfields.
%li(a0, 24)
%li(a1, %HDR.TD)
%call(&alloc_hdr)
- %st(a0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.td)
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.rest)
+ %stl(a0, td)
+ %ldl(t0, rest)
%car(t0, t0)
%heap_st(t0, a0, %TD.name)
- %ld(t1, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.nfields)
+ %ldl(t1, nfields)
%heap_st(t1, a0, %TD.nfields)
# ctor-prim = make_param_prim(prim_ctor_entry, td); bind ctor-name.
%la(a0, &prim_ctor_entry)
- %ld(a1, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.td)
+ %ldl(a1, td)
%call(&make_param_prim)
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.rest)
+ %ldl(t0, rest)
%cdr(t0, t0)
%car(t0, t0)
%car(t0, t0)
@@ -3905,9 +3875,9 @@
# pred-prim = make_param_prim(prim_predicate_entry, td); bind pred.
%la(a0, &prim_predicate_entry)
- %ld(a1, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.td)
+ %ldl(a1, td)
%call(&make_param_prim)
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.rest)
+ %ldl(t0, rest)
%cdr(t0, t0)
%cdr(t0, t0)
%car(t0, t0)
@@ -3915,37 +3885,37 @@
# Iterate clauses: bind accessor + optional mutator per clause.
%li(t0, 0)
- %st(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.idx)
+ %stl(t0, idx)
::clause_loop
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::done)
# accessor-prim with data = tagged idx; bind cadr(clause).
- %ld(a1, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.idx)
+ %ldl(a1, idx)
%shli(a1, a1, 3)
%la(a0, &prim_accessor_entry)
%call(&make_param_prim)
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.walk)
+ %ldl(t0, walk)
%car(t0, t0)
%cdr(t0, t0)
%car(t0, t0)
%bind_global_from_t0()
# Mutator? If cddr(clause) is a pair, bind it.
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.walk)
+ %ldl(t0, walk)
%car(t0, t0)
%cdr(t0, t0)
%cdr(t0, t0)
%if_nil(t1, t0, &::no_mutator)
- %ld(a1, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.idx)
+ %ldl(a1, idx)
%shli(a1, a1, 3)
%la(a0, &prim_mutator_entry)
%call(&make_param_prim)
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.walk)
+ %ldl(t0, walk)
%car(t0, t0)
%cdr(t0, t0)
%cdr(t0, t0)
@@ -3954,9 +3924,9 @@
::no_mutator
%advance_walk(24)
- %ld(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.idx)
+ %ldl(t0, idx)
%addi(t0, t0, 1)
- %st(t0, sp, %EVAL_DEFINE_RECORD_TYPE_LOCALS.idx)
+ %stl(t0, idx)
%b(&::clause_loop)
::done
@@ -3990,80 +3960,80 @@
# `length` after append is left zero (preserved by the cap > length
# invariant from bv_capacity_for + the BSS-zero heap), so syscalls that
# read the data_ptr as a C string still see a NUL terminator.
-%struct BV_PUTN_LOCALS { bv src n old_len } # .SIZE = 32
-%fn(bv_putn, %BV_PUTN_LOCALS.SIZE, {
- %st(a0, sp, %BV_PUTN_LOCALS.bv)
- %st(a1, sp, %BV_PUTN_LOCALS.src)
- %st(a2, sp, %BV_PUTN_LOCALS.n)
+
+%fn2(bv_putn, {bv src n old_len}, {
+ %stl(a0, bv)
+ %stl(a1, src)
+ %stl(a2, n)
%heap_ld(t0, a0, %BV.hdr)
%shri(t0, t0, 8) ; old_len
- %st(t0, sp, %BV_PUTN_LOCALS.old_len)
+ %stl(t0, old_len)
# bv_grow ensures cap >= old_len + n + 1, so cap > new_len.
%add(a1, t0, a2)
%addi(a1, a1, 1)
%call(&bv_grow)
- %ld(t0, sp, %BV_PUTN_LOCALS.bv)
+ %ldl(t0, bv)
%heap_ld(a0, t0, %BV.data)
- %ld(t1, sp, %BV_PUTN_LOCALS.old_len)
+ %ldl(t1, old_len)
%add(a0, a0, t1) ; dst = data + old_len
- %ld(a1, sp, %BV_PUTN_LOCALS.src)
- %ld(a2, sp, %BV_PUTN_LOCALS.n)
+ %ldl(a1, src)
+ %ldl(a2, n)
%call(&memcpy)
# hdr = (old_len + n) << 8 | HDR.BV. HDR.BV is 0.
- %ld(t0, sp, %BV_PUTN_LOCALS.old_len)
- %ld(t1, sp, %BV_PUTN_LOCALS.n)
+ %ldl(t0, old_len)
+ %ldl(t1, n)
%add(t0, t0, t1)
%shli(t0, t0, 8)
- %ld(t1, sp, %BV_PUTN_LOCALS.bv)
+ %ldl(t1, bv)
%heap_st(t0, t1, %BV.hdr)
- %ld(a0, sp, %BV_PUTN_LOCALS.bv)
+ %ldl(a0, bv)
})
# bv_putc(bv=a0, byte=a1) -> bv (a0). Append a single byte (low 8 bits
# of a1). Same growth + length-update protocol as bv_putn.
-%struct BV_PUTC_LOCALS { bv byte } # .SIZE = 16
-%fn(bv_putc, %BV_PUTC_LOCALS.SIZE, {
- %st(a0, sp, %BV_PUTC_LOCALS.bv)
- %st(a1, sp, %BV_PUTC_LOCALS.byte)
+
+%fn2(bv_putc, {bv byte}, {
+ %stl(a0, bv)
+ %stl(a1, byte)
%heap_ld(t0, a0, %BV.hdr)
%shri(t0, t0, 8) ; old_len
%addi(a1, t0, 2) ; min_cap = old_len + 2
%call(&bv_grow)
- %ld(t0, sp, %BV_PUTC_LOCALS.bv)
+ %ldl(t0, bv)
%heap_ld(t1, t0, %BV.hdr)
%shri(t1, t1, 8) ; old_len (re-read after grow)
%heap_ld(t2, t0, %BV.data)
%add(t2, t2, t1)
- %ld(a0, sp, %BV_PUTC_LOCALS.byte)
+ %ldl(a0, byte)
%sb(a0, t2, 0)
%addi(t1, t1, 1)
%shli(t1, t1, 8)
%heap_st(t1, t0, %BV.hdr)
- %ld(a0, sp, %BV_PUTC_LOCALS.bv)
+ %ldl(a0, bv)
})
# bv_putint(bv=a0, value=a1) -> bv (a0). Append decimal repr of (raw,
# untagged) value. Uses :writer_num_buf as a 24-byte scratch buffer
# (fmt_dec writes at most 20 bytes for a 64-bit signed integer).
-%struct BV_PUTINT_LOCALS { bv pad } # .SIZE = 16
-%fn(bv_putint, %BV_PUTINT_LOCALS.SIZE, {
- %st(a0, sp, %BV_PUTINT_LOCALS.bv)
+
+%fn2(bv_putint, {bv pad}, {
+ %stl(a0, bv)
%la(a0, &writer_num_buf)
%call(&fmt_dec) ; n_bytes (a0)
%mov(a2, a0)
%la(a1, &writer_num_buf)
- %ld(a0, sp, %BV_PUTINT_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
})
@@ -4080,11 +4050,11 @@
# bytes (display); mode = 1 emits them as `"..."` (write). Pairs are
# delegated to write_pair_to_bv so the recursion through PAIR has its
# own frame.
-%struct WRITE_TO_BV_LOCALS { val bv mode pad } # .SIZE = 32
-%fn(write_to_bv, %WRITE_TO_BV_LOCALS.SIZE, {
- %st(a0, sp, %WRITE_TO_BV_LOCALS.val)
- %st(a1, sp, %WRITE_TO_BV_LOCALS.bv)
- %st(a2, sp, %WRITE_TO_BV_LOCALS.mode)
+
+%fn2(write_to_bv, {val bv mode pad}, {
+ %stl(a0, val)
+ %stl(a1, bv)
+ %stl(a2, mode)
%tagof(t0, a0)
%li(t1, %TAG.PAIR)
@@ -4097,24 +4067,24 @@
%beq(t0, t1, &::imm)
# Fall-through: FIXNUM (the only remaining tag).
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
- %ld(a1, sp, %WRITE_TO_BV_LOCALS.val)
+ %ldl(a0, bv)
+ %ldl(a1, val)
%sari(a1, a1, 3)
%tail(&bv_putint)
::sym
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.val)
+ %ldl(a0, val)
%sari(a0, a0, 3)
%call(&sym_name)
%mov(a2, a1)
%mov(a1, a0)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::pair
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.val)
- %ld(a1, sp, %WRITE_TO_BV_LOCALS.bv)
- %ld(a2, sp, %WRITE_TO_BV_LOCALS.mode)
+ %ldl(a0, val)
+ %ldl(a1, bv)
+ %ldl(a2, mode)
%tail(&write_pair_to_bv)
::heap
@@ -4132,13 +4102,13 @@
%b(&::heap_unknown)
::heap_bv
- %ld(t0, sp, %WRITE_TO_BV_LOCALS.mode)
+ %ldl(t0, mode)
%beqz(t0, &::heap_bv_raw)
# write mode: emit `"`, then the raw bytes, then `"`.
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 34)
%call(&bv_putc)
- %ld(t0, sp, %WRITE_TO_BV_LOCALS.val)
+ %ldl(t0, val)
%heap_ld(a1, t0, %BV.data)
%heap_ld(a2, t0, %BV.hdr)
%shri(a2, a2, 8)
@@ -4147,45 +4117,45 @@
%tail(&bv_putc)
::heap_bv_raw
- %ld(t0, sp, %WRITE_TO_BV_LOCALS.val)
+ %ldl(t0, val)
%heap_ld(a1, t0, %BV.data)
%heap_ld(a2, t0, %BV.hdr)
%shri(a2, a2, 8)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::heap_closure
%la(a1, &str_closure)
%li(a2, 10)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::heap_prim
%la(a1, &str_prim)
%li(a2, 7)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::heap_td
%la(a1, &str_td)
%li(a2, 11)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::heap_rec
%la(a1, &str_rec)
%li(a2, 9)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::heap_unknown
%la(a1, &str_unknown)
%li(a2, 10)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::imm
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.val)
+ %ldl(a0, val)
%sari(a0, a0, 3)
%beqz(a0, &::imm_false)
%addi(t0, a0, -1)
@@ -4199,37 +4169,37 @@
# EOF (idx == 5) is the only remaining IMM.
%la(a1, &str_eof)
%li(a2, 5)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::imm_false
%la(a1, &str_false)
%li(a2, 2)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::imm_true
%la(a1, &str_true)
%li(a2, 2)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::imm_nil
%la(a1, &str_nil)
%li(a2, 2)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::imm_unspec
%la(a1, &str_unspec)
%li(a2, 8)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
::imm_unbound
%la(a1, &str_unbound)
%li(a2, 9)
- %ld(a0, sp, %WRITE_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%tail(&bv_putn)
})
@@ -4239,30 +4209,30 @@
# a separator and continue, emit ` . val)` for a dotted tail, or just
# emit `)` for a proper-list NIL.
#
-# Frame: 32 bytes
-# +0 pair walk
-# +8 bv (stable wrapper; reused across recursive calls)
-# +16 mode
-%struct WRITE_PAIR_TO_BV_LOCALS { pair bv mode pad } # .SIZE = 32
-%fn(write_pair_to_bv, %WRITE_PAIR_TO_BV_LOCALS.SIZE, {
- %st(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.pair)
- %st(a1, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
- %st(a2, sp, %WRITE_PAIR_TO_BV_LOCALS.mode)
-
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
+# Locals:
+# pair walk
+# bv (stable wrapper; reused across recursive calls)
+# mode
+# pad
+%fn2(write_pair_to_bv, {pair bv mode pad}, {
+ %stl(a0, pair)
+ %stl(a1, bv)
+ %stl(a2, mode)
+
+ %ldl(a0, bv)
%li(a1, 40)
%call(&bv_putc)
::loop
- %ld(t0, sp, %WRITE_PAIR_TO_BV_LOCALS.pair)
+ %ldl(t0, pair)
%car(a0, t0)
- %ld(a1, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
- %ld(a2, sp, %WRITE_PAIR_TO_BV_LOCALS.mode)
+ %ldl(a1, bv)
+ %ldl(a2, mode)
%call(&write_to_bv)
- %ld(t0, sp, %WRITE_PAIR_TO_BV_LOCALS.pair)
+ %ldl(t0, pair)
%cdr(t0, t0)
- %st(t0, sp, %WRITE_PAIR_TO_BV_LOCALS.pair)
+ %stl(t0, pair)
%if_nil(t1, t0, &::done)
%tagof(t1, t0)
@@ -4270,29 +4240,29 @@
%beq(t1, t2, &::cont)
# Dotted tail: emit ` . ` then write_to_bv(cdr).
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 32)
%call(&bv_putc)
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 46)
%call(&bv_putc)
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 32)
%call(&bv_putc)
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.pair)
- %ld(a1, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
- %ld(a2, sp, %WRITE_PAIR_TO_BV_LOCALS.mode)
+ %ldl(a0, pair)
+ %ldl(a1, bv)
+ %ldl(a2, mode)
%call(&write_to_bv)
%b(&::done)
::cont
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 32)
%call(&bv_putc)
%b(&::loop)
::done
- %ld(a0, sp, %WRITE_PAIR_TO_BV_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 41)
%tail(&bv_putc)
})
@@ -4301,15 +4271,15 @@
# delegate to write_to_bv; helper for display / write. The 16-byte
# starting capacity is the floor from bv_capacity_for; bv_putn /
# bv_putc grow as needed.
-%struct VALUE_TO_BV_LOCALS { val mode } # .SIZE = 16
-%fn(value_to_bv, %VALUE_TO_BV_LOCALS.SIZE, {
- %st(a0, sp, %VALUE_TO_BV_LOCALS.val)
- %st(a1, sp, %VALUE_TO_BV_LOCALS.mode)
+
+%fn2(value_to_bv, {val mode}, {
+ %stl(a0, val)
+ %stl(a1, mode)
%li(a0, 0)
%call(&bv_alloc)
%mov(a1, a0)
- %ld(a0, sp, %VALUE_TO_BV_LOCALS.val)
- %ld(a2, sp, %VALUE_TO_BV_LOCALS.mode)
+ %ldl(a0, val)
+ %ldl(a2, mode)
%tail(&write_to_bv)
})
@@ -4348,54 +4318,53 @@
# the byte at `length` is the BSS-zero NUL terminator, making the bv's
# data_ptr a valid C string for panic's eprint_cstr.
#
-# Frame: 16 bytes
-# +0 walk (initially args; advances over irritants)
-# +8 bv
-%struct PRIM_ERROR_ENTRY_LOCALS { walk bv } # .SIZE = 16
-%fn(prim_error_entry, %PRIM_ERROR_ENTRY_LOCALS.SIZE, {
- %st(a0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+# Locals:
+# walk (initially args; advances over irritants)
+# bv
+%fn2(prim_error_entry, {walk bv}, {
+ %stl(a0, walk)
%li(a0, 0)
%call(&bv_alloc)
- %st(a0, sp, %PRIM_ERROR_ENTRY_LOCALS.bv)
+ %stl(a0, bv)
%la(a1, &str_error_prefix)
%li(a2, 16)
- %ld(a0, sp, %PRIM_ERROR_ENTRY_LOCALS.bv)
+ %ldl(a0, bv)
%call(&bv_putn)
# First arg (the message) goes through write_to_bv with display mode.
- %ld(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %ldl(t0, walk)
%car(a0, t0)
- %ld(a1, sp, %PRIM_ERROR_ENTRY_LOCALS.bv)
+ %ldl(a1, bv)
%li(a2, 0)
%call(&write_to_bv)
- %ld(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %ldl(t0, walk)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %stl(t0, walk)
::loop
- %ld(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %ldl(t0, walk)
%if_nil(t1, t0, &::done)
- %ld(a0, sp, %PRIM_ERROR_ENTRY_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, 32)
%call(&bv_putc)
- %ld(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %ldl(t0, walk)
%car(a0, t0)
- %ld(a1, sp, %PRIM_ERROR_ENTRY_LOCALS.bv)
+ %ldl(a1, bv)
%li(a2, 0)
%call(&write_to_bv)
- %ld(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %ldl(t0, walk)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.walk)
+ %stl(t0, walk)
%b(&::loop)
::done
- %ld(t0, sp, %PRIM_ERROR_ENTRY_LOCALS.bv)
+ %ldl(t0, bv)
%heap_ld(a0, t0, %BV.data)
%tail(&runtime_error)
})
@@ -4406,33 +4375,32 @@
# pass through verbatim. Returns the assembled bv; the caller decides
# how to consume it (e.g. (display (format ...))).
#
-# Frame: 32 bytes
-# +0 out bv
-# +8 template bv
-# +16 args walk
-# +24 idx (current byte offset into template)
-%struct PRIM_FORMAT_ENTRY_LOCALS { out template args idx } # .SIZE = 32
-%fn(prim_format_entry, %PRIM_FORMAT_ENTRY_LOCALS.SIZE, {
- %st(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args) ; spill incoming args while we set up
+# Locals:
+# out bv
+# template bv
+# args walk
+# idx (current byte offset into template)
+%fn2(prim_format_entry, {out template args idx}, {
+ %stl(a0, args) ; spill incoming args while we set up
%li(a0, 0)
%call(&bv_alloc)
- %st(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %stl(a0, out)
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%car(t1, t0)
- %st(t1, sp, %PRIM_FORMAT_ENTRY_LOCALS.template)
+ %stl(t1, template)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
+ %stl(t0, args)
%li(t0, 0)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %stl(t0, idx)
::loop
- %ld(t1, sp, %PRIM_FORMAT_ENTRY_LOCALS.template)
+ %ldl(t1, template)
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8) ; template length
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %ldl(t0, idx)
%beq(t0, t2, &::done)
%heap_ld(a3, t1, %BV.data)
@@ -4443,18 +4411,18 @@
%beqz(t1, &::tilde)
# Plain byte: emit and advance.
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%mov(a1, a3)
%call(&bv_putc)
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %ldl(t0, idx)
%addi(t0, t0, 1)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %stl(t0, idx)
%b(&::loop)
::tilde
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %ldl(t0, idx)
%addi(t0, t0, 1)
- %ld(t1, sp, %PRIM_FORMAT_ENTRY_LOCALS.template)
+ %ldl(t1, template)
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8)
%beq(t0, t2, &::tilde_lit)
@@ -4464,7 +4432,7 @@
%lb(a3, t1, 0) ; spec
%addi(t0, t0, 1) ; advance past spec
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %stl(t0, idx)
%addi(t1, a3, -97) ; 'a'
%beqz(t1, &::spec_a)
@@ -4479,73 +4447,73 @@
# Unknown directive: emit `~` then the spec byte verbatim. Re-read
# the spec byte from the template since bv_putc may clobber a3.
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%li(a1, 126)
%call(&bv_putc)
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.template)
+ %ldl(t0, template)
%heap_ld(t1, t0, %BV.data)
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %ldl(t0, idx)
%addi(t0, t0, -1)
%add(t1, t1, t0)
%lb(a1, t1, 0)
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%call(&bv_putc)
%b(&::loop)
::tilde_lit
# `~` at end of template: emit literal `~` and finish next iter.
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%li(a1, 126)
%call(&bv_putc)
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %ldl(t0, idx)
%addi(t0, t0, 1)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.idx)
+ %stl(t0, idx)
%b(&::loop)
::spec_a
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%car(a0, t0)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
- %ld(a1, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %stl(t0, args)
+ %ldl(a1, out)
%li(a2, 0)
%call(&write_to_bv)
%b(&::loop)
::spec_s
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%car(a0, t0)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
- %ld(a1, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %stl(t0, args)
+ %ldl(a1, out)
%li(a2, 1)
%call(&write_to_bv)
%b(&::loop)
::spec_d
- %ld(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
+ %ldl(t0, args)
%car(t1, t0)
%cdr(t0, t0)
- %st(t0, sp, %PRIM_FORMAT_ENTRY_LOCALS.args)
+ %stl(t0, args)
%sari(a1, t1, 3)
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%call(&bv_putint)
%b(&::loop)
::spec_pct
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%li(a1, 10)
%call(&bv_putc)
%b(&::loop)
::spec_tilde
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
%li(a1, 126)
%call(&bv_putc)
%b(&::loop)
::done
- %ld(a0, sp, %PRIM_FORMAT_ENTRY_LOCALS.out)
+ %ldl(a0, out)
})
# =========================================================================
@@ -4562,16 +4530,16 @@
# to syscalls expecting a C string.
# wrap_syscall_result(raw=a0) -> (#t . r) or (#f . errno).
-%struct WRAP_SYSCALL_RESULT_LOCALS { raw pad } # .SIZE = 16
-%fn(wrap_syscall_result, %WRAP_SYSCALL_RESULT_LOCALS.SIZE, {
- %st(a0, sp, %WRAP_SYSCALL_RESULT_LOCALS.raw)
+
+%fn2(wrap_syscall_result, {raw pad}, {
+ %stl(a0, raw)
%bltz(a0, &::err)
%shli(a1, a0, 3)
%li(a0, %imm_val(%IMM.TRUE))
%tail(&cons)
::err
- %ld(t0, sp, %WRAP_SYSCALL_RESULT_LOCALS.raw)
+ %ldl(t0, raw)
%li(t1, 0)
%sub(t0, t1, t0)
%shli(a1, t0, 3)
@@ -4592,9 +4560,9 @@
# sys_clone() -> r (a0). Linux clone(SIGCHLD, 0, 0, 0, 0) -- fork-style.
# Saves and restores s0 around the syscall because %p1_syscall reads s0
# as the 5th OS-syscall argument.
-%struct SYS_CLONE_LOCALS { saved_s0 pad } # .SIZE = 16
-%fn(sys_clone, %SYS_CLONE_LOCALS.SIZE, {
- %st(s0, sp, %SYS_CLONE_LOCALS.saved_s0)
+
+%fn2(sys_clone, {saved_s0 pad}, {
+ %stl(s0, saved_s0)
%li(s0, 0)
%li(a1, 17)
@@ -4604,7 +4572,7 @@
%li(a0, %p1_sys_clone)
%syscall
- %ld(s0, sp, %SYS_CLONE_LOCALS.saved_s0)
+ %ldl(s0, saved_s0)
})
# sys_execve(path=a0, argv=a1, envp=a2) -> -errno (a0). Only returns on
@@ -4631,23 +4599,22 @@
# Walks `list` (cons-list of bytevectors), allocates (count+1)*8 bytes,
# writes each bv's data_ptr, terminates with NULL.
#
-# Frame: 24 bytes
-# +0 list
-# +8 count
-# +16 array ptr (raw)
-%struct BUILD_EXECVE_ARGV_LOCALS { list count array } # .SIZE = 24
-%fn(build_execve_argv, %BUILD_EXECVE_ARGV_LOCALS.SIZE, {
- %st(a0, sp, %BUILD_EXECVE_ARGV_LOCALS.list)
+# Locals:
+# list
+# count
+# array ptr (raw)
+%fn2(build_execve_argv, {list count array}, {
+ %stl(a0, list)
%call(&list_length) ; clobbers a0 -> count
- %st(a0, sp, %BUILD_EXECVE_ARGV_LOCALS.count)
+ %stl(a0, count)
%addi(a0, a0, 1)
%shli(a0, a0, 3)
%call(&alloc_bytes)
- %st(a0, sp, %BUILD_EXECVE_ARGV_LOCALS.array)
+ %stl(a0, array)
- %ld(t0, sp, %BUILD_EXECVE_ARGV_LOCALS.list)
- %ld(t1, sp, %BUILD_EXECVE_ARGV_LOCALS.array)
+ %ldl(t0, list)
+ %ldl(t1, array)
::fill_loop
%if_nil(t2, t0, &::fill_done)
@@ -4662,7 +4629,7 @@
%li(t2, 0)
%st(t2, t1, 0)
- %ld(a0, sp, %BUILD_EXECVE_ARGV_LOCALS.array)
+ %ldl(a0, array)
})
# (sys-read fd buf count)
@@ -4719,13 +4686,13 @@
})
# (sys-execve path argv-list)
-%struct PRIM_SYS_EXECVE_ENTRY_LOCALS { path pad } # .SIZE = 16
-%fn(prim_sys_execve_entry, %PRIM_SYS_EXECVE_ENTRY_LOCALS.SIZE, {
+
+%fn2(prim_sys_execve_entry, {path pad}, {
%args2(t0, a0, a0) ; t0 = path bv, a0 = argv-list
- %st(t0, sp, %PRIM_SYS_EXECVE_ENTRY_LOCALS.path)
+ %stl(t0, path)
%call(&build_execve_argv)
%mov(a1, a0)
- %ld(a0, sp, %PRIM_SYS_EXECVE_ENTRY_LOCALS.path)
+ %ldl(a0, path)
%heap_ld(a0, a0, %BV.data) ; path data ptr
%li(a2, 0)
%call(&sys_execve)
@@ -4750,71 +4717,70 @@
# NUL-terminated entry into a fresh bytevector and consing them in order
# via the head/tail trick.
#
-# Frame: 40 bytes
-# +0 argv ptr (advancing 8 bytes per iteration)
-# +8 count remaining (decrementing from saved_argc)
-# +16 list head
-# +24 list tail
-# +32 current bv (across memcpy)
-%struct PRIM_SYS_ARGV_ENTRY_LOCALS { argv count head tail bv } # .SIZE = 40
-%fn(prim_sys_argv_entry, %PRIM_SYS_ARGV_ENTRY_LOCALS.SIZE, {
+# Locals:
+# argv ptr (advancing 8 bytes per iteration)
+# count remaining (decrementing from saved_argc)
+# head
+# tail
+# bv
+%fn2(prim_sys_argv_entry, {argv count head tail bv}, {
%ld_global(t0, &saved_argv)
- %st(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.argv)
+ %stl(t0, argv)
%ld_global(t0, &saved_argc)
- %st(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.count)
+ %stl(t0, count)
%li(t0, %imm_val(%IMM.NIL))
- %st(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.head)
- %st(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.tail)
+ %stl(t0, head)
+ %stl(t0, tail)
::loop
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.count)
+ %ldl(t0, count)
%beqz(t0, &::done)
# len = strlen(*argv)
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.argv)
+ %ldl(t0, argv)
%ld(a0, t0, 0)
%call(&strlen)
# bv = bv_alloc(len)
%call(&bv_alloc)
- %st(a0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.bv)
+ %stl(a0, bv)
# memcpy(bv.data_ptr, *argv, len-from-bv-hdr).
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.bv)
+ %ldl(t0, bv)
%heap_ld(a0, t0, %BV.data)
- %ld(t1, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.argv)
+ %ldl(t1, argv)
%ld(a1, t1, 0)
%heap_ld(t1, t0, %BV.hdr)
%shri(a2, t1, 8)
%call(&memcpy)
# cell = cons(bv, NIL); append to list head/tail.
- %ld(a0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.bv)
+ %ldl(a0, bv)
%li(a1, %imm_val(%IMM.NIL))
%call(&cons)
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.head)
+ %ldl(t0, head)
%if_nil(t1, t0, &::first)
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.tail)
+ %ldl(t0, tail)
%set_cdr(a0, t0)
- %st(a0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.tail)
+ %stl(a0, tail)
%b(&::advance)
::first
- %st(a0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.head)
- %st(a0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.tail)
+ %stl(a0, head)
+ %stl(a0, tail)
::advance
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.argv)
+ %ldl(t0, argv)
%addi(t0, t0, 8)
- %st(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.argv)
- %ld(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.count)
+ %stl(t0, argv)
+ %ldl(t0, count)
%addi(t0, t0, -1)
- %st(t0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.count)
+ %stl(t0, count)
%b(&::loop)
::done
- %ld(a0, sp, %PRIM_SYS_ARGV_ENTRY_LOCALS.head)
+ %ldl(a0, head)
})
# (eof-object) and (eof-object? x).
@@ -5026,31 +4992,9 @@
:name_ch_newline "newline"
# =========================================================================
-# Startup -- bss_init / heap_init
+# Startup -- heap_init
# =========================================================================
-# bss_init() -> none. Walks bss_init_tbl once and writes &ELF_end + OFF_*
-# into each pointer slot. Same idiom as M1pp.P1: a tiny init table walked
-# once. Leaf.
-:bss_init
-%scope bss_init
- %la(t0, &ELF_end)
- %la(t1, &bss_init_tbl)
- %la(t2, &bss_init_tbl_end)
-
- ::loop
- %beq(t1, t2, &::done)
- %ld(a0, t1, 0)
- %ld(a2, t1, 8)
- %add(a2, a2, t0)
- %st(a2, a0, 0)
- %addi(t1, t1, 16)
- %b(&::loop)
- ::done
-
- %ret
-%endscope
-
# heap_init() -> none. Sets heap_next (&heap_buf rounded up to 8-byte
# alignment) and heap_end (heap_buf + HEAP_CAP_BYTES). cons assumes
# 8-byte-aligned heap_next so every pair pointer's low 3 bits are exactly
@@ -5070,16 +5014,17 @@
%ret
# =========================================================================
-# BSS pointer-init table
+# BSS arena table
# =========================================================================
#
-# Each entry: 8-byte slot pointer (4-byte label ref + 4 bytes pad) +
-# 8-byte offset constant. p1_main walks this once at startup.
-:bss_init_tbl
-&readbuf_buf_ptr %(0) $(0)
-&heap_buf_ptr %(0) $(%READBUF_CAP_BYTES)
-&symtab_buf_ptr %(0) $((+ %READBUF_CAP_BYTES %HEAP_CAP_BYTES))
-:bss_init_tbl_end
+# (slot, size) rows for libp1pp's init_arenas, walked once at startup.
+# init_arenas threads a running offset, so each arena starts where the
+# previous one ended.
+:arena_table
+%arena_entry(&readbuf_buf_ptr, %READBUF_CAP_BYTES)
+%arena_entry(&heap_buf_ptr, %HEAP_CAP_BYTES)
+%arena_entry(&symtab_buf_ptr, (* %SYMTAB_CAP_SLOTS %SYMENT.SIZE))
+:arena_table_end
# =========================================================================
# Scalar BSS (file-resident, zero-initialized)