start throwing error on duplicate label

One less error that's only in the bootstrap phase.

On the other hand, for simplicity I got rid of the ability to override
the Entry label. One less special case, but we're also going further
from the ability to run subsets of layers. We haven't really been
exercising it for a long time, though (commit 7842, March 2021 when we
made baremetal the default).
This commit is contained in:
Kartik K. Agaram 2021-08-22 21:06:36 -07:00
parent b41aed4a9a
commit 827dd4a7fe
24 changed files with 385 additions and 76 deletions

View File

@ -5,9 +5,9 @@
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
Entry: # just exit; can't test _write just yet
bb/copy-to-ebx 0/imm32
e8/call syscall_exit/disp32
#? Entry: # just exit; can't test _write just yet
#? bb/copy-to-ebx 0/imm32
#? e8/call syscall_exit/disp32
_write: # fd: int, s: (addr array byte)
# . prologue

View File

@ -5,19 +5,19 @@
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
Entry: # manual test
# check-ints-equal(34, 34)
# . . push args
68/push "error in check-ints-equal"/imm32
68/push 34/imm32
68/push 34/imm32
# . . call
e8/call check-ints-equal/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# syscall_exit(0)
bb/copy-to-ebx 0/imm32
e8/call syscall_exit/disp32
#? Entry: # manual test
#? # check-ints-equal(34, 34)
#? # . . push args
#? 68/push "error in check-ints-equal"/imm32
#? 68/push 34/imm32
#? 68/push 34/imm32
#? # . . call
#? e8/call check-ints-equal/disp32
#? # . . discard args
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
#? # syscall_exit(0)
#? bb/copy-to-ebx 0/imm32
#? e8/call syscall_exit/disp32
# print msg to stderr if a != b, otherwise print "."
check-ints-equal: # a: int, b: int, msg: (addr array byte)

View File

@ -22,11 +22,11 @@
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
Entry: # run all tests
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
# syscall_exit(Num-test-failures)
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
e8/call syscall_exit/disp32
#? Entry: # run all tests
#? e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
#? # syscall_exit(Num-test-failures)
#? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
#? e8/call syscall_exit/disp32
kernel-string-equal?: # s: (addr kernel-string), benchmark: (addr array byte) -> result/eax: boolean
# pseudocode:

View File

@ -16,26 +16,26 @@
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
Entry: # manual test
# var ad/ecx: allocation-descriptor
68/push 0/imm32/limit
68/push 0/imm32/curr
89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
# new-segment(0x1000, ad)
# . . push args
51/push-ecx
68/push 0x1000/imm32
# . . call
e8/call new-segment/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# var eax: (addr _) = ad->curr
8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
# write to *eax to check that we have access to the newly-allocated segment
c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0x34/imm32 # copy to *eax
# syscall_exit(eax)
89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx
e8/call syscall_exit/disp32
#? Entry: # manual test
#? # var ad/ecx: allocation-descriptor
#? 68/push 0/imm32/limit
#? 68/push 0/imm32/curr
#? 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
#? # new-segment(0x1000, ad)
#? # . . push args
#? 51/push-ecx
#? 68/push 0x1000/imm32
#? # . . call
#? e8/call new-segment/disp32
#? # . . discard args
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
#? # var eax: (addr _) = ad->curr
#? 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
#? # write to *eax to check that we have access to the newly-allocated segment
#? c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0x34/imm32 # copy to *eax
#? # syscall_exit(eax)
#? 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx
#? e8/call syscall_exit/disp32
new-segment: # len: int, ad: (addr allocation-descriptor)
# . prologue

View File

@ -5,12 +5,12 @@
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
Entry: # run all tests
#? e8/call test-compare-equal-strings/disp32
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
# syscall_exit(Num-test-failures)
8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
e8/call syscall_exit/disp32
#? Entry: # run all tests
#? #? e8/call test-compare-equal-strings/disp32
#? e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
#? # syscall_exit(Num-test-failures)
#? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx
#? e8/call syscall_exit/disp32
string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> result/eax: boolean
# pseudocode:

View File

