commit 600fbdc515633243f8e9ef9b04f9c84ff07af210
parent e77067e3f9ee54059d2c6e972d3265b0088f0cc9
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 3 May 2026 18:08:38 -0700
Update scheme1 for M1pp hex2pp pipeline
Diffstat:
4 files changed, 1192 insertions(+), 1140 deletions(-)
diff --git a/docs/DEBUG.md b/docs/DEBUG.md
@@ -1,6 +1,6 @@
# DEBUG
-Debugging facilities for the cc / P1pp / M1 / hex2 pipeline. Each
+Debugging facilities for the cc / P1pp / M1pp / hex2pp pipeline. Each
section: what the tool does, how to turn it on, what you get back.
## Tracepoints (`%trace` / `--cc-trace-emit`)
@@ -36,7 +36,7 @@ Cost: register save/restore traffic plus one call per traced function.
Off by default; the `%trace` macro itself lives in
[P1/P1pp.P1pp](../P1/P1pp.P1pp) (§Tracepoint) and can also be invoked
manually — drop a `%trace(&label, len)` into any `combined.M1pp`
-snapshot under `build/$ARCH/.work/<src>/`, re-run the m1pp/M0/hex2
+snapshot under `build/$ARCH/.work/<src>/`, re-run the M1pp/hex2pp
stages, and bisect by stderr position. `%trace` preserves the exposed
P1 registers (`a0..a3`, `t0..t2`, `s0..s3`) by borrowing temporary
stack space, so it is safe to add inside an active `%fn` body after
@@ -48,14 +48,14 @@ To map an address back to its function, see the lookup tool below.
## Address → label lookup (`m1-symbols.py lookup`)
Resolves a runtime address (e.g. from a `%trace` line) to its
-enclosing function. Reads the label map straight out of `prog.hex2`
-and finds the largest label address `<= target`, skipping M1pp's
-mangled macro-locals (`:@name` → `:name__N`) so a trace address
+enclosing function. Reads the label map straight out of `expanded.hex2pp`
+(or legacy `prog.hex2`) and finds the largest label address `<= target`,
+skipping M1pp's mangled macro-locals (`:@name` → `:name__N`) so a trace address
resolves to the *function* containing it, not the trace's own
`:@here`.
```sh
-# Pass the ELF; the tool reads <ELF>.workdir to find prog.hex2.
+# Pass the ELF; the tool reads <ELF>.workdir to find expanded.hex2pp.
scripts/m1-symbols.py lookup --elf build/aarch64/tests/cc/007-call-with-args 0x6019fc 0x6018fc
# 0x6019fc main+0x24
# 0x6018fc g+0x2c
@@ -66,8 +66,9 @@ scripts/m1-symbols.py lookup --elf build/aarch64/tests/cc/007-call-with-args 0x6
| scripts/m1-symbols.py lookup --elf build/aarch64/tests/cc/007-call-with-args
```
-Other input modes: `--hex2 <prog.hex2>` (skip the sidecar lookup) or
-`--map <file>` (use a pre-built map from `m1-symbols.py map`). Pass
+Other input modes: `--hex2 <expanded.hex2pp|prog.hex2>` (skip the
+sidecar lookup) or `--map <file>` (use a pre-built map from
+`m1-symbols.py map`). Pass
`--include-macro-locals` to see the closest label even when it's a
`name__N` artifact — useful when you want to know which trace site
fired vs. which function it sits in.
@@ -78,7 +79,8 @@ Output is `0xADDR\tLABEL+0xN`, tab-separated, one per line.
llvm-objdump wrapper that handles two quirks of our seed ELF: oversized
ph_memsz (truncated to ph_filesz on a temp copy) and the absent section
-table (replaced by labels injected from `prog.hex2`). The output has
+table (replaced by labels injected from `expanded.hex2pp`, or legacy
+`prog.hex2`). The output has
real `<funcname>:` headers and `<PT_LOAD#0+0xNNN>` xrefs rewritten to
`<label+offset>`:
@@ -119,22 +121,23 @@ Every P1pp/P1 build leaves its intermediates next to the ELF:
```
build/$ARCH/.work/<src-path>/
combined.M1pp # backend + frontend + libp1pp + user TU, catm'd
- expanded.M1 # m1pp output, ready for M0
- prog.hex2 # M0 output (hex2 with labels)
- linked.hex2 # ELF header + prog.hex2
+ expanded.hex2pp # M1pp output, ready for hex2pp
+ linked.hex2pp # ELF header + expanded.hex2pp
cc.log # cc.scm stderr (if --cc-debug or trace-emit)
- p1pp.log # m1pp/M0/hex2 stderr
+ p1pp.log # M1pp/hex2pp stderr
```
Each ELF also gets a one-line `<elf>.workdir` sidecar pointing at this
directory — that's how `disasm-elf.sh` and `m1-symbols.py lookup
---elf` find `prog.hex2`. On a failing build the runner prints the
+--elf` find `expanded.hex2pp` (or legacy `prog.hex2` for raw-P1
+builds). On a failing build the runner prints the
partial-intermediates path; on a passing build the files stay around
for inspection.
To re-run a single intermediate stage by hand: edit the file in place
-and invoke the next tool directly (`build/$ARCH/tools/M0
-prog.hex2.M0`, etc.). Useful for poking `%trace` calls into
+and invoke the next tool directly (`build/$ARCH/M1pp/M1pp
+combined.M1pp expanded.hex2pp`, then `build/$ARCH/hex2pp/hex2pp
+-B 0x600000 linked.hex2pp out`). Useful for poking `%trace` calls into
`combined.M1pp` without recompiling cc.scm.
## End-to-end debugging recipe
diff --git a/scheme1/scheme1.P1pp b/scheme1/scheme1.P1pp
@@ -2,7 +2,7 @@
#
# Build chain:
# catm P1-<arch>.M1pp P1.M1pp P1pp.P1pp scheme1/scheme1.P1pp \
-# | m1pp -> M0 -> hex2 -> ELF
+# | m1pp -> hex2pp -> ELF
#
# Run chain:
# catm scheme1/prelude.scm prog.scm | scheme1
@@ -148,19 +148,11 @@
%call(&runtime_error)
%endm
-# Intern a special-form name and stash the tagged-symbol value in a
-# labeled slot. `name` and `slot` are written as full label refs
-# (`&foo`) so the macro can substitute them verbatim into %la sites.
-# Pad the string `str` (including its M1 auto-null) to an 8-byte boundary.
-# Uses quoted-literal hex form required by riscv64 stage0 M0.
-%macro align8_pad(str)
- %select((= (% (+ (strlen str) 1) 8) 0), ,
- %select((= (% (+ (strlen str) 1) 8) 1), '00000000000000',
- %select((= (% (+ (strlen str) 1) 8) 2), '000000000000',
- %select((= (% (+ (strlen str) 1) 8) 3), '0000000000',
- %select((= (% (+ (strlen str) 1) 8) 4), '00000000',
- %select((= (% (+ (strlen str) 1) 8) 5), '000000',
- %select((= (% (+ (strlen str) 1) 8) 6), '0000', '00')))))))
+# Emit an 8-aligned NUL-terminated string.
+%macro cstr8(str)
+ str
+ 00
+ .align 8
%endm
# Intern `str` into `slot` and declare its padded string data inline.
@@ -172,8 +164,7 @@
%st_global(a0, slot, t0)
%b(&@end)
:name_ ## key
- str
- %align8_pad(str)
+ %cstr8(str)
:@end
%endm
@@ -268,7 +259,7 @@
# if argc < 2 goto usage
%li(t0, 2)
- %bltu(a0, t0, &::usage)
+ %bltu(a0, t0, &.usage)
# Initialize
%la(a0, &ELF_end)
@@ -286,11 +277,11 @@
%call(&load_source)
# read-eval loop
- %loop_tag(eval, {
+ %loop_scoped({
# eof = skip_ws()
%call(&skip_ws)
# if eof break
- %bnez(a0, &::eval_end)
+ %if_nez(a0, { %break })
# expr = parse_one()
%call(&parse_one)
# eval(expr, env=nil)
@@ -302,7 +293,7 @@
%li(a0, 0)
%eret
- ::usage
+ :.usage
%la(a0, &msg_usage)
%call(&print_cstr)
%li(a0, 2)
@@ -320,103 +311,103 @@
# a0 = 1 if readbuf_pos >= readbuf_len after skipping (caller hit EOF),
# else 0. Leaf.
:skip_ws
-%scope skip_ws
+.scope
%lda_global(t0, t2, &readbuf_pos)
%ld_global(t1, &readbuf_len)
- ::loop
- %beq(t0, t1, &::done)
+ :.loop
+ %beq(t0, t1, &.done)
%readbuf_byte(a0, t0)
- %is_ws_branch(a1, a0, &::step)
- %bceq(a0, -59, &::comment, a1) ; ';'
- %b(&::done)
- ::comment
+ %is_ws_branch(a1, a0, &.step)
+ %bceq(a0, -59, &.comment, a1) ; ';'
+ %b(&.done)
+ :.comment
# Consume up to and including the next LF, or to EOF.
%addi(t0, t0, 1)
- %beq(t0, t1, &::done)
+ %beq(t0, t1, &.done)
%readbuf_byte(a0, t0)
- %bcne(a0, -10, &::comment, a1) ; LF
- ::step
+ %bcne(a0, -10, &.comment, a1) ; LF
+ :.step
%addi(t0, t0, 1)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%st(t0, t2, 0)
%li(a0, 1)
- %beq(t0, t1, &::ret)
+ %beq(t0, t1, &.ret)
%li(a0, 0)
- ::ret
+ :.ret
%ret
-%endscope
+.endscope
# parse_one() -> tagged value in a0
%fn(parse_one, 0, {
%call(&skip_ws)
- %bnez(a0, &::eof)
+ %bnez(a0, &.eof)
%ld_global(t0, &readbuf_pos)
%readbuf_byte(a0, t0)
- %bceq(a0, -40, &::lparen, a1)
- %bceq(a0, -41, &::rparen, a1)
- %bceq(a0, -35, &::hash, a1)
- %bceq(a0, -39, &::quote, a1)
- %bceq(a0, -44, &::comma, a1)
- %bceq(a0, -34, &::string, a1)
+ %bceq(a0, -40, &.lparen, a1)
+ %bceq(a0, -41, &.rparen, a1)
+ %bceq(a0, -35, &.hash, a1)
+ %bceq(a0, -39, &.quote, a1)
+ %bceq(a0, -44, &.comma, a1)
+ %bceq(a0, -34, &.string, a1)
%tail(&parse_atom)
- ::lparen
+ :.lparen
# Consume '(' and read items until ')'.
%lda_global(t1, t0, &readbuf_pos)
%readbuf_advance(t1, t0)
%tail(&parse_list)
- ::rparen
+ :.rparen
%die(msg_unexp_rparen)
- ::string
+ :.string
# Consume opening '"' and tail to parse_string. parse_string scans
# through the matching '"' (consuming it) and returns a tagged bv.
%lda_global(t1, t0, &readbuf_pos)
%readbuf_advance(t1, t0)
%tail(&parse_string)
- ::hash
+ :.hash
# Consume '#' plus its type byte; dispatch on the type byte.
%lda_global(t0, t2, &readbuf_pos)
%addi(t0, t0, 1)
- %readbuf_at_eof(t0, t1, &::eof)
+ %readbuf_at_eof(t0, t1, &.eof)
%readbuf_byte(a0, t0)
%readbuf_advance(t0, t2)
- %bceq(a0, -116, &::true_lit, a1) ; 't'
- %bceq(a0, -102, &::false_lit, a1) ; 'f'
- %bceq(a0, -120, &::hex_lit, a1) ; 'x'
- %bceq(a0, -88, &::hex_lit, a1) ; 'X'
- %bceq(a0, -92, &::char_lit, a1) ; '\\'
- %bceq(a0, -117, &::u8_lit, a1) ; 'u'
+ %bceq(a0, -116, &.true_lit, a1) ; 't'
+ %bceq(a0, -102, &.false_lit, a1) ; 'f'
+ %bceq(a0, -120, &.hex_lit, a1) ; 'x'
+ %bceq(a0, -88, &.hex_lit, a1) ; 'X'
+ %bceq(a0, -92, &.char_lit, a1) ; '\\'
+ %bceq(a0, -117, &.u8_lit, a1) ; 'u'
%die(msg_bad_hash)
- ::true_lit
+ :.true_lit
%li(a0, %imm_val(%IMM.TRUE))
%eret
- ::false_lit
+ :.false_lit
%li(a0, %imm_val(%IMM.FALSE))
%eret
- ::hex_lit
+ :.hex_lit
# t0 sits at the first hex digit; t1 = readbuf_len. Scan to ws/paren/EOF,
# then parse_hex over the slice (with optional leading '-').
%mov(a3, t0)
- ::hex_scan
- %beq(t0, t1, &::hex_end)
+ :.hex_scan
+ %beq(t0, t1, &.hex_end)
%readbuf_byte(a0, t0)
- %is_ws_branch(a1, a0, &::hex_end)
- %bceq(a0, -40, &::hex_end, a1)
- %bceq(a0, -41, &::hex_end, a1)
+ %is_ws_branch(a1, a0, &.hex_end)
+ %bceq(a0, -40, &.hex_end, a1)
+ %bceq(a0, -41, &.hex_end, a1)
%addi(t0, t0, 1)
- %b(&::hex_scan)
- ::hex_end
+ %b(&.hex_scan)
+ :.hex_end
%st_global(t0, &readbuf_pos, t2)
%ld_global(a0, &readbuf_buf_ptr)
@@ -424,11 +415,11 @@
%sub(a1, t0, a3)
%lb(t2, a0, 0)
%addi(t2, t2, -45) ; '-'
- %beqz(t2, &::hex_neg)
+ %beqz(t2, &.hex_neg)
%call(&parse_hex)
%mkfix(a0, a0)
%eret
- ::hex_neg
+ :.hex_neg
%addi(a0, a0, 1)
%addi(a1, a1, -1)
%call(&parse_hex)
@@ -437,7 +428,7 @@
%mkfix(a0, a0)
%eret
- ::quote
+ :.quote
# Consume the leading '\''; recurse into parse_one for the datum;
# then build (quote <datum>).
%lda_global(t0, t2, &readbuf_pos)
@@ -450,7 +441,7 @@
%mov(a0, t0)
%tail(&cons)
- ::comma
+ :.comma
# Consume the leading ','; recurse into parse_one for the datum;
# build (unquote <datum>). The comma sugar exists so pmatch
# patterns can be written as `,ident`. Outside pmatch
@@ -466,29 +457,29 @@
%mov(a0, t0)
%tail(&cons)
- ::char_lit
+ :.char_lit
# Cursor is already past '#\\'; parse_char scans the body and returns
# a tagged fixnum (the u8 char value).
%tail(&parse_char)
- ::u8_lit
+ :.u8_lit
# Cursor is past '#u'. Demand '8' then '('; consume both and tail to
# parse_u8_body, which reads the element list and packs it into a bv.
%lda_global(t0, t2, &readbuf_pos)
- %readbuf_at_eof(t0, t1, &::u8_bad)
+ %readbuf_at_eof(t0, t1, &.u8_bad)
%readbuf_byte(a0, t0)
- %bcne(a0, -56, &::u8_bad, a1) ; '8'
+ %bcne(a0, -56, &.u8_bad, a1) ; '8'
%addi(t0, t0, 1)
- %beq(t0, t1, &::u8_bad)
+ %beq(t0, t1, &.u8_bad)
%readbuf_byte(a0, t0)
- %bcne(a0, -40, &::u8_bad, a1) ; '('
+ %bcne(a0, -40, &.u8_bad, a1) ; '('
%readbuf_advance(t0, t2)
%tail(&parse_u8_body)
- ::u8_bad
+ :.u8_bad
%die(msg_bad_hash)
- ::eof
+ :.eof
%die(msg_unexp_eof)
})
@@ -503,25 +494,25 @@
%stl(t0, head)
%stl(t0, tail)
- ::loop
+ :.loop
%call(&skip_ws)
- %bnez(a0, &::eof)
+ %bnez(a0, &.eof)
%ld_global(t0, &readbuf_pos)
%ld_global(t1, &readbuf_len)
%readbuf_byte(a0, t0)
- %bceq(a0, -41, &::close, a1)
+ %bceq(a0, -41, &.close, a1)
# Dotted-pair separator: '.' followed by ws/paren/EOF (otherwise the
# '.' is part of an identifier and parse_atom handles it).
- %bcne(a0, -46, &::not_dot, a1) ; '.'
+ %bcne(a0, -46, &.not_dot, a1) ; '.'
%addi(a2, t0, 1)
- %beq(a2, t1, &::do_dot)
+ %beq(a2, t1, &.do_dot)
%readbuf_byte(a3, a2)
- %is_ws_branch(a1, a3, &::do_dot)
- %bceq(a3, -40, &::do_dot, a1)
- %bceq(a3, -41, &::do_dot, a1)
- ::not_dot
+ %is_ws_branch(a1, a3, &.do_dot)
+ %bceq(a3, -40, &.do_dot, a1)
+ %bceq(a3, -41, &.do_dot, a1)
+ :.not_dot
# Not ')': parse one item, append.
%call(&parse_one)
@@ -530,19 +521,19 @@
# If head is NIL, both head and tail = new cons; else set-cdr! tail = new.
%ldl(t0, head)
- %bine(t0, %imm_val(%IMM.NIL), &::link, t1)
+ %bine(t0, %imm_val(%IMM.NIL), &.link, t1)
%stl(a0, head)
%stl(a0, tail)
- %b(&::loop)
+ %b(&.loop)
- ::link
+ :.link
%ldl(t0, tail)
# set-cdr! tail = a0 -> store a0 at [tail + 7] (raw + 8)
%set_cdr(a0, t0)
%stl(a0, tail)
- %b(&::loop)
+ %b(&.loop)
- ::do_dot
+ :.do_dot
# Consume the '.', read one datum, splice it in as the cdr of the
# tail cons. Then expect a closing ')' (with optional ws).
%lda_global(t0, t1, &readbuf_pos)
@@ -551,22 +542,22 @@
%ldl(t0, tail)
%set_cdr(a0, t0)
%call(&skip_ws)
- %bnez(a0, &::eof)
+ %bnez(a0, &.eof)
%lda_global(t0, t1, &readbuf_pos)
%readbuf_byte(a0, t0)
- %bcne(a0, -41, &::eof, a1) ; ')'
+ %bcne(a0, -41, &.eof, a1) ; ')'
%readbuf_advance(t0, t1)
%ldl(a0, head)
%eret
- ::close
+ :.close
# Consume ')' and return head.
%lda_global(t1, t0, &readbuf_pos)
%readbuf_advance(t1, t0)
%ldl(a0, head)
%eret
- ::eof
+ :.eof
%die(msg_unterm_list)
})
@@ -589,15 +580,15 @@
%heap_ld(t0, a0, %BV.data)
%ldl(a0, list) ; list cursor
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%untag_fix(t1, t1)
%sb(t1, t0, 0)
%addi(t0, t0, 1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%ldl(a0, result)
})
@@ -606,37 +597,37 @@
# digits, and the extended chars ! $ % & * + - . / : < = > ? @ ^ _ ~ .
# Clobbers t0, t1, a1.
:is_ident_byte
-%scope is_ident_byte
- %brange(a0, -48, 10, t0, t1, &::ok) ; '0'..'9'
- %brange(a0, -65, 26, t0, t1, &::ok) ; 'A'..'Z'
- %brange(a0, -97, 26, t0, t1, &::ok) ; 'a'..'z'
-
- %bceq(a0, -33, &::ok, t0) ; '!'
- %bceq(a0, -36, &::ok, t0) ; '$'
- %bceq(a0, -37, &::ok, t0) ; '%'
- %bceq(a0, -38, &::ok, t0) ; '&'
- %bceq(a0, -42, &::ok, t0) ; '*'
- %bceq(a0, -43, &::ok, t0) ; '+'
- %bceq(a0, -45, &::ok, t0) ; '-'
- %bceq(a0, -46, &::ok, t0) ; '.'
- %bceq(a0, -47, &::ok, t0) ; '/'
- %bceq(a0, -58, &::ok, t0) ; ':'
- %bceq(a0, -60, &::ok, t0) ; '<'
- %bceq(a0, -61, &::ok, t0) ; '='
- %bceq(a0, -62, &::ok, t0) ; '>'
- %bceq(a0, -63, &::ok, t0) ; '?'
- %bceq(a0, -64, &::ok, t0) ; '@'
- %bceq(a0, -94, &::ok, t0) ; '^'
- %bceq(a0, -95, &::ok, t0) ; '_'
- %bceq(a0, -126, &::ok, t0) ; '~'
+.scope
+ %brange(a0, -48, 10, t0, t1, &.ok) ; '0'..'9'
+ %brange(a0, -65, 26, t0, t1, &.ok) ; 'A'..'Z'
+ %brange(a0, -97, 26, t0, t1, &.ok) ; 'a'..'z'
+
+ %bceq(a0, -33, &.ok, t0) ; '!'
+ %bceq(a0, -36, &.ok, t0) ; '$'
+ %bceq(a0, -37, &.ok, t0) ; '%'
+ %bceq(a0, -38, &.ok, t0) ; '&'
+ %bceq(a0, -42, &.ok, t0) ; '*'
+ %bceq(a0, -43, &.ok, t0) ; '+'
+ %bceq(a0, -45, &.ok, t0) ; '-'
+ %bceq(a0, -46, &.ok, t0) ; '.'
+ %bceq(a0, -47, &.ok, t0) ; '/'
+ %bceq(a0, -58, &.ok, t0) ; ':'
+ %bceq(a0, -60, &.ok, t0) ; '<'
+ %bceq(a0, -61, &.ok, t0) ; '='
+ %bceq(a0, -62, &.ok, t0) ; '>'
+ %bceq(a0, -63, &.ok, t0) ; '?'
+ %bceq(a0, -64, &.ok, t0) ; '@'
+ %bceq(a0, -94, &.ok, t0) ; '^'
+ %bceq(a0, -95, &.ok, t0) ; '_'
+ %bceq(a0, -126, &.ok, t0) ; '~'
%li(a1, 0)
%ret
- ::ok
+ :.ok
%li(a1, 1)
%ret
-%endscope
+.endscope
# parse_atom() -> tagged value (fixnum or symbol) in a0.
# Reads until whitespace or paren or EOF, then dispatches by first byte.
@@ -654,18 +645,18 @@
%ld_global(t2, &readbuf_len)
- ::scan
- %beq(t1, t2, &::end)
+ :.scan
+ %beq(t1, t2, &.end)
%readbuf_byte(a0, t1)
- %is_ws_branch(a1, a0, &::end)
- %bceq(a0, -40, &::end, a1) ; '('
- %bceq(a0, -41, &::end, a1) ; ')'
+ %is_ws_branch(a1, a0, &.end)
+ %bceq(a0, -40, &.end, a1) ; '('
+ %bceq(a0, -41, &.end, a1) ; ')'
%addi(t1, t1, 1)
- %b(&::scan)
+ %b(&.scan)
- ::end
+ :.end
%stl(t1, end)
%st(t1, t0, 0)
@@ -678,41 +669,41 @@
# '0'..'9' -> int
%addi(a1, t1, -48)
%li(a2, 10)
- %bltu(a1, a2, &::is_int)
+ %bltu(a1, a2, &.is_int)
# '-' or '+' followed by digit -> int. A lone '+' or '-' falls
# through to is_sym (those tokens stay valid identifiers).
- %bceq(t1, -45, &::sign, a1) ; '-'
- %bceq(t1, -43, &::sign, a1) ; '+'
- %b(&::is_sym)
- ::sign
+ %bceq(t1, -45, &.sign, a1) ; '-'
+ %bceq(t1, -43, &.sign, a1) ; '+'
+ %b(&.is_sym)
+ :.sign
%ldl(t2, end)
%addi(t0, t0, 1)
- %beq(t0, t2, &::is_sym)
+ %beq(t0, t2, &.is_sym)
%readbuf_byte(a0, t0)
%addi(a1, a0, -48)
- %bltu(a1, a2, &::is_int)
+ %bltu(a1, a2, &.is_int)
# fall through to is_sym
- ::is_sym
+ :.is_sym
# Validate every byte; abort on the first non-ident byte.
%ldl(t0, start)
%stl(t0, cursor)
- ::sym_loop
+ :.sym_loop
%ldl(t0, cursor)
%ldl(t1, end)
- %beq(t0, t1, &::sym_intern)
+ %beq(t0, t1, &.sym_intern)
%readbuf_byte(a0, t0)
%call(&is_ident_byte)
- %beqz(a1, &::sym_bad)
+ %beqz(a1, &.sym_bad)
%ldl(t0, cursor)
%addi(t0, t0, 1)
%stl(t0, cursor)
- %b(&::sym_loop)
+ %b(&.sym_loop)
- ::sym_bad
+ :.sym_bad
%die(msg_bad_ident)
- ::sym_intern
+ :.sym_intern
%ldl(a0, start)
%ld_global(t0, &readbuf_buf_ptr)
%add(a0, t0, a0)
@@ -721,7 +712,7 @@
%sub(a1, t1, t2)
%tail(&intern)
- ::is_int
+ :.is_int
%ldl(t0, start)
%ldl(t1, end)
%ld_global(a0, &readbuf_buf_ptr)
@@ -729,17 +720,17 @@
%sub(a1, t1, t0) ; len = end - start
# P1pp's parse_dec handles '-' but not '+'; strip '+' here.
%lb(t2, a0, 0)
- %bcne(t2, -43, &::no_plus, t2) ; '+'
+ %bcne(t2, -43, &.no_plus, t2) ; '+'
%addi(a0, a0, 1)
%addi(a1, a1, -1)
- ::no_plus
+ :.no_plus
%stl(a1, cursor) ; save adjusted len (cursor slot is free on int path)
%call(&parse_dec) ; P1pp: -> (raw_val=a0, consumed=a1)
%ldl(t0, cursor)
- %bne(a1, t0, &::int_bad) ; partial parse -> bad
+ %bne(a1, t0, &.int_bad) ; partial parse -> bad
%mkfix(a0, a0)
%eret
- ::int_bad
+ :.int_bad
%die(msg_bad_number)
})
@@ -762,43 +753,43 @@
%ld_global(t2, &readbuf_len)
%li(a0, 0)
- ::scan
- %beq(t1, t2, &::eof)
+ :.scan
+ %beq(t1, t2, &.eof)
%readbuf_byte(a3, t1)
- %bceq(a3, -34, &::scan_done, a1) ; '"'
- %bceq(a3, -92, &::scan_esc, a1) ; '\\'
+ %bceq(a3, -34, &.scan_done, a1) ; '"'
+ %bceq(a3, -92, &.scan_esc, a1) ; '\\'
%addi(t1, t1, 1)
%addi(a0, a0, 1)
- %b(&::scan)
+ %b(&.scan)
- ::scan_esc
+ :.scan_esc
# Backslash plus the next byte yield one decoded byte. \xHEX; runs
# until the terminating ';' (validated in pass 2); every other escape
# is exactly two source bytes.
%addi(t1, t1, 1)
- %beq(t1, t2, &::eof)
+ %beq(t1, t2, &.eof)
%readbuf_byte(a3, t1)
- %bceq(a3, -120, &::scan_hex, a1) ; 'x'
+ %bceq(a3, -120, &.scan_hex, a1) ; 'x'
%addi(t1, t1, 1)
%addi(a0, a0, 1)
- %b(&::scan)
+ %b(&.scan)
- ::scan_hex
+ :.scan_hex
# Skip past 'x' and scan to the terminating ';'. EOF before ';'
# falls into the unterminated-string path below, matching how an
# unterminated body is reported.
%addi(t1, t1, 1)
- ::scan_hex_loop
- %beq(t1, t2, &::eof)
+ :.scan_hex_loop
+ %beq(t1, t2, &.eof)
%readbuf_byte(a3, t1)
- %bceq(a3, -59, &::scan_hex_done, a1) ; ';'
+ %bceq(a3, -59, &.scan_hex_done, a1) ; ';'
%addi(t1, t1, 1)
- %b(&::scan_hex_loop)
- ::scan_hex_done
+ %b(&.scan_hex_loop)
+ :.scan_hex_done
%addi(t1, t1, 1) ; consume ';'
%addi(a0, a0, 1) ; +1 output byte
- %b(&::scan)
- ::scan_done
+ %b(&.scan)
+ :.scan_done
%stl(t1, end)
%call(&str_alloc)
@@ -809,41 +800,41 @@
%ldl(t2, end)
%heap_ld(a3, a0, %BV.data)
- ::fill
- %beq(t1, t2, &::fill_done)
+ :.fill
+ %beq(t1, t2, &.fill_done)
%readbuf_byte(a1, t1)
- %bceq(a1, -92, &::fill_esc, a2) ; '\\'
+ %bceq(a1, -92, &.fill_esc, a2) ; '\\'
%sb(a1, a3, 0)
%addi(a3, a3, 1)
%addi(t1, t1, 1)
- %b(&::fill)
+ %b(&.fill)
- ::fill_esc
+ :.fill_esc
%addi(t1, t1, 1) ; consume backslash
%readbuf_byte(a1, t1)
- %bceq(a1, -110, &::esc_n, a2) ; 'n'
- %bceq(a1, -116, &::esc_t, a2) ; 't'
- %bceq(a1, -114, &::esc_r, a2) ; 'r'
- %bceq(a1, -92, &::write_byte, a2) ; '\\'
- %bceq(a1, -34, &::write_byte, a2) ; '"'
- %bceq(a1, -120, &::esc_hex, a2) ; 'x'
+ %bceq(a1, -110, &.esc_n, a2) ; 'n'
+ %bceq(a1, -116, &.esc_t, a2) ; 't'
+ %bceq(a1, -114, &.esc_r, a2) ; 'r'
+ %bceq(a1, -92, &.write_byte, a2) ; '\\'
+ %bceq(a1, -34, &.write_byte, a2) ; '"'
+ %bceq(a1, -120, &.esc_hex, a2) ; 'x'
%die(msg_bad_escape)
- ::esc_n
+ :.esc_n
%li(a1, 10)
- %b(&::write_byte)
- ::esc_t
+ %b(&.write_byte)
+ :.esc_t
%li(a1, 9)
- %b(&::write_byte)
- ::esc_r
+ %b(&.write_byte)
+ :.esc_r
%li(a1, 13)
- ::write_byte
+ :.write_byte
%sb(a1, a3, 0)
%addi(a3, a3, 1)
%addi(t1, t1, 1)
- %b(&::fill)
+ %b(&.fill)
- ::esc_hex
+ :.esc_hex
# Skip past 'x'. parse_hex consumes hex digits; demand at least one,
# value <= 255, and an immediate ';' terminator. parse_hex clobbers
# t0/t1/t2 and a2/a3, so spill the cursor (t1) and write ptr (a3)
@@ -855,31 +846,31 @@
%add(a0, t0, t1) ; ptr to first hex digit
%sub(a1, t2, t1) ; max len (bytes left in body)
%call(&parse_hex) ; -> (a0=value, a1=consumed)
- %beqz(a1, &::hex_bad)
+ %beqz(a1, &.hex_bad)
%li(t0, 255)
- %bltu(t0, a0, &::hex_bad)
+ %bltu(t0, a0, &.hex_bad)
%ldl(t1, start)
%add(t1, t1, a1) ; t1 = position of expected ';'
%ldl(t2, end)
- %beq(t1, t2, &::hex_bad)
+ %beq(t1, t2, &.hex_bad)
%readbuf_byte(t0, t1)
- %bcne(t0, -59, &::hex_bad, t0) ; ';'
+ %bcne(t0, -59, &.hex_bad, t0) ; ';'
%addi(t1, t1, 1) ; consume ';'
%ldl(a3, spill)
%sb(a0, a3, 0)
%addi(a3, a3, 1)
- %b(&::fill)
+ %b(&.fill)
- ::hex_bad
+ :.hex_bad
%die(msg_bad_escape)
- ::fill_done
+ :.fill_done
%addi(t1, t1, 1) ; consume closing '"'
%st_global(t1, &readbuf_pos, t0)
%ldl(a0, bv)
%eret
- ::eof
+ :.eof
%die(msg_unterm_string)
})
@@ -891,7 +882,7 @@
%la(a1, name_label)
%li(a2, len)
%call(&memcmp)
- %bnez(a0, &::bad)
+ %bnez(a0, &.bad)
%li(a0, value)
%mkfix(a0, a0)
%eret
@@ -912,22 +903,22 @@
%ld_global(t2, &readbuf_len)
- %beq(t1, t2, &::short)
+ %beq(t1, t2, &.short)
# Always consume the first byte unconditionally — it might itself be
# a delimiter (e.g., '(' in `#\(`) and is still the character value.
%addi(t1, t1, 1)
- ::scan
- %beq(t1, t2, &::scan_done)
+ :.scan
+ %beq(t1, t2, &.scan_done)
%readbuf_byte(a0, t1)
- %is_ws_branch(a1, a0, &::scan_done)
- %bceq(a0, -40, &::scan_done, a1) ; '('
- %bceq(a0, -41, &::scan_done, a1) ; ')'
+ %is_ws_branch(a1, a0, &.scan_done)
+ %bceq(a0, -40, &.scan_done, a1) ; '('
+ %bceq(a0, -41, &.scan_done, a1) ; ')'
%addi(t1, t1, 1)
- %b(&::scan)
+ %b(&.scan)
- ::scan_done
+ :.scan_done
%stl(t1, end)
%st(t1, t0, 0)
@@ -935,7 +926,7 @@
%ldl(t1, end)
%sub(a2, t1, t0) ; length
- %bieq(a2, 1, &::single, a3)
+ %bieq(a2, 1, &.single, a3)
%ld_global(t2, &readbuf_buf_ptr)
%add(t2, t2, t0) ; t2 = slice ptr
@@ -943,49 +934,49 @@
# Hex form: first byte is 'x'.
%lb(a0, t2, 0)
%addi(a1, a0, -120) ; 'x'
- %beqz(a1, &::hex_form)
+ %beqz(a1, &.hex_form)
# Named form: dispatch on length.
- %bieq(a2, 3, &::try_tab, a3)
- %bieq(a2, 4, &::try_null, a3)
- %bieq(a2, 5, &::try_space, a3)
- %bieq(a2, 6, &::try_return, a3)
- %bieq(a2, 7, &::try_newline, a3)
- %b(&::bad)
-
- ::single
+ %bieq(a2, 3, &.try_tab, a3)
+ %bieq(a2, 4, &.try_null, a3)
+ %bieq(a2, 5, &.try_space, a3)
+ %bieq(a2, 6, &.try_return, a3)
+ %bieq(a2, 7, &.try_newline, a3)
+ %b(&.bad)
+
+ :.single
%ld_global(t2, &readbuf_buf_ptr)
%add(t2, t2, t0)
%lb(a0, t2, 0)
%mkfix(a0, a0)
%eret
- ::hex_form
+ :.hex_form
%addi(a0, t2, 1)
%addi(a1, a2, -1)
%call(&parse_hex)
%mkfix(a0, a0)
%eret
- ::try_tab
+ :.try_tab
%match_named_char(&name_ch_tab, 3, 9)
- ::try_null
+ :.try_null
%match_named_char(&name_ch_null, 4, 0)
- ::try_space
+ :.try_space
%match_named_char(&name_ch_space, 5, 32)
- ::try_return
+ :.try_return
%match_named_char(&name_ch_return, 6, 13)
- ::try_newline
+ :.try_newline
%match_named_char(&name_ch_newline, 7, 10)
- ::bad
+ :.bad
%die(msg_bad_char)
- ::short
+ :.short
%die(msg_bad_char)
})
@@ -1006,62 +997,62 @@
%stl(a1, env)
%tagof(t0, a0)
- %bieq(t0, %TAG.SYM, &::sym, t1)
- %bieq(t0, %TAG.PAIR, &::pair, t1)
+ %bieq(t0, %TAG.SYM, &.sym, t1)
+ %bieq(t0, %TAG.PAIR, &.pair, t1)
# FIXNUM, HEAP, IMM all self-evaluate.
%eret
- ::sym
+ :.sym
# Walk the env alist. Each cell is ((sym . val) . rest). On hit,
# return cdr(binding); on NIL, fall back to the symbol's global slot.
# a0 still holds the tagged sym; a1 still holds env.
- ::env_walk
- %if_nil(t0, a1, &::env_miss)
+ :.env_walk
+ %if_nil(t0, a1, &.env_miss)
%car(t1, a1) ; t1 = (sym . val)
%car(t2, t1) ; t2 = sym in binding
- %beq(t2, a0, &::env_hit)
+ %beq(t2, a0, &.env_hit)
%cdr(a1, a1)
- %b(&::env_walk)
+ %b(&.env_walk)
- ::env_hit
+ :.env_hit
%cdr(a0, t1)
%eret
- ::env_miss
+ :.env_miss
%untag_sym(a0, a0)
%call(&sym_global)
- %bieq(a0, %imm_val(%IMM.UNBOUND), &::unbound, t0)
+ %bieq(a0, %imm_val(%IMM.UNBOUND), &.unbound, t0)
%eret
- ::unbound
+ :.unbound
%die(msg_unbound)
- ::pair
+ :.pair
# 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.
%ldl(t0, expr)
%car(t0, t0) ; t0 = head
- %dispatch_form(&sym_quote, &::do_quote)
- %dispatch_form(&sym_if, &::do_if)
- %dispatch_form(&sym_lambda, &::do_lambda)
- %dispatch_form(&sym_define, &::do_define)
- %dispatch_form(&sym_begin, &::do_begin)
- %dispatch_form(&sym_cond, &::do_cond)
- %dispatch_form(&sym_let, &::do_let)
- %dispatch_form(&sym_letstar, &::do_letstar)
- %dispatch_form(&sym_let_values, &::do_let_values)
- %dispatch_form(&sym_letstar_values, &::do_letstar_values)
- %dispatch_form(&sym_and, &::do_and)
- %dispatch_form(&sym_or, &::do_or)
- %dispatch_form(&sym_when, &::do_when)
- %dispatch_form(&sym_case, &::do_case)
- %dispatch_form(&sym_setbang, &::do_setbang)
- %dispatch_form(&sym_define_record_type, &::do_define_record_type)
- %dispatch_form(&sym_pmatch, &::do_pmatch)
- %dispatch_form(&sym_do, &::do_do)
+ %dispatch_form(&sym_quote, &.do_quote)
+ %dispatch_form(&sym_if, &.do_if)
+ %dispatch_form(&sym_lambda, &.do_lambda)
+ %dispatch_form(&sym_define, &.do_define)
+ %dispatch_form(&sym_begin, &.do_begin)
+ %dispatch_form(&sym_cond, &.do_cond)
+ %dispatch_form(&sym_let, &.do_let)
+ %dispatch_form(&sym_letstar, &.do_letstar)
+ %dispatch_form(&sym_let_values, &.do_let_values)
+ %dispatch_form(&sym_letstar_values, &.do_letstar_values)
+ %dispatch_form(&sym_and, &.do_and)
+ %dispatch_form(&sym_or, &.do_or)
+ %dispatch_form(&sym_when, &.do_when)
+ %dispatch_form(&sym_case, &.do_case)
+ %dispatch_form(&sym_setbang, &.do_setbang)
+ %dispatch_form(&sym_define_record_type, &.do_define_record_type)
+ %dispatch_form(&sym_pmatch, &.do_pmatch)
+ %dispatch_form(&sym_do, &.do_do)
# Apply car to cdr
# fn = eval(car(expr), env)
@@ -1080,41 +1071,41 @@
%ldl(a0, fn)
%tail(&apply)
- ::do_quote
+ :.do_quote
%tail_to_handler(&eval_quote)
- ::do_if
+ :.do_if
%tail_to_handler(&eval_if)
- ::do_lambda
+ :.do_lambda
%tail_to_handler(&eval_lambda)
- ::do_define
+ :.do_define
%tail_to_handler(&eval_define)
- ::do_begin
+ :.do_begin
%tail_to_handler(&eval_body)
- ::do_cond
+ :.do_cond
%tail_to_handler(&eval_cond)
- ::do_let
+ :.do_let
%tail_to_handler(&eval_let)
- ::do_letstar
+ :.do_letstar
%tail_to_handler(&eval_letstar)
- ::do_let_values
+ :.do_let_values
%tail_to_handler(&eval_let_values)
- ::do_letstar_values
+ :.do_letstar_values
%tail_to_handler(&eval_letstar_values)
- ::do_and
+ :.do_and
%tail_to_handler(&eval_and)
- ::do_or
+ :.do_or
%tail_to_handler(&eval_or)
- ::do_when
+ :.do_when
%tail_to_handler(&eval_when)
- ::do_case
+ :.do_case
%tail_to_handler(&eval_case)
- ::do_setbang
+ :.do_setbang
%tail_to_handler(&eval_setbang)
- ::do_define_record_type
+ :.do_define_record_type
%tail_to_handler(&eval_define_record_type)
- ::do_pmatch
+ :.do_pmatch
%tail_to_handler(&eval_pmatch)
- ::do_do
+ :.do_do
%tail_to_handler(&eval_do)
})
@@ -1136,9 +1127,9 @@
%stl(t0, head)
%stl(t0, tail)
- ::loop
+ :.loop
%ldl(t0, args)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
# val = eval(car(args), env)
%car(a0, t0)
@@ -1150,20 +1141,20 @@
%call(&cons)
%ldl(t0, head)
- %if_nil(t1, t0, &::first)
+ %if_nil(t1, t0, &.first)
%ldl(t0, tail)
%set_cdr(a0, t0)
%stl(a0, tail)
- %b(&::advance)
+ %b(&.advance)
- ::first
+ :.first
%stl(a0, head)
%stl(a0, tail)
- ::advance
+ :.advance
%advance_walk(args)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%ldl(a0, head)
})
@@ -1178,10 +1169,10 @@
%stl(a1, args)
%hdr_type(t0, a0)
- %bieq(t0, %HDR.PRIM, &::prim, t1)
- %bieq(t0, %HDR.CLOSURE, &::closure, t1)
+ %bieq(t0, %HDR.PRIM, &.prim, t1)
+ %bieq(t0, %HDR.CLOSURE, &.closure, t1)
- ::prim
+ :.prim
# Primitive calling convention:
# a0 = args list (proper list of evaluated args)
# a1 = the PRIM object itself (HEAP-tagged)
@@ -1197,7 +1188,7 @@
%ldl(a0, args)
%tailr(t0)
- ::closure
+ :.closure
# Closure layout (HEAP-tagged): [hdr][params][body][env]
%heap_ld(t0, a0, %CLOSURE.params)
%heap_ld(t1, a0, %CLOSURE.body)
@@ -1274,7 +1265,7 @@
%car(a0, a0)
%call(&eval)
- %bieq(a0, %imm_val(%IMM.FALSE), &::else_branch, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.else_branch, t0)
# then-branch: tail-eval(cadr(rest), env)
%ldl(a0, rest)
@@ -1283,19 +1274,19 @@
%ldl(a1, env)
%tail(&eval)
- ::else_branch
+ :.else_branch
# If cddr(rest) is NIL, this is single-arm `if` -> UNSPEC.
%ldl(t0, rest)
%cdr(t0, t0)
%cdr(t0, t0)
- %if_nil(t1, t0, &::no_else)
+ %if_nil(t1, t0, &.no_else)
# else-branch: tail-eval(car(cddr(rest)), env)
%car(a0, t0)
%ldl(a1, env)
%tail(&eval)
- ::no_else
+ :.no_else
%li(a0, %imm_val(%IMM.UNSPEC))
})
@@ -1353,7 +1344,7 @@
# If car(rest) is a pair, this is the lambda-sugar form.
%car(t0, a0)
%tagof(t1, t0)
- %bieq(t1, %TAG.PAIR, &::sugar, t2)
+ %bieq(t1, %TAG.PAIR, &.sugar, t2)
# Plain define: value = eval(car(cdr(rest)), env)
%ldl(t0, rest)
@@ -1368,7 +1359,7 @@
%li(a0, %imm_val(%IMM.UNSPEC))
%eret
- ::sugar
+ :.sugar
# rest = ((name . params) . body); build (params . body) for eval_lambda.
%ldl(t0, rest)
%car(t0, t0)
@@ -1414,24 +1405,24 @@
%ldl(t1, rest)
%car(t1, t1) ; target sym
- ::loop
+ :.loop
%ldl(t2, env)
- %if_nil(t0, t2, &::miss)
+ %if_nil(t0, t2, &.miss)
%car(t0, t2)
%car(t0, t0) ; cell sym
- %beq(t0, t1, &::hit)
+ %beq(t0, t1, &.hit)
%cdr(t2, t2)
%stl(t2, env)
- %b(&::loop)
+ %b(&.loop)
- ::hit
+ :.hit
%car(t0, t2) ; re-fetch binding cell
%ldl(a0, saved)
%set_cdr(a0, t0) ; mutate cell's cdr
%li(a0, %imm_val(%IMM.UNSPEC))
%eret
- ::miss
+ :.miss
# Miss: rebind global.
%ldl(a0, saved)
%ldl(t0, rest)
@@ -1455,21 +1446,21 @@
%stl(a0, clauses)
%stl(a1, env)
- ::loop
+ :.loop
%ldl(t0, clauses)
- %if_nil(t1, t0, &::no_match)
+ %if_nil(t1, t0, &.no_match)
%car(t1, t0) ; clause
%car(t2, t1) ; test_expr
%ld_global(a0, &sym_else)
- %beq(t2, a0, &::else_clause)
+ %beq(t2, a0, &.else_clause)
%mov(a0, t2)
%ldl(a1, env)
%call(&eval)
%li(t0, %imm_val(%IMM.FALSE))
- %beq(a0, t0, &::next)
+ %beq(a0, t0, &.next)
# Truthy. Spill test value and inspect cdr(clause): empty -> UNSPEC,
# car == => -> arrow path, else regular body.
@@ -1477,16 +1468,16 @@
%ldl(t0, clauses)
%car(t0, t0)
%cdr(t0, t0)
- %if_nil(t1, t0, &::no_match)
+ %if_nil(t1, t0, &.no_match)
%car(t1, t0)
%ld_global(t2, &sym_arrow)
- %beq(t1, t2, &::arrow)
+ %beq(t1, t2, &.arrow)
%mov(a0, t0) ; regular body
%ldl(a1, env)
%tail(&eval_body)
- ::arrow
+ :.arrow
%cdr(t0, t0)
%car(a0, t0) ; proc-expr
%ldl(a1, env)
@@ -1499,18 +1490,18 @@
%ldl(a0, proc)
%tail(&apply)
- ::else_clause
+ :.else_clause
%ldl(t0, clauses)
%car(t0, t0)
%cdr(a0, t0)
%ldl(a1, env)
%tail(&eval_body)
- ::next
+ :.next
%advance_walk(clauses)
- %b(&::loop)
+ %b(&.loop)
- ::no_match
+ :.no_match
%li(a0, %imm_val(%IMM.UNSPEC))
})
@@ -1533,7 +1524,7 @@
# Named let?
%car(t0, a0)
%tagof(t1, t0)
- %bieq(t1, %TAG.SYM, &::named, t2)
+ %bieq(t1, %TAG.SYM, &.named, t2)
%ldl(t0, rest)
%car(t0, t0) ; bindings
@@ -1541,9 +1532,9 @@
%ldl(t0, env)
%stl(t0, new_env) ; new_env = env
- ::loop
+ :.loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%car(t1, t0) ; pair = (name init)
%cdr(t2, t1)
@@ -1568,15 +1559,15 @@
%stl(a0, new_env)
%advance_walk(walk)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(a0, rest)
%cdr(a0, a0) ; body
%ldl(a1, new_env)
%tail(&eval_body)
- ::named
+ :.named
%ldl(a0, rest)
%ldl(a1, env)
%tail(&eval_let_named)
@@ -1601,9 +1592,9 @@
%ldl(t0, env)
%stl(t0, new_env)
- ::loop
+ :.loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%car(t1, t0)
%cdr(t2, t1)
@@ -1626,8 +1617,8 @@
%stl(a0, new_env)
%advance_walk(walk)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%ldl(a0, rest)
%cdr(a0, a0)
@@ -1656,9 +1647,9 @@
%ldl(t0, env)
%stl(t0, new_env) ; new_env = env
- ::loop
+ :.loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%car(t1, t0) ; clause = (formals init)
%cdr(t2, t1)
@@ -1683,8 +1674,8 @@
%stl(a0, new_env)
%advance_walk(walk)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%ldl(a0, rest)
%cdr(a0, a0) ; body
@@ -1711,9 +1702,9 @@
%ldl(t0, env)
%stl(t0, new_env)
- ::loop
+ :.loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%car(t1, t0)
%cdr(t2, t1)
@@ -1736,8 +1727,8 @@
%stl(a0, new_env)
%advance_walk(walk)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%ldl(a0, rest)
%cdr(a0, a0)
@@ -1755,36 +1746,36 @@
# env
%fn2(eval_and, {rest env}, {
%li(t0, %imm_val(%IMM.TRUE))
- %if_nil(t1, a0, &::done_imm)
+ %if_nil(t1, a0, &.done_imm)
- ::loop
+ :.loop
%stl(a0, rest)
%stl(a1, env)
# If cdr(rest) is NIL, the head is the last form -> tail-eval.
%cdr(t0, a0)
- %if_nil(t1, t0, &::last)
+ %if_nil(t1, t0, &.last)
# Non-last: eval, short-circuit on #f, otherwise advance.
%car(a0, a0)
%call(&eval)
%li(t0, %imm_val(%IMM.FALSE))
- %beq(a0, t0, &::done)
+ %beq(a0, t0, &.done)
%ldl(a0, rest)
%cdr(a0, a0)
%ldl(a1, env)
- %b(&::loop)
+ %b(&.loop)
- ::last
+ :.last
%ldl(a0, rest)
%car(a0, a0)
%ldl(a1, env)
%tail(&eval)
- ::done
+ :.done
%eret
- ::done_imm
+ :.done_imm
%mov(a0, t0)
})
@@ -1798,33 +1789,33 @@
# env
%fn2(eval_or, {rest env}, {
%li(t0, %imm_val(%IMM.FALSE))
- %if_nil(t1, a0, &::done_imm)
+ %if_nil(t1, a0, &.done_imm)
- ::loop
+ :.loop
%stl(a0, rest)
%stl(a1, env)
%cdr(t0, a0)
- %if_nil(t1, t0, &::last)
+ %if_nil(t1, t0, &.last)
%car(a0, a0)
%call(&eval)
- %bine(a0, %imm_val(%IMM.FALSE), &::done, t0)
+ %bine(a0, %imm_val(%IMM.FALSE), &.done, t0)
%ldl(a0, rest)
%cdr(a0, a0)
%ldl(a1, env)
- %b(&::loop)
+ %b(&.loop)
- ::last
+ :.last
%ldl(a0, rest)
%car(a0, a0)
%ldl(a1, env)
%tail(&eval)
- ::done
+ :.done
%eret
- ::done_imm
+ :.done_imm
%mov(a0, t0)
})
@@ -1843,14 +1834,14 @@
%car(a0, a0) ; test
%call(&eval)
- %bieq(a0, %imm_val(%IMM.FALSE), &::skip, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.skip, t0)
%ldl(a0, rest)
%cdr(a0, a0) ; body
%ldl(a1, env)
%tail(&eval_body)
- ::skip
+ :.skip
%li(a0, %imm_val(%IMM.UNSPEC))
})
@@ -1881,49 +1872,49 @@
%call(&eval)
%stl(a0, subject)
- ::loop
+ :.loop
%ldl(t0, clauses)
- %if_nil(t1, t0, &::no_match)
+ %if_nil(t1, t0, &.no_match)
%car(t1, t0) ; clause
%car(t2, t1) ; head: datum-list or `else`
%ld_global(a3, &sym_else)
- %beq(t2, a3, &::do_else)
+ %beq(t2, a3, &.do_else)
# Walk the datum list, eq?-compare each against subject.
%stl(t2, datums)
%ldl(a0, subject)
- ::scan
+ :.scan
%ldl(t0, datums)
- %if_nil(t1, t0, &::next_clause)
+ %if_nil(t1, t0, &.next_clause)
%car(t1, t0) ; datum
- %beq(t1, a0, &::do_body)
+ %beq(t1, a0, &.do_body)
%cdr(t0, t0)
%stl(t0, datums)
- %b(&::scan)
+ %b(&.scan)
- ::do_body
+ :.do_body
%ldl(t0, clauses)
%car(t0, t0)
%cdr(a0, t0) ; body
%ldl(a1, env)
%tail(&eval_body)
- ::do_else
+ :.do_else
%ldl(t0, clauses)
%car(t0, t0)
%cdr(a0, t0) ; body
%ldl(a1, env)
%tail(&eval_body)
- ::next_clause
+ :.next_clause
%ldl(t0, clauses)
%cdr(t0, t0)
%stl(t0, clauses)
- %b(&::loop)
+ %b(&.loop)
- ::no_match
+ :.no_match
%li(a0, %imm_val(%IMM.UNSPEC))
})
@@ -1958,22 +1949,22 @@
%call(&eval)
%stl(a0, subject)
- ::loop
+ :.loop
%ldl(t0, clauses)
- %if_nil(t1, t0, &::no_match)
+ %if_nil(t1, t0, &.no_match)
%car(t1, t0) ; clause
%car(t2, t1) ; pat
%ld_global(a3, &sym_else)
- %beq(t2, a3, &::do_else)
+ %beq(t2, a3, &.do_else)
# pmatch_match(pat, subject, env_outer) -> (a0=env_ext, a1=ok)
%mov(a0, t2)
%ldl(a1, subject)
%ldl(a2, env_outer)
%call(&pmatch_match)
- %beqz(a1, &::next)
+ %beqz(a1, &.next)
%stl(a0, env_ext) ; env_ext
@@ -1985,13 +1976,13 @@
# Guard form? tail is a pair, car(tail) is a pair, head of car(tail)
# eq? sym_guard.
%tagof(t1, t0)
- %bine(t1, %TAG.PAIR, &::body_simple, t2)
+ %bine(t1, %TAG.PAIR, &.body_simple, t2)
%car(t1, t0) ; first form of tail
%tagof(t2, t1)
- %bine(t2, %TAG.PAIR, &::body_simple, a0)
+ %bine(t2, %TAG.PAIR, &.body_simple, a0)
%car(a0, t1) ; head of first form
%ld_global(a1, &sym_guard)
- %bne(a0, a1, &::body_simple)
+ %bne(a0, a1, &.body_simple)
# Guard clause. guards = cdr(car(tail)); body = cdr(tail).
%cdr(a0, t1)
@@ -1999,26 +1990,26 @@
%cdr(t0, t0)
%stl(t0, body)
- ::g_loop
+ :.g_loop
%ldl(t0, guard)
- %if_nil(t1, t0, &::body_run)
+ %if_nil(t1, t0, &.body_run)
%car(a0, t0) ; guard expr
%ldl(a1, env_ext) ; env_ext
%call(&eval)
- %bieq(a0, %imm_val(%IMM.FALSE), &::next, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.next, t0)
%ldl(t0, guard)
%cdr(t0, t0)
%stl(t0, guard)
- %b(&::g_loop)
+ %b(&.g_loop)
- ::body_run
+ :.body_run
%ldl(a0, body)
%ldl(a1, env_ext)
%tail(&eval_body)
- ::body_simple
+ :.body_simple
# tail itself is the body (no guard wrapper). Tail-call eval_body
# with the extended env; tail position of the matched clause's body
# is preserved.
@@ -2026,20 +2017,20 @@
%ldl(a1, env_ext)
%tail(&eval_body)
- ::do_else
+ :.do_else
%ldl(t0, clauses)
%car(t0, t0)
%cdr(a0, t0) ; body
%ldl(a1, env_outer) ; env_outer (no bindings introduced)
%tail(&eval_body)
- ::next
+ :.next
%ldl(t0, clauses)
%cdr(t0, t0)
%stl(t0, clauses)
- %b(&::loop)
+ %b(&.loop)
- ::no_match
+ :.no_match
%die(msg_pmatch_no_match)
})
@@ -2088,9 +2079,9 @@
%stl(t0, vals_head)
%stl(t0, vals_tail)
- ::init_loop
+ :.init_loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::init_done)
+ %if_nil(t1, t0, &.init_done)
# spec = car(walk); init-expr = car(cdr(spec)).
%car(t1, t0)
@@ -2122,37 +2113,37 @@
%call(&cons)
%ldl(t0, pairs_head)
- %if_nil(t1, t0, &::pairs_first)
+ %if_nil(t1, t0, &.pairs_first)
%ldl(t0, pairs_tail)
%set_cdr(a0, t0)
%stl(a0, pairs_tail)
- %b(&::vals_alloc)
+ %b(&.vals_alloc)
- ::pairs_first
+ :.pairs_first
%stl(a0, pairs_head)
%stl(a0, pairs_tail)
- ::vals_alloc
+ :.vals_alloc
# vcell = cons(NIL, NIL). Append onto vals list.
%li(a0, %imm_val(%IMM.NIL))
%li(a1, %imm_val(%IMM.NIL))
%call(&cons)
%ldl(t0, vals_head)
- %if_nil(t1, t0, &::vals_first)
+ %if_nil(t1, t0, &.vals_first)
%ldl(t0, vals_tail)
%set_cdr(a0, t0)
%stl(a0, vals_tail)
- %b(&::init_advance)
+ %b(&.init_advance)
- ::vals_first
+ :.vals_first
%stl(a0, vals_head)
%stl(a0, vals_tail)
- ::init_advance
+ :.init_advance
%advance_walk(walk)
- %b(&::init_loop)
- ::init_done
+ %b(&.init_loop)
+ :.init_done
# body = cddr(rest).
%ldl(t0, rest)
@@ -2160,7 +2151,7 @@
%cdr(t0, t0)
%stl(t0, body)
- ::iter_loop
+ :.iter_loop
# test = car(car(cdr(rest))). Eval in new_env.
%ldl(t0, rest)
%cdr(t0, t0)
@@ -2169,36 +2160,36 @@
%ldl(a1, new_env)
%call(&eval)
- %bieq(a0, %imm_val(%IMM.FALSE), &::commands, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.commands, t0)
# Truthy: results = cdr(car(cdr(rest))).
%ldl(t0, rest)
%cdr(t0, t0)
%car(t0, t0)
%cdr(t0, t0) ; results
- %if_nil(t1, t0, &::no_results)
+ %if_nil(t1, t0, &.no_results)
%mov(a0, t0)
%ldl(a1, new_env)
%tail(&eval_body)
- ::no_results
+ :.no_results
%li(a0, %imm_val(%IMM.UNSPEC))
%eret
- ::commands
+ :.commands
%ldl(t0, body)
%stl(t0, walk)
- ::cmd_loop
+ :.cmd_loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::step_phase)
+ %if_nil(t1, t0, &.step_phase)
%car(a0, t0)
%ldl(a1, new_env)
%call(&eval)
%advance_walk(walk)
- %b(&::cmd_loop)
+ %b(&.cmd_loop)
- ::step_phase
+ :.step_phase
# Compute new step values. walk = specs, pair_walk = pairs_head,
# val_walk = vals_head. For each spec: if spec has step (cddr non-NIL),
# val = eval(step, new_env); else val = cdr(binding_pair) (current).
@@ -2211,51 +2202,51 @@
%ldl(t0, vals_head)
%stl(t0, val_walk)
- ::step_loop
+ :.step_loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::update_phase)
+ %if_nil(t1, t0, &.update_phase)
%car(t1, t0) ; spec
%cdr(t2, t1)
%cdr(t2, t2) ; (step?) or NIL
- %if_nil(t1, t2, &::no_step)
+ %if_nil(t1, t2, &.no_step)
%car(a0, t2) ; step
%ldl(a1, new_env)
%call(&eval)
- %b(&::store_val)
+ %b(&.store_val)
- ::no_step
+ :.no_step
%ldl(t0, pair_walk)
%car(t0, t0) ; binding pair
%cdr(a0, t0) ; current val
- ::store_val
+ :.store_val
%ldl(t0, val_walk)
%set_car(a0, t0)
%advance_walk(walk)
%advance_walk(pair_walk)
%advance_walk(val_walk)
- %b(&::step_loop)
+ %b(&.step_loop)
- ::update_phase
+ :.update_phase
# Walk pairs_head and vals_head; set-cdr!(pair, val) for each.
%ldl(t0, pairs_head)
%stl(t0, pair_walk)
%ldl(t0, vals_head)
%stl(t0, val_walk)
- ::update_loop
+ :.update_loop
%ldl(t0, pair_walk)
- %if_nil(t1, t0, &::iter_loop)
+ %if_nil(t1, t0, &.iter_loop)
%car(t1, t0) ; binding pair
%ldl(t0, val_walk)
%car(t2, t0) ; new val
%set_cdr(t2, t1)
%advance_walk(pair_walk)
%advance_walk(val_walk)
- %b(&::update_loop)
+ %b(&.update_loop)
})
# pmatch_match(pat=a0, subj=a1, env=a2) -> (env=a0, ok=a1)
@@ -2296,34 +2287,34 @@
%tagof(t0, a0)
%li(t1, %TAG.PAIR)
- %beq(t0, t1, &::pair_pat)
+ %beq(t0, t1, &.pair_pat)
# Atomic pattern. Identity covers fixnum / symbol / immediate / same
# heap pointer.
- %beq(a0, a1, &::ok)
+ %beq(a0, a1, &.ok)
# HDR.BV equality.
- %bine(t0, %TAG.HEAP, &::no, t1)
+ %bine(t0, %TAG.HEAP, &.no, t1)
%hdr_type(t1, a0)
- %bine(t1, %HDR.BV, &::no, t2)
+ %bine(t1, %HDR.BV, &.no, t2)
%tagof(t1, a1)
- %bine(t1, %TAG.HEAP, &::no, t2)
+ %bine(t1, %TAG.HEAP, &.no, t2)
%hdr_type(t1, a1)
- %bine(t1, %HDR.BV, &::no, t2)
+ %bine(t1, %HDR.BV, &.no, t2)
%call(&bv_equal_check)
- %bieq(a0, %imm_val(%IMM.TRUE), &::ok, t0)
- %b(&::no)
+ %bieq(a0, %imm_val(%IMM.TRUE), &.ok, t0)
+ %b(&.no)
- ::pair_pat
+ :.pair_pat
%car(t0, a0) ; phead
%ld_global(t1, &sym_unquote)
- %beq(t0, t1, &::binder)
+ %beq(t0, t1, &.binder)
%ld_global(t1, &sym_dollar)
- %beq(t0, t1, &::record_pat)
+ %beq(t0, t1, &.record_pat)
# Structural pair. subj must be a pair too.
%tagof(t0, a1)
- %bine(t0, %TAG.PAIR, &::no, t1)
+ %bine(t0, %TAG.PAIR, &.no, t1)
# Recurse on the cars; on success, recurse on the cdrs as a tail call.
%ldl(t0, pat)
@@ -2332,7 +2323,7 @@
%car(a1, t0)
%ldl(a2, env)
%call(&pmatch_match)
- %beqz(a1, &::no)
+ %beqz(a1, &.no)
%mov(a2, a0) ; env_after_car
%ldl(t0, pat)
@@ -2341,22 +2332,22 @@
%cdr(a1, t0)
%tail(&pmatch_match)
- ::binder
+ :.binder
# Validate (unquote <sym>): cdr(pat) is a pair, cdr(cdr(pat)) is NIL,
# car(cdr(pat)) is a symbol.
%ldl(t0, pat)
%cdr(t1, t0) ; cdr(pat)
%tagof(t0, t1)
- %bine(t0, %TAG.PAIR, &::bad, t2)
+ %bine(t0, %TAG.PAIR, &.bad, t2)
%cdr(t0, t1) ; cdr(cdr(pat))
- %bine(t0, %imm_val(%IMM.NIL), &::bad, t2)
+ %bine(t0, %imm_val(%IMM.NIL), &.bad, t2)
%car(t0, t1) ; pident (kept in t0)
%tagof(t2, t0)
- %bine(t2, %TAG.SYM, &::bad, a3)
+ %bine(t2, %TAG.SYM, &.bad, a3)
# Wildcard? Compare against sym_underscore; if so, no binding.
%ld_global(t1, &sym_underscore)
- %beq(t0, t1, &::ok)
+ %beq(t0, t1, &.ok)
# Bind: env' = cons(cons(pident, subj), env). pident lives in t0;
# cons clobbers t0..t2, so move it into a0 right away.
@@ -2368,7 +2359,7 @@
%li(a1, 1)
%eret
- ::record_pat
+ :.record_pat
# pat = ($ pred-sym (f1 p1) (f2 p2) ...). Resolve pred-sym -> PRIM via
# eval, pull TD from PRIM.data, type-check subj, then iterate the
# (fname pat_i) clauses. Clobbers `pat` local once we begin the loop:
@@ -2377,10 +2368,10 @@
%ldl(t0, pat)
%cdr(t1, t0) ; (pred-sym . clauses)
%tagof(t0, t1)
- %bine(t0, %TAG.PAIR, &::no, t2)
+ %bine(t0, %TAG.PAIR, &.no, t2)
%car(t0, t1) ; t0 = pred-sym
%tagof(t2, t0)
- %bine(t2, %TAG.SYM, &::no, a3)
+ %bine(t2, %TAG.SYM, &.no, a3)
%cdr(t2, t1) ; t2 = clauses
%stl(t2, flw)
@@ -2392,44 +2383,44 @@
# Verify HEAP / HDR.PRIM, entry == &prim_predicate_entry; extract TD
# from PRIM.data; sanity-check TD is HEAP / HDR.TD.
%tagof(t0, a0)
- %bine(t0, %TAG.HEAP, &::no, t1)
+ %bine(t0, %TAG.HEAP, &.no, t1)
%hdr_type(t0, a0)
- %bine(t0, %HDR.PRIM, &::no, t1)
+ %bine(t0, %HDR.PRIM, &.no, t1)
%heap_ld(t1, a0, %PRIM.entry_w)
%la(t2, &prim_predicate_entry)
- %bne(t1, t2, &::no)
+ %bne(t1, t2, &.no)
%heap_ld(t1, a0, %PRIM.data) ; t1 = TD
%tagof(t0, t1)
%li(t2, %TAG.HEAP)
- %bne(t0, t2, &::no)
+ %bne(t0, t2, &.no)
%hdr_type(t0, t1)
%li(t2, %HDR.TD)
- %bne(t0, t2, &::no)
+ %bne(t0, t2, &.no)
%stl(t1, td)
# Verify subj is HDR.REC with REC.td == TD.
%ldl(a0, subj)
%tagof(t0, a0)
%li(t1, %TAG.HEAP)
- %bne(t0, t1, &::no)
+ %bne(t0, t1, &.no)
%hdr_type(t0, a0)
%li(t1, %HDR.REC)
- %bne(t0, t1, &::no)
+ %bne(t0, t1, &.no)
%heap_ld(t0, a0, %REC.td)
%ldl(t1, td)
- %bne(t0, t1, &::no)
+ %bne(t0, t1, &.no)
- ::record_field_loop
+ :.record_field_loop
# flw points at remaining (fname pat_i) clauses; NIL ends the loop.
%ldl(t0, flw)
- %if_nil(t1, t0, &::ok)
+ %if_nil(t1, t0, &.ok)
%car(t1, t0) ; t1 = clause
%tagof(t0, t1)
- %bine(t0, %TAG.PAIR, &::no, t2)
+ %bine(t0, %TAG.PAIR, &.no, t2)
%car(t2, t1) ; t2 = fname
%cdr(t1, t1) ; t1 = (pat_i)
%tagof(t0, t1)
- %bine(t0, %TAG.PAIR, &::no, a3)
+ %bine(t0, %TAG.PAIR, &.no, a3)
%car(a3, t1) ; a3 = pat_i
%stl(a3, pat) ; reuse `pat` local for pat_i across recursion
@@ -2439,15 +2430,15 @@
%ldl(t0, td)
%heap_ld(t0, t0, %TD.fields)
%li(t1, 0)
- ::record_field_idx_loop
- %if_nil(a3, t0, &::no)
+ :.record_field_idx_loop
+ %if_nil(a3, t0, &.no)
%car(a3, t0)
- %beq(a3, t2, &::record_field_found)
+ %beq(a3, t2, &.record_field_found)
%cdr(t0, t0)
%addi(t1, t1, 1)
- %b(&::record_field_idx_loop)
+ %b(&.record_field_idx_loop)
- ::record_field_found
+ :.record_field_found
# val = ld(subj_tagged + (idx<<3) + 13). Same offset arithmetic as
# prim_accessor_entry. Compute the address into a1 directly so the
# recursive call's val arg is in place.
@@ -2460,24 +2451,24 @@
%ldl(a0, pat)
%ldl(a2, env)
%call(&pmatch_match)
- %beqz(a1, &::no)
+ %beqz(a1, &.no)
%stl(a0, env)
%ldl(t0, flw)
%cdr(t0, t0)
%stl(t0, flw)
- %b(&::record_field_loop)
+ %b(&.record_field_loop)
- ::ok
+ :.ok
%ldl(a0, env)
%li(a1, 1)
%eret
- ::no
+ :.no
%li(a1, 0)
%eret
- ::bad
+ :.bad
%die(msg_bad_unquote_pattern)
})
@@ -2520,9 +2511,9 @@
%car(t0, t0) ; bindings
%stl(t0, walk)
- ::p1_loop
+ :.p1_loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::p1_done)
+ %if_nil(t1, t0, &.p1_done)
%car(t1, t0)
%car(t2, t1) ; name
@@ -2531,21 +2522,21 @@
%call(&cons) ; cell = (name . NIL)
%ldl(t0, head)
- %if_nil(t1, t0, &::p1_first)
+ %if_nil(t1, t0, &.p1_first)
%ldl(t0, tail)
%set_cdr(a0, t0)
%stl(a0, tail)
- %b(&::p1_advance)
+ %b(&.p1_advance)
- ::p1_first
+ :.p1_first
%stl(a0, head)
%stl(a0, tail)
- ::p1_advance
+ :.p1_advance
%advance_walk(walk)
- %b(&::p1_loop)
+ %b(&.p1_loop)
- ::p1_done
+ :.p1_done
%ldl(t0, head)
%stl(t0, params) ; save params
@@ -2558,9 +2549,9 @@
%car(t0, t0)
%stl(t0, walk)
- ::p2_loop
+ :.p2_loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::p2_done)
+ %if_nil(t1, t0, &.p2_done)
%car(t1, t0)
%cdr(t2, t1)
@@ -2573,21 +2564,21 @@
%call(&cons) ; cell = (val . NIL)
%ldl(t0, head)
- %if_nil(t1, t0, &::p2_first)
+ %if_nil(t1, t0, &.p2_first)
%ldl(t0, tail)
%set_cdr(a0, t0)
%stl(a0, tail)
- %b(&::p2_advance)
+ %b(&.p2_advance)
- ::p2_first
+ :.p2_first
%stl(a0, head)
%stl(a0, tail)
- ::p2_advance
+ :.p2_advance
%advance_walk(walk)
- %b(&::p2_loop)
+ %b(&.p2_loop)
- ::p2_done
+ :.p2_done
# 4. Closure: eval_lambda((params . body), self_env).
%ldl(a0, params) ; params
%ldl(t0, rest)
@@ -2620,16 +2611,16 @@
%stl(a1, args)
%stl(a2, env)
- ::loop
+ :.loop
%ldl(t0, params)
%tagof(t1, t0)
%li(t2, %TAG.PAIR)
- %beq(t1, t2, &::pair)
+ %beq(t1, t2, &.pair)
%li(t2, %TAG.SYM)
- %beq(t1, t2, &::rest_bind)
- %b(&::done)
+ %beq(t1, t2, &.rest_bind)
+ %b(&.done)
- ::pair
+ :.pair
# binding = cons(car(params), car(args))
%ldl(t0, params)
%car(a0, t0)
@@ -2645,9 +2636,9 @@
# advance params and args
%advance_walk(params)
%advance_walk(args)
- %b(&::loop)
+ %b(&.loop)
- ::rest_bind
+ :.rest_bind
# binding = cons(params_sym, args_list); env = cons(binding, env)
%ldl(a0, params)
%ldl(a1, args)
@@ -2656,7 +2647,7 @@
%call(&cons)
%stl(a0, env)
- ::done
+ :.done
%ldl(a0, env)
})
@@ -2673,7 +2664,7 @@
# body
# env
%fn2(eval_body, {body env}, {
- ::loop
+ :.loop
%stl(a0, body)
%stl(a1, env)
@@ -2682,16 +2673,16 @@
%car(t0, a0) ; form
%tagof(t1, t0)
%li(t2, %TAG.PAIR)
- %bne(t1, t2, &::not_define)
+ %bne(t1, t2, &.not_define)
%car(t1, t0) ; head sym
%ld_global(t2, &sym_define)
- %beq(t1, t2, &::internal_define)
+ %beq(t1, t2, &.internal_define)
- ::not_define
+ :.not_define
# If cdr(body) is NIL, body's car is the last form.
%ldl(a0, body)
%cdr(t0, a0)
- %if_nil(t1, t0, &::last)
+ %if_nil(t1, t0, &.last)
# Non-last form: eval and discard, advance.
%car(a0, a0)
@@ -2700,15 +2691,15 @@
%ldl(a0, body)
%cdr(a0, a0)
%ldl(a1, env)
- %b(&::loop)
+ %b(&.loop)
- ::last
+ :.last
%ldl(a0, body)
%car(a0, a0)
%ldl(a1, env)
%tail(&eval)
- ::internal_define
+ :.internal_define
%die(msg_internal_define)
})
@@ -2732,23 +2723,23 @@
%ld_global(a1, &readbuf_buf_ptr)
%li(a2, %READBUF_CAP_BYTES)
%call(&read_file)
- %bltz(a0, &::fail)
+ %bltz(a0, &.fail)
# If the read filled (or would have filled) the buffer, the source
# is at least cap bytes; refuse rather than silently truncate.
# read_file does a single sys_read so n == cap is the only saturation
# signal we have. We treat n >= cap as overflow defensively.
%li(t0, %READBUF_CAP_BYTES)
- %bltu(a0, t0, &::ok)
+ %bltu(a0, t0, &.ok)
%die(msg_readbuf_full)
- ::ok
+ :.ok
%st_global(a0, &readbuf_len, t0)
%li(a0, 0)
%st_global(a0, &readbuf_pos, t0)
%eret
- ::fail
+ :.fail
%die(msg_load_fail)
})
@@ -2768,92 +2759,92 @@
# cons(car=a0, cdr=a1) -> tagged pair (a0). Allocates 16 bytes.
:cons
-%scope cons
+.scope
%ld_global(t2, ¤t_heap_next_ptr)
%ld(t0, t2, 0)
%addi(t1, t0, %PAIR.SIZE)
%ld_global(a3, ¤t_heap_end_ptr)
%ld(a3, a3, 0)
- %bltu(a3, t1, &::oom)
+ %bltu(a3, t1, &.oom)
%st(a0, t0, %PAIR.car)
%st(a1, t0, %PAIR.cdr)
%st(t1, t2, 0)
%addi(a0, t0, %TAG.PAIR)
%ret
- ::oom
+ :.oom
%b(&heap_oom_die)
-%endscope
+.endscope
# cons_main(car=a0, cdr=a1) -> tagged pair (a0). Allocates in main
# regardless of current heap selection. Used for process-global
# interpreter metadata that is represented as Scheme pairs.
:cons_main
-%scope cons_main
+.scope
%la(t2, &heap_next)
%ld(t0, t2, 0)
%addi(t1, t0, %PAIR.SIZE)
%ld_global(a3, &heap_end)
- %bltu(a3, t1, &::oom)
+ %bltu(a3, t1, &.oom)
%st(a0, t0, %PAIR.car)
%st(a1, t0, %PAIR.cdr)
%st(t1, t2, 0)
%addi(a0, t0, %TAG.PAIR)
%ret
- ::oom
+ :.oom
%die(msg_heap_full)
-%endscope
+.endscope
# alloc_hdr(bytes=a0, hdr_word=a1) -> tagged heap obj (a0)
# Rounds bytes up to a multiple of 8 and writes hdr_word at offset 0.
:alloc_hdr
-%scope alloc_hdr
+.scope
%alignup(a0, a0, 8, t0)
%ld_global(t2, ¤t_heap_next_ptr)
%ld(t0, t2, 0)
%add(t1, t0, a0)
%ld_global(a3, ¤t_heap_end_ptr)
%ld(a3, a3, 0)
- %bltu(a3, t1, &::oom)
+ %bltu(a3, t1, &.oom)
%st(t1, t2, 0)
%st(a1, t0, 0)
%addi(a0, t0, 3)
%ret
- ::oom
+ :.oom
%b(&heap_oom_die)
-%endscope
+.endscope
# alloc_hdr_main(bytes=a0, hdr_word=a1) -> tagged heap obj (a0), allocated
# in main regardless of current heap selection.
:alloc_hdr_main
-%scope alloc_hdr_main
+.scope
%alignup(a0, a0, 8, t0)
%la(t2, &heap_next)
%ld(t0, t2, 0)
%add(t1, t0, a0)
%ld_global(a3, &heap_end)
- %bltu(a3, t1, &::oom)
+ %bltu(a3, t1, &.oom)
%st(t1, t2, 0)
%st(a1, t0, 0)
%addi(a0, t0, 3)
%ret
- ::oom
+ :.oom
%die(msg_heap_full)
-%endscope
+.endscope
# list_length(list=a0) -> count (a0). Linear walk; clobbers a0 (used as
# the cursor). Callers that need the list afterward must save it first.
:list_length
-%scope list_length
+.scope
%li(t0, 0)
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%addi(t0, t0, 1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
# =========================================================================
# Multiple-values protocol
@@ -2894,15 +2885,15 @@
%ldl(t0, list)
%addi(t1, a0, 5)
- ::loop
- %if_nil(t2, t0, &::done)
+ :.loop
+ %if_nil(t2, t0, &.done)
%car(t2, t0)
%st(t2, t1, 0)
%addi(t1, t1, 8)
%cdr(t0, t0)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(a0, mv)
})
@@ -2916,9 +2907,9 @@
# count (remaining slot count)
%fn2(mv_to_list, {ptr count}, {
%tagof(t0, a0)
- %bine(t0, %TAG.HEAP, &::single, t1)
+ %bine(t0, %TAG.HEAP, &.single, t1)
%hdr_type(t0, a0)
- %bine(t0, %HDR.MV, &::single, t1)
+ %bine(t0, %HDR.MV, &.single, t1)
# MV-pack: count = (hdr >> 8); header sits at raw+0 = tagged-3.
%ld(t0, a0, -3)
@@ -2935,9 +2926,9 @@
%li(a0, %imm_val(%IMM.NIL))
- ::loop
+ :.loop
%ldl(t0, count)
- %beqz(t0, &::done)
+ %beqz(t0, &.done)
%ldl(t1, ptr)
%ld(t2, t1, 0)
@@ -2951,12 +2942,12 @@
%ldl(t0, count)
%addi(t0, t0, -1)
%stl(t0, count)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%eret
- ::single
+ :.single
# Non-MV: return (val . NIL).
%li(a1, %imm_val(%IMM.NIL))
%tail(&cons)
@@ -2978,43 +2969,43 @@
%li(t0, 0)
%stl(t0, idx)
- ::scan
+ :.scan
# idx >= count? -> append
%ldl(t0, idx)
%ld_global(t1, &symtab_count)
- %bltu(t0, t1, &::probe)
- %b(&::append)
+ %bltu(t0, t1, &.probe)
+ %b(&.append)
- ::probe
+ :.probe
%symtab_entry(t1, t0, t2)
%stl(t1, entry_ptr)
# entry.name_len == name_len ?
%ld(t2, t1, %SYMENT.name_len)
%ldl(a2, name_len)
- %bne(t2, a2, &::next)
+ %bne(t2, a2, &.next)
# memcmp(entry.name_ptr, name_ptr, len)
%ld(a0, t1, %SYMENT.name_ptr)
%ldl(a1, name_ptr)
%ldl(a2, name_len)
%call(&memcmp)
- %beqz(a0, &::found)
+ %beqz(a0, &.found)
- ::next
+ :.next
%ldl(t0, idx)
%addi(t0, t0, 1)
%stl(t0, idx)
- %b(&::scan)
+ %b(&.scan)
- ::append
+ :.append
# Bounds check; on overflow exit 5 with a message.
%ldl(t0, idx)
%li(t1, %SYMTAB_CAP_SLOTS)
- %bltu(t0, t1, &::append_ok)
+ %bltu(t0, t1, &.append_ok)
%die(msg_symtab_full)
- ::append_ok
+ :.append_ok
# Copy the name into a stable main-heap buffer. The caller-provided
# ptr may live in readbuf_buf (parse_atom), and the current heap may
# be scratch while user code is being read/evaluated. Symtab names
@@ -3041,7 +3032,7 @@
# fall through with idx in t0 = sp[16]
- ::found
+ :.found
%ldl(t0, idx)
%shli(a0, t0, 3)
%ori(a0, a0, %TAG.SYM)
@@ -3087,10 +3078,10 @@
%la(t0, &prim_table_end)
%stl(t0, end)
- ::loop
+ :.loop
%ldl(t0, walk)
%ldl(t1, end)
- %beq(t0, t1, &::done)
+ %beq(t0, t1, &.done)
# alloc_hdr(24, HDR.PRIM) -> HEAP-tagged a0. The third slot (offset 13
# from tagged) holds per-instance data and stays zero for the
@@ -3119,9 +3110,9 @@
%ldl(t0, walk)
%addi(t0, t0, 24)
%stl(t0, walk)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
})
%fn(register_globals, 0, {
@@ -3175,44 +3166,44 @@
# of the two boolean immediates.
:prim_nullq_entry
-%scope prim_nullq
+.scope
%car(t0, a0)
%li(a0, %imm_val(%IMM.TRUE))
- %if_nil(t1, t0, &::end)
+ %if_nil(t1, t0, &.end)
%li(a0, %imm_val(%IMM.FALSE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
:prim_pairq_entry
-%scope prim_pairq
+.scope
%car(t0, a0)
%tagof(t1, t0)
%li(t2, %TAG.PAIR)
%li(a0, %imm_val(%IMM.FALSE))
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (string? x) -- #t iff x is a HEAP-tagged HDR.BV. Bytevectors back the
# string type until characters get a distinct repr; this prim is also
# the bytevector? predicate.
:prim_stringq_entry
-%scope prim_stringq
+.scope
%car(t0, a0)
%li(a0, %imm_val(%IMM.FALSE))
%tagof(t1, t0)
%li(t2, %TAG.HEAP)
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%hdr_type(t1, t0)
%li(t2, %HDR.BV)
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (set-car! pair val) / (set-cdr! pair val) -- in-place pair mutation.
# No type check (matches car/cdr's lax stance); both return UNSPEC.
@@ -3243,18 +3234,18 @@
# advance via cdr, then car. Out-of-range is undefined behavior, same
# as car/cdr on '().
:prim_list_ref_entry
-%scope prim_list_ref
+.scope
%args2(t0, t1, a0)
%sari(t1, t1, 3)
- ::loop
- %beqz(t1, &::done)
+ :.loop
+ %beqz(t1, &.done)
%cdr(t0, t0)
%addi(t1, t1, -1)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%car(a0, t0)
%ret
-%endscope
+.endscope
# (assq key alist) -> matching pair or #f. Walks alist, comparing
# car of each pair to key by identity (eq?); first match wins. Pure
@@ -3262,22 +3253,22 @@
# define so file-scope alist lookups (e.g. cc.scm scope-bind!'s
# redecl check) don't pay bind_params env-cons cost per step.
:prim_assq_entry
-%scope prim_assq
+.scope
%args2(t0, t1, a0) ; t0=key, t1=alist
- ::loop
- %if_nil(t2, t1, &::miss)
+ :.loop
+ %if_nil(t2, t1, &.miss)
%car(t2, t1) ; pair = (car alist)
%car(a0, t2) ; (car pair)
- %beq(a0, t0, &::hit)
+ %beq(a0, t0, &.hit)
%cdr(t1, t1)
- %b(&::loop)
- ::hit
+ %b(&.loop)
+ :.hit
%mov(a0, t2)
%ret
- ::miss
+ :.miss
%li(a0, %imm_val(%IMM.FALSE))
%ret
-%endscope
+.endscope
# (assoc key alist) -> matching pair or #f. Same shape as assq but
# the key compare goes through equal_recurse, which means we need a
@@ -3292,25 +3283,25 @@
%stl(t0, key)
%stl(t1, cursor)
- ::loop
+ :.loop
%ldl(t1, cursor)
- %if_nil(t2, t1, &::miss)
+ %if_nil(t2, t1, &.miss)
%car(t2, t1) ; pair = (car cursor)
%stl(t2, pair)
%car(a0, t2) ; (car pair)
%ldl(a1, key)
%call(&equal_recurse)
- %bieq(a0, %imm_val(%IMM.FALSE), &::next, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.next, t0)
%ldl(a0, pair)
%eret
- ::next
+ :.next
%ldl(t1, cursor)
%cdr(t1, t1)
%stl(t1, cursor)
- %b(&::loop)
+ %b(&.loop)
- ::miss
+ :.miss
%li(a0, %imm_val(%IMM.FALSE))
})
@@ -3328,9 +3319,9 @@
%li(t0, %imm_val(%IMM.NIL))
%stl(t0, acc)
- ::loop
+ :.loop
%ldl(t0, xs)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%car(a0, t0)
%ldl(a1, acc)
%call(&cons)
@@ -3338,9 +3329,9 @@
%ldl(t0, xs)
%cdr(t0, t0)
%stl(t0, xs)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(a0, acc)
})
@@ -3362,15 +3353,15 @@
%li(t0, 0)
%mov(t1, a0)
- ::sum_loop
- %if_nil(t2, t1, &::sum_done)
+ :.sum_loop
+ %if_nil(t2, t1, &.sum_done)
%car(t2, t1)
%heap_ld(a0, t2, %BV.hdr)
%shri(a0, a0, 8)
%add(t0, t0, a0)
%cdr(t1, t1)
- %b(&::sum_loop)
- ::sum_done
+ %b(&.sum_loop)
+ :.sum_done
%stl(t0, total)
%mov(a0, t0)
@@ -3380,9 +3371,9 @@
%li(t0, 0)
%stl(t0, write)
- ::copy_loop
+ :.copy_loop
%ldl(t0, args)
- %if_nil(t1, t0, &::copy_done)
+ %if_nil(t1, t0, &.copy_done)
%car(t1, t0) ; src bv
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8) ; src length
@@ -3400,8 +3391,8 @@
%stl(t0, args)
%call(&memcpy)
- %b(&::copy_loop)
- ::copy_done
+ %b(&.copy_loop)
+ :.copy_done
%ldl(a0, result)
})
@@ -3452,19 +3443,19 @@
%li(t0, 10)
%stl(t0, radix)
%cdr(t1, a0)
- %if_nil(t0, t1, &::have_radix)
+ %if_nil(t0, t1, &.have_radix)
%car(t0, t1)
%sari(t0, t0, 3)
%stl(t0, radix)
- ::have_radix
+ :.have_radix
%li(a0, 0)
%call(&str_alloc)
%ldl(a1, value)
%ldl(t0, radix)
- %bieq(t0, 16, &::hex, t1)
+ %bieq(t0, 16, &.hex, t1)
%tail(&str_putint)
- ::hex
+ :.hex
%tail(&str_puthex)
})
@@ -3479,9 +3470,9 @@
%car(t2, a0)
%tagof(t0, t2)
- %bine(t0, %TAG.HEAP, &::fail, t1)
+ %bine(t0, %TAG.HEAP, &.fail, t1)
%hdr_type(t0, t2)
- %bine(t0, %HDR.BV, &::fail, t1)
+ %bine(t0, %HDR.BV, &.fail, t1)
%heap_ld(t0, t2, %BV.data)
%heap_ld(t1, t2, %BV.hdr)
@@ -3492,278 +3483,278 @@
# Inspect the optional radix arg.
%ldl(t0, args)
%cdr(t0, t0)
- %if_nil(t1, t0, &::dec)
+ %if_nil(t1, t0, &.dec)
%car(t1, t0)
%sari(t1, t1, 3)
- %bieq(t1, 16, &::hex, t2)
+ %bieq(t1, 16, &.hex, t2)
- ::dec
+ :.dec
%ldl(a0, ptr)
%ldl(a1, len)
- %beqz(a1, &::fail)
+ %beqz(a1, &.fail)
%lb(t0, a0, 0)
- %bcne(t0, -43, &::dec_no_plus, t0) ; '+'
+ %bcne(t0, -43, &.dec_no_plus, t0) ; '+'
%addi(a0, a0, 1)
%addi(a1, a1, -1)
- %beqz(a1, &::fail)
- ::dec_no_plus
+ %beqz(a1, &.fail)
+ :.dec_no_plus
%stl(a1, len) ; save adjusted len
%call(&parse_dec) ; P1pp: -> (raw_val=a0, consumed=a1)
%ldl(t0, len)
- %bne(a1, t0, &::fail) ; partial parse -> fail
+ %bne(a1, t0, &.fail) ; partial parse -> fail
%mkfix(a0, a0)
- %b(&::end)
+ %b(&.end)
- ::hex
+ :.hex
# Strip optional leading '+' / '-'.
%li(t0, 0)
%stl(t0, sign)
%ldl(t0, len)
- %beqz(t0, &::fail)
+ %beqz(t0, &.fail)
%ldl(t1, ptr)
%lb(t2, t1, 0)
%addi(t0, t2, -45) ; '-'
- %beqz(t0, &::hex_neg)
+ %beqz(t0, &.hex_neg)
%addi(t0, t2, -43) ; '+'
- %beqz(t0, &::hex_skip_sign)
- %b(&::hex_parse)
- ::hex_neg
+ %beqz(t0, &.hex_skip_sign)
+ %b(&.hex_parse)
+ :.hex_neg
%li(t0, 1)
%stl(t0, sign)
- ::hex_skip_sign
+ :.hex_skip_sign
%ldl(t0, ptr)
%addi(t0, t0, 1)
%stl(t0, ptr)
%ldl(t0, len)
%addi(t0, t0, -1)
%stl(t0, len)
- %beqz(t0, &::fail)
+ %beqz(t0, &.fail)
- ::hex_parse
+ :.hex_parse
%ldl(a0, ptr)
%ldl(a1, len)
%call(&parse_hex) ; -> (a0=value, a1=consumed)
%ldl(t0, len)
- %bne(a1, t0, &::fail) ; demand full consumption
+ %bne(a1, t0, &.fail) ; demand full consumption
%ldl(t0, sign)
- %beqz(t0, &::hex_pos)
+ %beqz(t0, &.hex_pos)
%li(t1, 0)
%sub(a0, t1, a0)
- ::hex_pos
+ :.hex_pos
%mkfix(a0, a0)
- %b(&::end)
+ %b(&.end)
- ::fail
+ :.fail
%li(a0, %imm_val(%IMM.FALSE))
- ::end
+ :.end
})
# (boolean? x) -- #t iff x is the IMM.FALSE or IMM.TRUE singleton.
:prim_booleanq_entry
-%scope prim_booleanq
+.scope
%car(t0, a0)
%li(a0, %imm_val(%IMM.TRUE))
%li(t1, %imm_val(%IMM.FALSE))
- %beq(t0, t1, &::end)
+ %beq(t0, t1, &.end)
%li(t1, %imm_val(%IMM.TRUE))
- %beq(t0, t1, &::end)
+ %beq(t0, t1, &.end)
%li(a0, %imm_val(%IMM.FALSE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (integer? x) -- #t iff x is a fixnum (low 3 tag bits == TAG.FIXNUM == 0).
:prim_integerq_entry
-%scope prim_integerq
+.scope
%car(t0, a0)
%tagof(t1, t0)
%li(a0, %imm_val(%IMM.FALSE))
- %bnez(t1, &::end)
+ %bnez(t1, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (symbol? x) -- #t iff x is TAG.SYM (interned symbol index, not a heap obj).
:prim_symbolq_entry
-%scope prim_symbolq
+.scope
%car(t0, a0)
%tagof(t1, t0)
%li(t2, %TAG.SYM)
%li(a0, %imm_val(%IMM.FALSE))
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (procedure? x) -- #t iff x is HEAP-tagged with header HDR.CLOSURE or HDR.PRIM.
:prim_procedureq_entry
-%scope prim_procedureq
+.scope
%car(t0, a0)
%tagof(t1, t0)
%li(t2, %TAG.HEAP)
%li(a0, %imm_val(%IMM.FALSE))
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%hdr_type(t1, t0)
%li(t2, %HDR.CLOSURE)
- %beq(t1, t2, &::yes)
+ %beq(t1, t2, &.yes)
%li(t2, %HDR.PRIM)
- %beq(t1, t2, &::yes)
- %b(&::end)
- ::yes
+ %beq(t1, t2, &.yes)
+ %b(&.end)
+ :.yes
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
:prim_zeroq_entry
-%scope prim_zeroq
+.scope
%car(t0, a0)
%li(a0, %imm_val(%IMM.FALSE))
- %bnez(t0, &::end)
+ %bnez(t0, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
:prim_not_entry
-%scope prim_not
+.scope
%car(t0, a0)
%li(t1, %imm_val(%IMM.FALSE))
%li(a0, %imm_val(%IMM.FALSE))
- %bne(t0, t1, &::end)
+ %bne(t0, t1, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
:prim_eqq_entry
-%scope prim_eqq
+.scope
%car(t0, a0)
%cdr(t1, a0)
%car(t1, t1)
%li(a0, %imm_val(%IMM.FALSE))
- %bne(t0, t1, &::end)
+ %bne(t0, t1, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# Variadic arithmetic. (+ ...) folds with identity 0; (* ...) folds with
# identity 1; (- x) is unary negate, (- x y z ...) folds left.
:prim_plus_entry
-%scope prim_plus
+.scope
%li(t0, 0) ; tagged 0; tag bits stay 0 across %add
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%add(t0, t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
# (- x) -> -x; (- x y ...) -> x - y - ... . (-) is undefined behavior
# per the primitive-failure policy.
:prim_minus_entry
-%scope prim_minus
+.scope
%car(t0, a0) ; seed = first arg (tagged)
%cdr(a0, a0)
- %if_nil(t1, a0, &::neg)
- ::loop
- %if_nil(t1, a0, &::done)
+ %if_nil(t1, a0, &.neg)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%sub(t0, t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::neg
+ %b(&.loop)
+ :.neg
%li(t1, 0) ; unary: 0 - seed
%sub(t0, t1, t0)
- ::done
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
# Multiply keeps the accumulator tagged and untags each incoming arg:
# (a<<3) * b == (a*b)<<3, so the loop preserves the fixnum tag.
:prim_mult_entry
-%scope prim_mult
+.scope
%li(t0, 8) ; tagged 1 = mkfix(1)
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%untag_fix(t1, t1)
%mul(t0, t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
# Variadic chained comparisons: (op a b c ...) ⇔ (a op b) ∧ (b op c) ∧ ...
# Walks the tail with a single live `prev` register; a0 is reused as the
# args cursor and finally as the result. <2 args is undefined behavior.
:prim_eq_entry
-%scope prim_eq
+.scope
%car(t0, a0) ; prev = first
%cdr(a0, a0)
- ::loop
- %if_nil(t1, a0, &::true)
+ :.loop
+ %if_nil(t1, a0, &.true)
%car(t1, a0) ; curr
- %bne(t0, t1, &::false)
+ %bne(t0, t1, &.false)
%mov(t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::true
+ %b(&.loop)
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
%ret
- ::false
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
%ret
-%endscope
+.endscope
:prim_lt_entry
-%scope prim_lt
+.scope
%car(t0, a0)
%cdr(a0, a0)
- ::loop
- %if_nil(t1, a0, &::true)
+ :.loop
+ %if_nil(t1, a0, &.true)
%car(t1, a0)
- %blt(t0, t1, &::ok) ; prev < curr -> continue
+ %blt(t0, t1, &.ok) ; prev < curr -> continue
%li(a0, %imm_val(%IMM.FALSE))
%ret
- ::ok
+ :.ok
%mov(t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::true
+ %b(&.loop)
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
%ret
-%endscope
+.endscope
:prim_gt_entry
-%scope prim_gt
+.scope
%car(t0, a0)
%cdr(a0, a0)
- ::loop
- %if_nil(t1, a0, &::true)
+ :.loop
+ %if_nil(t1, a0, &.true)
%car(t1, a0)
- %blt(t1, t0, &::ok) ; curr < prev <=> prev > curr -> continue
+ %blt(t1, t0, &.ok) ; curr < prev <=> prev > curr -> continue
%li(a0, %imm_val(%IMM.FALSE))
%ret
- ::ok
+ :.ok
%mov(t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::true
+ %b(&.loop)
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
%ret
-%endscope
+.endscope
# (quotient x y) -- truncating integer division. Both fixnums are tagged
# (real << 3); div(tagged, tagged) yields the raw quotient (the shifts
@@ -3785,46 +3776,46 @@
# XOR with another tagged fixnum preserves the tag in the accumulator.
# Identities: bit-and -> -1 (tagged -8), bit-or -> 0, bit-xor -> 0.
:prim_bit_and_entry
-%scope prim_bit_and
+.scope
%li(t0, -8) ; tagged -1; AND-identity preserves the tag
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%and(t0, t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
:prim_bit_or_entry
-%scope prim_bit_or
+.scope
%li(t0, 0)
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%or(t0, t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
:prim_bit_xor_entry
-%scope prim_bit_xor
+.scope
%li(t0, 0)
- ::loop
- %if_nil(t1, a0, &::done)
+ :.loop
+ %if_nil(t1, a0, &.done)
%car(t1, a0)
%xor(t0, t0, t1)
%cdr(a0, a0)
- %b(&::loop)
- ::done
+ %b(&.loop)
+ :.done
%mov(a0, t0)
%ret
-%endscope
+.endscope
# (bit-not n) -- bitwise complement. Untag, XOR with -1 (= ~n), retag.
# Can't XOR the tagged value directly: that would flip the low 3 tag bits.
@@ -3839,23 +3830,23 @@
# (arithmetic-shift n k): k > 0 means left shift; k < 0 means arith right.
# Untag both, branch on sign of k, retag.
:prim_arith_shift_entry
-%scope prim_arith_shift
+.scope
%car(t0, a0)
%cdr(t1, a0)
%car(t1, t1)
%untag_fix(t0, t0)
%untag_fix(t1, t1)
- %bltz(t1, &::right)
+ %bltz(t1, &.right)
%shl(a0, t0, t1)
%mkfix(a0, a0)
%ret
- ::right
+ :.right
%li(t2, 0)
%sub(t1, t2, t1)
%sar(a0, t0, t1)
%mkfix(a0, a0)
%ret
-%endscope
+.endscope
# Bytevectors are 24-byte HEAP-tagged wrappers pointing at a separately
# allocated data buffer; this gives them dynamic-array semantics — capacity
@@ -3881,54 +3872,54 @@
# alloc_bytes(size=a0) -> raw addr (a0). Untagged data buffer; size is
# rounded up to 8 to keep the next bump 8-byte-aligned.
:alloc_bytes
-%scope alloc_bytes
+.scope
%alignup(a0, a0, 8, t0)
%ld_global(t2, ¤t_heap_next_ptr)
%ld(t1, t2, 0)
%add(t0, t1, a0)
%ld_global(a3, ¤t_heap_end_ptr)
%ld(a3, a3, 0)
- %bltu(a3, t0, &::oom)
+ %bltu(a3, t0, &.oom)
%st(t0, t2, 0)
%mov(a0, t1)
%ret
- ::oom
+ :.oom
%b(&heap_oom_die)
-%endscope
+.endscope
# alloc_bytes_main(size=a0) -> raw addr (a0). Untagged data buffer in the
# main heap regardless of current heap selection. Used for interpreter-
# owned stable storage such as symtab names, which must survive scratch
# resets even when user code is currently allocating in scratch.
:alloc_bytes_main
-%scope alloc_bytes_main
+.scope
%alignup(a0, a0, 8, t0)
%la(t2, &heap_next)
%ld(t1, t2, 0)
%add(t0, t1, a0)
%ld_global(a3, &heap_end)
- %bltu(a3, t0, &::oom)
+ %bltu(a3, t0, &.oom)
%st(t0, t2, 0)
%mov(a0, t1)
%ret
- ::oom
+ :.oom
%die(msg_heap_full)
-%endscope
+.endscope
# bv_capacity_for(n=a0) -> smallest power-of-two ≥ n, minimum 16. Pure
# bytevector sizing -- no NUL slack. Callers building "strings" call
# bv_capacity_for(raw_len + 1) to reserve room for the trailing NUL.
:bv_capacity_for
-%scope bv_capacity_for
+.scope
%li(t0, 16)
- ::loop
- %bltu(t0, a0, &::shift) ; t0 < a0: keep doubling
+ :.loop
+ %bltu(t0, a0, &.shift) ; t0 < a0: keep doubling
%mov(a0, t0) ; t0 >= a0: done
%ret
- ::shift
+ :.shift
%shli(t0, t0, 1)
- %b(&::loop)
-%endscope
+ %b(&.loop)
+.endscope
# bv_alloc(raw_len=a0) -> tagged bv (a0). Length = raw_len, capacity from
# bv_capacity_for, data buffer uninitialized. data_ptr lives in a frame
@@ -3972,15 +3963,15 @@
%stl(a1, min_cap)
%ld(t0, a0, 13) ; bv.cap (raw offset 16; not in BV struct)
- %bltu(t0, a1, &::need)
+ %bltu(t0, a1, &.need)
%ldl(a0, bv)
%eret
- ::need
- ::loop
+ :.need
+ :.loop
%shli(t0, t0, 1)
%ldl(t1, min_cap)
- %bltu(t0, t1, &::loop)
+ %bltu(t0, t1, &.loop)
%stl(t0, min_cap)
%mov(a0, t0)
@@ -4011,15 +4002,15 @@
%li(t2, 0)
%cdr(t0, a0)
- %if_nil(t1, t0, &::no_fill)
+ %if_nil(t1, t0, &.no_fill)
%car(t0, t0)
%sari(t2, t0, 3)
- ::no_fill
+ :.no_fill
%stl(t2, fill)
%ldl(a0, args)
%car_fix(a0, a0)
- %bltz(a0, &::bad_len)
+ %bltz(a0, &.bad_len)
%call(&bv_alloc)
%stl(a0, wrapper)
@@ -4030,18 +4021,18 @@
%heap_ld(t2, a1, %BV.data)
%li(a1, 0)
- ::fill_loop
- %beq(a1, t0, &::fill_done)
+ :.fill_loop
+ %beq(a1, t0, &.fill_done)
%sb(t1, t2, 0)
%addi(t2, t2, 1)
%addi(a1, a1, 1)
- %b(&::fill_loop)
- ::fill_done
+ %b(&.fill_loop)
+ :.fill_done
%ldl(a0, wrapper)
%eret
- ::bad_len
+ :.bad_len
%die(msg_bv_oob)
})
@@ -4066,41 +4057,41 @@
})
:prim_bv_u8_ref_entry
-%scope prim_bv_u8_ref
+.scope
%args2(t0, t1, a0) ; bv, tagged idx
%sari(t1, t1, 3) ; raw idx
- %bltz(t1, &::oob)
+ %bltz(t1, &.oob)
%heap_ld(a0, t0, %BV.hdr)
%shri(a0, a0, 8) ; length
- %bltu(t1, a0, &::ok)
- ::oob
+ %bltu(t1, a0, &.ok)
+ :.oob
%die(msg_bv_oob)
- ::ok
+ :.ok
%heap_ld(t2, t0, %BV.data)
%add(t2, t2, t1)
%lb(a0, t2, 0)
%mkfix(a0, a0)
%ret
-%endscope
+.endscope
:prim_bv_u8_set_entry
-%scope prim_bv_u8_set
+.scope
%args3(t0, t2, t1, a0) ; bv, idx, val
%sari(t2, t2, 3) ; raw idx
%sari(t1, t1, 3) ; raw val
- %bltz(t2, &::oob)
+ %bltz(t2, &.oob)
%heap_ld(a0, t0, %BV.hdr)
%shri(a0, a0, 8) ; length
- %bltu(t2, a0, &::ok)
- ::oob
+ %bltu(t2, a0, &.ok)
+ :.oob
%die(msg_bv_oob)
- ::ok
+ :.ok
%heap_ld(a0, t0, %BV.data)
%add(a0, a0, t2)
%sb(t1, a0, 0)
%li(a0, %imm_val(%IMM.UNSPEC))
%ret
-%endscope
+.endscope
# (bytevector-copy src start end) -> fresh bv of length end-start.
# Bounds: 0 <= start <= end <= src.length.
@@ -4119,11 +4110,11 @@
# Bounds: start >= 0; end >= start (signed catches negative end since
# start is now non-negative); src.length >= end.
- %bltz(t2, &::oob)
- %blt(t1, t2, &::oob)
+ %bltz(t2, &.oob)
+ %blt(t1, t2, &.oob)
%heap_ld(a0, t0, %BV.hdr)
%shri(a0, a0, 8) ; src.length
- %blt(a0, t1, &::oob)
+ %blt(a0, t1, &.oob)
%sub(a0, t1, t2) ; count
%call(&bv_alloc)
@@ -4141,20 +4132,20 @@
%heap_ld(a1, a3, %BV.hdr)
%shri(a1, a1, 8) ; count
- ::copy_loop
- %beqz(a1, &::copy_done)
+ :.copy_loop
+ %beqz(a1, &.copy_done)
%lb(t0, t2, 0)
%sb(t0, a2, 0)
%addi(t2, t2, 1)
%addi(a2, a2, 1)
%addi(a1, a1, -1)
- %b(&::copy_loop)
+ %b(&.copy_loop)
- ::copy_done
+ :.copy_done
%ldl(a0, wrapper)
%eret
- ::oob
+ :.oob
%die(msg_bv_oob)
})
@@ -4189,25 +4180,25 @@
# src-start >= 0
%ldl(t0, src_start)
- %bltz(t0, &::oob)
+ %bltz(t0, &.oob)
# src-end >= src-start (signed catches negative src-end)
%ldl(t1, src_end)
- %blt(t1, t0, &::oob)
+ %blt(t1, t0, &.oob)
# src-end <= src.length
%ldl(t2, src)
%heap_ld(a0, t2, %BV.hdr)
%shri(a0, a0, 8)
- %blt(a0, t1, &::oob)
+ %blt(a0, t1, &.oob)
# dst-start >= 0
%ldl(t2, dst_start)
- %bltz(t2, &::oob)
+ %bltz(t2, &.oob)
# dst-start + count <= dst.length
%sub(a0, t1, t0) ; count = src-end - src-start
%add(a0, a0, t2) ; dst-start + count
%ldl(t1, dst)
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8)
- %blt(t2, a0, &::oob)
+ %blt(t2, a0, &.oob)
# Set up copy. dst ptr = dst.data + dst-start; src ptr = src.data +
# src-start; count = src-end - src-start.
@@ -4222,20 +4213,20 @@
%ldl(a3, src_end)
%sub(a3, a3, a2) ; count
- ::loop
- %beqz(a3, &::done)
+ :.loop
+ %beqz(a3, &.done)
%lb(t1, a1, 0)
%sb(t1, t0, 0)
%addi(t0, t0, 1)
%addi(a1, a1, 1)
%addi(a3, a3, -1)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%li(a0, %imm_val(%IMM.UNSPEC))
%eret
- ::oob
+ :.oob
%die(msg_bv_oob)
})
@@ -4245,58 +4236,58 @@
# branch). Compares lengths first, then walks bytes; %lb is zero-extending
# on every backend, so a single %bne is enough for the byte test.
:bv_equal_check
-%scope bv_equal_check
+.scope
%heap_ld(t0, a0, %BV.hdr)
%shri(t0, t0, 8) ; len_a
%heap_ld(t1, a1, %BV.hdr)
%shri(t1, t1, 8) ; len_b
- %bne(t0, t1, &::false)
+ %bne(t0, t1, &.false)
%heap_ld(a2, a0, %BV.data)
%heap_ld(a3, a1, %BV.data)
- ::loop
- %beqz(t0, &::true)
+ :.loop
+ %beqz(t0, &.true)
%lb(t1, a2, 0)
%lb(t2, a3, 0)
- %bne(t1, t2, &::false)
+ %bne(t1, t2, &.false)
%addi(a2, a2, 1)
%addi(a3, a3, 1)
%addi(t0, t0, -1)
- %b(&::loop)
+ %b(&.loop)
- ::true
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
%ret
- ::false
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
%ret
-%endscope
+.endscope
# (bytevector=? a b) -- structural equality on bytevectors. Non-bv
# inputs return #f rather than aborting, matching the lax stance the
# other predicates take until LISP.md pins a stricter policy.
:prim_bytevector_eq_entry
-%scope prim_bytevector_eq
+.scope
%args2(t0, t1, a0)
%tagof(t2, t0)
%li(a0, %TAG.HEAP)
- %bne(t2, a0, &::false)
+ %bne(t2, a0, &.false)
%tagof(t2, t1)
- %bne(t2, a0, &::false)
+ %bne(t2, a0, &.false)
%hdr_type(t2, t0)
%li(a0, %HDR.BV)
- %bne(t2, a0, &::false)
+ %bne(t2, a0, &.false)
%hdr_type(t2, t1)
- %bne(t2, a0, &::false)
+ %bne(t2, a0, &.false)
%mov(a0, t0)
%mov(a1, t1)
%b(&bv_equal_check)
- ::false
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
%ret
-%endscope
+.endscope
# equal_recurse(a=a0, b=a1) -> a0 (IMM.TRUE / IMM.FALSE). Identity covers
# fixnums, symbols, immediates, and any case where both arguments are the
@@ -4312,59 +4303,59 @@
%stl(a0, a)
%stl(a1, b)
- %beq(a0, a1, &::true)
+ %beq(a0, a1, &.true)
%tagof(t0, a0)
%tagof(t1, a1)
- %bne(t0, t1, &::false)
+ %bne(t0, t1, &.false)
- %bieq(t0, %TAG.PAIR, &::pair, t1)
- %bieq(t0, %TAG.HEAP, &::heap, t1)
- %b(&::false)
+ %bieq(t0, %TAG.PAIR, &.pair, t1)
+ %bieq(t0, %TAG.HEAP, &.heap, t1)
+ %b(&.false)
- ::pair
+ :.pair
%ldl(t0, a)
%ldl(t1, b)
%car(a0, t0)
%car(a1, t1)
%call(&equal_recurse)
- %bieq(a0, %imm_val(%IMM.FALSE), &::done, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.done, t0)
%ldl(t0, a)
%ldl(t1, b)
%cdr(a0, t0)
%cdr(a1, t1)
%tail(&equal_recurse)
- ::heap
+ :.heap
%ldl(t0, a)
%ldl(t1, b)
%hdr_type(t2, t0)
%hdr_type(a0, t1)
- %bne(t2, a0, &::false) ; differing heap classes -> #f
+ %bne(t2, a0, &.false) ; differing heap classes -> #f
%li(a0, %HDR.BV)
- %beq(t2, a0, &::heap_bv)
+ %beq(t2, a0, &.heap_bv)
%li(a0, %HDR.REC)
- %beq(t2, a0, &::heap_rec)
- %b(&::false) ; CLOSURE/PRIM/TD: identity-only
+ %beq(t2, a0, &.heap_rec)
+ %b(&.false) ; CLOSURE/PRIM/TD: identity-only
- ::heap_bv
+ :.heap_bv
%mov(a0, t0)
%mov(a1, t1)
%tail(&bv_equal_check)
- ::heap_rec
+ :.heap_rec
%mov(a0, t0)
%mov(a1, t1)
%tail(&rec_equal_check)
- ::true
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
- %b(&::done)
+ %b(&.done)
- ::false
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
- ::done
+ :.done
})
# rec_equal_check(a=a0, b=a1) -> a0 (IMM.TRUE / IMM.FALSE). Both args
@@ -4383,17 +4374,17 @@
%heap_ld(t0, a0, %REC.td) ; td_a
%heap_ld(t1, a1, %REC.td) ; td_b
- %bne(t0, t1, &::false)
+ %bne(t0, t1, &.false)
%heap_ld(t1, t0, %TD.nfields)
%stl(t1, nfields)
%li(t0, 0)
%stl(t0, i) ; i = 0
- ::loop
+ :.loop
%ldl(t0, i)
%ldl(t1, nfields)
- %beq(t0, t1, &::true)
+ %beq(t0, t1, &.true)
%shli(t2, t0, 3)
%addi(t2, t2, 13) ; field offset = 13 + 8*i
@@ -4404,21 +4395,21 @@
%add(t1, t1, t2)
%ld(a1, t1, 0) ; b's field i
%call(&equal_recurse)
- %bieq(a0, %imm_val(%IMM.FALSE), &::done, t0)
+ %bieq(a0, %imm_val(%IMM.FALSE), &.done, t0)
%ldl(t0, i)
%addi(t0, t0, 1)
%stl(t0, i)
- %b(&::loop)
+ %b(&.loop)
- ::true
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
- %b(&::done)
+ %b(&.done)
- ::false
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
- ::done
+ :.done
})
# (equal? a b) -- thin prim wrapper that unpacks the args list and falls
@@ -4469,10 +4460,10 @@
%stl(t0, head)
%stl(t0, tail)
- ::loop
+ :.loop
%ldl(t0, walk)
%cdr(t1, t0)
- %if_nil(t2, t1, &::last)
+ %if_nil(t2, t1, &.last)
# cell = cons(car(walk), NIL); append to head/tail.
%car(a0, t0)
@@ -4480,32 +4471,32 @@
%call(&cons)
%ldl(t0, head)
- %if_nil(t1, t0, &::first)
+ %if_nil(t1, t0, &.first)
%ldl(t0, tail)
%set_cdr(a0, t0)
%stl(a0, tail)
- %b(&::advance)
+ %b(&.advance)
- ::first
+ :.first
%stl(a0, head)
%stl(a0, tail)
- ::advance
+ :.advance
%advance_walk(walk)
- %b(&::loop)
+ %b(&.loop)
- ::last
+ :.last
# car(walk) is the trailing list. If head is NIL there were no leading
# args -- return the trailing list directly. Otherwise splice it onto
# the tail and return head.
%car(a0, t0)
%ldl(t1, head)
- %if_nil(t2, t1, &::done)
+ %if_nil(t2, t1, &.done)
%ldl(t1, tail)
%set_cdr(a0, t1)
%ldl(a0, head)
- ::done
+ :.done
})
# Records: TDs (type descriptors) and instances. A TD is a 24-byte heap
@@ -4565,34 +4556,34 @@
%ldl(t0, args)
%addi(t1, a0, 13)
- ::fill_loop
- %if_nil(t2, t0, &::fill_done)
+ :.fill_loop
+ %if_nil(t2, t0, &.fill_done)
%car(t2, t0)
%st(t2, t1, 0)
%addi(t1, t1, 8)
%cdr(t0, t0)
- %b(&::fill_loop)
- ::fill_done
+ %b(&.fill_loop)
+ :.fill_done
%ldl(a0, record)
})
# predicate: prim.data = TD; args = (rec).
:prim_predicate_entry
-%scope prim_predicate
+.scope
%car(t0, a0)
%heap_ld(t1, a1, %PRIM.data)
%tagof(t2, t0)
%li(a0, %imm_val(%IMM.FALSE))
- %bine(t2, %TAG.HEAP, &::end, a2)
+ %bine(t2, %TAG.HEAP, &.end, a2)
%hdr_type(t2, t0)
- %bine(t2, %HDR.REC, &::end, a2)
+ %bine(t2, %HDR.REC, &.end, a2)
%heap_ld(t2, t0, %REC.td)
- %bne(t2, t1, &::end)
+ %bne(t2, t1, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# accessor: prim.data = tagged field index; args = (rec).
:prim_accessor_entry
@@ -4605,7 +4596,7 @@
# mutator: prim.data = tagged field index; args = (rec val).
:prim_mutator_entry
-%scope prim_mutator
+.scope
%car(t0, a0)
%cdr(t1, a0)
%car(t1, t1)
@@ -4615,7 +4606,7 @@
%st(t1, t2, 0)
%li(a0, %imm_val(%IMM.UNSPEC))
%ret
-%endscope
+.endscope
# eval_define_record_type(rest=a0, env=a1) -> UNSPEC.
# rest = (name (ctor f1 ...) pred clause1 clause2 ...)
@@ -4674,9 +4665,9 @@
%ldl(t0, walk)
%stl(t0, fl_cur)
- ::fl_loop
+ :.fl_loop
%ldl(t0, fl_cur)
- %if_nil(t1, t0, &::fl_done)
+ %if_nil(t1, t0, &.fl_done)
# cell = cons(car(car(fl_cur)), NIL)
%car(t1, t0)
%car(a0, t1)
@@ -4685,21 +4676,21 @@
# Splice into list: if head is NIL, head = tail = cell.
# Else set-cdr!(tail, cell); tail = cell.
%ldl(t1, fl_head)
- %bine(t1, %imm_val(%IMM.NIL), &::fl_append, t2)
+ %bine(t1, %imm_val(%IMM.NIL), &.fl_append, t2)
%stl(a0, fl_head)
%stl(a0, fl_tail)
- %b(&::fl_next)
- ::fl_append
+ %b(&.fl_next)
+ :.fl_append
%ldl(t1, fl_tail)
%set_cdr(a0, t1)
%stl(a0, fl_tail)
- ::fl_next
+ :.fl_next
%ldl(t0, fl_cur)
%cdr(t0, t0)
%stl(t0, fl_cur)
- %b(&::fl_loop)
+ %b(&.fl_loop)
- ::fl_done
+ :.fl_done
%ldl(t0, td)
%ldl(t1, fl_head)
%heap_st(t1, t0, %TD.fields)
@@ -4728,9 +4719,9 @@
%li(t0, 0)
%stl(t0, idx)
- ::clause_loop
+ :.clause_loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
# accessor-prim with data = tagged idx; bind cadr(clause).
%ldl(a1, idx)
@@ -4749,7 +4740,7 @@
%car(t0, t0)
%cdr(t0, t0)
%cdr(t0, t0)
- %if_nil(t1, t0, &::no_mutator)
+ %if_nil(t1, t0, &.no_mutator)
%ldl(a1, idx)
%mkfix(a1, a1)
@@ -4763,14 +4754,14 @@
%car(t0, t0)
%set_global(t0, a0)
- ::no_mutator
+ :.no_mutator
%advance_walk(walk)
%ldl(t0, idx)
%addi(t0, t0, 1)
%stl(t0, idx)
- %b(&::clause_loop)
+ %b(&.clause_loop)
- ::done
+ :.done
%li(a0, %imm_val(%IMM.UNSPEC))
})
@@ -4981,10 +4972,10 @@
%stl(a0, bv)
%stl(a1, value)
- %bltz(a1, &::neg)
- %b(&::pos)
+ %bltz(a1, &.neg)
+ %b(&.pos)
- ::neg
+ :.neg
%ldl(a0, bv)
%li(a1, 45) ; '-'
%call(&str_putc)
@@ -4993,7 +4984,7 @@
%sub(t0, t1, t0)
%stl(t0, value)
- ::pos
+ :.pos
%la(a0, &writer_num_buf)
%ldl(a1, value)
%call(&fmt_hex) ; n_bytes (a0)
@@ -5028,10 +5019,10 @@
%stl(a2, mode)
%tagof(t0, a0)
- %bieq(t0, %TAG.PAIR, &::pair, t1)
- %bieq(t0, %TAG.SYM, &::sym, t1)
- %bieq(t0, %TAG.HEAP, &::heap, t1)
- %bieq(t0, %TAG.IMM, &::imm, t1)
+ %bieq(t0, %TAG.PAIR, &.pair, t1)
+ %bieq(t0, %TAG.SYM, &.sym, t1)
+ %bieq(t0, %TAG.HEAP, &.heap, t1)
+ %bieq(t0, %TAG.IMM, &.imm, t1)
# Fall-through: FIXNUM (the only remaining tag).
%ldl(a0, bv)
@@ -5039,7 +5030,7 @@
%sari(a1, a1, 3)
%tail(&str_putint)
- ::sym
+ :.sym
%ldl(a0, val)
%sari(a0, a0, 3)
%call(&sym_name)
@@ -5048,24 +5039,24 @@
%ldl(a0, bv)
%tail(&str_putn)
- ::pair
+ :.pair
%ldl(a0, val)
%ldl(a1, bv)
%ldl(a2, mode)
%tail(&write_pair_to_bv)
- ::heap
+ :.heap
%hdr_type(t0, a0)
- %bieq(t0, %HDR.BV, &::heap_bv, t1)
- %bieq(t0, %HDR.CLOSURE, &::heap_closure, t1)
- %bieq(t0, %HDR.PRIM, &::heap_prim, t1)
- %bieq(t0, %HDR.TD, &::heap_td, t1)
- %bieq(t0, %HDR.REC, &::heap_rec, t1)
- %b(&::heap_unknown)
-
- ::heap_bv
+ %bieq(t0, %HDR.BV, &.heap_bv, t1)
+ %bieq(t0, %HDR.CLOSURE, &.heap_closure, t1)
+ %bieq(t0, %HDR.PRIM, &.heap_prim, t1)
+ %bieq(t0, %HDR.TD, &.heap_td, t1)
+ %bieq(t0, %HDR.REC, &.heap_rec, t1)
+ %b(&.heap_unknown)
+
+ :.heap_bv
%ldl(t0, mode)
- %beqz(t0, &::heap_bv_raw)
+ %beqz(t0, &.heap_bv_raw)
# write mode: emit `"`, then the raw bytes, then `"`.
%ldl(a0, bv)
%li(a1, 34)
@@ -5078,7 +5069,7 @@
%li(a1, 34)
%tail(&str_putc)
- ::heap_bv_raw
+ :.heap_bv_raw
%ldl(t0, val)
%heap_ld(a1, t0, %BV.data)
%heap_ld(a2, t0, %BV.hdr)
@@ -5086,79 +5077,79 @@
%ldl(a0, bv)
%tail(&str_putn)
- ::heap_closure
+ :.heap_closure
%la(a1, &str_closure)
%li(a2, 10)
%ldl(a0, bv)
%tail(&str_putn)
- ::heap_prim
+ :.heap_prim
%la(a1, &str_prim)
%li(a2, 7)
%ldl(a0, bv)
%tail(&str_putn)
- ::heap_td
+ :.heap_td
%la(a1, &str_td)
%li(a2, 11)
%ldl(a0, bv)
%tail(&str_putn)
- ::heap_rec
+ :.heap_rec
%la(a1, &str_rec)
%li(a2, 9)
%ldl(a0, bv)
%tail(&str_putn)
- ::heap_unknown
+ :.heap_unknown
%la(a1, &str_unknown)
%li(a2, 10)
%ldl(a0, bv)
%tail(&str_putn)
- ::imm
+ :.imm
%ldl(a0, val)
%sari(a0, a0, 3)
- %beqz(a0, &::imm_false)
+ %beqz(a0, &.imm_false)
%addi(t0, a0, -1)
- %beqz(t0, &::imm_true)
+ %beqz(t0, &.imm_true)
%addi(t0, a0, -2)
- %beqz(t0, &::imm_nil)
+ %beqz(t0, &.imm_nil)
%addi(t0, a0, -3)
- %beqz(t0, &::imm_unspec)
+ %beqz(t0, &.imm_unspec)
%addi(t0, a0, -4)
- %beqz(t0, &::imm_unbound)
+ %beqz(t0, &.imm_unbound)
# EOF (idx == 5) is the only remaining IMM.
%la(a1, &str_eof)
%li(a2, 5)
%ldl(a0, bv)
%tail(&str_putn)
- ::imm_false
+ :.imm_false
%la(a1, &str_false)
%li(a2, 2)
%ldl(a0, bv)
%tail(&str_putn)
- ::imm_true
+ :.imm_true
%la(a1, &str_true)
%li(a2, 2)
%ldl(a0, bv)
%tail(&str_putn)
- ::imm_nil
+ :.imm_nil
%la(a1, &str_nil)
%li(a2, 2)
%ldl(a0, bv)
%tail(&str_putn)
- ::imm_unspec
+ :.imm_unspec
%la(a1, &str_unspec)
%li(a2, 8)
%ldl(a0, bv)
%tail(&str_putn)
- ::imm_unbound
+ :.imm_unbound
%la(a1, &str_unbound)
%li(a2, 9)
%ldl(a0, bv)
@@ -5185,7 +5176,7 @@
%li(a1, 40)
%call(&str_putc)
- ::loop
+ :.loop
%ldl(t0, pair)
%car(a0, t0)
%ldl(a1, bv)
@@ -5196,10 +5187,10 @@
%cdr(t0, t0)
%stl(t0, pair)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%tagof(t1, t0)
%li(t2, %TAG.PAIR)
- %beq(t1, t2, &::cont)
+ %beq(t1, t2, &.cont)
# Dotted tail: emit ` . ` then write_to_bv(cdr).
%ldl(a0, bv)
@@ -5215,15 +5206,15 @@
%ldl(a1, bv)
%ldl(a2, mode)
%call(&write_to_bv)
- %b(&::done)
+ %b(&.done)
- ::cont
+ :.cont
%ldl(a0, bv)
%li(a1, 32)
%call(&str_putc)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(a0, bv)
%li(a1, 41)
%tail(&str_putc)
@@ -5307,9 +5298,9 @@
%cdr(t0, t0)
%stl(t0, walk)
- ::loop
+ :.loop
%ldl(t0, walk)
- %if_nil(t1, t0, &::done)
+ %if_nil(t1, t0, &.done)
%ldl(a0, bv)
%li(a1, 32)
@@ -5324,9 +5315,9 @@
%ldl(t0, walk)
%cdr(t0, t0)
%stl(t0, walk)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(t0, bv)
%heap_ld(a0, t0, %BV.data)
%tail(&runtime_error)
@@ -5360,19 +5351,19 @@
%li(t0, 0)
%stl(t0, idx)
- ::loop
+ :.loop
%ldl(t1, template)
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8) ; template length
%ldl(t0, idx)
- %beq(t0, t2, &::done)
+ %beq(t0, t2, &.done)
%heap_ld(a3, t1, %BV.data)
%add(a3, a3, t0)
%lb(a3, a3, 0) ; byte = template.data[idx]
%addi(t1, a3, -126) ; '~'
- %beqz(t1, &::tilde)
+ %beqz(t1, &.tilde)
# Plain byte: emit and advance.
%ldl(a0, out)
@@ -5381,15 +5372,15 @@
%ldl(t0, idx)
%addi(t0, t0, 1)
%stl(t0, idx)
- %b(&::loop)
+ %b(&.loop)
- ::tilde
+ :.tilde
%ldl(t0, idx)
%addi(t0, t0, 1)
%ldl(t1, template)
%heap_ld(t2, t1, %BV.hdr)
%shri(t2, t2, 8)
- %beq(t0, t2, &::tilde_lit)
+ %beq(t0, t2, &.tilde_lit)
%heap_ld(t1, t1, %BV.data)
%add(t1, t1, t0)
@@ -5399,17 +5390,17 @@
%stl(t0, idx)
%addi(t1, a3, -97) ; 'a'
- %beqz(t1, &::spec_a)
+ %beqz(t1, &.spec_a)
%addi(t1, a3, -115) ; 's'
- %beqz(t1, &::spec_s)
+ %beqz(t1, &.spec_s)
%addi(t1, a3, -100) ; 'd'
- %beqz(t1, &::spec_d)
+ %beqz(t1, &.spec_d)
%addi(t1, a3, -120) ; 'x'
- %beqz(t1, &::spec_x)
+ %beqz(t1, &.spec_x)
%addi(t1, a3, -37) ; '%'
- %beqz(t1, &::spec_pct)
+ %beqz(t1, &.spec_pct)
%addi(t1, a3, -126) ; '~'
- %beqz(t1, &::spec_tilde)
+ %beqz(t1, &.spec_tilde)
# Unknown directive: emit `~` then the spec byte verbatim. Re-read
# the spec byte from the template since str_putc may clobber a3.
@@ -5424,9 +5415,9 @@
%lb(a1, t1, 0)
%ldl(a0, out)
%call(&str_putc)
- %b(&::loop)
+ %b(&.loop)
- ::tilde_lit
+ :.tilde_lit
# `~` at end of template: emit literal `~` and finish next iter.
%ldl(a0, out)
%li(a1, 126)
@@ -5434,9 +5425,9 @@
%ldl(t0, idx)
%addi(t0, t0, 1)
%stl(t0, idx)
- %b(&::loop)
+ %b(&.loop)
- ::spec_a
+ :.spec_a
%ldl(t0, args)
%car(a0, t0)
%cdr(t0, t0)
@@ -5444,9 +5435,9 @@
%ldl(a1, out)
%li(a2, 0)
%call(&write_to_bv)
- %b(&::loop)
+ %b(&.loop)
- ::spec_s
+ :.spec_s
%ldl(t0, args)
%car(a0, t0)
%cdr(t0, t0)
@@ -5454,9 +5445,9 @@
%ldl(a1, out)
%li(a2, 1)
%call(&write_to_bv)
- %b(&::loop)
+ %b(&.loop)
- ::spec_d
+ :.spec_d
%ldl(t0, args)
%car(t1, t0)
%cdr(t0, t0)
@@ -5464,9 +5455,9 @@
%sari(a1, t1, 3)
%ldl(a0, out)
%call(&str_putint)
- %b(&::loop)
+ %b(&.loop)
- ::spec_x
+ :.spec_x
%ldl(t0, args)
%car(t1, t0)
%cdr(t0, t0)
@@ -5474,21 +5465,21 @@
%sari(a1, t1, 3)
%ldl(a0, out)
%call(&str_puthex)
- %b(&::loop)
+ %b(&.loop)
- ::spec_pct
+ :.spec_pct
%ldl(a0, out)
%li(a1, 10)
%call(&str_putc)
- %b(&::loop)
+ %b(&.loop)
- ::spec_tilde
+ :.spec_tilde
%ldl(a0, out)
%li(a1, 126)
%call(&str_putc)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(a0, out)
})
@@ -5511,12 +5502,12 @@
%fn2(wrap_syscall_result, {raw pad}, {
%stl(a0, raw)
- %bltz(a0, &::err)
+ %bltz(a0, &.err)
%mkfix(a1, a0)
%li(a0, %imm_val(%IMM.TRUE))
%tail(&cons)
- ::err
+ :.err
%ldl(t0, raw)
%li(t1, 0)
%sub(t0, t1, t0)
@@ -5594,16 +5585,16 @@
%ldl(t0, list)
%ldl(t1, array)
- ::fill_loop
- %if_nil(t2, t0, &::fill_done)
+ :.fill_loop
+ %if_nil(t2, t0, &.fill_done)
%car(a3, t0)
%heap_ld(a2, a3, %BV.data)
%st(a2, t1, 0)
%addi(t1, t1, 8)
%cdr(t0, t0)
- %b(&::fill_loop)
+ %b(&.fill_loop)
- ::fill_done
+ :.fill_done
%li(t2, 0)
%st(t2, t1, 0)
@@ -5718,9 +5709,9 @@
%stl(t0, head)
%stl(t0, tail)
- ::loop
+ :.loop
%ldl(t0, count)
- %beqz(t0, &::done)
+ %beqz(t0, &.done)
# len = strlen(*argv)
%ldl(t0, argv)
@@ -5748,41 +5739,41 @@
%call(&cons)
%ldl(t0, head)
- %if_nil(t1, t0, &::first)
+ %if_nil(t1, t0, &.first)
%ldl(t0, tail)
%set_cdr(a0, t0)
%stl(a0, tail)
- %b(&::advance)
+ %b(&.advance)
- ::first
+ :.first
%stl(a0, head)
%stl(a0, tail)
- ::advance
+ :.advance
%ldl(t0, argv)
%addi(t0, t0, 8)
%stl(t0, argv)
%ldl(t0, count)
%addi(t0, t0, -1)
%stl(t0, count)
- %b(&::loop)
+ %b(&.loop)
- ::done
+ :.done
%ldl(a0, head)
})
# (eof? x). The `eof` value itself is bound at startup in p1_main as a
# direct global -> IMM.EOF, not via a primitive thunk.
:prim_eofq_entry
-%scope prim_eofq
+.scope
%car(t0, a0)
%li(t1, %imm_val(%IMM.EOF))
%li(a0, %imm_val(%IMM.FALSE))
- %bne(t0, t1, &::end)
+ %bne(t0, t1, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (heap-usage) -> tagged fixnum: bytes consumed since heap_init
# (heap_next - heap_buf_ptr). Used by cc to instrument per-phase
@@ -5860,22 +5851,22 @@
# small sym indices) yield false because their masked values are far
# below heap_buf_ptr.
:prim_heap_in_main_q_entry
-%scope prim_heap_in_main_q
+.scope
%car(t0, a0)
%li(t1, -8)
%and(t0, t0, t1)
%ld_global(t1, &heap_buf_ptr)
- %bltu(t0, t1, &::false)
+ %bltu(t0, t1, &.false)
%li(t2, %HEAP_CAP_BYTES)
%add(t1, t1, t2)
- %bltu(t0, t1, &::true)
- ::false
+ %bltu(t0, t1, &.true)
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
%ret
- ::true
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
%ret
-%endscope
+.endscope
# (heap-in-current? obj) -> bool. True iff obj's masked pointer falls
# inside whichever heap is currently selected (main or scratch).
@@ -5884,32 +5875,32 @@
# is current. Tag bits are masked off; non-pointer values yield #f.
# Used by deep-copy as the "already in target arena" short-circuit.
:prim_heap_in_current_q_entry
-%scope prim_heap_in_current_q
+.scope
%car(t0, a0)
%li(t1, -8)
%and(t0, t0, t1)
%ld_global(t1, ¤t_heap_next_ptr)
%la(t2, &heap_next)
- %bne(t1, t2, &::scratch)
+ %bne(t1, t2, &.scratch)
%ld_global(t1, &heap_buf_ptr)
- %bltu(t0, t1, &::false)
+ %bltu(t0, t1, &.false)
%li(t2, %HEAP_CAP_BYTES)
%add(t1, t1, t2)
- %bltu(t0, t1, &::true)
- %b(&::false)
- ::scratch
+ %bltu(t0, t1, &.true)
+ %b(&.false)
+ :.scratch
%ld_global(t1, &scratch_buf_ptr)
- %bltu(t0, t1, &::false)
+ %bltu(t0, t1, &.false)
%li(t2, %SCRATCH_CAP_BYTES)
%add(t1, t1, t2)
- %bltu(t0, t1, &::true)
- ::false
+ %bltu(t0, t1, &.true)
+ :.false
%li(a0, %imm_val(%IMM.FALSE))
%ret
- ::true
+ :.true
%li(a0, %imm_val(%IMM.TRUE))
%ret
-%endscope
+.endscope
# Record introspection. Surfaces the unsafe %record-* helpers (heap
# layout: [HDR.REC][td][f0..fN-1], field i at tagged + 13 + 8*i;
@@ -5920,19 +5911,19 @@
# (record? obj) -> bool. True iff obj is HEAP-tagged with HDR.REC.
:prim_recordq_entry
-%scope prim_recordq
+.scope
%car(t0, a0)
%li(a0, %imm_val(%IMM.FALSE))
%tagof(t1, t0)
%li(t2, %TAG.HEAP)
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%hdr_type(t1, t0)
%li(t2, %HDR.REC)
- %bne(t1, t2, &::end)
+ %bne(t1, t2, &.end)
%li(a0, %imm_val(%IMM.TRUE))
- ::end
+ :.end
%ret
-%endscope
+.endscope
# (record-td rec) -> td. Reads the TD slot from the record header. No
# kind check; caller is expected to gate with record? if needed.
@@ -5953,7 +5944,7 @@
# (record-set! rec idx val) -> unspec. In-place store at slot idx.
:prim_record_set_bang_entry
-%scope prim_record_set_bang
+.scope
%car(t0, a0) ; rec
%cdr(a0, a0)
%car(t1, a0) ; idx (tagged fixnum)
@@ -5964,7 +5955,7 @@
%st(t2, t0, 0)
%li(a0, %imm_val(%IMM.UNSPEC))
%ret
-%endscope
+.endscope
# (make-record/td td) -> fresh record allocated in the current heap.
# Reads td.nfields, allocates 16 + nfields*8 bytes with HDR.REC, sets
@@ -5996,14 +5987,14 @@
%addi(t1, a0, 13)
%li(t2, %imm_val(%IMM.UNSPEC))
- ::fill_loop
- %beqz(t0, &::fill_done)
+ :.fill_loop
+ %beqz(t0, &.fill_done)
%st(t2, t1, 0)
%addi(t1, t1, 8)
%addi(t0, t0, -1)
- %b(&::fill_loop)
+ %b(&.fill_loop)
- ::fill_done
+ :.fill_done
%ldl(a0, record)
})
@@ -6061,29 +6052,29 @@
# msg_heap_full vs msg_scratch_full by comparing current_heap_next_ptr
# against &heap_next, then tails into runtime_error via %die.
:heap_oom_die
-%scope heap_oom_die
+.scope
%ld_global(t0, ¤t_heap_next_ptr)
%la(t1, &heap_next)
- %beq(t0, t1, &::main)
+ %beq(t0, t1, &.main)
%die(msg_scratch_full)
- ::main
+ :.main
%die(msg_heap_full)
-%endscope
+.endscope
# (values . xs) -- multiple-values producer. Single-arg case returns the
# arg unchanged so (values x) is interchangeable with x in any 1-value
# context; 0 or 2+ args materialize an MV-pack.
:prim_values_entry
-%scope prim_values
- %if_nil(t0, a0, &::pack)
+.scope
+ %if_nil(t0, a0, &.pack)
%cdr(t0, a0)
- %if_nil(t1, t0, &::single)
- ::pack
+ %if_nil(t1, t0, &.single)
+ :.pack
%b(&list_to_mv)
- ::single
+ :.single
%car(a0, a0)
%ret
-%endscope
+.endscope
# (call-with-values producer consumer) -- apply producer to no args, then
# normalize its result (via mv_to_list) and tail-apply the consumer to the
@@ -6149,108 +6140,109 @@
# disassembly so trailing strings don't decode as bogus instructions.
:_text_end
+.align 8
# Primitive surface names.
-:name_sys_exit "sys-exit" '00000000000000'
-:name_cons "cons" '000000'
-:name_car "car" '00000000'
-:name_cdr "cdr" '00000000'
-:name_nullq "null?" '0000'
-:name_pairq "pair?" '0000'
-:name_stringq "string?"
-:name_set_car "set-car!" '00000000000000'
-:name_set_cdr "set-cdr!" '00000000000000'
-:name_length "length" '00'
-:name_list_ref "list-ref" '00000000000000'
-:name_assq "assq" '000000'
-:name_assoc "assoc" '0000'
-:name_reverse "reverse"
-:name_str_to_sym "string->symbol" '00'
-:name_sym_to_str "symbol->string" '00'
-:name_num_to_str "number->string" '00'
-:name_str_to_num "string->number" '00'
-:name_bv_append "bytevector-append" '000000000000'
-:name_booleanq "boolean?" '00000000000000'
-:name_integerq "integer?" '00000000000000'
-:name_symbolq "symbol?"
-:name_procedureq "procedure?" '0000000000'
-:name_zeroq "zero?" '0000'
-:name_not "not" '00000000'
-:name_eqq "eq?" '00000000'
-:name_equal "equal?" '00'
-:name_plus "+" '000000000000'
-:name_minus "-" '000000000000'
-:name_mult "*" '000000000000'
-:name_eq "=" '000000000000'
-:name_lt "<" '000000000000'
-:name_gt ">" '000000000000'
-:name_quotient "quotient" '00000000000000'
-:name_remainder "remainder" '000000000000'
-:name_bit_and "bit-and"
-:name_bit_or "bit-or" '00'
-:name_bit_xor "bit-xor"
-:name_bit_not "bit-not"
-:name_arith_shift "arithmetic-shift" '00000000000000'
-:name_apply "apply" '0000'
-:name_make_bv "make-bytevector"
-:name_bv_length "bytevector-length" '000000000000'
-:name_string_length "string-length" '0000'
-:name_bv_u8_ref "bytevector-u8-ref" '000000000000'
-:name_bv_u8_set "bytevector-u8-set!" '0000000000'
-:name_bv_copy "bytevector-copy"
-:name_bv_copy_b "bytevector-copy!" '00000000000000'
-:name_bv_eq "bytevector=?" '000000'
-
-:name_sys_read "sys-read" '00000000000000'
-:name_sys_write "sys-write" '000000000000'
-:name_sys_close "sys-close" '000000000000'
-:name_sys_openat "sys-openat" '0000000000'
-:name_sys_clone "sys-clone" '000000000000'
-:name_sys_execve "sys-execve" '0000000000'
-:name_sys_waitid "sys-waitid" '0000000000'
-:name_sys_argv "sys-argv" '00000000000000'
-:name_eof "eof" '00000000'
-:name_eofq "eof?" '000000'
-:name_values "values" '00'
-:name_call_with_values "call-with-values" '00000000000000'
-:name_display "display"
-:name_write "write" '0000'
-:name_error "error" '0000'
-:name_format "format" '00'
-:name_heap_mark "heap-mark" '000000000000'
-:name_heap_rewind_bang "heap-rewind!" '000000'
-:name_heap_usage "heap-usage" '0000000000'
-:name_use_scratch_heap_bang "use-scratch-heap!" '000000000000'
-:name_use_main_heap_bang "use-main-heap!" '00'
-:name_reset_scratch_heap_bang "reset-scratch-heap!" '00000000'
-:name_heap_in_main_q "heap-in-main?" '0000'
-:name_heap_in_current_q "heap-in-current?" '00000000000000'
-:name_recordq "record?"
-:name_record_td "record-td" '000000000000'
-:name_record_ref "record-ref" '0000000000'
-:name_record_set_bang "record-set!" '00000000'
-:name_make_record_td "make-record/td" '00'
-:name_td_nfields "td-nfields" '0000000000'
-:name_td_name "td-name"
-:name_tagged_value "tagged-value" '000000'
-:name_peek_u8 "peek-u8"
-:name_current_heap_next "current-heap-next" '000000000000'
+:name_sys_exit %cstr8("sys-exit")
+:name_cons %cstr8("cons")
+:name_car %cstr8("car")
+:name_cdr %cstr8("cdr")
+:name_nullq %cstr8("null?")
+:name_pairq %cstr8("pair?")
+:name_stringq %cstr8("string?")
+:name_set_car %cstr8("set-car!")
+:name_set_cdr %cstr8("set-cdr!")
+:name_length %cstr8("length")
+:name_list_ref %cstr8("list-ref")
+:name_assq %cstr8("assq")
+:name_assoc %cstr8("assoc")
+:name_reverse %cstr8("reverse")
+:name_str_to_sym %cstr8("string->symbol")
+:name_sym_to_str %cstr8("symbol->string")
+:name_num_to_str %cstr8("number->string")
+:name_str_to_num %cstr8("string->number")
+:name_bv_append %cstr8("bytevector-append")
+:name_booleanq %cstr8("boolean?")
+:name_integerq %cstr8("integer?")
+:name_symbolq %cstr8("symbol?")
+:name_procedureq %cstr8("procedure?")
+:name_zeroq %cstr8("zero?")
+:name_not %cstr8("not")
+:name_eqq %cstr8("eq?")
+:name_equal %cstr8("equal?")
+:name_plus %cstr8("+")
+:name_minus %cstr8("-")
+:name_mult %cstr8("*")
+:name_eq %cstr8("=")
+:name_lt %cstr8("<")
+:name_gt %cstr8(">")
+:name_quotient %cstr8("quotient")
+:name_remainder %cstr8("remainder")
+:name_bit_and %cstr8("bit-and")
+:name_bit_or %cstr8("bit-or")
+:name_bit_xor %cstr8("bit-xor")
+:name_bit_not %cstr8("bit-not")
+:name_arith_shift %cstr8("arithmetic-shift")
+:name_apply %cstr8("apply")
+:name_make_bv %cstr8("make-bytevector")
+:name_bv_length %cstr8("bytevector-length")
+:name_string_length %cstr8("string-length")
+:name_bv_u8_ref %cstr8("bytevector-u8-ref")
+:name_bv_u8_set %cstr8("bytevector-u8-set!")
+:name_bv_copy %cstr8("bytevector-copy")
+:name_bv_copy_b %cstr8("bytevector-copy!")
+:name_bv_eq %cstr8("bytevector=?")
+
+:name_sys_read %cstr8("sys-read")
+:name_sys_write %cstr8("sys-write")
+:name_sys_close %cstr8("sys-close")
+:name_sys_openat %cstr8("sys-openat")
+:name_sys_clone %cstr8("sys-clone")
+:name_sys_execve %cstr8("sys-execve")
+:name_sys_waitid %cstr8("sys-waitid")
+:name_sys_argv %cstr8("sys-argv")
+:name_eof %cstr8("eof")
+:name_eofq %cstr8("eof?")
+:name_values %cstr8("values")
+:name_call_with_values %cstr8("call-with-values")
+:name_display %cstr8("display")
+:name_write %cstr8("write")
+:name_error %cstr8("error")
+:name_format %cstr8("format")
+:name_heap_mark %cstr8("heap-mark")
+:name_heap_rewind_bang %cstr8("heap-rewind!")
+:name_heap_usage %cstr8("heap-usage")
+:name_use_scratch_heap_bang %cstr8("use-scratch-heap!")
+:name_use_main_heap_bang %cstr8("use-main-heap!")
+:name_reset_scratch_heap_bang %cstr8("reset-scratch-heap!")
+:name_heap_in_main_q %cstr8("heap-in-main?")
+:name_heap_in_current_q %cstr8("heap-in-current?")
+:name_recordq %cstr8("record?")
+:name_record_td %cstr8("record-td")
+:name_record_ref %cstr8("record-ref")
+:name_record_set_bang %cstr8("record-set!")
+:name_make_record_td %cstr8("make-record/td")
+:name_td_nfields %cstr8("td-nfields")
+:name_td_name %cstr8("td-name")
+:name_tagged_value %cstr8("tagged-value")
+:name_peek_u8 %cstr8("peek-u8")
+:name_current_heap_next %cstr8("current-heap-next")
# Writer string constants. Lengths are hard-coded at the str_putn call
-# sites (write_to_bv branches). No NUL needed in the source bytes --
-# str_putn takes (ptr, n).
-:str_false "#f" '000000000000'
-:str_true "#t" '000000000000'
-:str_nil "()" '000000000000'
-:str_unspec "#!unspec" '0000000000000000'
-:str_unbound "#!unbound" '00000000000000'
-:str_eof "#!eof" '000000'
-:str_closure "#<closure>" '000000000000'
-:str_prim "#<prim>" '00'
-:str_td "#<rec-type>" '0000000000'
-:str_rec "#<record>" '00000000000000'
-:str_unknown "#<unknown>" '000000000000'
-:str_error_prefix "scheme1: error: "
+# sites (write_to_bv branches). They are emitted through cstr8 so the
+# labels remain aligned and are also safe as C strings if reused later.
+:str_false %cstr8("#f")
+:str_true %cstr8("#t")
+:str_nil %cstr8("()")
+:str_unspec %cstr8("#!unspec")
+:str_unbound %cstr8("#!unbound")
+:str_eof %cstr8("#!eof")
+:str_closure %cstr8("#<closure>")
+:str_prim %cstr8("#<prim>")
+:str_td %cstr8("#<rec-type>")
+:str_rec %cstr8("#<record>")
+:str_unknown %cstr8("#<unknown>")
+:str_error_prefix %cstr8("scheme1: error: ")
# Primitive registration table. Each entry: 8-byte name_ptr (4-byte label
# ref + 4 pad), 8-byte name_len, 8-byte entry_label (4 ref + 4 pad).
@@ -6339,36 +6331,36 @@
&name_call_with_values %(0) $(16) &prim_call_with_values_entry %(0)
:prim_table_end
-;; Each :msg_ entry must be an exact multiple of 8 bytes so that entries
-;; stay 8-aligned (text + M0-auto-NUL + '0a' + zero padding).
-;; len+2+pad == 0 mod 8 (len = text chars, 2 = NUL+'0a', pad = trailing zeros).
-:msg_usage "scheme1: usage: scheme1 SOURCE.scm" '0a' '00000000' ;; 34+1+1+4=40
-:msg_load_fail "scheme1: failed to read source" '0a' ;; 30+1+1+0=32
-:msg_symtab_full "scheme1: symbol table full" '0a' '00000000' ;; 26+1+1+4=32
-:msg_unexp_rparen "scheme1: unexpected ')'" '0a' '00000000000000' ;; 23+1+1+7=32
-:msg_bad_hash "scheme1: bad #-syntax" '0a' '00' ;; 21+1+1+1=24
-:msg_unexp_eof "scheme1: unexpected EOF in form" '0a' '00000000000000' ;; 31+1+1+7=40
-:msg_unterm_list "scheme1: unterminated list" '0a' '00000000' ;; 26+1+1+4=32
-:msg_unbound "scheme1: unbound variable" '0a' '0000000000' ;; 25+1+1+5=32
-:msg_not_proc "scheme1: not a procedure" '0a' '000000000000' ;; 24+1+1+6=32
-:msg_heap_full "scheme1: heap exhausted" '0a' '00000000000000' ;; 23+1+1+7=32
-:msg_scratch_full "scheme1: scratch exhausted" '0a' '00000000' ;; 26+1+1+4=32
-:msg_readbuf_full "scheme1: source buffer overflow" '0a' '00000000000000' ;; 31+1+1+7=40
-:msg_bv_oob "scheme1: bytevector index out of range" '0a' ;; 38+1+1+0=40
-:msg_unterm_string "scheme1: unterminated string literal" '0a' '0000' ;; 36+1+1+2=40
-:msg_bad_escape "scheme1: bad string escape" '0a' '00000000' ;; 26+1+1+4=32
-:msg_bad_char "scheme1: bad #\\ character literal" '0a' '00000000' ;; 34+1+1+4=40
-:msg_bad_number "scheme1: bad number literal" '0a' '000000' ;; 27+1+1+3=32
-:msg_bad_ident "scheme1: bad identifier" '0a' '00000000000000' ;; 23+1+1+7=32
-:msg_internal_define "scheme1: internal define is not supported" '0a' '0000000000' ;; 41+1+1+5=48
-:msg_pmatch_no_match "scheme1: pmatch: no clause matched" '0a' '00000000' ;; 34+1+1+4=40
-:msg_bad_unquote_pattern "scheme1: pmatch: malformed ,-pattern" '0a' '0000' ;; 36+1+1+2=40
-
-:name_ch_tab "tab" '00000000' ;; 3+1+4=8
-:name_ch_null "null" '000000' ;; 4+1+3=8
-:name_ch_space "space" '0000' ;; 5+1+2=8
-:name_ch_return "return" '00' ;; 6+1+1=8
-:name_ch_newline "newline" ;; 7+1+0=8
+;; Error messages are NUL-terminated C strings. The embedded newline
+;; keeps the old stderr formatting; runtime_error's panic path appends
+;; another newline, which shell command substitution trims in tests.
+:msg_usage %cstr8("scheme1: usage: scheme1 SOURCE.scm\n")
+:msg_load_fail %cstr8("scheme1: failed to read source\n")
+:msg_symtab_full %cstr8("scheme1: symbol table full\n")
+:msg_unexp_rparen %cstr8("scheme1: unexpected ')'\n")
+:msg_bad_hash %cstr8("scheme1: bad #-syntax\n")
+:msg_unexp_eof %cstr8("scheme1: unexpected EOF in form\n")
+:msg_unterm_list %cstr8("scheme1: unterminated list\n")
+:msg_unbound %cstr8("scheme1: unbound variable\n")
+:msg_not_proc %cstr8("scheme1: not a procedure\n")
+:msg_heap_full %cstr8("scheme1: heap exhausted\n")
+:msg_scratch_full %cstr8("scheme1: scratch exhausted\n")
+:msg_readbuf_full %cstr8("scheme1: source buffer overflow\n")
+:msg_bv_oob %cstr8("scheme1: bytevector index out of range\n")
+:msg_unterm_string %cstr8("scheme1: unterminated string literal\n")
+:msg_bad_escape %cstr8("scheme1: bad string escape\n")
+:msg_bad_char %cstr8("scheme1: bad #\\ character literal\n")
+:msg_bad_number %cstr8("scheme1: bad number literal\n")
+:msg_bad_ident %cstr8("scheme1: bad identifier\n")
+:msg_internal_define %cstr8("scheme1: internal define is not supported\n")
+:msg_pmatch_no_match %cstr8("scheme1: pmatch: no clause matched\n")
+:msg_bad_unquote_pattern %cstr8("scheme1: pmatch: malformed ,-pattern\n")
+
+:name_ch_tab %cstr8("tab")
+:name_ch_null %cstr8("null")
+:name_ch_space %cstr8("space")
+:name_ch_return %cstr8("return")
+:name_ch_newline %cstr8("newline")
# =========================================================================
# BSS arena table
diff --git a/scripts/disasm-elf.sh b/scripts/disasm-elf.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-## disasm-elf.sh — disassemble a hex2-emitted ELF with llvm-objdump.
+## disasm-elf.sh — disassemble a hex2pp-emitted ELF with llvm-objdump.
##
## Our seed ELF.hex2 sets ph_memsz to 512 MB (so the BSS region past
## ELF_end is mappable), but ph_filesz is just the on-disk size.
@@ -18,9 +18,10 @@
## override and see the header bytes.
##
## boot-build-p1*.sh writes a one-line sidecar at <elf>.workdir pointing
-## at build/$ARCH/.work/<src-without-ext>/, where prog.hex2 lives. When
-## that sidecar is present we extract a label map via scripts/m1-symbols.py
-## and:
+## at build/$ARCH/.work/<src-without-ext>/. P1pp builds store
+## expanded.hex2pp there; legacy raw-P1 seed builds store prog.hex2.
+## When that sidecar is present we extract a label map via
+## scripts/m1-symbols.py and:
## - default --stop-address to :_text_end if that sentinel label is
## present, so trailing rodata doesn't decode as bogus instructions
## - inject "<label>:" headers and rewrite "<PT_LOAD#0+0xNNN>" xrefs
@@ -86,10 +87,10 @@ if [ "$have_start" -eq 0 ]; then
set -- "--start-address=0x$(printf '%x' "$ENTRY")" "$@"
fi
-# Locate prog.hex2 via the <elf>.workdir sidecar produced by
-# boot-build-p1*.sh. The sidecar holds a repo-relative path
-# (build/$ARCH/.work/<src>/), so resolve it against the repo root
-# inferred from this script's location — works regardless of cwd.
+# Locate expanded.hex2pp (new P1pp path) or prog.hex2 (legacy raw-P1
+# path) via the <elf>.workdir sidecar produced by boot-build-p1*.sh.
+# The sidecar holds a repo-relative path (build/$ARCH/.work/<src>/), so
+# resolve it against the repo root inferred from this script's location.
HERE=$(dirname "$0")
REPO_ROOT=$(cd "$HERE/.." && pwd)
HEX2=""
@@ -99,10 +100,12 @@ if [ -e "$ELF.workdir" ]; then
/*) ;; # absolute, leave alone
*) workdir="$REPO_ROOT/$workdir" ;;
esac
- if [ -e "$workdir/prog.hex2" ]; then
+ if [ -e "$workdir/expanded.hex2pp" ]; then
+ HEX2="$workdir/expanded.hex2pp"
+ elif [ -e "$workdir/prog.hex2" ]; then
HEX2="$workdir/prog.hex2"
else
- echo "disasm-elf: $ELF.workdir -> $workdir, but no prog.hex2 there" >&2
+ echo "disasm-elf: $ELF.workdir -> $workdir, but no expanded.hex2pp or prog.hex2 there" >&2
fi
elif [ "${NO_LABELS:-0}" != "1" ]; then
echo "disasm-elf: no $ELF.workdir sidecar; rebuild for label annotation" >&2
diff --git a/scripts/m1-symbols.py b/scripts/m1-symbols.py
@@ -1,21 +1,29 @@
#!/usr/bin/env python3
-"""m1-symbols.py — extract labels from a hex2 file and annotate disassembly.
+"""m1-symbols.py — extract labels from a hex2/hex2pp file and annotate disassembly.
-The hex2 produced by M0 in this project uses a small grammar:
+The expanded hex2pp produced by M1pp in this project uses a small grammar:
:LABEL declares LABEL at the current byte offset (zero bytes)
- &LABEL 4-byte absolute address reference (low 32 bits of LABEL)
- 'XXXX... raw byte literal; (len(token)-1)/2 bytes (no closing quote)
+ !LABEL 1-byte relative label reference
+ @LABEL/$LABEL 2-byte label reference
+ ~LABEL 3-byte relative label reference
+ %LABEL/&LABEL ptrsize-byte label reference (4 by default)
XXXX... bare hex; len(token)/2 bytes
- # ... comment to end-of-line
+ .align N pads to N-byte boundary
+ .fill N B emits N copies of B
+ # ... / ; ... comment to end-of-line
+
+Legacy prog.hex2 files from the seed M0 path are still accepted; their
+'XXXX... raw byte literals are counted as before.
Label addresses = BASE + HEADER + cumulative byte offset, where BASE is the
ELF load address (0x600000) and HEADER is the size of the on-disk ELF header
-+ phdr that sits in front of M0's output (0x78 bytes for our seed ELF).
++ phdr that sits in front of expanded hex2pp/M0 output (0x78 bytes for our
+seed ELF).
Subcommands:
- map <prog.hex2> [--base 0x600000] [--header 0x78] [--ref-size 4]
+ map <expanded.hex2pp|prog.hex2> [--base 0x600000] [--header 0x78]
Print "0xADDR LABEL" lines, sorted by address.
annotate <map>
@@ -28,7 +36,8 @@ Subcommands:
delta=0). Pairs with `%trace`'s stderr output: paste a trace
address and get the enclosing function. With --elf, locates the
sibling <ELF>.workdir sidecar (written by boot-build-p1*.sh) to
- find prog.hex2, so you don't have to know the .work path.
+ find expanded.hex2pp or legacy prog.hex2, so you don't have to
+ know the .work path.
Reads addresses from stdin if none are passed positionally.
"""
@@ -37,18 +46,61 @@ import re
import sys
+REF_WIDTH = {
+ '!': 1,
+ '@': 2,
+ '$': 2,
+ '~': 3,
+}
+
+
+def _parse_int(tok):
+ return int(tok, 0)
+
+
def parse_hex2(path, ref_size=4):
"""Yield (offset, label) pairs in declaration order."""
offset = 0
+ ptrsize = ref_size
seen_unknown = set()
with open(path) as f:
for lineno, line in enumerate(f, 1):
- line = line.split('#', 1)[0]
- for tok in line.split():
+ line = line.split('#', 1)[0].split(';', 1)[0]
+ toks = line.split()
+ i = 0
+ while i < len(toks):
+ tok = toks[i]
if tok.startswith(':'):
yield offset, tok[1:]
- elif tok.startswith('&'):
- offset += ref_size
+ elif tok in ('.scope', '.endscope'):
+ pass
+ elif tok == '.ptrsize':
+ if i + 1 >= len(toks):
+ sys.stderr.write(f"{path}:{lineno}: missing .ptrsize value\n")
+ else:
+ ptrsize = _parse_int(toks[i + 1])
+ i += 1
+ elif tok == '.align':
+ if i + 1 >= len(toks):
+ sys.stderr.write(f"{path}:{lineno}: missing .align value\n")
+ else:
+ n = _parse_int(toks[i + 1])
+ offset += (-offset) % n
+ # Optional pad pattern is a source token but does not
+ # change the number of emitted bytes beyond the pad.
+ if i + 2 < len(toks) and re.fullmatch(r'[0-9A-Fa-f]+', toks[i + 2]):
+ i += 1
+ i += 1
+ elif tok == '.fill':
+ if i + 2 >= len(toks):
+ sys.stderr.write(f"{path}:{lineno}: missing .fill args\n")
+ else:
+ offset += _parse_int(toks[i + 1])
+ i += 2
+ elif tok[:1] in ('%', '&'):
+ offset += ptrsize
+ elif tok[:1] in REF_WIDTH:
+ offset += REF_WIDTH[tok[:1]]
elif tok.startswith("'"):
offset += (len(tok) - 1) // 2
elif re.fullmatch(r'[0-9A-Fa-f]+', tok):
@@ -63,6 +115,7 @@ def parse_hex2(path, ref_size=4):
f"{path}:{lineno}: skipping unrecognized token "
f"{tok!r} (subsequent same-prefix tokens silenced)\n"
)
+ i += 1
def cmd_map(args):
@@ -183,10 +236,11 @@ def _resolve_hex2_from_elf(elf_path):
repo_root = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..'))
workdir = os.path.join(repo_root, workdir)
- hex2 = os.path.join(workdir, 'prog.hex2')
- if not os.path.exists(hex2):
- sys.exit(f"m1-symbols: {sidecar} -> {workdir}, but no prog.hex2 there")
- return hex2
+ for name in ('expanded.hex2pp', 'prog.hex2'):
+ hex2 = os.path.join(workdir, name)
+ if os.path.exists(hex2):
+ return hex2
+ sys.exit(f"m1-symbols: {sidecar} -> {workdir}, but no expanded.hex2pp or prog.hex2 there")
def _build_map_from_args(args):
@@ -241,8 +295,8 @@ def main():
help='resolve addrs to nearest preceding label')
src = p_lk.add_mutually_exclusive_group(required=True)
src.add_argument('--elf', help='ELF path; uses <ELF>.workdir sidecar '
- 'to find prog.hex2')
- src.add_argument('--hex2', help='prog.hex2 path')
+ 'to find expanded.hex2pp or prog.hex2')
+ src.add_argument('--hex2', help='expanded.hex2pp or prog.hex2 path')
src.add_argument('--map', help='pre-built address->label map '
'(from `m1-symbols.py map`)')
p_lk.add_argument('--base', type=lambda s: int(s, 0), default=0x600000)