@ -42,18 +42,18 @@ Next-alloc-id: # int
# . op subop mod rm32 base index scale r32
# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
# Let's start initializing the default allocation descriptor.
Entry:
# initialize heap
# . Heap = new-segment(Heap-size)
# . . push args
68/push Heap/imm32
ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size
# . . call
e8/call new-segment/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
#? # Let's start initializing the default allocation descriptor.
#?
#? Entry:
#? # initialize heap
#? # . Heap = new-segment(Heap-size)
#? # . . push args
#? 68/push Heap/imm32
#? ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size
#? # . . call
#? e8/call new-segment/disp32
#? # . . discard args
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
$array-equal-main:end:

View File

@ -700,6 +700,154 @@ $test-get-or-insert:end:
5d/pop-to-ebp
c3/return
# save 'key' to the next available row
# if key already exists, abort
# if there are no rows free, abort
# return the address of the value
insert-or-abort: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int, ad: (addr allocation-descriptor) -> result/eax: (addr T)
# pseudocode:
# curr = table->data
# max = &table->data[table->write]
# while curr < max
# var c: (addr array byte) = lookup(*curr)
# if string-equal?(key, c)
# abort
# curr += row-size
# if table->write >= table->size
# abort
# zero-out(max, row-size)
# copy-array(ad, key, max)
# table->write += row-size
# return max+8
#
# . prologue
55/push-ebp
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# . save registers
51/push-ecx
52/push-edx
56/push-esi
# esi = table
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# var curr/ecx: (addr handle array byte) = table->data
8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx
# var max/edx: (addr byte) = &table->data[table->write]
8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx
$insert-or-abort:search-loop:
# if (curr >= max) break
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
73/jump-if-addr>= $insert-or-abort:not-found/disp8
# var c/eax: (addr array byte) = lookup(*curr)
# . . push args
ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4)
ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx
# . . call
e8/call lookup/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# if (string-equal?(key, c)) abort
# . eax = string-equal?(key, c)
# . . push args
50/push-eax
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
# . . call
e8/call string-equal?/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . if (eax != false) abort
3d/compare-eax-and 0/imm32/false
0f 85/jump-if-!= $insert-or-abort:error-duplicate/disp32
# curr += row-size
03/add 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # add *(ebp+16) to ecx
# loop
eb/jump $insert-or-abort:search-loop/disp8
$insert-or-abort:not-found:
# if (table->write >= table->size) abort
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8)
0f 83/jump-if-addr>= $insert-or-abort:error-full/disp32
# zero-out(max, row-size)
# . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
52/push-edx
# . . call
e8/call zero-out/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# copy-array(ad, key, max)
# . . push args
52/push-edx
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20)
# . . call
e8/call copy-array/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# table->write += row-size
# . eax = row-size
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
# . table->write += eax
01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi
# return max+8
# . eax = max
89/copy 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # copy edx to eax
# . eax += 8
05/add-to-eax 8/imm32
$insert-or-abort:end:
# . restore registers
5e/pop-to-esi
5a/pop-to-edx
59/pop-to-ecx
# . epilogue
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
5d/pop-to-ebp
c3/return
$insert-or-abort:error-duplicate:
# . _write(2/stderr, error)
# . . push args
68/push "insert-or-abort: key already exists: "/imm32
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . _write(2/stderr, key)
# . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . _write(2/stderr, "\n")
# . . push args
68/push "\n"/imm32
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . syscall_exit(1)
bb/copy-to-ebx 1/imm32
e8/call syscall_exit/disp32
# never gets here
$insert-or-abort:error-full:
# . _write(2/stderr, error)
# . . push args
68/push "insert-or-abort: table is full\n"/imm32
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . syscall_exit(1)
bb/copy-to-ebx 1/imm32
e8/call syscall_exit/disp32
# never gets here
# if no row is found, save 'key' to the next available row
# if there are no rows free, abort
# return the address of the value
@ -1321,6 +1469,169 @@ $test-get-or-insert-slice:end:
5d/pop-to-ebp
c3/return
# if no row is found, save 'key' in the next available row
# if there are no rows free, abort
insert-slice-or-abort: # table: (addr stream {(handle array byte), T}), key: (addr slice), row-size: int, ad: (addr allocation-descriptor) -> result/eax: (addr T)
# pseudocode:
# curr = table->data
# max = &table->data[table->write]
# while curr < max
# var c: (addr array byte) = lookup(*curr)
# if slice-equal?(key, *curr)
# return curr+8
# curr += row-size
# if table->write >= table->size
# abort
# zero-out(max, row-size)
# slice-to-string(ad, key, max)
# table->write += row-size
# return max+8
#
# . prologue
55/push-ebp
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# . save registers
51/push-ecx
52/push-edx
56/push-esi
# esi = table
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# var curr/ecx: (addr handle array byte) = table->data
8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx
# var max/edx: (addr byte) = &table->data[table->write]
8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx
$insert-slice-or-abort:search-loop:
# if (curr >= max) break
39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
73/jump-if-addr>= $insert-slice-or-abort:not-found/disp8
# var c/eax: (addr array byte) = lookup(*curr)
# . . push args
ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4)
ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx
# . . call
e8/call lookup/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# if (slice-equal?(key, c)) abort
# . eax = slice-equal?(key, c)
# . . push args
50/push-eax
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
# . . call
e8/call slice-equal?/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . if (eax != false) abort
3d/compare-eax-and 0/imm32/false
0f 85/jump-if-!= $insert-slice-or-abort:error-duplicate/disp32
# curr += row-size
03/add 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # add *(ebp+16) to ecx
# loop
eb/jump $insert-slice-or-abort:search-loop/disp8
$insert-slice-or-abort:not-found:
# result/eax = 0
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
# if (table->write >= table->size) abort
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(esi+8)
0f 8d/jump-if->= $insert-slice-or-abort:error-full/disp32
# zero-out(max, row-size)
# . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
52/push-edx
# . . call
e8/call zero-out/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# slice-to-string(ad, key, max)
# . . push args
52/push-edx
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20)
# . . call
e8/call slice-to-string/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
# table->write += row-size
# . eax = row-size
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
# . table->write += eax
01/add 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # add eax to *esi
# return max+8
# . eax = max
89/copy 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # copy edx to eax
# . eax += 8
05/add-to-eax 8/imm32
$insert-slice-or-abort:end:
# . restore registers
5e/pop-to-esi
5a/pop-to-edx
59/pop-to-ecx
# . epilogue
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
5d/pop-to-ebp
c3/return
$insert-slice-or-abort:error-duplicate:
# . flush(Stderr)
# . . push args
68/push Stderr/imm32
# . . call
e8/call flush/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# . _write(2/stderr, error)
# . . push args
68/push "insert-slice-or-abort: key already exists: "/imm32
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . write-slice-buffered(Stderr, key)
# . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
68/push Stderr/imm32
# . . call
e8/call write-slice-buffered/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . flush(Stderr)
# . . push args
68/push Stderr/imm32
# . . call
e8/call flush/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
# . _write(2/stderr, "\n")
# . . push args
68/push "\n"/imm32
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . syscall_exit(1)
bb/copy-to-ebx 1/imm32
e8/call syscall_exit/disp32
# never gets here
$insert-slice-or-abort:error-full:
# . _write(2/stderr, error)
# . . push args
68/push "insert-slice-or-abort: table is full\n"/imm32
68/push 2/imm32/stderr
# . . call
e8/call _write/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
# . syscall_exit(1)
bb/copy-to-ebx 1/imm32
e8/call syscall_exit/disp32
# never gets here
# if no row is found, stop(ed)
get-or-stop: # table: (addr stream {(handle array byte), T}), key: (addr array byte), row-size: int,
# abort-message-prefix: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
linux/hex

Binary file not shown.

Binary file not shown.

View File

@ -216,7 +216,7 @@ load-labels: # in: (addr buffered-file), labels: (stream {label-name, address}
# read-line-buffered(in, line)
# if (line->write == 0) break # end of file
# var word-slice/ecx: (addr slice) = next-word(line)
# var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row)
# var dest/edi: (addr int) = insert-slice-or-abort(labels, word-slice, 12 bytes/row)
# word-slice = next-word(line)
# var address/eax: int = parse-hex-int-from-slice(word-slice)
# *dest = address
@ -333,15 +333,15 @@ $load-labels:loop:
#? # . . discard args
#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
#? # }}}
# var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap)
# . eax = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap)
# var dest/edi: (addr int) = insert-slice-or-abort(labels, word-slice, 12 bytes/row, Heap)
# . eax = insert-slice-or-abort(labels, word-slice, 12 bytes/row, Heap)
# . . push args
68/push Heap/imm32
68/push 0xc/imm32/row-size
52/push-edx
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
# . . call
e8/call get-or-insert-slice/disp32
e8/call insert-slice-or-abort/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
# . edi = eax

BIN
linux/mu

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -468,6 +468,8 @@ compute-addresses: # in: (addr stream byte), labels: (addr stream {(handle arra
# current-address = new-address
# else if label?(word-slice)
# strip trailing ':' from word-slice
# var tmp/eax: (addr int) = insert-slice-or-abort(labels, word-slice)
# *tmp = current-address
# trace("label '" word-slice "' is at address " current-address ".")
# # labels occupy no space, so no need to increment offsets
# else
@ -661,14 +663,14 @@ $compute-addresses:case-label:
0f 84/jump-if-= $compute-addresses:case-default/disp32
# strip trailing ':' from word-slice
ff 1/subop/decrement 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # decrement *(edx+4)
# var tmp/eax: (addr int) = get-or-insert-slice(labels, word-slice, row-size=12)
# var tmp/eax: (addr int) = insert-slice-or-abort(labels, word-slice, row-size=12)
# . . push args
68/push Heap/imm32
68/push 0xc/imm32/row-size
52/push-edx
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
# . . call
e8/call get-or-insert-slice/disp32
e8/call insert-slice-or-abort/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
# *tmp = current-address

Binary file not shown.

View File

@ -451,7 +451,7 @@ compute-offsets: # in: (addr stream byte), segments: (addr stream {(handle arra
# break (next line)
# else if label?(word-slice)
# strip trailing ':' from word-slice
# linfo: (addr label-info) = get-or-insert-slice(labels, word-slice)
# linfo: (addr label-info) = insert-slice-or-abort(labels, word-slice)
# linfo->segment-name = curr-segment-name
# trace("label '", word-slice, "' is in segment '", curr-segment-name, "'.")
# linfo->segment-offset = segment-offset
@ -753,15 +753,15 @@ $compute-offsets:case-label:
0f 84/jump-if-= $compute-offsets:case-default/disp32
# strip trailing ':' from word-slice
ff 1/subop/decrement 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # decrement *(edx+4)
# linfo/edi = get-or-insert-slice(labels, word-slice, row-size=24)
# . eax = get-or-insert-slice(labels, word-slice, row-size=24)
# linfo/edi = insert-slice-or-abort(labels, word-slice, row-size=24)
# . eax = insert-slice-or-abort(labels, word-slice, row-size=24)
# . . push args
68/push Heap/imm32
68/push 0x18/imm32/row-size
52/push-edx
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
# . . call
e8/call get-or-insert-slice/disp32
e8/call insert-slice-or-abort/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
# . edi = eax

View File

@ -227,7 +227,7 @@ test "$1" = 'record' || git diff --exit-code sigils
}
echo calls
cat [012]*.subx subx-params.subx calls.subx | sigils > a.sigils
cat [012]*.subx subx-params.subx calls.subx | ./sigils > a.sigils
bootstrap/bootstrap translate a.sigils -o calls
test "$1" = 'record' || git diff --exit-code calls
{
@ -241,7 +241,7 @@ test "$1" = 'record' || git diff --exit-code calls
}
echo braces
cat [012]*.subx subx-params.subx braces.subx | calls | sigils > a.sigils
cat [012]*.subx subx-params.subx braces.subx | ./calls | ./sigils > a.sigils
bootstrap/bootstrap translate a.sigils -o braces
test "$1" = 'record' || git diff --exit-code braces
{
@ -255,7 +255,7 @@ test "$1" = 'record' || git diff --exit-code braces
}
echo mu
cat [0-2]*.subx mu.subx | braces | calls | sigils > a.sigils
cat [0-2]*.subx mu.subx | ./braces | ./calls | ./sigils > a.sigils
bootstrap/bootstrap translate a.sigils -o mu
test "$1" = 'record' || git diff --exit-code mu
{

Binary file not shown.

View File

@ -138,10 +138,6 @@ Functions are called using the following syntax:
Function arguments must be either literals (integers or strings) or a reg/mem
operand using the syntax in the previous section.
A special label on Linux is `Entry`, which can be used to specify/override the
entry point of the program. It doesn't have to be unique, and the latest
definition will override earlier ones.
Another special pair of labels are the block delimiters `{` and `}`. They can
be nested, and jump instructions can take arguments `loop` or `break` that
jump to the enclosing `{` and `}` respectively.