From 5396e24cba8390ca2d70d99c7e8772eee4ec3a11 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 18 May 2021 13:01:59 -0700 Subject: [PATCH] . --- html/102keyboard.subx.html | 2 +- html/103grapheme.subx.html | 2 +- html/108write.subx.html | 10 +- html/112read-byte.subx.html | 43 +- html/115write-byte.subx.html | 75 +- html/118parse-hex-int.subx.html | 19 +- html/120allocate.subx.html | 1577 +- html/121new-stream.subx.html | 135 +- html/123slice.subx.html | 386 +- html/126write-int-decimal.subx.html | 572 +- html/301array-equal.subx.html | 14 +- html/302stack_allocate.subx.html | 2 +- html/308allocate-array.subx.html | 2 +- html/309stream.subx.html | 404 +- html/310copy-bytes.subx.html | 18 +- html/311decimal-int.subx.html | 16 +- html/312copy.subx.html | 2 +- html/313index-bounds-check.subx.html | 50 +- html/315stack-debug.subx.html | 6 +- html/316colors.subx.html | 2 +- html/317abort.subx.html | 394 + html/400.mu.html | 200 +- html/411string.mu.html | 20 +- html/500fake-screen.mu.html | 71 +- html/501draw-text.mu.html | 11 - html/506math.mu.html | 114 + html/507line.mu.html | 171 + html/508circle.mu.html | 152 + html/509bezier.mu.html | 378 + html/boot.subx.html | 554 +- html/colors.mu.html | 6 +- html/ex10.mu.html | 2 +- html/ex11.mu.html | 323 + html/ex2.mu.html | 11 +- html/ex9.mu.html | 4 +- html/hest-life.mu.html | 1089 + html/life.mu.html | 4 +- html/linux/304screen.subx.html | 2 +- html/linux/306files.subx.html | 332 +- html/linux/311decimal-int.subx.html | 2 +- html/linux/312copy.subx.html | 2 +- html/linux/313index-bounds-check.subx.html | 188 +- html/linux/400.mu.html | 6 +- html/linux/404stream.mu.html | 4 +- html/linux/bootstrap/017jump_disp8.cc.html | 24 + html/linux/bootstrap/018jump_disp32.cc.html | 24 + html/linux/braces.subx.html | 84 +- html/linux/branches.mu.html | 99 + html/linux/calls.subx.html | 28 +- html/linux/labels_baremetal.subx.html | 2458 + html/linux/mu.subx.html | 61381 +++++++++--------- html/linux/print-file.mu.html | 2 +- html/linux/sigils.subx.html | 34 +- html/linux/stack_array.subx.html | 699 + html/linux/survey_baremetal.subx.html | 3656 +- html/linux/survey_elf.subx.html | 4 +- html/linux/tile/rpn.mu.html | 2 +- html/mandelbrot-fixed.mu.html | 454 +- html/mandelbrot.mu.html | 303 +- html/mu-init.subx.html | 41 +- html/mu_instructions.html | 4 + html/rpn.mu.html | 4 +- html/shell/cell.mu.html | 377 +- html/shell/evaluate.mu.html | 2578 +- html/shell/gap-buffer.mu.html | 36 +- html/shell/global.mu.html | 3984 +- html/shell/grapheme-stack.mu.html | 22 +- html/shell/macroexpand.mu.html | 428 + html/shell/main.mu.html | 169 +- html/shell/parse.mu.html | 410 +- html/shell/print.mu.html | 452 +- html/shell/sandbox.mu.html | 659 +- html/shell/tokenize.mu.html | 1622 +- html/shell/trace.mu.html | 2619 +- 74 files changed, 47941 insertions(+), 42093 deletions(-) create mode 100644 html/317abort.subx.html create mode 100644 html/506math.mu.html create mode 100644 html/507line.mu.html create mode 100644 html/508circle.mu.html create mode 100644 html/509bezier.mu.html create mode 100644 html/ex11.mu.html create mode 100644 html/hest-life.mu.html create mode 100644 html/linux/branches.mu.html create mode 100644 html/linux/labels_baremetal.subx.html create mode 100644 html/linux/stack_array.subx.html create mode 100644 html/shell/macroexpand.mu.html diff --git a/html/102keyboard.subx.html b/html/102keyboard.subx.html index eb272040..b4fd8a3b 100644 --- a/html/102keyboard.subx.html +++ b/html/102keyboard.subx.html @@ -94,7 +94,7 @@ if ('onhashchange' in window) { 37 # var next-key/eax: byte = *buffer-byte-addr 38 8a/byte-> *ecx 0/r32/AL 39 # if (next-key != 0) lock and remove from keyboard buffer -40 81 7/subop/compare %eax 0/imm32 +40 3d/compare-eax-with 0/imm32 41 { 42 74/jump-if-= break/disp8 43 fa/disable-interrupts diff --git a/html/103grapheme.subx.html b/html/103grapheme.subx.html index 915dd02b..fdbf0e99 100644 --- a/html/103grapheme.subx.html +++ b/html/103grapheme.subx.html @@ -102,7 +102,7 @@ if ('onhashchange' in window) { 45 # var xcurr/eax: int = x*8 + 7 46 8b/-> *(ebp+0xc) 0/r32/eax # font-width - 1 47 c1 4/subop/shift-left %eax 3/imm8 - 48 81 0/subop/add %eax 7/imm32 + 48 05/add-to-eax 7/imm32 49 # var xmin/ecx: int = x*8 50 8b/-> *(ebp+0xc) 1/r32/ecx 51 c1 4/subop/shift-left %ecx 3/imm8 diff --git a/html/108write.subx.html b/html/108write.subx.html index 4249e689..7f5a6178 100644 --- a/html/108write.subx.html +++ b/html/108write.subx.html @@ -254,7 +254,7 @@ if ('onhashchange' in window) { 194 73/jump-if-addr>= $_append-4:end/disp8 195 # if (out >= outend) abort # just to catch test failures fast 196 39/compare 3/mod/direct 7/rm32/edi . . . 2/r32/edx . . # compare edi with edx -197 73/jump-if-addr>= $_append-4:end/disp8 # TODO: abort +197 0f 83/jump-if-addr>= $_append-4:abort/disp32 198 # *out = *in 199 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 3/r32/BL . . # copy byte at *esi to BL 200 88/copy-byte 0/mod/indirect 7/rm32/edi . . . 3/r32/BL . . # copy byte at BL to *edi @@ -277,7 +277,13 @@ if ('onhashchange' in window) { 217 5d/pop-to-ebp 218 c3/return 219 -220 # . . vim:nowrap:textwidth=0 +220 $_append-4:abort: +221 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "_append-4: stream full at " 3 0) # 3=cyan +222 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax 3 0) +223 (abort "") +224 # never gets here +225 +226 # . . vim:nowrap:textwidth=0 diff --git a/html/112read-byte.subx.html b/html/112read-byte.subx.html index 8ec265a5..95e260c6 100644 --- a/html/112read-byte.subx.html +++ b/html/112read-byte.subx.html @@ -82,7 +82,7 @@ if ('onhashchange' in window) { 23 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 24 # if (f->read >= f->write) abort 25 3b/compare 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # compare ecx with *esi - 26 0f 8d/jump-if->= $read-byte:abort/disp32 + 26 0f 8d/jump-if->= $read-byte:abort/disp32 27 # result = f->data[f->read] 28 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 29 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL @@ -97,23 +97,23 @@ if ('onhashchange' in window) { 38 5d/pop-to-ebp 39 c3/return 40 - 41 $read-byte:abort: - 42 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "read-byte: empty stream" 3 0) # 3=cyan - 43 { - 44 eb/jump loop/disp8 - 45 } - 46 # never gets here - 47 - 48 == data - 49 - 50 _test-input-stream: # (stream byte) - 51 # current write index - 52 0/imm32 - 53 # current read index - 54 0/imm32 - 55 # size - 56 0x400/imm32 # 1024 bytes - 57 # data (64 lines x 16 bytes/line) + 41 $read-byte:abort: + 42 (abort "read-byte: empty stream") + 43 # never gets here + 44 + 45 == data + 46 + 47 _test-input-stream: # (stream byte) + 48 # current write index + 49 0/imm32 + 50 # current read index + 51 0/imm32 + 52 # size + 53 0x400/imm32 # 1024 bytes + 54 # data (64 lines x 16 bytes/line) + 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 56 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 58 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -175,11 +175,8 @@ if ('onhashchange' in window) { 116 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 117 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 118 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -119 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -121 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -122 -123 # . . vim:nowrap:textwidth=0 +119 +120 # . . vim:nowrap:textwidth=0 diff --git a/html/115write-byte.subx.html b/html/115write-byte.subx.html index a2e626f2..7ac34eb1 100644 --- a/html/115write-byte.subx.html +++ b/html/115write-byte.subx.html @@ -83,7 +83,7 @@ if ('onhashchange' in window) { 23 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx 24 # if (f->write >= f->size) abort 25 3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(edi+8) -26 7d/jump-if->= $append-byte:abort/disp8 +26 7d/jump-if->= $append-byte:abort/disp8 27 $append-byte:to-stream: 28 # write to stream 29 # f->data[f->write] = LSB(n) @@ -102,44 +102,41 @@ if ('onhashchange' in window) { 42 5d/pop-to-ebp 43 c3/return 44 -45 $append-byte:abort: -46 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "append-byte: out of space\n" 3 0) # 3=cyan -47 { -48 eb/jump loop/disp8 -49 } -50 # never gets here -51 -52 test-append-byte-single: -53 # - check that append-byte writes to first byte of 'file' -54 # setup -55 # . clear-stream(_test-stream) -56 # . . push args -57 68/push _test-stream/imm32 -58 # . . call -59 e8/call clear-stream/disp32 -60 # . . discard args -61 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -62 # append-byte(_test-stream, 'A') -63 # . . push args -64 68/push 0x41/imm32 -65 68/push _test-stream/imm32 -66 # . . call -67 e8/call append-byte/disp32 -68 # . . discard args -69 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -70 # check-stream-equal(_test-stream, "A", msg) -71 # . . push args -72 68/push "F - test-append-byte-single"/imm32 -73 68/push "A"/imm32 -74 68/push _test-stream/imm32 -75 # . . call -76 e8/call check-stream-equal/disp32 -77 # . . discard args -78 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -79 # . end -80 c3/return -81 -82 # . . vim:nowrap:textwidth=0 +45 $append-byte:abort: +46 (abort "append-byte: out of space") +47 # never gets here +48 +49 test-append-byte-single: +50 # - check that append-byte writes to first byte of 'file' +51 # setup +52 # . clear-stream(_test-stream) +53 # . . push args +54 68/push _test-stream/imm32 +55 # . . call +56 e8/call clear-stream/disp32 +57 # . . discard args +58 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +59 # append-byte(_test-stream, 'A') +60 # . . push args +61 68/push 0x41/imm32 +62 68/push _test-stream/imm32 +63 # . . call +64 e8/call append-byte/disp32 +65 # . . discard args +66 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +67 # check-stream-equal(_test-stream, "A", msg) +68 # . . push args +69 68/push "F - test-append-byte-single"/imm32 +70 68/push "A"/imm32 +71 68/push _test-stream/imm32 +72 # . . call +73 e8/call check-stream-equal/disp32 +74 # . . discard args +75 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +76 # . end +77 c3/return +78 +79 # . . vim:nowrap:textwidth=0 diff --git a/html/118parse-hex-int.subx.html b/html/118parse-hex-int.subx.html index 50b2f1f4..65501a2b 100644 --- a/html/118parse-hex-int.subx.html +++ b/html/118parse-hex-int.subx.html @@ -924,11 +924,11 @@ if ('onhashchange' in window) { 865 $from-hex-char:check0: 866 # if (eax < '0') goto abort 867 3d/compare-eax-with 0x30/imm32/0 -868 7c/jump-if-< $from-hex-char:abort/disp8 +868 7c/jump-if-< $from-hex-char:abort/disp8 869 $from-hex-char:check1: 870 # if (eax > 'f') goto abort 871 3d/compare-eax-with 0x66/imm32/f -872 7f/jump-if-> $from-hex-char:abort/disp8 +872 7f/jump-if-> $from-hex-char:abort/disp8 873 $from-hex-char:check2: 874 # if (eax > '9') goto next check 875 3d/compare-eax-with 0x39/imm32/9 @@ -940,20 +940,17 @@ if ('onhashchange' in window) { 881 $from-hex-char:check3: 882 # if (eax < 'a') goto abort 883 3d/compare-eax-with 0x61/imm32/a -884 7c/jump-if-< $from-hex-char:abort/disp8 +884 7c/jump-if-< $from-hex-char:abort/disp8 885 $from-hex-char:letter: 886 # return eax - ('a'-10) 887 2d/subtract-from-eax 0x57/imm32/a-10 888 c3/return 889 -890 $from-hex-char:abort: -891 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "invalid hex char" 3 0) # 3=cyan -892 { -893 eb/jump loop/disp8 -894 } -895 # never gets here -896 -897 # . . vim:nowrap:textwidth=0 +890 $from-hex-char:abort: +891 (abort "invalid hex char") +892 # never gets here +893 +894 # . . vim:nowrap:textwidth=0 diff --git a/html/120allocate.subx.html b/html/120allocate.subx.html index cd7568b7..e5b5d820 100644 --- a/html/120allocate.subx.html +++ b/html/120allocate.subx.html @@ -125,7 +125,7 @@ if ('onhashchange' in window) { 64 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 65 50/push-eax 66 # . . call - 67 e8/call zero-out/disp32 + 67 e8/call zero-out/disp32 68 # . . discard args 69 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 70 $allocate:end: @@ -173,7 +173,7 @@ if ('onhashchange' in window) { 112 # TODO: move this check up before any state updates when we support error recovery 113 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 3/index/ebx . 0/r32/eax 4/disp8 . # copy eax+ebx+4 to eax 114 3b/compare 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # compare eax with *(ecx+4) -115 73/jump-if->=-signed $allocate-raw:abort/disp8 +115 73/jump-if->=-signed $allocate-raw:abort/disp8 116 $allocate-raw:commit: 117 # ad->curr += n+4 118 89/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy eax to *ecx @@ -190,789 +190,810 @@ if ('onhashchange' in window) { 129 5d/pop-to-ebp 130 c3/return 131 -132 $allocate-raw:abort: -133 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "allocate: failed" 3 0) # 3=cyan -134 { -135 eb/jump loop/disp8 -136 } -137 # never gets here -138 -139 test-allocate-raw-success: -140 # . prologue -141 55/push-ebp -142 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -143 # var ad/ecx: allocation-descriptor containing 16 bytes -144 # . var end/ecx: (addr byte) -145 89/<- %ecx 4/r32/esp -146 # . var start/edx: (addr byte) = end - 16 -147 81 5/subop/subtract %esp 0x10/imm32 -148 89/<- %edx 4/r32/esp -149 # . ad = {start, end} -150 51/push-ecx -151 52/push-edx -152 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -153 # var expected-payload/ebx = ad->curr -154 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx -155 # var h/edx: handle = {0, 0} -156 68/push 0/imm32 -157 68/push 0/imm32 -158 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx -159 # *Next-alloc-id = 0x34 -160 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id -161 # allocate-raw(ad, 3, h) -162 # . . push args -163 52/push-edx -164 68/push 3/imm32 -165 51/push-ecx -166 # . . call -167 e8/call allocate-raw/disp32 -168 # . . discard args -169 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -170 # check-ints-equal(h->alloc-id, 0x34, msg) -171 # . . push args -172 68/push "F - test-allocate-raw-success: sets alloc-id in handle"/imm32 -173 68/push 0x34/imm32 -174 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx -175 # . . call -176 e8/call check-ints-equal/disp32 -177 # . . discard args -178 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -179 # check-ints-equal(h->payload, expected-payload, msg) -180 # . . push args -181 68/push "F - test-allocate-raw-success: sets payload in handle"/imm32 -182 53/push-ebx -183 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) -184 # . . call -185 e8/call check-ints-equal/disp32 -186 # . . discard args -187 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -188 # check-ints-equal(h->payload->alloc-id, 0x34, msg) -189 # . . push args -190 68/push "F - test-allocate-raw-success: sets alloc-id in payload"/imm32 -191 68/push 0x34/imm32 -192 ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx -193 # . . call -194 e8/call check-ints-equal/disp32 -195 # . . discard args -196 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -197 # check-ints-equal(*Next-alloc-id, 0x35, msg) -198 # . . push args -199 68/push "F - test-allocate-raw-success: increments Next-alloc-id"/imm32 -200 68/push 0x35/imm32 -201 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id -202 # . . call -203 e8/call check-ints-equal/disp32 -204 # . . discard args -205 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -206 # check-ints-equal(ad->curr - expected-payload, 3 + 4 for alloc-id, msg) -207 # . . push args -208 68/push "F - test-allocate-raw-success: updates allocation descriptor"/imm32 -209 68/push 7/imm32 -210 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -211 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax -212 50/push-eax -213 # . . call -214 e8/call check-ints-equal/disp32 -215 # . . discard args -216 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -217 # clean up -218 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x100/imm32 # copy to *Next-alloc-id -219 # . reclaim locals -220 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp -221 # . epilogue -222 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -223 5d/pop-to-ebp -224 c3/return -225 -226 lookup: # h: (handle _T) -> result/eax: (addr _T) -227 # . prologue -228 55/push-ebp -229 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -230 # . save registers -231 51/push-ecx -232 # eax = 0 -233 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -234 # ecx = handle->alloc_id -235 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -236 # if (ecx == 0) return 0 -237 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0/imm32 # compare ecx -238 74/jump-if-= $lookup:end/disp8 -239 # eax = handle->address (payload) -240 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax -241 # if (ecx != *eax) abort -242 39/compare 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # compare *eax and ecx -243 75/jump-if-!= $lookup:abort/disp8 -244 # add 4 to eax -245 05/add-to-eax 4/imm32 -246 $lookup:end: -247 # . restore registers -248 59/pop-to-ecx -249 # . epilogue -250 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -251 5d/pop-to-ebp -252 c3/return -253 -254 $lookup:abort: -255 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "lookup: failed" 3 0) # 3=cyan -256 { -257 eb/jump loop/disp8 -258 } -259 # never gets here -260 -261 test-lookup-success: -262 # . prologue -263 55/push-ebp -264 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -265 # var ad/ebx: allocation-descriptor containing 16 bytes -266 # . var end/ecx: (addr byte) -267 89/<- %ecx 4/r32/esp -268 # . var start/edx: (addr byte) = end - 16 -269 81 5/subop/subtract %esp 0x10/imm32 -270 89/<- %edx 4/r32/esp -271 # . ad = {start, end} -272 51/push-ecx -273 52/push-edx -274 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx -275 # var handle/ecx: handle -276 68/push 0/imm32/address -277 68/push 0/imm32/alloc-id -278 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -279 # var old-top/edx = ad->curr -280 8b/copy 0/mod/indirect 3/rm32/ebx . . . 2/r32/edx . . # copy *ebx to edx -281 # allocate-raw(ad, 2, handle) -282 # . . push args -283 51/push-ecx -284 68/push 2/imm32/size -285 53/push-ebx -286 # . . call -287 e8/call allocate-raw/disp32 -288 # . . discard args -289 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -290 # eax = lookup(handle) -291 # . . push args -292 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) -293 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx -294 # . . call -295 e8/call lookup/disp32 -296 # . . discard args -297 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -298 # eax contains old top of heap, except skipping the alloc-id in the payload -299 # . check-ints-equal(eax, old-top+4, msg) -300 # . . push args -301 68/push "F - test-lookup-success"/imm32 -302 81 0/subop/add 3/mod/direct 2/rm32/edx . . . . . 4/imm32 # add to edx -303 52/push-edx -304 50/push-eax -305 # . . call -306 e8/call check-ints-equal/disp32 -307 # . . discard args -308 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -309 # clean up -310 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x100/imm32 # copy to *Next-alloc-id -311 # . reclaim locals -312 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp -313 # . epilogue -314 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -315 5d/pop-to-ebp -316 c3/return -317 -318 test-lookup-null-returns-null: -319 # . prologue -320 55/push-ebp -321 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -322 # var handle/ecx: handle -323 68/push 0/imm32/address -324 68/push 0/imm32/alloc-id -325 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -326 # eax = lookup(handle) -327 # . . push args -328 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) -329 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx -330 # . . call -331 e8/call lookup/disp32 -332 # . . discard args -333 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -334 # check-ints-equal(eax, 0, msg) -335 # . . push args -336 68/push "F - test-lookup-null-returns-null"/imm32 -337 68/push 0/imm32 -338 50/push-eax -339 # . . call -340 e8/call check-ints-equal/disp32 -341 # . . discard args -342 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -343 # . reclaim locals -344 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -345 # . epilogue -346 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -347 5d/pop-to-ebp -348 c3/return -349 -350 _pending-test-lookup-failure: -351 # . prologue -352 55/push-ebp -353 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -354 # var ad/ecx: allocation-descriptor containing 16 bytes -355 # . var end/ecx: (addr byte) -356 89/<- %ecx 4/r32/esp -357 # . var start/edx: (addr byte) = end - 16 -358 81 5/subop/subtract %esp 0x10/imm32 -359 89/<- %edx 4/r32/esp -360 # . ad = {start, end} -361 51/push-ecx -362 52/push-edx -363 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -364 # var h1/ecx: handle -365 68/push 0/imm32/address -366 68/push 0/imm32/alloc-id -367 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -368 # var old_top/ebx = ad->curr -369 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx -370 # first allocation, to h1 -371 # . allocate(ad, 2, h1) -372 # . . push args -373 51/push-ecx -374 68/push 2/imm32/size -375 56/push-esi -376 # . . call -377 e8/call allocate/disp32 -378 # . . discard args -379 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -380 # reset ad->curr to mimic reclamation -381 89/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy ebx to *esi -382 # second allocation that returns the same address as the first -383 # var h2/edx: handle -384 68/push 0/imm32/address -385 68/push 0/imm32/alloc-id -386 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx -387 # . allocate(ad, 2, h2) -388 # . . push args -389 52/push-edx -390 68/push 2/imm32/size -391 56/push-esi -392 # . . call -393 e8/call allocate/disp32 -394 # . . discard args -395 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -396 # check-ints-equal(h1->address, h2->address, msg) -397 # . . push args -398 68/push "F - test-lookup-failure"/imm32 -399 ff 6/subop/push 1/mod/*+disp8 2/rm32/ecx . . . . 4/disp8 . # push *(edx+4) -400 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) -401 # . . call -402 e8/call check-ints-equal/disp32 -403 # . . discard args -404 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -405 # lookup(h1) should crash -406 # . . push args -407 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) -408 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx -409 # . . call -410 e8/call lookup/disp32 -411 # should never get past this point -412 # . . discard args -413 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -414 # clean up -415 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x100/imm32 # copy to *Next-alloc-id -416 # . reclaim locals -417 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp -418 # . epilogue -419 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -420 5d/pop-to-ebp -421 c3/return -422 -423 # when comparing handles, just treat them as pure values -424 handle-equal?: # a: (handle _T), b: (handle _T) -> result/eax: boolean -425 # . prologue -426 55/push-ebp -427 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -428 # . save registers -429 51/push-ecx -430 # eax = false -431 b8/copy-to-eax 0/imm32/false -432 $handle-equal?:compare-alloc-id: -433 # ecx = a->alloc_id -434 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -435 # if (ecx != b->alloc_id) return false -436 39/compare 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # compare ecx and *(ebp+16) -437 75/jump-if-!= $handle-equal?:end/disp8 -438 $handle-equal?:compare-address: -439 # ecx = handle->address -440 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx -441 # if (ecx != b->address) return false -442 39/compare 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x14/disp8 . # compare ecx and *(ebp+20) -443 75/jump-if-!= $handle-equal?:end/disp8 -444 $handle-equal?:return-true: -445 # return true -446 b8/copy-to-eax 1/imm32/true -447 $handle-equal?:end: -448 # . restore registers -449 59/pop-to-ecx -450 # . epilogue -451 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -452 5d/pop-to-ebp -453 c3/return -454 -455 copy-handle: # src: (handle _T), dest: (addr handle _T) -456 # . prologue -457 55/push-ebp -458 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -459 # . save registers -460 50/push-eax -461 51/push-ecx -462 # ecx = dest -463 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # copy *(ebp+16) to ecx -464 # *dest = src -465 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax -466 89/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy eax to *ecx -467 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax -468 89/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4) -469 $copy-handle:end: -470 # . restore registers -471 59/pop-to-ecx -472 58/pop-to-eax -473 # . epilogue -474 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -475 5d/pop-to-ebp -476 c3/return -477 -478 # helper: create a nested allocation descriptor (useful for tests) -479 allocate-region: # ad: (addr allocation-descriptor), n: int, out: (addr handle allocation-descriptor) +132 $allocate-raw:abort: +133 (abort "allocate: failed") +134 # never gets here +135 +136 test-allocate-raw-success: +137 # . prologue +138 55/push-ebp +139 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +140 # var ad/ecx: allocation-descriptor containing 16 bytes +141 # . var end/ecx: (addr byte) +142 89/<- %ecx 4/r32/esp +143 # . var start/edx: (addr byte) = end - 16 +144 81 5/subop/subtract %esp 0x10/imm32 +145 89/<- %edx 4/r32/esp +146 # . ad = {start, end} +147 51/push-ecx +148 52/push-edx +149 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +150 # var expected-payload/ebx = ad->curr +151 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx +152 # var h/edx: handle = {0, 0} +153 68/push 0/imm32 +154 68/push 0/imm32 +155 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx +156 # *Next-alloc-id = 0x34 +157 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id +158 # allocate-raw(ad, 3, h) +159 # . . push args +160 52/push-edx +161 68/push 3/imm32 +162 51/push-ecx +163 # . . call +164 e8/call allocate-raw/disp32 +165 # . . discard args +166 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +167 # check-ints-equal(h->alloc-id, 0x34, msg) +168 # . . push args +169 68/push "F - test-allocate-raw-success: sets alloc-id in handle"/imm32 +170 68/push 0x34/imm32 +171 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx +172 # . . call +173 e8/call check-ints-equal/disp32 +174 # . . discard args +175 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +176 # check-ints-equal(h->payload, expected-payload, msg) +177 # . . push args +178 68/push "F - test-allocate-raw-success: sets payload in handle"/imm32 +179 53/push-ebx +180 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) +181 # . . call +182 e8/call check-ints-equal/disp32 +183 # . . discard args +184 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +185 # check-ints-equal(h->payload->alloc-id, 0x34, msg) +186 # . . push args +187 68/push "F - test-allocate-raw-success: sets alloc-id in payload"/imm32 +188 68/push 0x34/imm32 +189 ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx +190 # . . call +191 e8/call check-ints-equal/disp32 +192 # . . discard args +193 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +194 # check-ints-equal(*Next-alloc-id, 0x35, msg) +195 # . . push args +196 68/push "F - test-allocate-raw-success: increments Next-alloc-id"/imm32 +197 68/push 0x35/imm32 +198 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id +199 # . . call +200 e8/call check-ints-equal/disp32 +201 # . . discard args +202 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +203 # check-ints-equal(ad->curr - expected-payload, 3 + 4 for alloc-id, msg) +204 # . . push args +205 68/push "F - test-allocate-raw-success: updates allocation descriptor"/imm32 +206 68/push 7/imm32 +207 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +208 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax +209 50/push-eax +210 # . . call +211 e8/call check-ints-equal/disp32 +212 # . . discard args +213 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +214 # clean up +215 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x100/imm32 # copy to *Next-alloc-id +216 # . reclaim locals +217 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp +218 # . epilogue +219 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +220 5d/pop-to-ebp +221 c3/return +222 +223 lookup: # h: (handle _T) -> result/eax: (addr _T) +224 # . prologue +225 55/push-ebp +226 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +227 # . save registers +228 51/push-ecx +229 # eax = 0 +230 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +231 # ecx = handle->alloc_id +232 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +233 # if (ecx == 0) return 0 +234 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0/imm32 # compare ecx +235 74/jump-if-= $lookup:end/disp8 +236 # eax = handle->address (payload) +237 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax +238 # if (ecx != *eax) abort +239 39/compare 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # compare *eax and ecx +240 75/jump-if-!= $lookup:abort/disp8 +241 # add 4 to eax +242 05/add-to-eax 4/imm32 +243 $lookup:end: +244 # . restore registers +245 59/pop-to-ecx +246 # . epilogue +247 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +248 5d/pop-to-ebp +249 c3/return +250 +251 $lookup:abort: +252 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "lookup failed: (" 3 0) # 3=cyan +253 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+8) 3 0) +254 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 ", " 3 0) +255 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0xc) 3 0) +256 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 ") -> " 3 0) +257 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +258 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 ". Contents of a few words starting from address 0: " 3 0) +259 b8/copy-to-eax 0/imm32 +260 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 2 0) +261 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +262 40/increment-eax +263 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +264 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +265 40/increment-eax +266 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +267 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +268 40/increment-eax +269 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +270 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +271 40/increment-eax +272 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +273 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +274 40/increment-eax +275 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +276 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +277 40/increment-eax +278 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +279 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 2 0) +280 40/increment-eax +281 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *eax 3 0) +282 (abort "\n") +283 # never gets here +284 +285 test-lookup-success: +286 # . prologue +287 55/push-ebp +288 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +289 # var ad/ebx: allocation-descriptor containing 16 bytes +290 # . var end/ecx: (addr byte) +291 89/<- %ecx 4/r32/esp +292 # . var start/edx: (addr byte) = end - 16 +293 81 5/subop/subtract %esp 0x10/imm32 +294 89/<- %edx 4/r32/esp +295 # . ad = {start, end} +296 51/push-ecx +297 52/push-edx +298 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx +299 # var handle/ecx: handle +300 68/push 0/imm32/address +301 68/push 0/imm32/alloc-id +302 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +303 # var old-top/edx = ad->curr +304 8b/copy 0/mod/indirect 3/rm32/ebx . . . 2/r32/edx . . # copy *ebx to edx +305 # allocate-raw(ad, 2, handle) +306 # . . push args +307 51/push-ecx +308 68/push 2/imm32/size +309 53/push-ebx +310 # . . call +311 e8/call allocate-raw/disp32 +312 # . . discard args +313 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +314 # eax = lookup(handle) +315 # . . push args +316 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) +317 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx +318 # . . call +319 e8/call lookup/disp32 +320 # . . discard args +321 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +322 # eax contains old top of heap, except skipping the alloc-id in the payload +323 # . check-ints-equal(eax, old-top+4, msg) +324 # . . push args +325 68/push "F - test-lookup-success"/imm32 +326 81 0/subop/add 3/mod/direct 2/rm32/edx . . . . . 4/imm32 # add to edx +327 52/push-edx +328 50/push-eax +329 # . . call +330 e8/call check-ints-equal/disp32 +331 # . . discard args +332 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +333 # clean up +334 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x100/imm32 # copy to *Next-alloc-id +335 # . reclaim locals +336 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp +337 # . epilogue +338 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +339 5d/pop-to-ebp +340 c3/return +341 +342 test-lookup-null-returns-null: +343 # . prologue +344 55/push-ebp +345 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +346 # var handle/ecx: handle +347 68/push 0/imm32/address +348 68/push 0/imm32/alloc-id +349 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +350 # eax = lookup(handle) +351 # . . push args +352 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) +353 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx +354 # . . call +355 e8/call lookup/disp32 +356 # . . discard args +357 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +358 # check-ints-equal(eax, 0, msg) +359 # . . push args +360 68/push "F - test-lookup-null-returns-null"/imm32 +361 68/push 0/imm32 +362 50/push-eax +363 # . . call +364 e8/call check-ints-equal/disp32 +365 # . . discard args +366 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +367 # . reclaim locals +368 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +369 # . epilogue +370 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +371 5d/pop-to-ebp +372 c3/return +373 +374 _pending-test-lookup-failure: +375 # . prologue +376 55/push-ebp +377 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +378 # var ad/ecx: allocation-descriptor containing 16 bytes +379 # . var end/ecx: (addr byte) +380 89/<- %ecx 4/r32/esp +381 # . var start/edx: (addr byte) = end - 16 +382 81 5/subop/subtract %esp 0x10/imm32 +383 89/<- %edx 4/r32/esp +384 # . ad = {start, end} +385 51/push-ecx +386 52/push-edx +387 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +388 # var h1/ecx: handle +389 68/push 0/imm32/address +390 68/push 0/imm32/alloc-id +391 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +392 # var old_top/ebx = ad->curr +393 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx +394 # first allocation, to h1 +395 # . allocate(ad, 2, h1) +396 # . . push args +397 51/push-ecx +398 68/push 2/imm32/size +399 56/push-esi +400 # . . call +401 e8/call allocate/disp32 +402 # . . discard args +403 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +404 # reset ad->curr to mimic reclamation +405 89/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy ebx to *esi +406 # second allocation that returns the same address as the first +407 # var h2/edx: handle +408 68/push 0/imm32/address +409 68/push 0/imm32/alloc-id +410 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx +411 # . allocate(ad, 2, h2) +412 # . . push args +413 52/push-edx +414 68/push 2/imm32/size +415 56/push-esi +416 # . . call +417 e8/call allocate/disp32 +418 # . . discard args +419 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +420 # check-ints-equal(h1->address, h2->address, msg) +421 # . . push args +422 68/push "F - test-lookup-failure"/imm32 +423 ff 6/subop/push 1/mod/*+disp8 2/rm32/ecx . . . . 4/disp8 . # push *(edx+4) +424 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) +425 # . . call +426 e8/call check-ints-equal/disp32 +427 # . . discard args +428 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +429 # lookup(h1) should crash +430 # . . push args +431 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) +432 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx +433 # . . call +434 e8/call lookup/disp32 +435 # should never get past this point +436 # . . discard args +437 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +438 # clean up +439 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x100/imm32 # copy to *Next-alloc-id +440 # . reclaim locals +441 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp +442 # . epilogue +443 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +444 5d/pop-to-ebp +445 c3/return +446 +447 # when comparing handles, just treat them as pure values +448 handle-equal?: # a: (handle _T), b: (handle _T) -> result/eax: boolean +449 # . prologue +450 55/push-ebp +451 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +452 # . save registers +453 51/push-ecx +454 # eax = false +455 b8/copy-to-eax 0/imm32/false +456 $handle-equal?:compare-alloc-id: +457 # ecx = a->alloc_id +458 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +459 # if (ecx != b->alloc_id) return false +460 39/compare 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # compare ecx and *(ebp+16) +461 75/jump-if-!= $handle-equal?:end/disp8 +462 $handle-equal?:compare-address: +463 # ecx = handle->address +464 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx +465 # if (ecx != b->address) return false +466 39/compare 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x14/disp8 . # compare ecx and *(ebp+20) +467 75/jump-if-!= $handle-equal?:end/disp8 +468 $handle-equal?:return-true: +469 # return true +470 b8/copy-to-eax 1/imm32/true +471 $handle-equal?:end: +472 # . restore registers +473 59/pop-to-ecx +474 # . epilogue +475 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +476 5d/pop-to-ebp +477 c3/return +478 +479 copy-handle: # src: (handle _T), dest: (addr handle _T) 480 # . prologue 481 55/push-ebp 482 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 483 # . save registers 484 50/push-eax 485 51/push-ecx -486 # allocate(ad, n, out) -487 # . . push args -488 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) -489 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -490 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -491 # . . call -492 e8/call allocate/disp32 -493 # . . discard args -494 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -495 # eax = out->payload -496 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax -497 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax -498 # skip payload->allocid -499 05/add-to-eax 4/imm32 -500 # if (eax == 0) abort -501 3d/compare-eax-and 0/imm32 -502 74/jump-if-= $allocate-region:abort/disp8 -503 # earmark 8 bytes at the start for a new allocation descriptor -504 # . *eax = eax + 8 -505 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx -506 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 8/imm32 # add to ecx -507 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax -508 # . *(eax+4) = eax + n -509 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx -510 03/add 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # add *(ebp+12) to ecx -511 89/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy ecx to *(eax+4) -512 # . restore registers -513 59/pop-to-ecx -514 58/pop-to-eax -515 # . epilogue -516 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -517 5d/pop-to-ebp -518 c3/return -519 -520 # We could create a more general '$abort' jump target, but then we'd need to do -521 # a conditional jump followed by loading the error message and an unconditional -522 # jump. Or we'd need to unconditionally load the error message before a -523 # conditional jump, even if it's unused the vast majority of the time. This way -524 # we bloat a potentially cold segment in RAM so we can abort with a single -525 # instruction. -526 $allocate-region:abort: -527 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "allocate-region: failed to allocate" 3 0) # 3=cyan -528 { -529 eb/jump loop/disp8 -530 } -531 # never gets here -532 -533 # Claim the next 'n+4' bytes of memory and initialize the first 4 to n. -534 # Abort if there isn't enough memory in 'ad'. -535 allocate-array: # ad: (addr allocation-descriptor), n: int, out: (addr handle _) -536 # . prologue -537 55/push-ebp -538 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -539 # . save registers -540 50/push-eax -541 51/push-ecx -542 52/push-edx -543 # ecx = n -544 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx -545 # var size/edx: int = n+4 -546 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy ecx+4 to edx -547 # allocate(ad, size, out) -548 # . . push args -549 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) -550 52/push-edx -551 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -552 # . . call -553 e8/call allocate/disp32 -554 # . . discard args -555 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -556 # *out->payload = n -557 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax -558 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax -559 # . skip payload->allocid -560 05/add-to-eax 4/imm32 -561 # . -562 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax -563 $allocate-array:end: -564 # . restore registers -565 5a/pop-to-edx -566 59/pop-to-ecx -567 58/pop-to-eax -568 # . epilogue -569 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -570 5d/pop-to-ebp -571 c3/return -572 -573 test-allocate-array: -574 # . prologue -575 55/push-ebp -576 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -577 # var ad/ecx: allocation-descriptor containing 16 bytes -578 # . var end/ecx: (addr byte) -579 89/<- %ecx 4/r32/esp -580 # . var start/edx: (addr byte) = end - 16 -581 81 5/subop/subtract %esp 0x10/imm32 -582 89/<- %edx 4/r32/esp -583 # . ad = {start, end} -584 51/push-ecx -585 52/push-edx -586 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -587 # var expected-payload/ebx = ad->curr -588 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx -589 # var h/edx: handle = {0, 0} -590 68/push 0/imm32 -591 68/push 0/imm32 -592 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx -593 # *Next-alloc-id = 0x34 -594 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id -595 # allocate-array(ad, 3, h) -596 # . . push args -597 52/push-edx -598 68/push 3/imm32 -599 51/push-ecx -600 # . . call -601 e8/call allocate-array/disp32 -602 # . . discard args -603 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -604 # check-ints-equal(h->alloc-id, 0x34, msg) -605 # . . push args -606 68/push "F - test-allocate-array: sets alloc-id in handle"/imm32 -607 68/push 0x34/imm32 -608 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx -609 # . . call -610 e8/call check-ints-equal/disp32 -611 # . . discard args -612 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -613 # check-ints-equal(h->payload, expected-payload, msg) -614 # . . push args -615 68/push "F - test-allocate-array: sets payload in handle"/imm32 -616 53/push-ebx -617 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) -618 # . . call -619 e8/call check-ints-equal/disp32 -620 # . . discard args -621 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -622 # check-ints-equal(h->payload->alloc-id, 0x34, msg) -623 # . . push args -624 68/push "F - test-allocate-array: sets alloc-id in payload"/imm32 -625 68/push 0x34/imm32 -626 ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx -627 # . . call -628 e8/call check-ints-equal/disp32 -629 # . . discard args -630 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -631 # check-ints-equal(h->payload->size, 3, msg) -632 # . . push args -633 68/push "F - test-allocate-array: sets array size in payload"/imm32 -634 68/push 3/imm32 -635 ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) -636 # . . call -637 e8/call check-ints-equal/disp32 -638 # . . discard args -639 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -640 # check-ints-equal(*Next-alloc-id, 0x35, msg) -641 # . . push args -642 68/push "F - test-allocate-array: increments Next-alloc-id"/imm32 -643 68/push 0x35/imm32 -644 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id -645 # . . call -646 e8/call check-ints-equal/disp32 -647 # . . discard args -648 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -649 # check-ints-equal(ad->curr - expected-payload, 3 + 4 for alloc-id + 4 for array size, msg) -650 # . . push args -651 68/push "F - test-allocate-array: updates allocation descriptor"/imm32 -652 68/push 0xb/imm32 -653 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -654 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax -655 50/push-eax -656 # . . call -657 e8/call check-ints-equal/disp32 -658 # . . discard args -659 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -660 # clean up -661 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id -662 # . reclaim locals -663 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp -664 # . epilogue -665 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -666 5d/pop-to-ebp -667 c3/return -668 -669 copy-array: # ad: (addr allocation-descriptor), src: (addr array _T), out: (addr handle array _T) -670 # . prologue -671 55/push-ebp -672 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -673 # . save registers -674 50/push-eax -675 51/push-ecx -676 52/push-edx -677 56/push-esi -678 # esi = src -679 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi -680 # var size/ecx: int = src->size+4 -681 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx -682 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx -683 # allocate(ad, size, out) -684 # . . push args -685 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) -686 51/push-ecx -687 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -688 # . . call -689 e8/call allocate/disp32 -690 # . . discard args -691 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -692 # var payload/eax: (addr byte) = out->payload -693 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax -694 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax -695 # . skip payload->allocid -696 05/add-to-eax 4/imm32 -697 # var max/ecx: (addr byte) = payload + size -698 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx -699 # _append-4(payload, max, src, &src->data[src->size]) -700 # . . push &src->data[src->size] -701 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx -702 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 2/index/edx . 2/r32/edx 4/disp8 . # copy esi+edx+4 to edx -703 52/push-edx -704 # . . push src -705 56/push-esi -706 # . . push max +486 # ecx = dest +487 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0x10/disp8 . # copy *(ebp+16) to ecx +488 # *dest = src +489 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax +490 89/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy eax to *ecx +491 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax +492 89/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4) +493 $copy-handle:end: +494 # . restore registers +495 59/pop-to-ecx +496 58/pop-to-eax +497 # . epilogue +498 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +499 5d/pop-to-ebp +500 c3/return +501 +502 # helper: create a nested allocation descriptor (useful for tests) +503 allocate-region: # ad: (addr allocation-descriptor), n: int, out: (addr handle allocation-descriptor) +504 # . prologue +505 55/push-ebp +506 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +507 # . save registers +508 50/push-eax +509 51/push-ecx +510 # allocate(ad, n, out) +511 # . . push args +512 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) +513 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +514 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +515 # . . call +516 e8/call allocate/disp32 +517 # . . discard args +518 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +519 # eax = out->payload +520 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax +521 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax +522 # skip payload->allocid +523 05/add-to-eax 4/imm32 +524 # if (eax == 0) abort +525 3d/compare-eax-and 0/imm32 +526 74/jump-if-= $allocate-region:abort/disp8 +527 # earmark 8 bytes at the start for a new allocation descriptor +528 # . *eax = eax + 8 +529 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx +530 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 8/imm32 # add to ecx +531 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax +532 # . *(eax+4) = eax + n +533 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx +534 03/add 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # add *(ebp+12) to ecx +535 89/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy ecx to *(eax+4) +536 # . restore registers +537 59/pop-to-ecx +538 58/pop-to-eax +539 # . epilogue +540 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +541 5d/pop-to-ebp +542 c3/return +543 +544 # We could create a more general '$abort' jump target, but then we'd need to do +545 # a conditional jump followed by loading the error message and an unconditional +546 # jump. Or we'd need to unconditionally load the error message before a +547 # conditional jump, even if it's unused the vast majority of the time. This way +548 # we bloat a potentially cold segment in RAM so we can abort with a single +549 # instruction. +550 $allocate-region:abort: +551 (abort "allocate-region: failed to allocate") +552 # never gets here +553 +554 # Claim the next 'n+4' bytes of memory and initialize the first 4 to n. +555 # Abort if there isn't enough memory in 'ad'. +556 allocate-array: # ad: (addr allocation-descriptor), n: int, out: (addr handle _) +557 # . prologue +558 55/push-ebp +559 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +560 # . save registers +561 50/push-eax +562 51/push-ecx +563 52/push-edx +564 # ecx = n +565 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx +566 # var size/edx: int = n+4 +567 8d/copy-address 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy ecx+4 to edx +568 # allocate(ad, size, out) +569 # . . push args +570 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) +571 52/push-edx +572 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +573 # . . call +574 e8/call allocate/disp32 +575 # . . discard args +576 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +577 # *out->payload = n +578 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax +579 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax +580 # . skip payload->allocid +581 05/add-to-eax 4/imm32 +582 # . +583 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax +584 $allocate-array:end: +585 # . restore registers +586 5a/pop-to-edx +587 59/pop-to-ecx +588 58/pop-to-eax +589 # . epilogue +590 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +591 5d/pop-to-ebp +592 c3/return +593 +594 test-allocate-array: +595 # . prologue +596 55/push-ebp +597 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +598 # var ad/ecx: allocation-descriptor containing 16 bytes +599 # . var end/ecx: (addr byte) +600 89/<- %ecx 4/r32/esp +601 # . var start/edx: (addr byte) = end - 16 +602 81 5/subop/subtract %esp 0x10/imm32 +603 89/<- %edx 4/r32/esp +604 # . ad = {start, end} +605 51/push-ecx +606 52/push-edx +607 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +608 # var expected-payload/ebx = ad->curr +609 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx +610 # var h/edx: handle = {0, 0} +611 68/push 0/imm32 +612 68/push 0/imm32 +613 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx +614 # *Next-alloc-id = 0x34 +615 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id +616 # allocate-array(ad, 3, h) +617 # . . push args +618 52/push-edx +619 68/push 3/imm32 +620 51/push-ecx +621 # . . call +622 e8/call allocate-array/disp32 +623 # . . discard args +624 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +625 # check-ints-equal(h->alloc-id, 0x34, msg) +626 # . . push args +627 68/push "F - test-allocate-array: sets alloc-id in handle"/imm32 +628 68/push 0x34/imm32 +629 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx +630 # . . call +631 e8/call check-ints-equal/disp32 +632 # . . discard args +633 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +634 # check-ints-equal(h->payload, expected-payload, msg) +635 # . . push args +636 68/push "F - test-allocate-array: sets payload in handle"/imm32 +637 53/push-ebx +638 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) +639 # . . call +640 e8/call check-ints-equal/disp32 +641 # . . discard args +642 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +643 # check-ints-equal(h->payload->alloc-id, 0x34, msg) +644 # . . push args +645 68/push "F - test-allocate-array: sets alloc-id in payload"/imm32 +646 68/push 0x34/imm32 +647 ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx +648 # . . call +649 e8/call check-ints-equal/disp32 +650 # . . discard args +651 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +652 # check-ints-equal(h->payload->size, 3, msg) +653 # . . push args +654 68/push "F - test-allocate-array: sets array size in payload"/imm32 +655 68/push 3/imm32 +656 ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) +657 # . . call +658 e8/call check-ints-equal/disp32 +659 # . . discard args +660 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +661 # check-ints-equal(*Next-alloc-id, 0x35, msg) +662 # . . push args +663 68/push "F - test-allocate-array: increments Next-alloc-id"/imm32 +664 68/push 0x35/imm32 +665 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id +666 # . . call +667 e8/call check-ints-equal/disp32 +668 # . . discard args +669 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +670 # check-ints-equal(ad->curr - expected-payload, 3 + 4 for alloc-id + 4 for array size, msg) +671 # . . push args +672 68/push "F - test-allocate-array: updates allocation descriptor"/imm32 +673 68/push 0xb/imm32 +674 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +675 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax +676 50/push-eax +677 # . . call +678 e8/call check-ints-equal/disp32 +679 # . . discard args +680 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +681 # clean up +682 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id +683 # . reclaim locals +684 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x20/imm32 # add to esp +685 # . epilogue +686 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +687 5d/pop-to-ebp +688 c3/return +689 +690 copy-array: # ad: (addr allocation-descriptor), src: (addr array _T), out: (addr handle array _T) +691 # . prologue +692 55/push-ebp +693 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +694 # . save registers +695 50/push-eax +696 51/push-ecx +697 52/push-edx +698 56/push-esi +699 # esi = src +700 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi +701 # var size/ecx: int = src->size+4 +702 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx +703 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx +704 # allocate(ad, size, out) +705 # . . push args +706 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) 707 51/push-ecx -708 # . . push payload -709 50/push-eax -710 # . . call -711 e8/call _append-4/disp32 -712 # . . discard args -713 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp -714 $copy-array:end: -715 # . restore registers -716 5e/pop-to-esi -717 5a/pop-to-edx -718 59/pop-to-ecx -719 58/pop-to-eax -720 # . epilogue -721 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -722 5d/pop-to-ebp -723 c3/return -724 -725 test-copy-array: -726 # . prologue -727 55/push-ebp -728 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -729 # var src/esi: (addr array int) = [3, 4, 5] -730 68/push 5/imm32 -731 68/push 4/imm32 -732 68/push 3/imm32 -733 68/push 0xc/imm32/size -734 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi -735 # var ad/ecx: allocation-descriptor containing 32 bytes -736 # . var end/ecx: (addr byte) -737 89/<- %ecx 4/r32/esp -738 # . var start/edx: (addr byte) = end - 32 -739 81 5/subop/subtract %esp 0x20/imm32 -740 89/<- %edx 4/r32/esp -741 # . ad = {start, end} -742 51/push-ecx -743 52/push-edx -744 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -745 # var expected-payload/ebx = ad->curr -746 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx -747 # var h/edx: handle = {0, 0} -748 68/push 0/imm32 -749 68/push 0/imm32 -750 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx -751 # *Next-alloc-id = 0x34 -752 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id -753 # copy-array(ad, src, h) -754 # . . push args -755 52/push-edx -756 56/push-esi -757 51/push-ecx -758 # . . call -759 e8/call copy-array/disp32 -760 # . . discard args -761 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -762 # check-ints-equal(h->alloc-id, 0x34, msg) -763 # . . push args -764 68/push "F - test-copy-array: sets alloc-id in handle"/imm32 -765 68/push 0x34/imm32 -766 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx -767 # . . call -768 e8/call check-ints-equal/disp32 -769 # . . discard args -770 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -771 # check-ints-equal(h->payload, expected-payload, msg) -772 # . . push args -773 68/push "F - test-copy-array: sets payload in handle"/imm32 -774 53/push-ebx -775 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) -776 # . . call -777 e8/call check-ints-equal/disp32 -778 # . . discard args -779 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -780 # check-ints-equal(h->payload->alloc-id, 0x34, msg) -781 # . . push args -782 68/push "F - test-copy-array: sets alloc-id in payload"/imm32 -783 68/push 0x34/imm32 -784 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx -785 # . . call -786 e8/call check-ints-equal/disp32 -787 # . . discard args -788 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -789 # var payload/eax: (addr int) = lookup(h) -790 # . . push args -791 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) -792 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx -793 # . . call -794 e8/call lookup/disp32 -795 # . . discard args -796 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -797 # check-ints-equal(payload->size, 0xc, msg) -798 # . . push args -799 68/push "F - test-copy-array: sets array size in payload"/imm32 -800 68/push 0xc/imm32 -801 ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax -802 # . . call -803 e8/call check-ints-equal/disp32 -804 # . . discard args -805 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -806 # check-ints-equal(*Next-alloc-id, 0x35, msg) -807 # . . push args -808 68/push "F - test-copy-array: increments Next-alloc-id"/imm32 -809 68/push 0x35/imm32 -810 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id -811 # . . call -812 e8/call check-ints-equal/disp32 -813 # . . discard args -814 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -815 # check-ints-equal(ad->curr - expected-payload, 12 + 4 for alloc-id + 4 for size, msg) -816 # . . push args -817 68/push "F - test-copy-array: updates allocation descriptor"/imm32 -818 68/push 0x14/imm32 -819 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -820 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax -821 50/push-eax -822 # . . call -823 e8/call check-ints-equal/disp32 -824 # . . discard args -825 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -826 # clean up -827 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id -828 # . reclaim locals -829 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x40/imm32 # add to esp -830 # . epilogue -831 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -832 5d/pop-to-ebp -833 c3/return -834 -835 # Fill a region of memory with zeroes. -836 zero-out: # start: (addr byte), size: int -837 # pseudocode: -838 # curr/esi = start -839 # i/ecx = 0 -840 # while true -841 # if (i >= size) break -842 # *curr = 0 -843 # ++curr -844 # ++i -845 # -846 # . prologue -847 55/push-ebp -848 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -849 # . save registers -850 50/push-eax -851 51/push-ecx -852 52/push-edx -853 56/push-esi -854 # curr/esi = start -855 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi -856 # var i/ecx: int = 0 -857 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx -858 # edx = size -859 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx -860 $zero-out:loop: -861 # if (i >= size) break -862 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -863 7d/jump-if->= $zero-out:end/disp8 -864 # *curr = 0 -865 c6 0/subop/copy-byte 0/mod/direct 6/rm32/esi . . . . . 0/imm8 # copy byte to *esi -866 # ++curr -867 46/increment-esi -868 # ++i -869 41/increment-ecx -870 eb/jump $zero-out:loop/disp8 -871 $zero-out:end: -872 # . restore registers -873 5e/pop-to-esi -874 5a/pop-to-edx -875 59/pop-to-ecx -876 58/pop-to-eax -877 # . epilogue -878 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -879 5d/pop-to-ebp -880 c3/return -881 -882 test-zero-out: -883 # . prologue -884 55/push-ebp -885 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -886 # region/ecx = 34, 35, 36, 37 -887 68/push 0x37363534/imm32 -888 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -889 # zero-out(ecx, 3) -890 # . . push args -891 68/push 3/imm32/size -892 51/push-ecx -893 # . . call -894 e8/call zero-out/disp32 -895 # . . discard args -896 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -897 # first 3 bytes cleared, fourth left alone -898 # . check-ints-equal(*ecx, 0x37000000, msg) -899 # . . push args -900 68/push "F - test-zero-out"/imm32 -901 68/push 0x37000000/imm32 -902 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx -903 # . . call -904 e8/call check-ints-equal/disp32 -905 # . . discard args -906 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -907 # . reclaim locals -908 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -909 # . epilogue -910 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -911 5d/pop-to-ebp -912 c3/return -913 -914 # . . vim:nowrap:textwidth=0 +708 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +709 # . . call +710 e8/call allocate/disp32 +711 # . . discard args +712 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +713 # var payload/eax: (addr byte) = out->payload +714 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax +715 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax +716 # . skip payload->allocid +717 05/add-to-eax 4/imm32 +718 # var max/ecx: (addr byte) = payload + size +719 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx +720 # _append-4(payload, max, src, &src->data[src->size]) +721 # . . push &src->data[src->size] +722 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx +723 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 2/index/edx . 2/r32/edx 4/disp8 . # copy esi+edx+4 to edx +724 52/push-edx +725 # . . push src +726 56/push-esi +727 # . . push max +728 51/push-ecx +729 # . . push payload +730 50/push-eax +731 # . . call +732 e8/call _append-4/disp32 +733 # . . discard args +734 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +735 $copy-array:end: +736 # . restore registers +737 5e/pop-to-esi +738 5a/pop-to-edx +739 59/pop-to-ecx +740 58/pop-to-eax +741 # . epilogue +742 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +743 5d/pop-to-ebp +744 c3/return +745 +746 test-copy-array: +747 # . prologue +748 55/push-ebp +749 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +750 # var src/esi: (addr array int) = [3, 4, 5] +751 68/push 5/imm32 +752 68/push 4/imm32 +753 68/push 3/imm32 +754 68/push 0xc/imm32/size +755 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi +756 # var ad/ecx: allocation-descriptor containing 32 bytes +757 # . var end/ecx: (addr byte) +758 89/<- %ecx 4/r32/esp +759 # . var start/edx: (addr byte) = end - 32 +760 81 5/subop/subtract %esp 0x20/imm32 +761 89/<- %edx 4/r32/esp +762 # . ad = {start, end} +763 51/push-ecx +764 52/push-edx +765 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +766 # var expected-payload/ebx = ad->curr +767 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx +768 # var h/edx: handle = {0, 0} +769 68/push 0/imm32 +770 68/push 0/imm32 +771 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx +772 # *Next-alloc-id = 0x34 +773 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 0x34/imm32 # copy to *Next-alloc-id +774 # copy-array(ad, src, h) +775 # . . push args +776 52/push-edx +777 56/push-esi +778 51/push-ecx +779 # . . call +780 e8/call copy-array/disp32 +781 # . . discard args +782 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +783 # check-ints-equal(h->alloc-id, 0x34, msg) +784 # . . push args +785 68/push "F - test-copy-array: sets alloc-id in handle"/imm32 +786 68/push 0x34/imm32 +787 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx +788 # . . call +789 e8/call check-ints-equal/disp32 +790 # . . discard args +791 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +792 # check-ints-equal(h->payload, expected-payload, msg) +793 # . . push args +794 68/push "F - test-copy-array: sets payload in handle"/imm32 +795 53/push-ebx +796 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) +797 # . . call +798 e8/call check-ints-equal/disp32 +799 # . . discard args +800 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +801 # check-ints-equal(h->payload->alloc-id, 0x34, msg) +802 # . . push args +803 68/push "F - test-copy-array: sets alloc-id in payload"/imm32 +804 68/push 0x34/imm32 +805 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx +806 # . . call +807 e8/call check-ints-equal/disp32 +808 # . . discard args +809 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +810 # var payload/eax: (addr int) = lookup(h) +811 # . . push args +812 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) +813 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx +814 # . . call +815 e8/call lookup/disp32 +816 # . . discard args +817 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +818 # check-ints-equal(payload->size, 0xc, msg) +819 # . . push args +820 68/push "F - test-copy-array: sets array size in payload"/imm32 +821 68/push 0xc/imm32 +822 ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax +823 # . . call +824 e8/call check-ints-equal/disp32 +825 # . . discard args +826 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +827 # check-ints-equal(*Next-alloc-id, 0x35, msg) +828 # . . push args +829 68/push "F - test-copy-array: increments Next-alloc-id"/imm32 +830 68/push 0x35/imm32 +831 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 # push *Next-alloc-id +832 # . . call +833 e8/call check-ints-equal/disp32 +834 # . . discard args +835 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +836 # check-ints-equal(ad->curr - expected-payload, 12 + 4 for alloc-id + 4 for size, msg) +837 # . . push args +838 68/push "F - test-copy-array: updates allocation descriptor"/imm32 +839 68/push 0x14/imm32 +840 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +841 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax +842 50/push-eax +843 # . . call +844 e8/call check-ints-equal/disp32 +845 # . . discard args +846 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +847 # clean up +848 c7 0/subop/copy 0/mod/indirect 5/rm32/.disp32 . . . Next-alloc-id/disp32 1/imm32 # copy to *Next-alloc-id +849 # . reclaim locals +850 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x40/imm32 # add to esp +851 # . epilogue +852 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +853 5d/pop-to-ebp +854 c3/return +855 +856 # Fill a region of memory with zeroes. +857 zero-out: # start: (addr byte), size: int +858 # pseudocode: +859 # curr/esi = start +860 # i/ecx = 0 +861 # while true +862 # if (i >= size) break +863 # *curr = 0 +864 # ++curr +865 # ++i +866 # +867 # . prologue +868 55/push-ebp +869 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +870 # . save registers +871 50/push-eax +872 51/push-ecx +873 52/push-edx +874 56/push-esi +875 # curr/esi = start +876 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi +877 # var i/ecx: int = 0 +878 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx +879 # edx = size +880 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx +881 $zero-out:loop: +882 # if (i >= size) break +883 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +884 7d/jump-if->= $zero-out:end/disp8 +885 # *curr = 0 +886 c6 0/subop/copy-byte 0/mod/direct 6/rm32/esi . . . . . 0/imm8 # copy byte to *esi +887 # ++curr +888 46/increment-esi +889 # ++i +890 41/increment-ecx +891 eb/jump $zero-out:loop/disp8 +892 $zero-out:end: +893 # . restore registers +894 5e/pop-to-esi +895 5a/pop-to-edx +896 59/pop-to-ecx +897 58/pop-to-eax +898 # . epilogue +899 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +900 5d/pop-to-ebp +901 c3/return +902 +903 test-zero-out: +904 # . prologue +905 55/push-ebp +906 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +907 # region/ecx = 34, 35, 36, 37 +908 68/push 0x37363534/imm32 +909 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +910 # zero-out(ecx, 3) +911 # . . push args +912 68/push 3/imm32/size +913 51/push-ecx +914 # . . call +915 e8/call zero-out/disp32 +916 # . . discard args +917 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +918 # first 3 bytes cleared, fourth left alone +919 # . check-ints-equal(*ecx, 0x37000000, msg) +920 # . . push args +921 68/push "F - test-zero-out"/imm32 +922 68/push 0x37000000/imm32 +923 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx +924 # . . call +925 e8/call check-ints-equal/disp32 +926 # . . discard args +927 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +928 # . reclaim locals +929 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +930 # . epilogue +931 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +932 5d/pop-to-ebp +933 c3/return +934 +935 # . . vim:nowrap:textwidth=0 diff --git a/html/121new-stream.subx.html b/html/121new-stream.subx.html index 38e1f288..468d0ef9 100644 --- a/html/121new-stream.subx.html +++ b/html/121new-stream.subx.html @@ -79,7 +79,7 @@ if ('onhashchange' in window) { 20 f7 4/subop/multiply 1/mod/*+disp8 5/rm32/ebp . . 0xc/disp8 . # multiply *(ebp+12) into edx:eax 21 # . if overflow abort 22 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32 # compare edx - 23 75/jump-if-!= $new-stream:abort/disp8 + 23 75/jump-if-!= $new-stream:abort/disp8 24 # . edx = elemsize*length 25 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx 26 # var n/eax: int = size + 12 (for read, write and size) @@ -116,74 +116,71 @@ if ('onhashchange' in window) { 57 5d/pop-to-ebp 58 c3/return 59 - 60 $new-stream:abort: - 61 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "new-stream: size too large" 3 0) # 3=cyan - 62 { - 63 eb/jump loop/disp8 - 64 } - 65 # never gets here - 66 - 67 test-new-stream: - 68 # . prologue - 69 55/push-ebp - 70 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 71 # var ad/ecx: allocation-descriptor containing 16 bytes - 72 # . var end/ecx: (addr byte) - 73 89/<- %ecx 4/r32/esp - 74 # . var start/edx: (addr byte) = end - 32 - 75 81 5/subop/subtract %esp 0x20/imm32 - 76 89/<- %edx 4/r32/esp - 77 # . ad = {start, end} - 78 51/push-ecx - 79 52/push-edx - 80 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - 81 # var start/edx = ad->curr - 82 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - 83 # var h/ebx: (handle stream byte) - 84 68/push 0/imm32 - 85 68/push 0/imm32 - 86 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - 87 # new-stream(ad, 3, 2, h) - 88 # . . push args - 89 53/push-ebx - 90 68/push 2/imm32 - 91 68/push 3/imm32 - 92 51/push-ecx - 93 # . . call - 94 e8/call new-stream/disp32 - 95 # . . discard args - 96 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - 97 # eax = out->payload - 98 8b/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy *(ebx+4) to eax - 99 # check-ints-equal(eax, edx, msg) -100 # . . push args -101 68/push "F - test-new-stream: returns current pointer of allocation descriptor"/imm32 -102 52/push-edx -103 50/push-eax -104 # . . call -105 e8/call check-ints-equal/disp32 -106 # . . discard args -107 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -108 # skip payload->allocid -109 05/add-to-eax 4/imm32 -110 # check-ints-equal(eax->size, 6, msg) -111 # . . push args -112 68/push "F - test-new-stream: sets size correctly"/imm32 -113 68/push 6/imm32 -114 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . . 8/disp8 # push *(eax+8) -115 # . . call -116 e8/call check-ints-equal/disp32 -117 # . . discard args -118 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -119 # the rest is delegated to clear-stream() so we won't bother checking it -120 # . reclaim locals -121 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x30/imm32 # add to esp -122 # . epilogue -123 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -124 5d/pop-to-ebp -125 c3/return -126 -127 # . . vim:nowrap:textwidth=0 + 60 $new-stream:abort: + 61 (abort "new-stream: size too large") + 62 # never gets here + 63 + 64 test-new-stream: + 65 # . prologue + 66 55/push-ebp + 67 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 68 # var ad/ecx: allocation-descriptor containing 16 bytes + 69 # . var end/ecx: (addr byte) + 70 89/<- %ecx 4/r32/esp + 71 # . var start/edx: (addr byte) = end - 32 + 72 81 5/subop/subtract %esp 0x20/imm32 + 73 89/<- %edx 4/r32/esp + 74 # . ad = {start, end} + 75 51/push-ecx + 76 52/push-edx + 77 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + 78 # var start/edx = ad->curr + 79 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx + 80 # var h/ebx: (handle stream byte) + 81 68/push 0/imm32 + 82 68/push 0/imm32 + 83 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + 84 # new-stream(ad, 3, 2, h) + 85 # . . push args + 86 53/push-ebx + 87 68/push 2/imm32 + 88 68/push 3/imm32 + 89 51/push-ecx + 90 # . . call + 91 e8/call new-stream/disp32 + 92 # . . discard args + 93 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + 94 # eax = out->payload + 95 8b/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy *(ebx+4) to eax + 96 # check-ints-equal(eax, edx, msg) + 97 # . . push args + 98 68/push "F - test-new-stream: returns current pointer of allocation descriptor"/imm32 + 99 52/push-edx +100 50/push-eax +101 # . . call +102 e8/call check-ints-equal/disp32 +103 # . . discard args +104 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +105 # skip payload->allocid +106 05/add-to-eax 4/imm32 +107 # check-ints-equal(eax->size, 6, msg) +108 # . . push args +109 68/push "F - test-new-stream: sets size correctly"/imm32 +110 68/push 6/imm32 +111 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . . 8/disp8 # push *(eax+8) +112 # . . call +113 e8/call check-ints-equal/disp32 +114 # . . discard args +115 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +116 # the rest is delegated to clear-stream() so we won't bother checking it +117 # . reclaim locals +118 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x30/imm32 # add to esp +119 # . epilogue +120 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +121 5d/pop-to-ebp +122 c3/return +123 +124 # . . vim:nowrap:textwidth=0 diff --git a/html/123slice.subx.html b/html/123slice.subx.html index 7ad2d84e..8257f816 100644 --- a/html/123slice.subx.html +++ b/html/123slice.subx.html @@ -880,7 +880,7 @@ if ('onhashchange' in window) { 819 73/jump-if-addr>= $write-slice:loop-end/disp8 820 # if (out->write >= out->size) abort 821 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx - 822 7d/jump-if->= $write-slice:abort/disp8 + 822 7d/jump-if->= $write-slice:abort/disp8 823 # out->data[out->write] = *in 824 # . AL = *in 825 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax @@ -908,201 +908,195 @@ if ('onhashchange' in window) { 847 5d/pop-to-ebp 848 c3/return 849 - 850 $write-slice:abort: - 851 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "write-slice: out of space" 3 0) # 3=cyan - 852 { - 853 eb/jump loop/disp8 - 854 } - 855 # never gets here - 856 - 857 test-write-slice: - 858 # . prologue - 859 55/push-ebp - 860 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 861 # setup - 862 # . clear-stream(_test-stream) - 863 # . . push args - 864 68/push _test-stream/imm32 - 865 # . . call - 866 e8/call clear-stream/disp32 - 867 # . . discard args - 868 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 869 # (eax..ecx) = "Abc" - 870 b8/copy-to-eax "Abc"/imm32 - 871 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx - 872 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx - 873 05/add-to-eax 4/imm32 - 874 # var slice/ecx: slice = {eax, ecx} - 875 51/push-ecx - 876 50/push-eax - 877 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - 878 # write-slice(_test-stream, slice) - 879 # . . push args - 880 51/push-ecx - 881 68/push _test-stream/imm32 - 882 # . . call - 883 e8/call write-slice/disp32 - 884 # . . discard args - 885 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 886 # check-stream-equal(_test-stream, "Abc", msg) - 887 # . . push args - 888 68/push "F - test-write-slice"/imm32 - 889 68/push "Abc"/imm32 - 890 68/push _test-stream/imm32 - 891 # . . call - 892 e8/call check-stream-equal/disp32 - 893 # . . discard args - 894 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 895 # . epilogue - 896 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 897 5d/pop-to-ebp - 898 c3/return - 899 - 900 # copy a slice into a new (dynamically allocated) string - 901 slice-to-string: # ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte) - 902 # . prologue - 903 55/push-ebp - 904 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 905 # . save registers - 906 50/push-eax - 907 51/push-ecx - 908 52/push-edx - 909 53/push-ebx - 910 56/push-esi - 911 # esi = in - 912 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - 913 # var curr/edx: (addr byte) = in->start - 914 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx - 915 # var max/ebx: (addr byte) = in->end - 916 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 3/r32/ebx 4/disp8 . # copy *(esi+4) to ebx - 917 # var size/ecx: int = max - curr + 4 # total size of output string (including the initial 'size' field) - 918 89/copy 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # copy ebx to ecx - 919 29/subtract 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # subtract edx from ecx - 920 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx - 921 # allocate(ad, size, out) - 922 # . . push args - 923 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - 924 51/push-ecx - 925 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - 926 # . . call - 927 e8/call allocate/disp32 - 928 # . . discard args - 929 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 930 # eax = out->payload - 931 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax - 932 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax - 933 # skip payload->allocid - 934 05/add-to-eax 4/imm32 - 935 # if (eax == 0) abort - 936 3d/compare-eax-and 0/imm32 - 937 74/jump-if-= $slice-to-string:abort/disp8 - 938 # out->size = size-4 - 939 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax - 940 81 5/subop/subtract 0/mod/indirect 0/rm32/eax . . . . . 4/imm32 # subtract 4 from *eax - 941 # save out - 942 50/push-eax - 943 $slice-to-string:initialize: - 944 # eax = _append-4(eax+4, eax+size, curr, max) # clobbering ecx - 945 # . . push args - 946 53/push-ebx - 947 52/push-edx - 948 # . . push eax+size (clobbering ecx) - 949 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx - 950 51/push-ecx - 951 # . . push eax+4 (clobbering eax) - 952 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 4/imm32 # add to eax - 953 50/push-eax - 954 # . . call - 955 e8/call _append-4/disp32 - 956 # . . discard args - 957 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - 958 # restore out (assumes _append-4 can't error) - 959 58/pop-to-eax - 960 $slice-to-string:end: - 961 # . restore registers - 962 5e/pop-to-esi - 963 5b/pop-to-ebx - 964 5a/pop-to-edx - 965 59/pop-to-ecx - 966 58/pop-to-eax - 967 # . epilogue - 968 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 969 5d/pop-to-ebp - 970 c3/return - 971 - 972 $slice-to-string:abort: - 973 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "slice-to-string: out of space\n" 3 0) # 3=cyan - 974 { - 975 eb/jump loop/disp8 - 976 } - 977 # never gets here - 978 - 979 test-slice-to-string: - 980 # . prologue - 981 55/push-ebp - 982 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 983 # var ad/edx: allocation-descriptor containing 16 bytes - 984 # . var end/ecx: (addr byte) - 985 89/<- %ecx 4/r32/esp - 986 81 5/subop/subtract %esp 0x10/imm32 - 987 # . var start/edx: (addr byte) = end - 0x10 - 988 89/<- %edx 4/r32/esp - 989 # . ad = {start, end} - 990 51/push-ecx - 991 52/push-edx - 992 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - 993 # (eax..ecx) = "Abc" - 994 b8/copy-to-eax "Abc"/imm32 - 995 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx - 996 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx - 997 05/add-to-eax 4/imm32 - 998 # var slice/ecx: slice = {eax, ecx} - 999 51/push-ecx -1000 50/push-eax -1001 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1002 # var h/ebx: (handle array byte) -1003 68/push 0/imm32 -1004 68/push 0/imm32 -1005 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx -1006 # slice-to-string(ad, slice, h) -1007 # . . push args -1008 53/push-ebx -1009 51/push-ecx -1010 52/push-edx -1011 # . . call -1012 e8/call slice-to-string/disp32 -1013 # . . discard args -1014 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1015 # eax = h->payload -1016 8b/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy *(ebx+4) to eax -1017 # skip payload->allocid -1018 05/add-to-eax 4/imm32 -1019 +-- 26 lines: #? # dump eax --------------------------------------------------------------------------------------------------------------------------------------------------------- -1045 # eax = string-equal?(eax, "Abc") -1046 # . . push args -1047 68/push "Abc"/imm32 -1048 50/push-eax -1049 # . . call -1050 e8/call string-equal?/disp32 -1051 # . . discard args -1052 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1053 # check-ints-equal(eax, 1, msg) -1054 # . . push args -1055 68/push "F - test-slice-to-string"/imm32 -1056 68/push 1/imm32/true -1057 50/push-eax -1058 # . . call -1059 e8/call check-ints-equal/disp32 -1060 # . . discard args -1061 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1062 # . reclaim locals -1063 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # add to esp -1064 # . epilogue -1065 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1066 5d/pop-to-ebp -1067 c3/return -1068 -1069 # . . vim:nowrap:textwidth=0 + 850 $write-slice:abort: + 851 (abort "write-slice: out of space") + 852 # never gets here + 853 + 854 test-write-slice: + 855 # . prologue + 856 55/push-ebp + 857 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 858 # setup + 859 # . clear-stream(_test-stream) + 860 # . . push args + 861 68/push _test-stream/imm32 + 862 # . . call + 863 e8/call clear-stream/disp32 + 864 # . . discard args + 865 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 866 # (eax..ecx) = "Abc" + 867 b8/copy-to-eax "Abc"/imm32 + 868 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 869 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx + 870 05/add-to-eax 4/imm32 + 871 # var slice/ecx: slice = {eax, ecx} + 872 51/push-ecx + 873 50/push-eax + 874 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + 875 # write-slice(_test-stream, slice) + 876 # . . push args + 877 51/push-ecx + 878 68/push _test-stream/imm32 + 879 # . . call + 880 e8/call write-slice/disp32 + 881 # . . discard args + 882 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 883 # check-stream-equal(_test-stream, "Abc", msg) + 884 # . . push args + 885 68/push "F - test-write-slice"/imm32 + 886 68/push "Abc"/imm32 + 887 68/push _test-stream/imm32 + 888 # . . call + 889 e8/call check-stream-equal/disp32 + 890 # . . discard args + 891 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 892 # . epilogue + 893 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 894 5d/pop-to-ebp + 895 c3/return + 896 + 897 # copy a slice into a new (dynamically allocated) string + 898 slice-to-string: # ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte) + 899 # . prologue + 900 55/push-ebp + 901 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 902 # . save registers + 903 50/push-eax + 904 51/push-ecx + 905 52/push-edx + 906 53/push-ebx + 907 56/push-esi + 908 # esi = in + 909 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi + 910 # var curr/edx: (addr byte) = in->start + 911 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx + 912 # var max/ebx: (addr byte) = in->end + 913 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 3/r32/ebx 4/disp8 . # copy *(esi+4) to ebx + 914 # var size/ecx: int = max - curr + 4 # total size of output string (including the initial 'size' field) + 915 89/copy 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # copy ebx to ecx + 916 29/subtract 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # subtract edx from ecx + 917 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx + 918 # allocate(ad, size, out) + 919 # . . push args + 920 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + 921 51/push-ecx + 922 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + 923 # . . call + 924 e8/call allocate/disp32 + 925 # . . discard args + 926 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 927 # eax = out->payload + 928 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax + 929 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax + 930 # skip payload->allocid + 931 05/add-to-eax 4/imm32 + 932 # if (eax == 0) abort + 933 3d/compare-eax-and 0/imm32 + 934 74/jump-if-= $slice-to-string:abort/disp8 + 935 # out->size = size-4 + 936 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax + 937 81 5/subop/subtract 0/mod/indirect 0/rm32/eax . . . . . 4/imm32 # subtract 4 from *eax + 938 # save out + 939 50/push-eax + 940 $slice-to-string:initialize: + 941 # eax = _append-4(eax+4, eax+size, curr, max) # clobbering ecx + 942 # . . push args + 943 53/push-ebx + 944 52/push-edx + 945 # . . push eax+size (clobbering ecx) + 946 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx + 947 51/push-ecx + 948 # . . push eax+4 (clobbering eax) + 949 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 4/imm32 # add to eax + 950 50/push-eax + 951 # . . call + 952 e8/call _append-4/disp32 + 953 # . . discard args + 954 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + 955 # restore out (assumes _append-4 can't error) + 956 58/pop-to-eax + 957 $slice-to-string:end: + 958 # . restore registers + 959 5e/pop-to-esi + 960 5b/pop-to-ebx + 961 5a/pop-to-edx + 962 59/pop-to-ecx + 963 58/pop-to-eax + 964 # . epilogue + 965 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 966 5d/pop-to-ebp + 967 c3/return + 968 + 969 $slice-to-string:abort: + 970 (abort "slice-to-string: out of space") + 971 # never gets here + 972 + 973 test-slice-to-string: + 974 # . prologue + 975 55/push-ebp + 976 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 977 # var ad/edx: allocation-descriptor containing 16 bytes + 978 # . var end/ecx: (addr byte) + 979 89/<- %ecx 4/r32/esp + 980 81 5/subop/subtract %esp 0x10/imm32 + 981 # . var start/edx: (addr byte) = end - 0x10 + 982 89/<- %edx 4/r32/esp + 983 # . ad = {start, end} + 984 51/push-ecx + 985 52/push-edx + 986 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + 987 # (eax..ecx) = "Abc" + 988 b8/copy-to-eax "Abc"/imm32 + 989 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 990 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx + 991 05/add-to-eax 4/imm32 + 992 # var slice/ecx: slice = {eax, ecx} + 993 51/push-ecx + 994 50/push-eax + 995 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + 996 # var h/ebx: (handle array byte) + 997 68/push 0/imm32 + 998 68/push 0/imm32 + 999 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx +1000 # slice-to-string(ad, slice, h) +1001 # . . push args +1002 53/push-ebx +1003 51/push-ecx +1004 52/push-edx +1005 # . . call +1006 e8/call slice-to-string/disp32 +1007 # . . discard args +1008 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1009 # eax = h->payload +1010 8b/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy *(ebx+4) to eax +1011 # skip payload->allocid +1012 05/add-to-eax 4/imm32 +1013 +-- 26 lines: #? # dump eax --------------------------------------------------------------------------------------------------------------------------------------------------------- +1039 # eax = string-equal?(eax, "Abc") +1040 # . . push args +1041 68/push "Abc"/imm32 +1042 50/push-eax +1043 # . . call +1044 e8/call string-equal?/disp32 +1045 # . . discard args +1046 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1047 # check-ints-equal(eax, 1, msg) +1048 # . . push args +1049 68/push "F - test-slice-to-string"/imm32 +1050 68/push 1/imm32/true +1051 50/push-eax +1052 # . . call +1053 e8/call check-ints-equal/disp32 +1054 # . . discard args +1055 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1056 # . reclaim locals +1057 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # add to esp +1058 # . epilogue +1059 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1060 5d/pop-to-ebp +1061 c3/return +1062 +1063 # . . vim:nowrap:textwidth=0 diff --git a/html/126write-int-decimal.subx.html b/html/126write-int-decimal.subx.html index 02126064..f7c26c32 100644 --- a/html/126write-int-decimal.subx.html +++ b/html/126write-int-decimal.subx.html @@ -150,7 +150,7 @@ if ('onhashchange' in window) { 89 74/jump-if-= $write-int32-decimal:write-break/disp8 90 # if (curr >= max) abort 91 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx - 92 73/jump-if-addr>= $write-int32-decimal:abort/disp8 + 92 73/jump-if-addr>= $write-int32-decimal:abort/disp8 93 $write-int32-decimal:write-char: 94 # *curr = AL 95 88/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy AL to byte at *ecx @@ -174,294 +174,288 @@ if ('onhashchange' in window) { 113 5d/pop-to-ebp 114 c3/return 115 -116 $write-int32-decimal:abort: -117 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "write-int32-decimal: stream out of space" 3 0) # 3=cyan -118 { -119 eb/jump loop/disp8 -120 } -121 # never gets here -122 -123 test-write-int32-decimal: -124 # - check that a single-digit number converts correctly -125 # setup -126 # . clear-stream(_test-stream) -127 # . . push args -128 68/push _test-stream/imm32 -129 # . . call -130 e8/call clear-stream/disp32 -131 # . . discard args -132 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -133 # write-int32-decimal(_test-stream, 9) -134 # . . push args -135 68/push 9/imm32 -136 68/push _test-stream/imm32 -137 # . . call -138 e8/call write-int32-decimal/disp32 -139 # . . discard args -140 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -141 # check-stream-equal(_test-stream, "9", msg) -142 # . . push args -143 68/push "F - test-write-int32-decimal"/imm32 -144 68/push "9"/imm32 -145 68/push _test-stream/imm32 -146 # . . call -147 e8/call check-stream-equal/disp32 -148 # . . discard args -149 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -150 # . end -151 c3/return -152 -153 test-write-int32-decimal-zero: -154 # - check that 0 converts correctly -155 # setup -156 # . clear-stream(_test-stream) -157 # . . push args -158 68/push _test-stream/imm32 -159 # . . call -160 e8/call clear-stream/disp32 -161 # . . discard args -162 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -163 # write-int32-decimal(_test-stream, 0) -164 # . . push args -165 68/push 0/imm32 -166 68/push _test-stream/imm32 -167 # . . call -168 e8/call write-int32-decimal/disp32 -169 # . . discard args -170 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -171 # check-stream-equal(_test-stream, "0", msg) -172 # . . push args -173 68/push "F - test-write-int32-decimal-zero"/imm32 -174 68/push "0"/imm32 -175 68/push _test-stream/imm32 -176 # . . call -177 e8/call check-stream-equal/disp32 -178 # . . discard args -179 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -180 # . end -181 c3/return -182 -183 test-write-int32-decimal-multiple-digits: -184 # - check that a multi-digit number converts correctly -185 # setup -186 # . clear-stream(_test-stream) -187 # . . push args -188 68/push _test-stream/imm32 -189 # . . call -190 e8/call clear-stream/disp32 -191 # . . discard args -192 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -193 # write-int32-decimal(_test-stream, 10) -194 # . . push args -195 68/push 0xa/imm32 -196 68/push _test-stream/imm32 -197 # . . call -198 e8/call write-int32-decimal/disp32 -199 # . . discard args -200 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -201 # check-stream-equal(_test-stream, "10", msg) -202 # . . push args -203 68/push "F - test-write-int32-decimal-multiple-digits"/imm32 -204 68/push "10"/imm32 -205 68/push _test-stream/imm32 -206 # . . call -207 e8/call check-stream-equal/disp32 -208 # . . discard args -209 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -210 # . end -211 c3/return -212 -213 test-write-int32-decimal-negative: -214 # - check that a negative single-digit number converts correctly -215 # setup -216 # . clear-stream(_test-stream) -217 # . . push args -218 68/push _test-stream/imm32 -219 # . . call -220 e8/call clear-stream/disp32 -221 # . . discard args -222 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -223 # write-int32-decimal(_test-stream, -9) -224 # . . push args -225 68/push -9/imm32 -226 68/push _test-stream/imm32 -227 # . . call -228 e8/call write-int32-decimal/disp32 -229 # . . discard args -230 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -231 +-- 26 lines: #? # dump _test-stream ------------------------------------------------------------------------------------------------------------------------------------------------ -257 # check-stream-equal(_test-stream, "-9", msg) -258 # . . push args -259 68/push "F - test-write-int32-decimal-negative"/imm32 -260 68/push "-9"/imm32 -261 68/push _test-stream/imm32 -262 # . . call -263 e8/call check-stream-equal/disp32 -264 # . . discard args -265 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -266 # . end -267 c3/return -268 -269 test-write-int32-decimal-negative-multiple-digits: -270 # - check that a multi-digit number converts correctly -271 # setup -272 # . clear-stream(_test-stream) -273 # . . push args -274 68/push _test-stream/imm32 -275 # . . call -276 e8/call clear-stream/disp32 -277 # . . discard args -278 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -279 # write-int32-decimal(_test-stream, -10) -280 # . . push args -281 68/push -0xa/imm32 -282 68/push _test-stream/imm32 -283 # . . call -284 e8/call write-int32-decimal/disp32 -285 # . . discard args -286 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -287 # check-stream-equal(_test-stream, "-10", msg) -288 # . . push args -289 68/push "F - test-write-int32-decimal-negative-multiple-digits"/imm32 -290 68/push "-10"/imm32 -291 68/push _test-stream/imm32 -292 # . . call -293 e8/call check-stream-equal/disp32 -294 # . . discard args -295 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -296 # . end -297 c3/return -298 -299 decimal-digit?: # c: grapheme -> result/eax: boolean -300 # . prologue -301 55/push-ebp -302 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -303 # . save registers -304 51/push-ecx -305 # ecx = c -306 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -307 # result = false -308 b8/copy-to-eax 0/imm32/false -309 # return false if c < '0' -310 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x30/imm32 # compare ecx -311 7c/jump-if-< $decimal-digit?:end/disp8 -312 # return (c <= '9') -313 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x39/imm32 # compare ecx -314 7f/jump-if-> $decimal-digit?:end/disp8 -315 $decimal-digit?:true: -316 b8/copy-to-eax 1/imm32/true -317 $decimal-digit?:end: -318 # . restore registers -319 59/pop-to-ecx -320 # . epilogue -321 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -322 5d/pop-to-ebp -323 c3/return -324 -325 test-decimal-digit-below-0: -326 # eax = decimal-digit?(0x2f) -327 # . . push args -328 68/push 0x2f/imm32 -329 # . . call -330 e8/call decimal-digit?/disp32 -331 # . . discard args -332 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -333 # check-ints-equal(eax, 0, msg) -334 # . . push args -335 68/push "F - test-decimal-digit-below-0"/imm32 -336 68/push 0/imm32/false -337 50/push-eax -338 # . . call -339 e8/call check-ints-equal/disp32 -340 # . . discard args -341 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -342 c3/return -343 -344 test-decimal-digit-0-to-9: -345 # eax = decimal-digit?(0x30) -346 # . . push args -347 68/push 0x30/imm32 -348 # . . call -349 e8/call decimal-digit?/disp32 -350 # . . discard args -351 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -352 # check-ints-equal(eax, 1, msg) -353 # . . push args -354 68/push "F - test-decimal-digit-at-0"/imm32 -355 68/push 1/imm32/true -356 50/push-eax -357 # . . call -358 e8/call check-ints-equal/disp32 -359 # . . discard args -360 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -361 # eax = decimal-digit?(0x39) -362 # . . push args -363 68/push 0x39/imm32 -364 # . . call -365 e8/call decimal-digit?/disp32 -366 # . . discard args -367 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -368 # check-ints-equal(eax, 1, msg) -369 # . . push args -370 68/push "F - test-decimal-digit-at-9"/imm32 -371 68/push 1/imm32/true -372 50/push-eax -373 # . . call -374 e8/call check-ints-equal/disp32 -375 # . . discard args -376 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -377 c3/return -378 -379 test-decimal-digit-above-9: -380 # eax = decimal-digit?(0x3a) -381 # . . push args -382 68/push 0x3a/imm32 -383 # . . call -384 e8/call decimal-digit?/disp32 -385 # . . discard args -386 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -387 # check-ints-equal(eax, 0, msg) -388 # . . push args -389 68/push "F - test-decimal-digit-above-9"/imm32 -390 68/push 0/imm32/false -391 50/push-eax -392 # . . call -393 e8/call check-ints-equal/disp32 -394 # . . discard args -395 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -396 c3/return -397 -398 to-decimal-digit: # in: grapheme -> out/eax: int -399 # . prologue -400 55/push-ebp -401 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -402 # eax = in -403 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax -404 $to-decimal-digit:check0: -405 # if (eax < '0') goto abort -406 3d/compare-eax-with 0x30/imm32/0 -407 7c/jump-if-< $to-decimal-digit:abort/disp8 -408 $to-decimal-digit:check1: -409 # if (eax > '9') goto abort -410 3d/compare-eax-with 0x39/imm32/f -411 7f/jump-if-> $to-decimal-digit:abort/disp8 -412 $to-decimal-digit:digit: -413 # return eax - '0' -414 2d/subtract-from-eax 0x30/imm32/0 -415 $to-decimal-digit:end: -416 # . epilogue -417 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -418 5d/pop-to-ebp -419 c3/return -420 -421 $to-decimal-digit:abort: -422 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "to-decimal-digit: not a digit character" 3 0) # 3=cyan -423 { -424 eb/jump loop/disp8 -425 } -426 # never gets here -427 -428 # . . vim:nowrap:textwidth=0 +116 $write-int32-decimal:abort: +117 (abort "write-int32-decimal: stream out of space") +118 # never gets here +119 +120 test-write-int32-decimal: +121 # - check that a single-digit number converts correctly +122 # setup +123 # . clear-stream(_test-stream) +124 # . . push args +125 68/push _test-stream/imm32 +126 # . . call +127 e8/call clear-stream/disp32 +128 # . . discard args +129 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +130 # write-int32-decimal(_test-stream, 9) +131 # . . push args +132 68/push 9/imm32 +133 68/push _test-stream/imm32 +134 # . . call +135 e8/call write-int32-decimal/disp32 +136 # . . discard args +137 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +138 # check-stream-equal(_test-stream, "9", msg) +139 # . . push args +140 68/push "F - test-write-int32-decimal"/imm32 +141 68/push "9"/imm32 +142 68/push _test-stream/imm32 +143 # . . call +144 e8/call check-stream-equal/disp32 +145 # . . discard args +146 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +147 # . end +148 c3/return +149 +150 test-write-int32-decimal-zero: +151 # - check that 0 converts correctly +152 # setup +153 # . clear-stream(_test-stream) +154 # . . push args +155 68/push _test-stream/imm32 +156 # . . call +157 e8/call clear-stream/disp32 +158 # . . discard args +159 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +160 # write-int32-decimal(_test-stream, 0) +161 # . . push args +162 68/push 0/imm32 +163 68/push _test-stream/imm32 +164 # . . call +165 e8/call write-int32-decimal/disp32 +166 # . . discard args +167 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +168 # check-stream-equal(_test-stream, "0", msg) +169 # . . push args +170 68/push "F - test-write-int32-decimal-zero"/imm32 +171 68/push "0"/imm32 +172 68/push _test-stream/imm32 +173 # . . call +174 e8/call check-stream-equal/disp32 +175 # . . discard args +176 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +177 # . end +178 c3/return +179 +180 test-write-int32-decimal-multiple-digits: +181 # - check that a multi-digit number converts correctly +182 # setup +183 # . clear-stream(_test-stream) +184 # . . push args +185 68/push _test-stream/imm32 +186 # . . call +187 e8/call clear-stream/disp32 +188 # . . discard args +189 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +190 # write-int32-decimal(_test-stream, 10) +191 # . . push args +192 68/push 0xa/imm32 +193 68/push _test-stream/imm32 +194 # . . call +195 e8/call write-int32-decimal/disp32 +196 # . . discard args +197 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +198 # check-stream-equal(_test-stream, "10", msg) +199 # . . push args +200 68/push "F - test-write-int32-decimal-multiple-digits"/imm32 +201 68/push "10"/imm32 +202 68/push _test-stream/imm32 +203 # . . call +204 e8/call check-stream-equal/disp32 +205 # . . discard args +206 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +207 # . end +208 c3/return +209 +210 test-write-int32-decimal-negative: +211 # - check that a negative single-digit number converts correctly +212 # setup +213 # . clear-stream(_test-stream) +214 # . . push args +215 68/push _test-stream/imm32 +216 # . . call +217 e8/call clear-stream/disp32 +218 # . . discard args +219 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +220 # write-int32-decimal(_test-stream, -9) +221 # . . push args +222 68/push -9/imm32 +223 68/push _test-stream/imm32 +224 # . . call +225 e8/call write-int32-decimal/disp32 +226 # . . discard args +227 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +228 +-- 26 lines: #? # dump _test-stream ------------------------------------------------------------------------------------------------------------------------------------------------ +254 # check-stream-equal(_test-stream, "-9", msg) +255 # . . push args +256 68/push "F - test-write-int32-decimal-negative"/imm32 +257 68/push "-9"/imm32 +258 68/push _test-stream/imm32 +259 # . . call +260 e8/call check-stream-equal/disp32 +261 # . . discard args +262 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +263 # . end +264 c3/return +265 +266 test-write-int32-decimal-negative-multiple-digits: +267 # - check that a multi-digit number converts correctly +268 # setup +269 # . clear-stream(_test-stream) +270 # . . push args +271 68/push _test-stream/imm32 +272 # . . call +273 e8/call clear-stream/disp32 +274 # . . discard args +275 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +276 # write-int32-decimal(_test-stream, -10) +277 # . . push args +278 68/push -0xa/imm32 +279 68/push _test-stream/imm32 +280 # . . call +281 e8/call write-int32-decimal/disp32 +282 # . . discard args +283 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +284 # check-stream-equal(_test-stream, "-10", msg) +285 # . . push args +286 68/push "F - test-write-int32-decimal-negative-multiple-digits"/imm32 +287 68/push "-10"/imm32 +288 68/push _test-stream/imm32 +289 # . . call +290 e8/call check-stream-equal/disp32 +291 # . . discard args +292 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +293 # . end +294 c3/return +295 +296 decimal-digit?: # c: grapheme -> result/eax: boolean +297 # . prologue +298 55/push-ebp +299 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +300 # . save registers +301 51/push-ecx +302 # ecx = c +303 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +304 # result = false +305 b8/copy-to-eax 0/imm32/false +306 # return false if c < '0' +307 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x30/imm32 # compare ecx +308 7c/jump-if-< $decimal-digit?:end/disp8 +309 # return (c <= '9') +310 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x39/imm32 # compare ecx +311 7f/jump-if-> $decimal-digit?:end/disp8 +312 $decimal-digit?:true: +313 b8/copy-to-eax 1/imm32/true +314 $decimal-digit?:end: +315 # . restore registers +316 59/pop-to-ecx +317 # . epilogue +318 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +319 5d/pop-to-ebp +320 c3/return +321 +322 test-decimal-digit-below-0: +323 # eax = decimal-digit?(0x2f) +324 # . . push args +325 68/push 0x2f/imm32 +326 # . . call +327 e8/call decimal-digit?/disp32 +328 # . . discard args +329 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +330 # check-ints-equal(eax, 0, msg) +331 # . . push args +332 68/push "F - test-decimal-digit-below-0"/imm32 +333 68/push 0/imm32/false +334 50/push-eax +335 # . . call +336 e8/call check-ints-equal/disp32 +337 # . . discard args +338 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +339 c3/return +340 +341 test-decimal-digit-0-to-9: +342 # eax = decimal-digit?(0x30) +343 # . . push args +344 68/push 0x30/imm32 +345 # . . call +346 e8/call decimal-digit?/disp32 +347 # . . discard args +348 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +349 # check-ints-equal(eax, 1, msg) +350 # . . push args +351 68/push "F - test-decimal-digit-at-0"/imm32 +352 68/push 1/imm32/true +353 50/push-eax +354 # . . call +355 e8/call check-ints-equal/disp32 +356 # . . discard args +357 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +358 # eax = decimal-digit?(0x39) +359 # . . push args +360 68/push 0x39/imm32 +361 # . . call +362 e8/call decimal-digit?/disp32 +363 # . . discard args +364 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +365 # check-ints-equal(eax, 1, msg) +366 # . . push args +367 68/push "F - test-decimal-digit-at-9"/imm32 +368 68/push 1/imm32/true +369 50/push-eax +370 # . . call +371 e8/call check-ints-equal/disp32 +372 # . . discard args +373 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +374 c3/return +375 +376 test-decimal-digit-above-9: +377 # eax = decimal-digit?(0x3a) +378 # . . push args +379 68/push 0x3a/imm32 +380 # . . call +381 e8/call decimal-digit?/disp32 +382 # . . discard args +383 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +384 # check-ints-equal(eax, 0, msg) +385 # . . push args +386 68/push "F - test-decimal-digit-above-9"/imm32 +387 68/push 0/imm32/false +388 50/push-eax +389 # . . call +390 e8/call check-ints-equal/disp32 +391 # . . discard args +392 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +393 c3/return +394 +395 to-decimal-digit: # in: grapheme -> out/eax: int +396 # . prologue +397 55/push-ebp +398 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +399 # eax = in +400 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax +401 $to-decimal-digit:check0: +402 # if (eax < '0') goto abort +403 3d/compare-eax-with 0x30/imm32/0 +404 7c/jump-if-< $to-decimal-digit:abort/disp8 +405 $to-decimal-digit:check1: +406 # if (eax > '9') goto abort +407 3d/compare-eax-with 0x39/imm32/f +408 7f/jump-if-> $to-decimal-digit:abort/disp8 +409 $to-decimal-digit:digit: +410 # return eax - '0' +411 2d/subtract-from-eax 0x30/imm32/0 +412 $to-decimal-digit:end: +413 # . epilogue +414 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +415 5d/pop-to-ebp +416 c3/return +417 +418 $to-decimal-digit:abort: +419 (abort "to-decimal-digit: not a digit character") +420 # never gets here +421 +422 # . . vim:nowrap:textwidth=0 diff --git a/html/301array-equal.subx.html b/html/301array-equal.subx.html index c80d945b..e47dee8c 100644 --- a/html/301array-equal.subx.html +++ b/html/301array-equal.subx.html @@ -293,7 +293,7 @@ if ('onhashchange' in window) { 233 81 0/subop/add %ebx 4/imm32 234 eb/jump $_parse-array-of-ints:loop1/disp8 235 $_parse-array-of-ints:break1: -236 (allocate-array *(ebp+8) %ebx *(ebp+0x10)) +236 (allocate-array *(ebp+8) %ebx *(ebp+0x10)) 237 $_parse-array-of-ints:pass2: 238 # var slice/edi: slice = {s->data, 0} 239 68/push 0/imm32/end @@ -302,7 +302,7 @@ if ('onhashchange' in window) { 242 89/<- %edi 4/r32/esp 243 # curr = lookup(out)->data 244 8b/-> *(ebp+0x10) 0/r32/eax -245 (lookup *eax *(eax+4)) # => eax +245 (lookup *eax *(eax+4)) # => eax 246 8d/copy-address *(eax+4) 1/r32/ecx 247 $_parse-array-of-ints:loop2: 248 # if (slice->start >= end) break @@ -357,7 +357,7 @@ if ('onhashchange' in window) { 297 89/<- %ecx 4/r32/esp 298 # 299 (_parse-array-of-ints Heap "1 2 3" %esi) -300 (lookup *esi *(esi+4)) # => eax +300 (lookup *esi *(esi+4)) # => eax 301 (array-equal? %ecx %eax) # => eax 302 (check-ints-equal %eax 1 "F - test-parse-array-of-ints") 303 # . epilogue @@ -376,7 +376,7 @@ if ('onhashchange' in window) { 316 89/<- %esi 4/r32/esp 317 # 318 (_parse-array-of-ints Heap "" %esi) -319 (lookup *esi *(esi+4)) # => eax +319 (lookup *esi *(esi+4)) # => eax 320 (check-ints-equal *eax 0 "F - test-parse-array-of-ints-empty") 321 # . epilogue 322 89/<- %esp 5/r32/ebp @@ -394,7 +394,7 @@ if ('onhashchange' in window) { 334 89/<- %esi 4/r32/esp 335 # 336 (_parse-array-of-ints Heap Space %esi) -337 (lookup *esi *(esi+4)) # => eax +337 (lookup *esi *(esi+4)) # => eax 338 (check-ints-equal *eax 0 "F - test-parse-array-of-ints-just-whitespace") 339 # . epilogue 340 89/<- %esp 5/r32/ebp @@ -417,7 +417,7 @@ if ('onhashchange' in window) { 357 89/<- %ecx 4/r32/esp 358 # 359 (_parse-array-of-ints Heap " 1 2 3 " %esi) -360 (lookup *esi *(esi+4)) # => eax +360 (lookup *esi *(esi+4)) # => eax 361 (array-equal? %ecx %eax) # => eax 362 (check-ints-equal %eax 1 "F - test-parse-array-of-ints-extra-whitespace") 363 # . epilogue @@ -452,7 +452,7 @@ if ('onhashchange' in window) { 392 89/<- %esi 4/r32/esp 393 # var b/eax: (addr array int) = parse-array-of-ints(Heap, expected) 394 (parse-array-of-ints *(ebp+0xc) %esi) -395 (lookup *esi *(esi+4)) # => eax +395 (lookup *esi *(esi+4)) # => eax 396 # 397 (array-equal? *(ebp+8) %eax) 398 (check-ints-equal %eax 1 *(ebp+0x10)) diff --git a/html/302stack_allocate.subx.html b/html/302stack_allocate.subx.html index ce087137..9b16a13a 100644 --- a/html/302stack_allocate.subx.html +++ b/html/302stack_allocate.subx.html @@ -104,7 +104,7 @@ if ('onhashchange' in window) { 47 89/<- *Push-n-zero-bytes-esp 4/r32/esp 48 81 0/subop/add *Push-n-zero-bytes-esp 4/imm32 49 81 0/subop/add *(ebp+4) 4/imm32 -50 (zero-out *Push-n-zero-bytes-esp *(ebp+4)) # n+4 +50 (zero-out *Push-n-zero-bytes-esp *(ebp+4)) # n+4 51 $push-n-zero-bytes:epilogue: 52 8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp # restore spill 53 c3/return diff --git a/html/308allocate-array.subx.html b/html/308allocate-array.subx.html index 4d16477c..4e7568ad 100644 --- a/html/308allocate-array.subx.html +++ b/html/308allocate-array.subx.html @@ -70,7 +70,7 @@ if ('onhashchange' in window) { 14 8b/-> *(ebp+0xc) 0/r32/eax 15 f7 4/subop/multiply-into-edx-eax *(ebp+0x10) 16 # TODO: check edx for overflow -17 (allocate-array *(ebp+8) %eax *(ebp+0x14)) +17 (allocate-array *(ebp+8) %eax *(ebp+0x14)) 18 $allocate-array2:end: 19 # . restore registers 20 5a/pop-to-edx diff --git a/html/309stream.subx.html b/html/309stream.subx.html index 5462575a..07fd0681 100644 --- a/html/309stream.subx.html +++ b/html/309stream.subx.html @@ -125,7 +125,7 @@ if ('onhashchange' in window) { 69 8b/-> *(ebp+0x10) 1/r32/ecx 70 01/add-to %ecx 2/r32/edx 71 3b/compare 1/r32/ecx *(edi+8) - 72 0f 8f/jump-if-> $write-to-stream:abort/disp32 + 72 0f 8f/jump-if-> $write-to-stream:abort/disp32 73 # var out/edx: (addr byte) = s->data + s->write 74 8d/copy-address *(edi+edx+0xc) 2/r32/edx 75 # var outend/ebx: (addr byte) = out + n @@ -153,210 +153,204 @@ if ('onhashchange' in window) { 97 5d/pop-to-ebp 98 c3/return 99 -100 $write-to-stream:abort: -101 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "write-to-stream: stream full" 3 0) # 3=cyan -102 { -103 eb/jump loop/disp8 -104 } -105 # never gets here -106 -107 read-from-stream: # s: (addr stream _), out: (addr byte), n: int -108 # . prologue -109 55/push-ebp -110 89/<- %ebp 4/r32/esp -111 # . save registers -112 50/push-eax -113 51/push-ecx -114 52/push-edx -115 53/push-ebx -116 56/push-esi -117 # esi = s -118 8b/-> *(ebp+8) 6/r32/esi -119 # var sread/edx: int = s->read -120 8b/-> *(esi+4) 2/r32/edx -121 # if (sread + n > s->write) abort -122 8b/-> *(ebp+0x10) 1/r32/ecx -123 01/add-to %ecx 2/r32/edx -124 3b/compare 1/r32/ecx *esi -125 0f 8f/jump-if-> $read-from-stream:abort/disp32 -126 # var in/edx: (addr byte) = s->data + s->read -127 8d/copy-address *(esi+edx+0xc) 2/r32/edx -128 # var inend/ebx: (addr byte) = in + n -129 8b/-> *(ebp+0x10) 3/r32/ebx -130 8d/copy-address *(edx+ebx) 3/r32/ebx -131 # eax = out -132 8b/-> *(ebp+0xc) 0/r32/eax -133 # var outend/ecx: (addr byte) = out + n -134 8b/-> *(ebp+0x10) 1/r32/ecx -135 8d/copy-address *(eax+ecx) 1/r32/ecx -136 # -137 (_append-4 %eax %ecx %edx %ebx) # => eax -138 # s->read += n -139 8b/-> *(ebp+0x10) 1/r32/ecx -140 01/add-to *(esi+4) 1/r32/ecx -141 $read-from-stream:end: -142 # . restore registers -143 5e/pop-to-esi -144 5b/pop-to-ebx -145 5a/pop-to-edx -146 59/pop-to-ecx -147 58/pop-to-eax -148 # . epilogue -149 89/<- %esp 5/r32/ebp -150 5d/pop-to-ebp -151 c3/return -152 -153 $read-from-stream:abort: -154 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "read-from-stream: stream empty" 3 0) # 3=cyan -155 { -156 eb/jump loop/disp8 -157 } -158 # never gets here -159 -160 stream-first: # s: (addr stream byte) -> result/eax: byte -161 # . prologue -162 55/push-ebp -163 89/<- %ebp 4/r32/esp -164 # . save registers -165 51/push-ecx -166 56/push-esi -167 # result = false -168 b8/copy-to-eax 0/imm32 -169 # esi = s -170 8b/-> *(ebp+8) 6/r32/esi -171 # var idx/ecx: int = s->read -172 8b/-> *(esi+4) 1/r32/ecx -173 # if idx >= s->write return 0 -174 3b/compare-with 1/r32/ecx *esi -175 7d/jump-if->= $stream-first:end/disp8 -176 # result = s->data[idx] -177 8a/byte-> *(esi+ecx+0xc) 0/r32/AL -178 $stream-first:end: -179 # . restore registers -180 5e/pop-to-esi -181 59/pop-to-ecx -182 # . epilogue -183 89/<- %esp 5/r32/ebp -184 5d/pop-to-ebp -185 c3/return -186 -187 stream-final: # s: (addr stream byte) -> result/eax: byte -188 # . prologue -189 55/push-ebp -190 89/<- %ebp 4/r32/esp -191 # . save registers -192 51/push-ecx -193 56/push-esi -194 # result = false -195 b8/copy-to-eax 0/imm32 -196 # esi = s -197 8b/-> *(ebp+8) 6/r32/esi -198 # var max/ecx: int = s->write -199 8b/-> *esi 1/r32/ecx -200 # if s->read >= max return 0 -201 39/compare-with *(esi+4) 1/r32/ecx -202 7d/jump-if->= $stream-final:end/disp8 -203 # var idx/ecx: int = max - 1 -204 49/decrement-ecx -205 # result = s->data[idx] -206 8a/byte-> *(esi+ecx+0xc) 0/r32/AL -207 $stream-final:end: -208 # . restore registers -209 5e/pop-to-esi -210 59/pop-to-ecx -211 # . epilogue -212 89/<- %esp 5/r32/ebp -213 5d/pop-to-ebp -214 c3/return -215 -216 # compare all the data in two streams (ignoring the read pointer) -217 streams-data-equal?: # f: (addr stream byte), s: (addr array byte) -> result/eax: boolean -218 # pseudocode: -219 # awrite = a->write -220 # if (awrite != b->write) return false -221 # i = 0 -222 # curra = a->data -223 # currb = b->data -224 # while i < awrite -225 # i1 = *curra -226 # i2 = *currb -227 # if (c1 != c2) return false -228 # i+=4, curra+=4, currb+=4 -229 # return true -230 # -231 # registers: -232 # i: ecx -233 # awrite: edx -234 # curra: esi -235 # currb: edi -236 # i1: eax -237 # i2: ebx -238 # -239 # . prologue -240 55/push-ebp -241 89/<- %ebp 4/r32/esp -242 # . save registers -243 51/push-ecx -244 52/push-edx -245 53/push-ebx -246 56/push-esi -247 57/push-edi -248 # esi = a -249 8b/-> *(ebp+8) 6/r32/esi -250 # edi = b -251 8b/-> *(ebp+0xc) 7/r32/edi -252 # var awrite/edx: int = a->write -253 8b/-> *esi 2/r32/edx -254 $streams-data-equal?:sizes: -255 # if (awrite != b->write) return false -256 39/compare *edi 2/r32/edx -257 75/jump-if-!= $streams-data-equal?:false/disp8 -258 # var curra/esi: (addr byte) = a->data -259 81 0/subop/add %esi 0xc/imm32 -260 # var currb/edi: (addr byte) = b->data -261 81 0/subop/add %edi 0xc/imm32 -262 # var i/ecx: int = 0 -263 31/xor-with %ecx 1/r32/ecx -264 # var vala/eax: int -265 31/xor-with %eax 0/r32/eax -266 # var valb/ebx: int -267 31/xor-with %ebx 3/r32/ebx -268 $streams-data-equal?:loop: -269 { -270 # if (i >= awrite) return true -271 39/compare %ecx 2/r32/edx -272 7d/jump-if->= $streams-data-equal?:true/disp8 -273 # var vala/eax: int = *curra -274 8a/byte-> *esi 0/r32/eax -275 # var valb/ebx: int = *currb -276 8a/byte-> *edi 3/r32/ebx -277 # if (vala != valb) return false -278 39/compare %eax 3/r32/ebx -279 75/jump-if-!= $streams-data-equal?:false/disp8 -280 # i++ -281 41/increment-ecx -282 # curra++ -283 46/increment-esi -284 # currb++ -285 47/increment-edi -286 eb/jump loop/disp8 -287 } -288 $streams-data-equal?:true: -289 b8/copy-to-eax 1/imm32 -290 eb/jump $streams-data-equal?:end/disp8 -291 $streams-data-equal?:false: -292 b8/copy-to-eax 0/imm32 -293 $streams-data-equal?:end: -294 # . restore registers -295 5f/pop-to-edi -296 5e/pop-to-esi -297 5b/pop-to-ebx -298 5a/pop-to-edx -299 59/pop-to-ecx -300 # . epilogue -301 89/<- %esp 5/r32/ebp -302 5d/pop-to-ebp -303 c3/return +100 $write-to-stream:abort: +101 (abort "write-to-stream: stream full") +102 # never gets here +103 +104 read-from-stream: # s: (addr stream _), out: (addr byte), n: int +105 # . prologue +106 55/push-ebp +107 89/<- %ebp 4/r32/esp +108 # . save registers +109 50/push-eax +110 51/push-ecx +111 52/push-edx +112 53/push-ebx +113 56/push-esi +114 # esi = s +115 8b/-> *(ebp+8) 6/r32/esi +116 # var sread/edx: int = s->read +117 8b/-> *(esi+4) 2/r32/edx +118 # if (sread + n > s->write) abort +119 8b/-> *(ebp+0x10) 1/r32/ecx +120 01/add-to %ecx 2/r32/edx +121 3b/compare 1/r32/ecx *esi +122 0f 8f/jump-if-> $read-from-stream:abort/disp32 +123 # var in/edx: (addr byte) = s->data + s->read +124 8d/copy-address *(esi+edx+0xc) 2/r32/edx +125 # var inend/ebx: (addr byte) = in + n +126 8b/-> *(ebp+0x10) 3/r32/ebx +127 8d/copy-address *(edx+ebx) 3/r32/ebx +128 # eax = out +129 8b/-> *(ebp+0xc) 0/r32/eax +130 # var outend/ecx: (addr byte) = out + n +131 8b/-> *(ebp+0x10) 1/r32/ecx +132 8d/copy-address *(eax+ecx) 1/r32/ecx +133 # +134 (_append-4 %eax %ecx %edx %ebx) # => eax +135 # s->read += n +136 8b/-> *(ebp+0x10) 1/r32/ecx +137 01/add-to *(esi+4) 1/r32/ecx +138 $read-from-stream:end: +139 # . restore registers +140 5e/pop-to-esi +141 5b/pop-to-ebx +142 5a/pop-to-edx +143 59/pop-to-ecx +144 58/pop-to-eax +145 # . epilogue +146 89/<- %esp 5/r32/ebp +147 5d/pop-to-ebp +148 c3/return +149 +150 $read-from-stream:abort: +151 (abort "read-from-stream: stream empty") +152 # never gets here +153 +154 stream-first: # s: (addr stream byte) -> result/eax: byte +155 # . prologue +156 55/push-ebp +157 89/<- %ebp 4/r32/esp +158 # . save registers +159 51/push-ecx +160 56/push-esi +161 # result = false +162 b8/copy-to-eax 0/imm32 +163 # esi = s +164 8b/-> *(ebp+8) 6/r32/esi +165 # var idx/ecx: int = s->read +166 8b/-> *(esi+4) 1/r32/ecx +167 # if idx >= s->write return 0 +168 3b/compare-with 1/r32/ecx *esi +169 7d/jump-if->= $stream-first:end/disp8 +170 # result = s->data[idx] +171 8a/byte-> *(esi+ecx+0xc) 0/r32/AL +172 $stream-first:end: +173 # . restore registers +174 5e/pop-to-esi +175 59/pop-to-ecx +176 # . epilogue +177 89/<- %esp 5/r32/ebp +178 5d/pop-to-ebp +179 c3/return +180 +181 stream-final: # s: (addr stream byte) -> result/eax: byte +182 # . prologue +183 55/push-ebp +184 89/<- %ebp 4/r32/esp +185 # . save registers +186 51/push-ecx +187 56/push-esi +188 # result = false +189 b8/copy-to-eax 0/imm32 +190 # esi = s +191 8b/-> *(ebp+8) 6/r32/esi +192 # var max/ecx: int = s->write +193 8b/-> *esi 1/r32/ecx +194 # if s->read >= max return 0 +195 39/compare-with *(esi+4) 1/r32/ecx +196 7d/jump-if->= $stream-final:end/disp8 +197 # var idx/ecx: int = max - 1 +198 49/decrement-ecx +199 # result = s->data[idx] +200 8a/byte-> *(esi+ecx+0xc) 0/r32/AL +201 $stream-final:end: +202 # . restore registers +203 5e/pop-to-esi +204 59/pop-to-ecx +205 # . epilogue +206 89/<- %esp 5/r32/ebp +207 5d/pop-to-ebp +208 c3/return +209 +210 # compare all the data in two streams (ignoring the read pointer) +211 streams-data-equal?: # f: (addr stream byte), s: (addr array byte) -> result/eax: boolean +212 # pseudocode: +213 # awrite = a->write +214 # if (awrite != b->write) return false +215 # i = 0 +216 # curra = a->data +217 # currb = b->data +218 # while i < awrite +219 # i1 = *curra +220 # i2 = *currb +221 # if (c1 != c2) return false +222 # i+=4, curra+=4, currb+=4 +223 # return true +224 # +225 # registers: +226 # i: ecx +227 # awrite: edx +228 # curra: esi +229 # currb: edi +230 # i1: eax +231 # i2: ebx +232 # +233 # . prologue +234 55/push-ebp +235 89/<- %ebp 4/r32/esp +236 # . save registers +237 51/push-ecx +238 52/push-edx +239 53/push-ebx +240 56/push-esi +241 57/push-edi +242 # esi = a +243 8b/-> *(ebp+8) 6/r32/esi +244 # edi = b +245 8b/-> *(ebp+0xc) 7/r32/edi +246 # var awrite/edx: int = a->write +247 8b/-> *esi 2/r32/edx +248 $streams-data-equal?:sizes: +249 # if (awrite != b->write) return false +250 39/compare *edi 2/r32/edx +251 75/jump-if-!= $streams-data-equal?:false/disp8 +252 # var curra/esi: (addr byte) = a->data +253 81 0/subop/add %esi 0xc/imm32 +254 # var currb/edi: (addr byte) = b->data +255 81 0/subop/add %edi 0xc/imm32 +256 # var i/ecx: int = 0 +257 31/xor-with %ecx 1/r32/ecx +258 # var vala/eax: int +259 31/xor-with %eax 0/r32/eax +260 # var valb/ebx: int +261 31/xor-with %ebx 3/r32/ebx +262 $streams-data-equal?:loop: +263 { +264 # if (i >= awrite) return true +265 39/compare %ecx 2/r32/edx +266 7d/jump-if->= $streams-data-equal?:true/disp8 +267 # var vala/eax: int = *curra +268 8a/byte-> *esi 0/r32/eax +269 # var valb/ebx: int = *currb +270 8a/byte-> *edi 3/r32/ebx +271 # if (vala != valb) return false +272 39/compare %eax 3/r32/ebx +273 75/jump-if-!= $streams-data-equal?:false/disp8 +274 # i++ +275 41/increment-ecx +276 # curra++ +277 46/increment-esi +278 # currb++ +279 47/increment-edi +280 eb/jump loop/disp8 +281 } +282 $streams-data-equal?:true: +283 b8/copy-to-eax 1/imm32 +284 eb/jump $streams-data-equal?:end/disp8 +285 $streams-data-equal?:false: +286 b8/copy-to-eax 0/imm32 +287 $streams-data-equal?:end: +288 # . restore registers +289 5f/pop-to-edi +290 5e/pop-to-esi +291 5b/pop-to-ebx +292 5a/pop-to-edx +293 59/pop-to-ecx +294 # . epilogue +295 89/<- %esp 5/r32/ebp +296 5d/pop-to-ebp +297 c3/return diff --git a/html/310copy-bytes.subx.html b/html/310copy-bytes.subx.html index d8fdba46..53cff9d8 100644 --- a/html/310copy-bytes.subx.html +++ b/html/310copy-bytes.subx.html @@ -130,13 +130,13 @@ if ('onhashchange' in window) { 72 8b/-> *esi 1/r32/ecx 73 2b/subtract *(esi+4) 1/r32/ecx 74 # allocate - 75 (allocate-array Heap %ecx *(ebp+0xc)) + 75 (allocate-array Heap %ecx *(ebp+0xc)) 76 # var in/edx: (addr byte) = s->data + s->read 77 8b/-> *(esi+4) 2/r32/edx 78 8d/copy-address *(esi+edx+0xc) 2/r32/edx 79 # var dest/eax: (addr byte) = data for out 80 8b/-> *(ebp+0xc) 0/r32/eax - 81 (lookup *eax *(eax+4)) # => eax + 81 (lookup *eax *(eax+4)) # => eax 82 8d/copy-address *(eax+4) 0/r32/eax 83 # 84 (copy-bytes %edx %eax %ecx) @@ -156,17 +156,17 @@ if ('onhashchange' in window) { 98 55/push-ebp 99 89/<- %ebp 4/r32/esp 100 # setup -101 (clear-stream _test-input-stream) -102 (write _test-input-stream "abc") +101 (clear-stream _test-input-stream) +102 (write _test-input-stream "abc") 103 # skip something -104 (read-byte _test-input-stream) # => eax +104 (read-byte _test-input-stream) # => eax 105 # var out/ecx: (handle array byte) 106 68/push 0/imm32 107 68/push 0/imm32 108 89/<- %ecx 4/r32/esp 109 # -110 (stream-to-array _test-input-stream %ecx) -111 (lookup *ecx *(ecx+4)) # => eax +110 (stream-to-array _test-input-stream %ecx) +111 (lookup *ecx *(ecx+4)) # => eax 112 (check-strings-equal %eax "bc") 113 # . epilogue 114 89/<- %esp 5/r32/ebp @@ -193,13 +193,13 @@ if ('onhashchange' in window) { 135 7c/jump-if-< $unquote-stream-to-array:end/disp8 136 81 5/subop/subtract %ecx 2/imm32 137 # allocate -138 (allocate-array Heap %ecx *(ebp+0xc)) +138 (allocate-array Heap %ecx *(ebp+0xc)) 139 # var in/edx: (addr byte) = s->data + s->read + 1 140 8b/-> *(esi+4) 2/r32/edx 141 8d/copy-address *(esi+edx+0xd) 2/r32/edx # Stream-data + 1 142 # var dest/eax: (addr byte) = data for out 143 8b/-> *(ebp+0xc) 0/r32/eax -144 (lookup *eax *(eax+4)) # => eax +144 (lookup *eax *(eax+4)) # => eax 145 8d/copy-address *(eax+4) 0/r32/eax 146 # 147 (copy-bytes %edx %eax %ecx) diff --git a/html/311decimal-int.subx.html b/html/311decimal-int.subx.html index 4d8f85f4..36596a40 100644 --- a/html/311decimal-int.subx.html +++ b/html/311decimal-int.subx.html @@ -126,7 +126,7 @@ if ('onhashchange' in window) { 66 4a/decrement-edx 67 # if it's a newline, break 68 8a/byte-> *edx 0/r32/eax - 69 81 4/subop/and %eax 0xff/imm32 + 69 25/and-eax-with 0xff/imm32 70 3d/compare-eax-and 0xa/imm32/newline 71 74/jump-if-= break/disp8 72 # not a newline, so restore it @@ -187,7 +187,7 @@ if ('onhashchange' in window) { 127 # if !decimal-digit?(*curr) return 0 128 8a/copy-byte *esi 1/r32/CL 129 50/push-eax -130 (decimal-digit? %ecx) # => eax +130 (decimal-digit? %ecx) # => eax 131 { 132 3d/compare-eax-and 0/imm32/false 133 75/jump-if-!= break/disp8 @@ -548,7 +548,7 @@ if ('onhashchange' in window) { 488 81 0/subop/add %ebx 4/imm32 489 eb/jump $_parse-array-of-decimal-ints:loop1/disp8 490 $_parse-array-of-decimal-ints:break1: -491 (allocate-array *(ebp+8) %ebx *(ebp+0x10)) +491 (allocate-array *(ebp+8) %ebx *(ebp+0x10)) 492 $_parse-array-of-decimal-ints:pass2: 493 # var slice/edi: slice = {s->data, 0} 494 68/push 0/imm32/end @@ -557,7 +557,7 @@ if ('onhashchange' in window) { 497 89/<- %edi 4/r32/esp 498 # curr = lookup(out)->data 499 8b/-> *(ebp+0x10) 0/r32/eax -500 (lookup *eax *(eax+4)) # => eax +500 (lookup *eax *(eax+4)) # => eax 501 8d/copy-address *(eax+4) 1/r32/ecx 502 $_parse-array-of-decimal-ints:loop2: 503 # if (slice->start >= end) break @@ -612,7 +612,7 @@ if ('onhashchange' in window) { 552 89/<- %ecx 4/r32/esp 553 # 554 (_parse-array-of-decimal-ints Heap "1 2 3" %esi) -555 (lookup *esi *(esi+4)) # => eax +555 (lookup *esi *(esi+4)) # => eax 556 (array-equal? %ecx %eax) # => eax 557 (check-ints-equal %eax 1 "F - test-parse-array-of-decimal-ints") 558 # . epilogue @@ -631,7 +631,7 @@ if ('onhashchange' in window) { 571 89/<- %esi 4/r32/esp 572 # 573 (_parse-array-of-decimal-ints Heap "" %esi) -574 (lookup *esi *(esi+4)) # => eax +574 (lookup *esi *(esi+4)) # => eax 575 (check-ints-equal *eax 0 "F - test-parse-array-of-decimal-ints-empty") 576 # . epilogue 577 89/<- %esp 5/r32/ebp @@ -649,7 +649,7 @@ if ('onhashchange' in window) { 589 89/<- %esi 4/r32/esp 590 # 591 (_parse-array-of-decimal-ints Heap Space %esi) -592 (lookup *esi *(esi+4)) # => eax +592 (lookup *esi *(esi+4)) # => eax 593 (check-ints-equal *eax 0 "F - test-parse-array-of-decimal-ints-just-whitespace") 594 # . epilogue 595 89/<- %esp 5/r32/ebp @@ -672,7 +672,7 @@ if ('onhashchange' in window) { 612 89/<- %ecx 4/r32/esp 613 # 614 (_parse-array-of-decimal-ints Heap " 1 2 3 " %esi) -615 (lookup *esi *(esi+4)) # => eax +615 (lookup *esi *(esi+4)) # => eax 616 (array-equal? %ecx %eax) # => eax 617 (check-ints-equal %eax 1 "F - test-parse-array-of-decimal-ints-extra-whitespace") 618 # . epilogue diff --git a/html/312copy.subx.html b/html/312copy.subx.html index 0d600548..ed936820 100644 --- a/html/312copy.subx.html +++ b/html/312copy.subx.html @@ -62,7 +62,7 @@ if ('onhashchange' in window) { 5 55/push-ebp 6 89/<- %ebp 4/r32/esp 7 # - 8 (copy-array Heap *(ebp+8) *(ebp+0xc)) + 8 (copy-array Heap *(ebp+8) *(ebp+0xc)) 9 $copy-array-object:end: 10 # . epilogue 11 89/<- %esp 5/r32/ebp diff --git a/html/313index-bounds-check.subx.html b/html/313index-bounds-check.subx.html index 52e406f5..9b7c3592 100644 --- a/html/313index-bounds-check.subx.html +++ b/html/313index-bounds-check.subx.html @@ -89,30 +89,32 @@ if ('onhashchange' in window) { 33 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " is too large for array '" 3 0) # 3=cyan 34 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x18) 3 0) # 3=cyan 35 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "'" 3 0) # 3=cyan -36 { -37 eb/jump loop/disp8 -38 } -39 # never gets here -40 $__check-mu-array-bounds:end: -41 # . restore registers -42 5a/pop-to-edx -43 59/pop-to-ecx -44 58/pop-to-eax -45 # . epilogue -46 89/<- %esp 5/r32/ebp -47 5d/pop-to-ebp -48 c3/return -49 -50 __check-mu-array-bounds:overflow: -51 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "fn " 3 0) # 3=cyan -52 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x14) 3 0) # 3=cyan -53 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 ": offset to array '" 3 0) # 3=cyan -54 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x18) 3 0) # 3=cyan -55 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "' overflowed 32 bits" 3 0) # 3=cyan -56 { -57 eb/jump loop/disp8 -58 } -59 # never gets here +36 (abort "") +37 # never gets here +38 $__check-mu-array-bounds:end: +39 # . restore registers +40 5a/pop-to-edx +41 59/pop-to-ecx +42 58/pop-to-eax +43 # . epilogue +44 89/<- %esp 5/r32/ebp +45 5d/pop-to-ebp +46 c3/return +47 +48 __check-mu-array-bounds:overflow: +49 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "fn " 3 0) # 3=cyan +50 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x14) 3 0) # 3=cyan +51 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 ": offset to array '" 3 0) # 3=cyan +52 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x18) 3 0) # 3=cyan +53 (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "' overflowed 32 bits" 3 0) # 3=cyan +54 (abort "") +55 # never gets here +56 +57 __mu-abort-null-index-base-address: +58 (abort "null address in 'index'") +59 +60 __mu-abort-null-get-base-address: +61 (abort "null address in 'get'") diff --git a/html/315stack-debug.subx.html b/html/315stack-debug.subx.html index c2155ae5..bd9d5e3f 100644 --- a/html/315stack-debug.subx.html +++ b/html/315stack-debug.subx.html @@ -68,10 +68,10 @@ if ('onhashchange' in window) { 10 50/push-eax 11 # 12 89/<- %eax 4/r32/esp - 13 81 7/subop/compare %eax 0x01000000/imm32 + 13 3d/compare-eax-and 0x01000000/imm32 14 { 15 7f/jump-if-> break/disp8 - 16 (abort "stack overflow") + 16 (abort "stack overflow") 17 } 18 $check-stack:end: 19 # . restore registers @@ -98,7 +98,7 @@ if ('onhashchange' in window) { 40 (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 %edx 0xf 0xc) 41 # restore cursor position 42 (set-cursor-position %eax %ecx) - 43 $check-stack:end: + 43 $show-stack-state:end: 44 # . restore registers 45 5a/pop-to-edx 46 59/pop-to-ecx diff --git a/html/316colors.subx.html b/html/316colors.subx.html index 6c62b26c..8a23c2e8 100644 --- a/html/316colors.subx.html +++ b/html/316colors.subx.html @@ -75,7 +75,7 @@ if ('onhashchange' in window) { 17 81 7/subop/compare %esi 0x100/imm32 18 { 19 7c/jump-if-< break/disp8 - 20 (abort "invalid color") + 20 (abort "invalid color") 21 } 22 # var color/esi: int = Colors-rgb[color] 23 b8/copy-to-eax Colors-rgb/imm32 diff --git a/html/317abort.subx.html b/html/317abort.subx.html new file mode 100644 index 00000000..f53236b1 --- /dev/null +++ b/html/317abort.subx.html @@ -0,0 +1,394 @@ + + + + +Mu - 317abort.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/317abort.subx +
+  1 # Dump a stack trace when you abort.
+  2 
+  3 == code
+  4 
+  5 abort:  # e: (addr array byte)
+  6     # . prologue
+  7     55/push-ebp
+  8     89/<- %ebp 4/r32/esp
+  9     #
+ 10     (set-cursor-position-on-real-screen 0 0)
+ 11     (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+8) 0xf 0xc)  # 0/real-screen, 0xf/fg=white, 0xc/bg=red
+ 12     (dump-call-stack)
+ 13     # crash
+ 14     {
+ 15       eb/jump loop/disp8
+ 16     }
+ 17 
+ 18 # Helpers below this point are not intended to be reused; they assume the
+ 19 # program will soon crash. In particular, they destroy the heap.
+ 20 
+ 21 dump-call-stack:
+ 22     # . prologue
+ 23     55/push-ebp
+ 24     89/<- %ebp 4/r32/esp
+ 25     # . save registers
+ 26     50/push-eax
+ 27     51/push-ecx
+ 28     52/push-edx
+ 29     53/push-ebx
+ 30     # var labels/edx: (addr stream {start-address, label-slice} 0x4000)
+ 31     # start addresses are in ascending order
+ 32     81 5/subop/subtract %esp 0x30000/imm32  # 0x4000 labels * 12 bytes per label
+ 33     68/push  0x30000/imm32
+ 34     68/push  0/imm32/read
+ 35     68/push  0/imm32/write
+ 36     89/<- %edx 4/r32/esp
+ 37     #
+ 38     (load-debug-symbols %edx)  # destroys the heap
+ 39     # traverse the linked list of ebp pointers: https://wiki.osdev.org/Stack_Trace
+ 40     8b/-> *ebp 3/r32/ebx
+ 41     {
+ 42       # loop termination check
+ 43       81 7/subop/compare %ebx 0/imm32
+ 44       0f 84/jump-if-= break/disp32
+ 45       # loop body
+ 46       (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "\n" 0 0xc)
+ 47       (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebx+4) 0xf 0xc)
+ 48       (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 " " 0 0xc)
+ 49       (containing-function %edx *(ebx+4))  # => eax, ecx
+ 50       (draw-slice-wrapping-right-then-down-from-cursor-over-full-screen 0 %eax %ecx 0 0xc)
+ 51       # loop update
+ 52       8b/-> *ebx 3/r32/ebx
+ 53       #
+ 54       e9/jump loop/disp32
+ 55     }
+ 56 $dump-call-stack:end:
+ 57     # . reclaim locals
+ 58     81 0/subop/add %esp 0x100c/imm32
+ 59     # . restore registers
+ 60     5b/pop-to-ebx
+ 61     5a/pop-to-edx
+ 62     59/pop-to-ecx
+ 63     58/pop-to-eax
+ 64     # . epilogue
+ 65     89/<- %esp 5/r32/ebp
+ 66     5d/pop-to-ebp
+ 67     c3/return
+ 68 
+ 69 load-debug-symbols:  # labels: (addr stream {start-address, label-slice})
+ 70     # . prologue
+ 71     55/push-ebp
+ 72     89/<- %ebp 4/r32/esp
+ 73     # . save registers
+ 74     50/push-eax
+ 75     51/push-ecx
+ 76     52/push-edx
+ 77     53/push-ebx
+ 78     # create space for a stream on the heap, clobbering any existing data
+ 79     # var s/ecx: (addr stream byte)
+ 80     b9/copy-to-ecx 0x03000000/imm32
+ 81     c7 0/subop/copy *ecx 0/imm32  # write index
+ 82     c7 0/subop/copy *(ecx+4) 0/imm32  # read index
+ 83     c7 0/subop/copy *(ecx+8) 0x01000000/imm32  # stream capacity = 16MB
+ 84     # load 0x400 sectors starting from sector 10080 = 0x2760
+ 85     (load-sectors Primary-bus-primary-drive 0x2760 0x100 %ecx)
+ 86     (load-sectors Primary-bus-primary-drive 0x2860 0x100 %ecx)
+ 87     (load-sectors Primary-bus-primary-drive 0x2960 0x100 %ecx)
+ 88     (load-sectors Primary-bus-primary-drive 0x2a60 0x100 %ecx)
+ 89     # - parse pointers to portions of this stream into labels
+ 90     # var curr/ecx: (addr byte) = s->data
+ 91     81 0/subop/add %ecx 0xc/imm32
+ 92     {
+ 93       # loop termination check
+ 94       b8/copy-to-eax 0/imm32
+ 95       8a/byte-> *ecx 0/r32/eax
+ 96       3d/compare-eax-and 0/imm32
+ 97       0f 84/jump-if-= break/disp32
+ 98       # loop body
+ 99       (skip-to-next-space %ecx)  # => edx
+100       42/increment-edx
+101       (skip-to-next-newline %edx)  # => ebx
+102       (parse-hex-int-helper %edx %ebx)  # => eax
+103       43/increment-ebx
+104       (label-append *(ebp+8) %eax %ecx %edx)
+105       # loop update
+106       89/<- %ecx 3/r32/ebx
+107       #
+108       e9/jump loop/disp32
+109     }
+110 $load-debug-symbols:end:
+111     # . restore registers
+112     5b/pop-to-ebx
+113     5a/pop-to-edx
+114     59/pop-to-ecx
+115     58/pop-to-eax
+116     # . epilogue
+117     89/<- %esp 5/r32/ebp
+118     5d/pop-to-ebp
+119     c3/return
+120 
+121 skip-to-next-space:  # curr: (addr byte) -> _/edx: (addr byte)
+122     # . prologue
+123     55/push-ebp
+124     89/<- %ebp 4/r32/esp
+125     # . save registers
+126     50/push-eax
+127     # eax = 0
+128     b8/copy-to-eax 0/imm32
+129     #
+130     8b/-> *(ebp+8) 2/r32/edx
+131     {
+132       8a/byte-> *edx 0/r32/eax
+133       3d/compare-eax-and 0x20/imm32/space
+134       0f 84/jump-if-= break/disp32
+135       3d/compare-eax-and 0/imm32
+136       {
+137         75/jump-if-!= break/disp8
+138         (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "done loading" 7 0)
+139         {
+140           eb/jump loop/disp8
+141         }
+142       }
+143       3d/compare-eax-and 0xa/imm32/newline
+144       {
+145         75/jump-if-!= break/disp8
+146         (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "unexpected newline" 7 0)
+147         {
+148           eb/jump loop/disp8
+149         }
+150       }
+151       42/increment-edx
+152       e9/jump loop/disp32
+153     }
+154 $skip-to-next-space:end:
+155     # . restore registers
+156     58/pop-to-eax
+157     # . epilogue
+158     89/<- %esp 5/r32/ebp
+159     5d/pop-to-ebp
+160     c3/return
+161 
+162 skip-to-next-newline:  # curr: (addr byte) -> _/ebx: (addr byte)
+163     # . prologue
+164     55/push-ebp
+165     89/<- %ebp 4/r32/esp
+166     # . save registers
+167     50/push-eax
+168     # eax = 0
+169     b8/copy-to-eax 0/imm32
+170     #
+171     8b/-> *(ebp+8) 3/r32/ebx
+172     {
+173       8a/byte-> *ebx 0/r32/eax
+174       3d/compare-eax-and 0xa/imm32/newline
+175       0f 84/jump-if-= break/disp32
+176       3d/compare-eax-and 0/imm32
+177       {
+178         75/jump-if-!= break/disp8
+179         (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "done loading" 7 0)
+180         {
+181           eb/jump loop/disp8
+182         }
+183       }
+184       3d/compare-eax-and 0x20/imm32/space
+185       {
+186         75/jump-if-!= break/disp8
+187         (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "unexpected space" 7 0)
+188         {
+189           eb/jump loop/disp8
+190         }
+191       }
+192       43/increment-ebx
+193       e9/jump loop/disp32
+194     }
+195 $skip-to-next-newline:end:
+196     # . restore registers
+197     58/pop-to-eax
+198     # . epilogue
+199     89/<- %esp 5/r32/ebp
+200     5d/pop-to-ebp
+201     c3/return
+202 
+203 label-append:  # labels: (addr stream {start-address, label-slice}), address: int, start: int, end: int
+204     # . prologue
+205     55/push-ebp
+206     89/<- %ebp 4/r32/esp
+207     # . save registers
+208     50/push-eax
+209     51/push-ecx
+210     56/push-esi
+211     # esi = labels
+212     8b/-> *(ebp+8) 6/r32/esi
+213     # ecx = labels->write
+214     8b/-> *esi 1/r32/ecx
+215     # labels->data[labels->write] = address
+216     8b/-> *(ebp+0xc) 0/r32/eax
+217     89/<- *(esi+ecx+0xc) 0/r32/eax
+218     # labels->data[labels->write+4] = start
+219     8b/-> *(ebp+0x10) 0/r32/eax
+220     89/<- *(esi+ecx+0x10) 0/r32/eax
+221     # labels->data[labels->write+8] = end
+222     8b/-> *(ebp+0x14) 0/r32/eax
+223     89/<- *(esi+ecx+0x14) 0/r32/eax
+224     # labels->write += 12
+225     81 0/subop/add *esi 0xc/imm32
+226 $label-append:end:
+227     # . restore registers
+228     5e/pop-to-esi
+229     59/pop-to-ecx
+230     58/pop-to-eax
+231     # . epilogue
+232     89/<- %esp 5/r32/ebp
+233     5d/pop-to-ebp
+234     c3/return
+235 
+236 containing-function:  # labels: (addr stream {start-address, label-slice}), address: int -> start/eax: (addr byte), end/ecx: (addr byte)
+237     # . prologue
+238     55/push-ebp
+239     89/<- %ebp 4/r32/esp
+240     # . save registers
+241     52/push-edx
+242     53/push-ebx
+243     56/push-esi
+244     # esi = labels
+245     8b/-> *(ebp+8) 6/r32/esi
+246     # var curr/ecx: (addr byte) = labels->data
+247     8d/copy-address *(esi+0xc) 1/r32/ecx
+248     # var max/edx: (addr byte) = labels->data + labels->write
+249     8b/-> *esi 2/r32/edx
+250     01/add-to %edx 1/r32/ecx
+251     # var previous-function-name/ebx: (addr slice) = 0
+252     bb/copy-to-ebx 0/imm32
+253     {
+254       # abort if not found
+255       39/compare %ecx 2/r32/edx
+256       {
+257         0f 82/jump-if-addr< break/disp32
+258         (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "failed to find function for address " 7 0)
+259         (draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0xc) 7 0)
+260         {
+261           eb/jump loop/disp8
+262         }
+263       }
+264       # if *curr > address, break
+265       8b/-> *ecx 0/r32/eax
+266       3b/compare 0/r32/eax *(ebp+0xc)
+267       0f 87/jump-if-addr> break/disp32
+268       # if **(curr+4) not '$' or '@', save curr to previous-function-name
+269       {
+270         8b/-> *(ecx+4) 0/r32/eax
+271         8a/byte-> *eax 0/r32/eax
+272         25/and-with-eax 0xff/imm32
+273         3d/compare-eax-and 0x24/imm32/$
+274         74/jump-if-= break/disp8
+275         3d/compare-eax-and 0x40/imm32/@
+276         74/jump-if-= break/disp8
+277         8d/copy-address *(ecx+4) 3/r32/ebx
+278       }
+279       # loop update
+280       81 0/subop/add %ecx 0xc/imm32
+281       #
+282       e9/jump loop/disp32
+283     }
+284     8b/-> *ebx 0/r32/eax
+285     8b/-> *(ebx+4) 1/r32/ecx
+286 $containing-function:end:
+287     # . restore registers
+288     5e/pop-to-esi
+289     5b/pop-to-ebx
+290     5a/pop-to-edx
+291     # . epilogue
+292     89/<- %esp 5/r32/ebp
+293     5d/pop-to-ebp
+294     c3/return
+295 
+296 # unlike variants in .mu files, this only supports ASCII
+297 draw-slice-wrapping-right-then-down-from-cursor-over-full-screen:  # screen: (addr screen), start: (addr byte), end: (addr byte), color: int, background-color: int
+298     # . prologue
+299     55/push-ebp
+300     89/<- %ebp 4/r32/esp
+301     # . save registers
+302     50/push-eax
+303     51/push-ecx
+304     52/push-edx
+305     # var curr/ecx: (addr byte) = start
+306     8b/-> *(ebp+0xc) 1/r32/ecx
+307     # edx = end
+308     8b/-> *(ebp+0x10) 2/r32/edx
+309     # eax = 0
+310     b8/copy-to-eax 0/imm32
+311     {
+312       # if (curr >= end) break
+313       39/compare %ecx 2/r32/edx
+314       73/jump-if-addr>= break/disp8
+315       # print *curr
+316       8a/byte-> *ecx 0/r32/eax
+317       (draw-grapheme-at-cursor *(ebp+8) %eax *(ebp+0x14) *(ebp+0x18))
+318       (move-cursor-rightward-and-downward *(ebp+8))
+319       #
+320       41/increment-ecx
+321       #
+322       eb/jump loop/disp8
+323     }
+324 $draw-slice-wrapping-right-then-down-from-cursor-over-full-screen:end:
+325     # . restore registers
+326     5a/pop-to-edx
+327     59/pop-to-ecx
+328     58/pop-to-eax
+329     # . epilogue
+330     89/<- %esp 5/r32/ebp
+331     5d/pop-to-ebp
+332     c3/return
+
+ + + diff --git a/html/400.mu.html b/html/400.mu.html index 4f4888fa..e7a56322 100644 --- a/html/400.mu.html +++ b/html/400.mu.html @@ -53,105 +53,107 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/400.mu
- 1 # screen
- 2 sig pixel-on-real-screen x: int, y: int, color: int
- 3 sig draw-grapheme-on-real-screen g: grapheme, x: int, y: int, color: int, background-color: int
- 4 sig cursor-position-on-real-screen -> _/eax: int, _/ecx: int
- 5 sig set-cursor-position-on-real-screen x: int, y: int
- 6 sig draw-cursor-on-real-screen g: grapheme
- 7 sig color-rgb color: int -> _/ecx: int, _/edx: int, _/ebx: int
- 8 
- 9 # keyboard
-10 sig read-key kbd: (addr keyboard) -> _/eax: byte
-11 
-12 # disk
-13 sig load-sectors disk: (addr disk), lba: int, n: int, out: (addr stream byte)
-14 sig store-sectors disk: (addr disk), lba: int, n: int, out: (addr stream byte)
-15 
-16 # mouse
-17 sig read-mouse-event -> _/eax: int, _/ecx: int
-18 
-19 # tests
-20 sig count-test-failure
-21 sig num-test-failures -> _/eax: int
-22 
-23 sig string-equal? s: (addr array byte), benchmark: (addr array byte) -> _/eax: boolean
-24 sig string-starts-with? s: (addr array byte), benchmark: (addr array byte) -> _/eax: boolean
-25 sig check-strings-equal s: (addr array byte), expected: (addr array byte), msg: (addr array byte)
-26 
-27 # debugging
-28 sig check-stack
-29 sig show-stack-state
-30 sig debug-print x: (addr array byte), fg: int, bg: int
-31 sig debug-print? -> _/eax: boolean
-32 sig turn-on-debug-print
-33 sig turn-off-debug-print
-34 
-35 # streams
-36 sig clear-stream f: (addr stream _)
-37 sig rewind-stream f: (addr stream _)
-38 sig stream-data-equal? f: (addr stream byte), s: (addr array byte) -> _/eax: boolean
-39 sig streams-data-equal? f: (addr stream byte), s: (addr stream byte) -> _/eax: boolean
-40 sig check-stream-equal f: (addr stream byte), s: (addr array byte), msg: (addr array byte)
-41 sig next-stream-line-equal? f: (addr stream byte), s: (addr array byte) -> _/eax: boolean
-42 sig check-next-stream-line-equal f: (addr stream byte), s: (addr array byte), msg: (addr array byte)
-43 sig write f: (addr stream byte), s: (addr array byte)
-44 sig write-stream f: (addr stream byte), s: (addr stream byte)
-45 sig read-byte s: (addr stream byte) -> _/eax: byte
-46 sig append-byte f: (addr stream byte), n: int  # really just a byte, but I want to pass in literal numbers
-47 #sig to-hex-char in/eax: int -> out/eax: int
-48 sig append-byte-hex f: (addr stream byte), n: int  # really just a byte, but I want to pass in literal numbers
-49 sig write-int32-hex f: (addr stream byte), n: int
-50 sig write-int32-hex-bits f: (addr stream byte), n: int, bits: int
-51 sig hex-int? in: (addr slice) -> _/eax: boolean
-52 sig parse-hex-int in: (addr array byte) -> _/eax: int
-53 sig parse-hex-int-from-slice in: (addr slice) -> _/eax: int
-54 #sig parse-hex-int-helper start: (addr byte), end: (addr byte) -> _/eax: int
-55 sig hex-digit? c: byte -> _/eax: boolean
-56 #sig from-hex-char in/eax: byte -> out/eax: nibble
-57 sig parse-decimal-int in: (addr array byte) -> _/eax: int
-58 sig parse-decimal-int-from-slice in: (addr slice) -> _/eax: int
-59 sig parse-decimal-int-from-stream in: (addr stream byte) -> _/eax: int
-60 #sig parse-decimal-int-helper start: (addr byte), end: (addr byte) -> _/eax: int
-61 sig decimal-size n: int -> _/eax: int
-62 #sig allocate ad: (addr allocation-descriptor), n: int, out: (addr handle _)
-63 #sig allocate-raw ad: (addr allocation-descriptor), n: int, out: (addr handle _)
-64 sig lookup h: (handle _T) -> _/eax: (addr _T)
-65 sig handle-equal? a: (handle _T), b: (handle _T) -> _/eax: boolean
-66 sig copy-handle src: (handle _T), dest: (addr handle _T)
-67 #sig allocate-region ad: (addr allocation-descriptor), n: int, out: (addr handle allocation-descriptor)
-68 #sig allocate-array ad: (addr allocation-descriptor), n: int, out: (addr handle _)
-69 sig copy-array ad: (addr allocation-descriptor), src: (addr array _T), out: (addr handle array _T)
-70 #sig zero-out start: (addr byte), size: int
-71 sig slice-empty? s: (addr slice) -> _/eax: boolean
-72 sig slice-equal? s: (addr slice), p: (addr array byte) -> _/eax: boolean
-73 sig slice-starts-with? s: (addr slice), head: (addr array byte) -> _/eax: boolean
-74 sig write-slice out: (addr stream byte), s: (addr slice)
-75 # bad name alert
-76 sig slice-to-string ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte)
-77 sig write-int32-decimal out: (addr stream byte), n: int
-78 sig decimal-digit? c: grapheme -> _/eax: boolean
-79 sig to-decimal-digit in: grapheme -> _/eax: int
-80 # bad name alert
-81 # next-word really tokenizes
-82 # next-raw-word really reads whitespace-separated words
-83 sig next-word line: (addr stream byte), out: (addr slice)  # skips '#' comments
-84 sig next-raw-word line: (addr stream byte), out: (addr slice)  # does not skip '#' comments
-85 sig stream-empty? s: (addr stream _) -> _/eax: boolean
-86 sig stream-full? s: (addr stream _) -> _/eax: boolean
-87 sig stream-to-array in: (addr stream _), out: (addr handle array _)
-88 sig unquote-stream-to-array in: (addr stream _), out: (addr handle array _)
-89 sig stream-first s: (addr stream byte) -> _/eax: byte
-90 sig stream-final s: (addr stream byte) -> _/eax: byte
-91 
-92 #sig copy-bytes src: (addr byte), dest: (addr byte), n: int
-93 sig copy-array-object src: (addr array _), dest-ah: (addr handle array _)
-94 sig array-equal? a: (addr array int), b: (addr array int) -> _/eax: boolean
-95 sig parse-array-of-ints s: (addr array byte), out: (addr handle array int)
-96 sig parse-array-of-decimal-ints s: (addr array byte), out: (addr handle array int)
-97 sig check-array-equal a: (addr array int), expected: (addr string), msg: (addr string)
-98 
-99 sig integer-divide a: int, b: int -> _/eax: int, _/edx: int
+  1 # screen
+  2 sig pixel-on-real-screen x: int, y: int, color: int
+  3 sig draw-grapheme-on-real-screen g: grapheme, x: int, y: int, color: int, background-color: int
+  4 sig cursor-position-on-real-screen -> _/eax: int, _/ecx: int
+  5 sig set-cursor-position-on-real-screen x: int, y: int
+  6 sig draw-cursor-on-real-screen g: grapheme
+  7 sig color-rgb color: int -> _/ecx: int, _/edx: int, _/ebx: int
+  8 
+  9 # keyboard
+ 10 sig read-key kbd: (addr keyboard) -> _/eax: byte
+ 11 
+ 12 # disk
+ 13 sig load-sectors disk: (addr disk), lba: int, n: int, out: (addr stream byte)
+ 14 sig store-sectors disk: (addr disk), lba: int, n: int, out: (addr stream byte)
+ 15 
+ 16 # mouse
+ 17 sig read-mouse-event -> _/eax: int, _/ecx: int
+ 18 
+ 19 # tests
+ 20 sig count-test-failure
+ 21 sig num-test-failures -> _/eax: int
+ 22 
+ 23 sig string-equal? s: (addr array byte), benchmark: (addr array byte) -> _/eax: boolean
+ 24 sig string-starts-with? s: (addr array byte), benchmark: (addr array byte) -> _/eax: boolean
+ 25 sig check-strings-equal s: (addr array byte), expected: (addr array byte), msg: (addr array byte)
+ 26 
+ 27 # debugging
+ 28 sig check-stack
+ 29 sig show-stack-state
+ 30 sig debug-print x: (addr array byte), fg: int, bg: int
+ 31 sig debug-print? -> _/eax: boolean
+ 32 sig turn-on-debug-print
+ 33 sig turn-off-debug-print
+ 34 sig abort e: (addr array byte)
+ 35 sig dump-call-stack
+ 36 
+ 37 # streams
+ 38 sig clear-stream f: (addr stream _)
+ 39 sig rewind-stream f: (addr stream _)
+ 40 sig stream-data-equal? f: (addr stream byte), s: (addr array byte) -> _/eax: boolean
+ 41 sig streams-data-equal? f: (addr stream byte), s: (addr stream byte) -> _/eax: boolean
+ 42 sig check-stream-equal f: (addr stream byte), s: (addr array byte), msg: (addr array byte)
+ 43 sig next-stream-line-equal? f: (addr stream byte), s: (addr array byte) -> _/eax: boolean
+ 44 sig check-next-stream-line-equal f: (addr stream byte), s: (addr array byte), msg: (addr array byte)
+ 45 sig write f: (addr stream byte), s: (addr array byte)
+ 46 sig write-stream f: (addr stream byte), s: (addr stream byte)
+ 47 sig read-byte s: (addr stream byte) -> _/eax: byte
+ 48 sig append-byte f: (addr stream byte), n: int  # really just a byte, but I want to pass in literal numbers
+ 49 #sig to-hex-char in/eax: int -> out/eax: int
+ 50 sig append-byte-hex f: (addr stream byte), n: int  # really just a byte, but I want to pass in literal numbers
+ 51 sig write-int32-hex f: (addr stream byte), n: int
+ 52 sig write-int32-hex-bits f: (addr stream byte), n: int, bits: int
+ 53 sig hex-int? in: (addr slice) -> _/eax: boolean
+ 54 sig parse-hex-int in: (addr array byte) -> _/eax: int
+ 55 sig parse-hex-int-from-slice in: (addr slice) -> _/eax: int
+ 56 #sig parse-hex-int-helper start: (addr byte), end: (addr byte) -> _/eax: int
+ 57 sig hex-digit? c: byte -> _/eax: boolean
+ 58 #sig from-hex-char in/eax: byte -> out/eax: nibble
+ 59 sig parse-decimal-int in: (addr array byte) -> _/eax: int
+ 60 sig parse-decimal-int-from-slice in: (addr slice) -> _/eax: int
+ 61 sig parse-decimal-int-from-stream in: (addr stream byte) -> _/eax: int
+ 62 #sig parse-decimal-int-helper start: (addr byte), end: (addr byte) -> _/eax: int
+ 63 sig decimal-size n: int -> _/eax: int
+ 64 #sig allocate ad: (addr allocation-descriptor), n: int, out: (addr handle _)
+ 65 #sig allocate-raw ad: (addr allocation-descriptor), n: int, out: (addr handle _)
+ 66 sig lookup h: (handle _T) -> _/eax: (addr _T)
+ 67 sig handle-equal? a: (handle _T), b: (handle _T) -> _/eax: boolean
+ 68 sig copy-handle src: (handle _T), dest: (addr handle _T)
+ 69 #sig allocate-region ad: (addr allocation-descriptor), n: int, out: (addr handle allocation-descriptor)
+ 70 #sig allocate-array ad: (addr allocation-descriptor), n: int, out: (addr handle _)
+ 71 sig copy-array ad: (addr allocation-descriptor), src: (addr array _T), out: (addr handle array _T)
+ 72 #sig zero-out start: (addr byte), size: int
+ 73 sig slice-empty? s: (addr slice) -> _/eax: boolean
+ 74 sig slice-equal? s: (addr slice), p: (addr array byte) -> _/eax: boolean
+ 75 sig slice-starts-with? s: (addr slice), head: (addr array byte) -> _/eax: boolean
+ 76 sig write-slice out: (addr stream byte), s: (addr slice)
+ 77 # bad name alert
+ 78 sig slice-to-string ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte)
+ 79 sig write-int32-decimal out: (addr stream byte), n: int
+ 80 sig decimal-digit? c: grapheme -> _/eax: boolean
+ 81 sig to-decimal-digit in: grapheme -> _/eax: int
+ 82 # bad name alert
+ 83 # next-word really tokenizes
+ 84 # next-raw-word really reads whitespace-separated words
+ 85 sig next-word line: (addr stream byte), out: (addr slice)  # skips '#' comments
+ 86 sig next-raw-word line: (addr stream byte), out: (addr slice)  # does not skip '#' comments
+ 87 sig stream-empty? s: (addr stream _) -> _/eax: boolean
+ 88 sig stream-full? s: (addr stream _) -> _/eax: boolean
+ 89 sig stream-to-array in: (addr stream _), out: (addr handle array _)
+ 90 sig unquote-stream-to-array in: (addr stream _), out: (addr handle array _)
+ 91 sig stream-first s: (addr stream byte) -> _/eax: byte
+ 92 sig stream-final s: (addr stream byte) -> _/eax: byte
+ 93 
+ 94 #sig copy-bytes src: (addr byte), dest: (addr byte), n: int
+ 95 sig copy-array-object src: (addr array _), dest-ah: (addr handle array _)
+ 96 sig array-equal? a: (addr array int), b: (addr array int) -> _/eax: boolean
+ 97 sig parse-array-of-ints s: (addr array byte), out: (addr handle array int)
+ 98 sig parse-array-of-decimal-ints s: (addr array byte), out: (addr handle array int)
+ 99 sig check-array-equal a: (addr array int), expected: (addr string), msg: (addr string)
+100 
+101 sig integer-divide a: int, b: int -> _/eax: int, _/edx: int
 
diff --git a/html/411string.mu.html b/html/411string.mu.html index 70cb7b88..34405d4c 100644 --- a/html/411string.mu.html +++ b/html/411string.mu.html @@ -102,46 +102,46 @@ if ('onhashchange' in window) { 42 var out-ah/edi: (addr handle array byte) <- address out-h 43 # prefix substrings 44 substring 0, 0, 3, out-ah - 45 var out/eax: (addr array byte) <- lookup *out-ah + 45 var out/eax: (addr array byte) <- lookup *out-ah 46 check-strings-equal out, "", "F - test-substring/null" 47 substring "", 0, 3, out-ah - 48 var out/eax: (addr array byte) <- lookup *out-ah + 48 var out/eax: (addr array byte) <- lookup *out-ah 49 #? print-string-to-real-screen out 50 #? print-string-to-real-screen "\n" 51 check-strings-equal out, "", "F - test-substring/empty" 52 # 53 substring "abcde", 0, 3, out-ah - 54 var out/eax: (addr array byte) <- lookup *out-ah + 54 var out/eax: (addr array byte) <- lookup *out-ah 55 #? print-string-to-real-screen out 56 #? print-string-to-real-screen "\n" 57 check-strings-equal out, "abc", "F - test-substring/truncate" 58 # 59 substring "abcde", 0, 5, out-ah - 60 var out/eax: (addr array byte) <- lookup *out-ah + 60 var out/eax: (addr array byte) <- lookup *out-ah 61 check-strings-equal out, "abcde", "F - test-substring/all" 62 # 63 substring "abcde", 0, 7, out-ah - 64 var out/eax: (addr array byte) <- lookup *out-ah + 64 var out/eax: (addr array byte) <- lookup *out-ah 65 check-strings-equal out, "abcde", "F - test-substring/too-small" 66 # substrings outside string 67 substring "abcde", 6, 1, out-ah - 68 var out/eax: (addr array byte) <- lookup *out-ah + 68 var out/eax: (addr array byte) <- lookup *out-ah 69 check-strings-equal out, "", "F - test-substring/start-too-large" 70 # trim prefix 71 substring "", 2, 3, out-ah - 72 var out/eax: (addr array byte) <- lookup *out-ah + 72 var out/eax: (addr array byte) <- lookup *out-ah 73 check-strings-equal out, "", "F - test-substring/middle-empty" 74 # 75 substring "abcde", 1, 2, out-ah - 76 var out/eax: (addr array byte) <- lookup *out-ah + 76 var out/eax: (addr array byte) <- lookup *out-ah 77 check-strings-equal out, "bc", "F - test-substring/middle-truncate" 78 # 79 substring "abcde", 1, 4, out-ah - 80 var out/eax: (addr array byte) <- lookup *out-ah + 80 var out/eax: (addr array byte) <- lookup *out-ah 81 check-strings-equal out, "bcde", "F - test-substring/middle-all" 82 # 83 substring "abcde", 1, 5, out-ah - 84 var out/eax: (addr array byte) <- lookup *out-ah + 84 var out/eax: (addr array byte) <- lookup *out-ah 85 check-strings-equal out, "bcde", "F - test-substring/middle-too-small" 86 } 87 diff --git a/html/500fake-screen.mu.html b/html/500fake-screen.mu.html index 81f96915..edf7b8f5 100644 --- a/html/500fake-screen.mu.html +++ b/html/500fake-screen.mu.html @@ -154,7 +154,7 @@ if ('onhashchange' in window) { 96 # fake screen 97 var idx/ecx: int <- screen-cell-index screen, x, y 98 var data-ah/eax: (addr handle array screen-cell) <- get screen, data - 99 var data/eax: (addr array screen-cell) <- lookup *data-ah + 99 var data/eax: (addr array screen-cell) <- lookup *data-ah 100 var offset/ecx: (offset screen-cell) <- compute-offset data, idx 101 var dest-cell/ecx: (addr screen-cell) <- index data, offset 102 var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data @@ -180,26 +180,26 @@ if ('onhashchange' in window) { 122 { 123 compare x, 0 124 break-if->= -125 abort "screen-cell-index: negative x" +125 abort "screen-cell-index: negative x" 126 } 127 { 128 var xmax/eax: (addr int) <- get screen, width 129 var xcurr/ecx: int <- copy x 130 compare xcurr, *xmax 131 break-if-< -132 abort "screen-cell-index: x too high" +132 abort "screen-cell-index: x too high" 133 } 134 { 135 compare y, 0 136 break-if->= -137 abort "screen-cell-index: negative y" +137 abort "screen-cell-index: negative y" 138 } 139 { 140 var ymax/eax: (addr int) <- get screen, height 141 var ycurr/ecx: int <- copy y 142 compare ycurr, *ymax 143 break-if-< -144 abort "screen-cell-index: y too high" +144 abort "screen-cell-index: y too high" 145 } 146 var width-addr/eax: (addr int) <- get screen, width 147 var result/ecx: int <- copy y @@ -314,7 +314,7 @@ if ('onhashchange' in window) { 256 } 257 set-cursor-position screen, 0, 0 258 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels -259 var pixels/eax: (addr array byte) <- lookup *pixels-ah +259 var pixels/eax: (addr array byte) <- lookup *pixels-ah 260 var i/ecx: int <- copy 0 261 var max/edx: int <- length pixels 262 { @@ -355,7 +355,7 @@ if ('onhashchange' in window) { 297 loop 298 } 299 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels -300 var pixels/eax: (addr array byte) <- lookup *pixels-ah +300 var pixels/eax: (addr array byte) <- lookup *pixels-ah 301 var y/ebx: int <- copy 0 302 var height-addr/edx: (addr int) <- get screen, height 303 var height/edx: int <- copy *height-addr @@ -471,7 +471,7 @@ if ('onhashchange' in window) { 413 fn screen-grapheme-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: grapheme { 414 var screen/esi: (addr screen) <- copy _screen 415 var data-ah/eax: (addr handle array screen-cell) <- get screen, data -416 var data/eax: (addr array screen-cell) <- lookup *data-ah +416 var data/eax: (addr array screen-cell) <- lookup *data-ah 417 var idx/ecx: int <- copy idx-on-stack 418 var offset/ecx: (offset screen-cell) <- compute-offset data, idx 419 var cell/eax: (addr screen-cell) <- index data, offset @@ -489,7 +489,7 @@ if ('onhashchange' in window) { 431 fn screen-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int { 432 var screen/esi: (addr screen) <- copy _screen 433 var data-ah/eax: (addr handle array screen-cell) <- get screen, data -434 var data/eax: (addr array screen-cell) <- lookup *data-ah +434 var data/eax: (addr array screen-cell) <- lookup *data-ah 435 var idx/ecx: int <- copy idx-on-stack 436 var offset/ecx: (offset screen-cell) <- compute-offset data, idx 437 var cell/eax: (addr screen-cell) <- index data, offset @@ -508,7 +508,7 @@ if ('onhashchange' in window) { 450 fn screen-background-color-at-idx _screen: (addr screen), idx-on-stack: int -> _/eax: int { 451 var screen/esi: (addr screen) <- copy _screen 452 var data-ah/eax: (addr handle array screen-cell) <- get screen, data -453 var data/eax: (addr array screen-cell) <- lookup *data-ah +453 var data/eax: (addr array screen-cell) <- lookup *data-ah 454 var idx/ecx: int <- copy idx-on-stack 455 var offset/ecx: (offset screen-cell) <- compute-offset data, idx 456 var cell/eax: (addr screen-cell) <- index data, offset @@ -527,11 +527,11 @@ if ('onhashchange' in window) { 469 # fake screen 470 var screen/esi: (addr screen) <- copy screen 471 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels -472 var pixels/eax: (addr array byte) <- lookup *pixels-ah +472 var pixels/eax: (addr array byte) <- lookup *pixels-ah 473 { 474 compare pixels, 0 475 break-if-!= -476 abort "pixel graphics not enabled for this screen" +476 abort "pixel graphics not enabled for this screen" 477 } 478 var idx/ecx: int <- pixel-index screen, x, y 479 var dest/ecx: (addr byte) <- index pixels, idx @@ -544,7 +544,7 @@ if ('onhashchange' in window) { 486 { 487 compare x, 0 488 break-if->= -489 abort "screen-cell-index: negative x" +489 abort "screen-cell-index: negative x" 490 } 491 { 492 var xmax-a/eax: (addr int) <- get screen, width @@ -552,12 +552,12 @@ if ('onhashchange' in window) { 494 xmax <- shift-left 3/log2-font-width 495 compare x, xmax 496 break-if-< -497 abort "screen-cell-index: x too high" +497 abort "screen-cell-index: x too high" 498 } 499 { 500 compare y, 0 501 break-if->= -502 abort "screen-cell-index: negative y" +502 abort "screen-cell-index: negative y" 503 } 504 { 505 var ymax-a/eax: (addr int) <- get screen, height @@ -565,7 +565,7 @@ if ('onhashchange' in window) { 507 ymax <- shift-left 4/log2-font-height 508 compare y, ymax 509 break-if-< -510 abort "screen-cell-index: y too high" +510 abort "screen-cell-index: y too high" 511 } 512 var width-addr/eax: (addr int) <- get screen, width 513 var result/ecx: int <- copy y @@ -574,6 +574,45 @@ if ('onhashchange' in window) { 516 result <- add x 517 return result 518 } +519 +520 # double-buffering primitive +521 # 'screen' must be a fake screen. 'target-screen' is usually real. +522 # Both screens must have the same size. +523 fn copy-pixels _screen: (addr screen), target-screen: (addr screen) { +524 var screen/esi: (addr screen) <- copy _screen +525 var pixels-ah/eax: (addr handle array byte) <- get screen, pixels +526 var _pixels/eax: (addr array byte) <- lookup *pixels-ah +527 var pixels/edi: (addr array byte) <- copy _pixels +528 var width-a/edx: (addr int) <- get screen, width +529 var width/edx: int <- copy *width-a +530 width <- shift-left 3/log2-font-width +531 var height-a/ebx: (addr int) <- get screen, height +532 var height/ebx: int <- copy *height-a +533 height <- shift-left 4/log2-font-height +534 var i/esi: int <- copy 0 +535 var y/ecx: int <- copy 0 +536 { +537 # screen top left pixels x y width height +538 compare y, height +539 break-if->= +540 var x/eax: int <- copy 0 +541 { +542 compare x, width +543 break-if->= +544 { +545 var color-addr/ebx: (addr byte) <- index pixels, i +546 var color/ebx: byte <- copy-byte *color-addr +547 var color2/ebx: int <- copy color +548 pixel target-screen, x, y, color2 +549 } +550 x <- increment +551 i <- increment +552 loop +553 } +554 y <- increment +555 loop +556 } +557 } diff --git a/html/501draw-text.mu.html b/html/501draw-text.mu.html index bc18cb25..0e951a27 100644 --- a/html/501draw-text.mu.html +++ b/html/501draw-text.mu.html @@ -533,17 +533,6 @@ if ('onhashchange' in window) { 475 width, height <- screen-size screen 476 draw-text-wrapping-down-then-right-from-cursor screen, text, 0/xmin, 0/ymin, width, height, color, background-color 477 } -478 -479 # hacky error-handling -480 # just go into an infinite loop -481 fn abort e: (addr array byte) { -482 var dummy1/eax: int <- copy 0 -483 var dummy2/ecx: int <- copy 0 -484 dummy1, dummy2 <- draw-text-wrapping-right-then-down-over-full-screen 0/screen, e, 0/x, 0x2f/y, 0xf/fg=white, 0xc/bg=red -485 { -486 loop -487 } -488 } diff --git a/html/506math.mu.html b/html/506math.mu.html new file mode 100644 index 00000000..9309b20c --- /dev/null +++ b/html/506math.mu.html @@ -0,0 +1,114 @@ + + + + +Mu - 506math.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/506math.mu +
+ 1 fn abs n: int -> _/eax: int {
+ 2   compare n, 0
+ 3   {
+ 4     break-if->=
+ 5     negate n
+ 6   }
+ 7   return n
+ 8 }
+ 9 
+10 fn sgn n: int -> _/eax: int {
+11   compare n, 0
+12   {
+13     break-if-<=
+14     return 1
+15   }
+16   {
+17     break-if->=
+18     return -1
+19   }
+20   return 0
+21 }
+22 
+23 fn shift-left-by n: int, bits: int -> _/eax: int {
+24   var i/eax: int <- copy bits
+25   {
+26     compare i, 0
+27     break-if-<=
+28     shift-left n, 1
+29     i <- decrement
+30     loop
+31   }
+32   return n
+33 }
+34 
+35 fn shift-right-by n: int, bits: int -> _/eax: int {
+36   var i/eax: int <- copy bits
+37   {
+38     compare i, 0
+39     break-if-<=
+40     shift-right n, 1
+41     i <- decrement
+42     loop
+43   }
+44   return n
+45 }
+46 
+47 fn clear-lowest-bits _n: (addr int), bits: int {
+48   var dest/edi: (addr int) <- copy _n
+49   var n/eax: int <- copy *dest
+50   n <- shift-right-by n, bits
+51   n <- shift-left-by n, bits
+52   copy-to *dest, n
+53 }
+
+ + + diff --git a/html/507line.mu.html b/html/507line.mu.html new file mode 100644 index 00000000..df492c93 --- /dev/null +++ b/html/507line.mu.html @@ -0,0 +1,171 @@ + + + + +Mu - 507line.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/507line.mu +
+  1 fn draw-line screen: (addr screen), x0: int, y0: int, x1: int, y1: int, color: int {
+  2   var dx: int
+  3   var dy: int
+  4   var sx: int
+  5   var sy: int
+  6   var err: int
+  7   # dx = abs(x1-x0)
+  8   var tmp2/ecx: int <- copy x1
+  9   tmp2 <- subtract x0
+ 10   var tmp/eax: int <- abs tmp2
+ 11   copy-to dx, tmp
+ 12   # sx = sgn(x1-x0)
+ 13   tmp <- sgn tmp2
+ 14   copy-to sx, tmp
+ 15   # dy = -abs(y1-y0)
+ 16   tmp2 <- copy y1
+ 17   tmp2 <- subtract y0
+ 18   tmp <- abs tmp2
+ 19   tmp <- negate
+ 20   copy-to dy, tmp
+ 21   # sy = sgn(y1-y0)
+ 22   tmp <- sgn tmp2
+ 23   copy-to sy, tmp
+ 24   # err = dx + dy
+ 25   tmp <- copy dy
+ 26   tmp <- add dx
+ 27   copy-to err, tmp
+ 28   #
+ 29   var x/ecx: int <- copy x0
+ 30   var y/edx: int <- copy y0
+ 31   $draw-line:loop: {
+ 32     pixel screen, x, y, color
+ 33     # if (x == x1 && y == y1) break
+ 34     {
+ 35       compare x, x1
+ 36       break-if-!=
+ 37       compare y, y1
+ 38       break-if-!=
+ 39       break $draw-line:loop
+ 40     }
+ 41     # e2 = err*2
+ 42     var e2/ebx: int <- copy err
+ 43     e2 <- shift-left 1
+ 44     # if (e2 >= dy) { err += dy; x += sx; }
+ 45     {
+ 46       compare e2, dy
+ 47       break-if-<
+ 48       tmp <- copy dy
+ 49       add-to err, tmp
+ 50       x <- add sx
+ 51     }
+ 52     # if (e2 <= dx) { err += dx; y += sy; }
+ 53     {
+ 54       compare e2, dx
+ 55       break-if->
+ 56       tmp <- copy dx
+ 57       add-to err, tmp
+ 58       y <- add sy
+ 59     }
+ 60     loop
+ 61   }
+ 62 }
+ 63 
+ 64 fn draw-horizontal-line screen: (addr screen), y: int, x0: int, x1: int, color: int {
+ 65   var x/eax: int <- copy x0
+ 66   {
+ 67     compare x, x1
+ 68     break-if->=
+ 69     pixel screen, x, y, color
+ 70     x <- increment
+ 71     loop
+ 72   }
+ 73 }
+ 74 
+ 75 fn draw-vertical-line screen: (addr screen), x: int, y0: int, y1: int, color: int {
+ 76   var y/eax: int <- copy y0
+ 77   {
+ 78     compare y, y1
+ 79     break-if->=
+ 80     pixel screen, x, y, color
+ 81     y <- increment
+ 82     loop
+ 83   }
+ 84 }
+ 85 
+ 86 fn draw-rect screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int, color: int {
+ 87   var y/eax: int <- copy ymin
+ 88   {
+ 89     compare y, ymax
+ 90     break-if->=
+ 91     draw-horizontal-line screen, y, xmin, xmax, color
+ 92     y <- increment
+ 93     loop
+ 94   }
+ 95 }
+ 96 
+ 97 # 0 <= u <= 1
+ 98 fn line-point u: float, x0: int, x1: int -> _/eax: int {
+ 99   var one/eax: int <- copy 1
+100   var u-prime/xmm0: float <- convert one
+101   u-prime <- subtract u
+102   var result/xmm1: float <- convert x0
+103   result <- multiply u-prime
+104   var term2/xmm2: float <- convert x1
+105   term2 <- multiply u
+106   result <- add term2
+107   var result/eax: int <- convert result
+108   return result
+109 }
+
+ + + diff --git a/html/508circle.mu.html b/html/508circle.mu.html new file mode 100644 index 00000000..c33aca77 --- /dev/null +++ b/html/508circle.mu.html @@ -0,0 +1,152 @@ + + + + +Mu - 508circle.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/508circle.mu +
+ 1 fn draw-circle screen: (addr screen), cx: int, cy: int, radius: int, color: int {
+ 2   var x: int
+ 3   var y: int
+ 4   var err: int
+ 5   # x = -r
+ 6   var tmp/eax: int <- copy radius
+ 7   tmp <- negate
+ 8   copy-to x, tmp
+ 9   # err = 2 - 2*r
+10   tmp <- copy radius
+11   tmp <- shift-left 1
+12   tmp <- negate
+13   tmp <- add 2
+14   copy-to err, tmp
+15   #
+16   var tmpx/ecx: int <- copy 0
+17   var tmpy/edx: int <- copy 0
+18   {
+19     # pixel(cx-x, cy+y)
+20     tmpx <- copy cx
+21     tmpx <- subtract x
+22     tmpy <- copy cy
+23     tmpy <- add y
+24     pixel screen, tmpx, tmpy, color
+25     # pixel(cx-y, cy-x)
+26     tmpx <- copy cx
+27     tmpx <- subtract y
+28     tmpy <- copy cy
+29     tmpy <- subtract x
+30     pixel screen, tmpx, tmpy, color
+31     # pixel(cx+x, cy-y)
+32     tmpx <- copy cx
+33     tmpx <- add x
+34     tmpy <- copy cy
+35     tmpy <- subtract y
+36     pixel screen, tmpx, tmpy, color
+37     # pixel(cx+y, cy+x)
+38     tmpx <- copy cx
+39     tmpx <- add y
+40     tmpy <- copy cy
+41     tmpy <- add x
+42     pixel screen, tmpx, tmpy, color
+43     # r = err
+44     tmp <- copy err
+45     copy-to radius, tmp
+46     # if (r <= y) { ++y; err += (y*2 + 1); }
+47     {
+48       tmpy <- copy y
+49       compare radius, tmpy
+50       break-if->
+51       increment y
+52       tmpy <- copy y
+53       tmpy <- shift-left 1
+54       tmpy <- increment
+55       add-to err, tmpy
+56     }
+57     # if (r > x || err > y) { ++x; err += (x*2 + 1); }
+58     $draw-circle:second-check: {
+59       {
+60         tmpx <- copy x
+61         compare radius, tmpx
+62         break-if->
+63         tmpy <- copy y
+64         compare err, tmpy
+65         break-if->
+66         break $draw-circle:second-check
+67       }
+68       increment x
+69       tmpx <- copy x
+70       tmpx <- shift-left 1
+71       tmpx <- increment
+72       add-to err, tmpx
+73     }
+74     # loop termination condition
+75     compare x, 0
+76     loop-if-<
+77   }
+78 }
+79 
+80 fn draw-disc screen: (addr screen), cx: int, cy: int, radius: int, color: int, border-color: int {
+81   var r/eax: int <- copy 0
+82   {
+83     compare r, radius
+84     break-if->=
+85     draw-circle screen, cx cy, r, color
+86     r <- increment
+87     loop
+88   }
+89   draw-circle screen, cx cy, r, border-color
+90 }
+
+ + + diff --git a/html/509bezier.mu.html b/html/509bezier.mu.html new file mode 100644 index 00000000..c7e376eb --- /dev/null +++ b/html/509bezier.mu.html @@ -0,0 +1,378 @@ + + + + +Mu - 509bezier.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/509bezier.mu +
+  1 # Draw a second-degree bezier curve using 3 control points.
+  2 #
+  3 # http://members.chello.at/easyfilter/bresenham.html says that this algorithm
+  4 # works only if "the gradient does not change sign". Either:
+  5 #   x0 >= x1 >= x2
+  6 # or:
+  7 #   x0 <= x1 <= x2
+  8 # Similarly for y0, y1 and y2.
+  9 #
+ 10 # This seems superficially similar to the notions of convex and concave, but I
+ 11 # think it isn't. I think it's purely a property of the frame of reference.
+ 12 # Rotating the axes can make the gradient change sign or stop changing sign
+ 13 # even as 3 points preserve fixed relative bearings to each other.
+ 14 fn draw-monotonic-bezier screen: (addr screen), x0: int, y0: int, x1: int, y1: int, x2: int, y2: int, color: int {
+ 15   var xx: int
+ 16   var yy: int
+ 17   var xy: int
+ 18   var sx: int
+ 19   var sy: int
+ 20   # sx = x2-x1
+ 21   var tmp/eax: int <- copy x2
+ 22   tmp <- subtract x1
+ 23   copy-to sx, tmp
+ 24   # sy = y2-y1
+ 25   tmp <- copy y2
+ 26   tmp <- subtract y1
+ 27   copy-to sy, tmp
+ 28   # xx = x0-x1
+ 29   tmp <- copy x0
+ 30   tmp <- subtract x1
+ 31   copy-to xx, tmp
+ 32   # yy = y0-y1
+ 33   tmp <- copy y0
+ 34   tmp <- subtract y1
+ 35   copy-to yy, tmp
+ 36   # cur = xx*sy - yy*sx
+ 37   var cur-f/xmm4: float <- convert xx
+ 38   {
+ 39     var sy-f/xmm1: float <- convert sy
+ 40     cur-f <- multiply sy-f
+ 41     var tmp2-f/xmm1: float <- convert yy
+ 42     var sx-f/xmm2: float <- convert sx
+ 43     tmp2-f <- multiply sx-f
+ 44     cur-f <- subtract tmp2-f
+ 45   }
+ 46   # if (xx*sx > 0) abort
+ 47   {
+ 48     tmp <- copy xx
+ 49     tmp <- multiply sx
+ 50     compare tmp, 0
+ 51     break-if-<=
+ 52     abort "bezier: gradient of x changes sign"
+ 53   }
+ 54   # if (yy*sy > 0) abort
+ 55   {
+ 56     tmp <- copy yy
+ 57     tmp <- multiply sy
+ 58     compare tmp, 0
+ 59     break-if-<=
+ 60     abort "bezier: gradient of y changes sign"
+ 61   }
+ 62   # swap P0 and P2 if necessary
+ 63   {
+ 64     # dist1 = sx*sx + sy*sy
+ 65     var dist1/ecx: int <- copy sx
+ 66     {
+ 67       dist1 <- multiply sx
+ 68       {
+ 69         break-if-not-overflow
+ 70         abort "bezier: overflow 1"
+ 71       }
+ 72       tmp <- copy sy
+ 73       tmp <- multiply sy
+ 74       {
+ 75         break-if-not-overflow
+ 76         abort "bezier: overflow 2"
+ 77       }
+ 78       dist1 <- add tmp
+ 79     }
+ 80     # dist2 = xx*xx + yy*yy
+ 81     var dist2/edx: int <- copy xx
+ 82     {
+ 83       dist2 <- multiply xx
+ 84       {
+ 85         break-if-not-overflow
+ 86         abort "bezier: overflow 3"
+ 87       }
+ 88       tmp <- copy yy
+ 89       tmp <- multiply yy
+ 90       {
+ 91         break-if-not-overflow
+ 92         abort "bezier: overflow 4"
+ 93       }
+ 94       dist2 <- add tmp
+ 95     }
+ 96     # if (dist1 <= dist2) break
+ 97     compare dist1, dist2
+ 98     break-if-<=
+ 99     # swap x0 and x2
+100     tmp <- copy x0
+101     copy-to x2, tmp
+102     tmp <- copy sx
+103     tmp <- add x1
+104     copy-to x0, tmp
+105     # swap y0 and y2
+106     tmp <- copy y0
+107     copy-to y2, tmp
+108     tmp <- copy sy
+109     tmp <- add y1
+110     copy-to y0, tmp
+111     # cur = -cur
+112     var negative-1/eax: int <- copy -1
+113     var negative-1-f/xmm1: float <- convert negative-1
+114     cur-f <- multiply negative-1-f
+115   }
+116   var x/ecx: int <- copy x0
+117   var y/edx: int <- copy y0
+118   var zero-f: float
+119   # plot a curved part if necessary
+120   $draw-monotonic-bezier:curve: {
+121     compare cur-f, zero-f
+122     break-if-=
+123     # xx += sx
+124     tmp <- copy sx
+125     add-to xx, tmp
+126     # sx = sgn(x2-x)
+127     tmp <- copy x2
+128     tmp <- subtract x
+129     tmp <- sgn tmp
+130     copy-to sx, tmp
+131     # xx *= sx
+132     tmp <- copy sx
+133     tmp <- multiply xx
+134     copy-to xx, tmp
+135     # yy += sy
+136     tmp <- copy sy
+137     add-to yy, tmp
+138     # sy = sgn(y2-y)
+139     tmp <- copy y2
+140     tmp <- subtract y
+141     tmp <- sgn tmp
+142     copy-to sy, tmp
+143     # yy *= sy
+144     tmp <- copy sy
+145     tmp <- multiply yy
+146     copy-to yy, tmp
+147     # xy = 2*xx*xy
+148     tmp <- copy xx
+149     tmp <- multiply yy
+150     {
+151       break-if-not-overflow
+152       abort "bezier: overflow 5"
+153     }
+154     tmp <- shift-left 1
+155     {
+156       break-if-not-overflow
+157       abort "bezier: overflow 6"
+158     }
+159     copy-to xy, tmp
+160     # xx *= xx
+161     tmp <- copy xx
+162     tmp <- multiply tmp
+163     {
+164       break-if-not-overflow
+165       abort "bezier: overflow 7"
+166     }
+167     copy-to xx, tmp
+168     # yy *= yy
+169     tmp <- copy yy
+170     tmp <- multiply tmp
+171     {
+172       break-if-not-overflow
+173       abort "bezier: overflow 7"
+174     }
+175     copy-to yy, tmp
+176     # if (cur*sx*sy < 0) negative curvature
+177     {
+178       var tmp-f/xmm0: float <- copy cur-f
+179       var sx-f/xmm1: float <- convert sx
+180       tmp-f <- multiply sx-f
+181       var sy-f/xmm1: float <- convert sy
+182       tmp-f <- multiply sy-f
+183       compare tmp-f, zero-f
+184       break-if-float>=
+185       #
+186       negate xx
+187       negate yy
+188       negate xy
+189       # cur = -cur
+190       var negative-1/eax: int <- copy -1
+191       var negative-1-f/xmm1: float <- convert negative-1
+192       cur-f <- multiply negative-1-f
+193     }
+194     var four/ebx: int <- copy 4
+195     var dx-f/xmm5: float <- convert four
+196     var dy-f/xmm6: float <- convert four
+197     # dx = 4*sy*cur*(x1-x0) + xx - xy
+198     {
+199       var tmp/xmm0: float <- convert sy
+200       dx-f <- multiply tmp
+201       dx-f <- multiply cur-f
+202       tmp <- convert x1
+203       var tmp2/xmm3: float <- convert x
+204       tmp <- subtract tmp2
+205       dx-f <- multiply tmp
+206       tmp <- convert xx
+207       dx-f <- add tmp
+208       tmp <- convert xy
+209       dx-f <- subtract tmp
+210     }
+211     # dy-f = 4*sx*cur*(y0-y1) + yy - xy
+212     {
+213       var tmp/xmm0: float <- convert sx
+214       dy-f <- multiply tmp
+215       dy-f <- multiply cur-f
+216       tmp <- convert y
+217       var tmp2/xmm3: float <- convert y1
+218       tmp <- subtract tmp2
+219       dy-f <- multiply tmp
+220       tmp <- convert yy
+221       dy-f <- add tmp
+222       tmp <- convert xy
+223       dy-f <- subtract tmp
+224     }
+225     # xx += xx
+226     tmp <- copy xx
+227     add-to xx, tmp
+228     # yy += yy
+229     tmp <- copy yy
+230     add-to yy, tmp
+231     # err = dx+dy+xy
+232     var err-f/xmm7: float <- copy dx-f
+233     err-f <- add dy-f
+234     var xy-f/xmm0: float <- convert xy
+235     err-f <- add xy-f
+236     #
+237     $draw-monotonic-bezier:loop: {
+238       pixel screen, x, y, color
+239       # if (x == x2 && y == y2) return
+240       {
+241         compare x, x2
+242         break-if-!=
+243         compare y, y2
+244         break-if-!=
+245         return
+246       }
+247       # perform-y-step? = (2*err < dx)
+248       var perform-y-step?/eax: boolean <- copy 0/false
+249       var two-err-f/xmm0: float <- copy err-f
+250       {
+251         var two/ebx: int <- copy 2
+252         var two-f/xmm1: float <- convert two
+253         two-err-f <- multiply two-f
+254         compare two-err-f, dx-f
+255         break-if-float>=
+256         perform-y-step? <- copy 1/true
+257       }
+258       # if (2*err > dy)
+259       {
+260         compare two-err-f, dy-f
+261         break-if-float<=
+262         # x += sx
+263         x <- add sx
+264         # dx -= xy
+265         var xy-f/xmm0: float <- convert xy
+266         dx-f <- subtract xy-f
+267         # dy += yy
+268         var yy-f/xmm0: float <- convert yy
+269         dy-f <- add yy-f
+270         # err += dy
+271         err-f <- add dy-f
+272       }
+273       # if perform-y-step?
+274       {
+275         compare perform-y-step?, 0/false
+276         break-if-=
+277         # y += sy
+278         y <- add sy
+279         # dy -= xy
+280         var xy-f/xmm0: float <- convert xy
+281         dy-f <- subtract xy-f
+282         # dx += xx
+283         var xx-f/xmm0: float <- convert xx
+284         dx-f <- add xx-f
+285         # err += dx
+286         err-f <- add dx-f
+287       }
+288       # if (dy < dx) loop
+289       compare dy-f, dx-f
+290       loop-if-float<
+291     }
+292   }
+293   # plot the remaining straight line
+294   draw-line screen, x y, x2 y2, color
+295 }
+296 
+297 # 0 <= u <= 1
+298 fn bezier-point u: float, x0: int, x1: int, x2: int -> _/eax: int {
+299   var one/eax: int <- copy 1
+300   var u-prime/xmm0: float <- convert one
+301   u-prime <- subtract u
+302   var result/xmm1: float <- convert x0
+303   result <- multiply u-prime
+304   result <- multiply u-prime
+305   var term2/xmm2: float <- convert x1
+306   term2 <- multiply u
+307   term2 <- multiply u-prime
+308   result <- add term2
+309   result <- add term2
+310   var term3/xmm2: float <- convert x2
+311   term3 <- multiply u
+312   term3 <- multiply u
+313   result <- add term3
+314   var result/eax: int <- convert result
+315   return result
+316 }
+
+ + + diff --git a/html/boot.subx.html b/html/boot.subx.html index ed9ad698..221fe044 100644 --- a/html/boot.subx.html +++ b/html/boot.subx.html @@ -292,7 +292,7 @@ if ('onhashchange' in window) { 232 233 fb/enable-interrupts 234 - 235 (initialize-mouse) + 235 (initialize-mouse) 236 237 ## enable floating point 238 db/floating-point-coprocessor e3/initialize @@ -514,272 +514,294 @@ if ('onhashchange' in window) { 889 890 == data 891 - 892 # We'll be gaining access just to the secondary drive on the primary bus for - 893 # now. It will have the designated 'data' disk so we don't mess with the code - 894 # disk. - 895 # - 896 # The type definition for this variable is in safe Mu (rather than unsafe - 897 # SubX) code. - 898 # All ports are 8-bit except data-port, which is 16-bit. - 899 Primary-bus-secondary-drive: - 900 # command-port: int (write) - 901 0x1f7/imm32 - 902 # status-port: int (read) - 903 0x1f7/imm32 - 904 # alternative-status-port: int (read) - 905 0x3f6/imm32 - 906 # error-port: int (read) - 907 0x1f1/imm32 - 908 # drive-and-head-port: int - 909 0x1f6/imm32 - 910 # sector-count-port: int - 911 0x1f2/imm32 - 912 # lba-low-port: int - 913 0x1f3/imm32 - 914 # lba-mid-port: int - 915 0x1f4/imm32 - 916 # lba-high-port: int - 917 0x1f5/imm32 - 918 # data-port: int - 919 0x1f0/imm32 - 920 # drive-code: byte # only drive-specific field - 921 0xf0/imm32 # LBA mode also enabled - 922 - 923 == code - 924 - 925 load-sectors: # disk: (addr disk), lba: int, n: int, out: (addr stream byte) - 926 # . prologue - 927 55/push-ebp - 928 89/<- %ebp 4/r32/esp - 929 # . save registers - 930 50/push-eax - 931 51/push-ecx - 932 52/push-edx - 933 # check for drive - 934 (drive-exists? *(ebp+8)) # => eax - 935 3d/compare-eax-and 0/imm32/false - 936 0f 84/jump-if-= $load-sectors:end/disp32 - 937 # kick off read - 938 (ata-drive-select *(ebp+8) *(ebp+0xc)) - 939 (clear-ata-error *(ebp+8)) - 940 (ata-sector-count *(ebp+8) *(ebp+0x10)) - 941 (ata-lba *(ebp+8) *(ebp+0xc)) - 942 (ata-command *(ebp+8) 0x20) # read sectors with retries - 943 # for each sector - 944 { - 945 # poll for results - 946 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "waiting for sector.." 7 0) - 947 (while-ata-busy *(ebp+8)) - 948 (until-ata-data-available *(ebp+8)) - 949 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "reading\n" 7 0) - 950 # var data-port/edx = disk->data-port - 951 8b/-> *(ebp+8) 0/r32/eax - 952 8b/-> *(eax+0x24) 2/r32/edx - 953 # emit results - 954 31/xor %eax 0/r32/eax - 955 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector - 956 { - 957 81 7/subop/compare %ecx 0/imm32 - 958 74/jump-if-= break/disp8 - 959 66 ed/read-port-dx-into-ax - 960 # write 2 bytes to stream one at a time - 961 (append-byte *(ebp+0x14) %eax) - 962 49/decrement-ecx - 963 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 - 964 (append-byte *(ebp+0x14) %eax) - 965 49/decrement-ecx - 966 eb/jump loop/disp8 - 967 } - 968 # next sector - 969 ff 1/subop/decrement *(ebp+0x10) - 970 #? (draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x10) 0xc 0) - 971 81 7/subop/compare *(ebp+0x10) 0/imm32 - 972 7e/jump-if-<= break/disp8 - 973 (wait-400ns *(ebp+8)) - 974 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "next sector\n" 7 0) - 975 e9/jump loop/disp32 - 976 } - 977 $load-sectors:end: - 978 # . restore registers - 979 5a/pop-to-edx - 980 59/pop-to-ecx - 981 58/pop-to-eax - 982 # . epilogue - 983 89/<- %esp 5/r32/ebp - 984 5d/pop-to-ebp - 985 c3/return - 986 - 987 store-sectors: # disk: (addr disk), lba: int, n: int, in: (addr stream byte) - 988 # . prologue - 989 55/push-ebp - 990 89/<- %ebp 4/r32/esp - 991 # . save registers - 992 50/push-eax - 993 51/push-ecx - 994 52/push-edx - 995 53/push-ebx - 996 # check for drive - 997 (drive-exists? *(ebp+8)) # => eax - 998 3d/compare-eax-and 0/imm32/false - 999 0f 84/jump-if-= $store-sectors:end/disp32 -1000 # kick off write -1001 (ata-drive-select *(ebp+8) *(ebp+0xc)) -1002 (clear-ata-error *(ebp+8)) -1003 (ata-sector-count *(ebp+8) *(ebp+0x10)) -1004 (ata-lba *(ebp+8) *(ebp+0xc)) -1005 (ata-command *(ebp+8) 0x30) # write sectors with retries -1006 # for each sector -1007 #? (set-cursor-position 0 0 0) -1008 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "0" 7 0) -1009 { -1010 # wait -1011 (while-ata-busy *(ebp+8)) -1012 (until-ata-ready-for-data *(ebp+8)) -1013 # var data-port/edx = disk->data-port -1014 8b/-> *(ebp+8) 0/r32/eax -1015 8b/-> *(eax+0x24) 2/r32/edx -1016 # send data -1017 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector -1018 # . var first-byte/ebx: byte -1019 # . when it's more than 0xff, we're at an even-numbered byte -1020 bb/copy-to-ebx 0xffff/imm32 -1021 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "D" 7 0) -1022 $store-sectors:store-sector: -1023 { -1024 81 7/subop/compare %ecx 0/imm32 -1025 74/jump-if-= break/disp8 -1026 # this loop is slow, but the ATA spec also requires a small delay -1027 (stream-empty? *(ebp+0x14)) # => eax -1028 3d/compare-eax-and 0/imm32/false -1029 75/jump-if-!= break/disp8 -1030 # read byte from stream -1031 (read-byte *(ebp+0x14)) # => eax -1032 # if we're at an odd-numbered byte, save it to first-byte -1033 81 7/subop/compare %ebx 0xff/imm32 -1034 { -1035 7e/jump-if-<= break/disp8 -1036 89/<- %ebx 0/r32/eax -1037 eb/jump $store-sectors:store-sector/disp8 -1038 } -1039 # otherwise OR it with first-byte and write it out -1040 c1/shift 4/subop/left %eax 8/imm8 -1041 09/or %eax 3/r32/ebx -1042 66 ef/write-ax-into-port-dx -1043 49/decrement-ecx -1044 49/decrement-ecx -1045 # reset first-byte -1046 bb/copy-to-ebx 0xffff/imm32 -1047 eb/jump loop/disp8 -1048 } -1049 # write out final first-byte if necessary -1050 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "I" 7 0) -1051 81 7/subop/compare %ebx 0xff/imm32 -1052 { -1053 7f/jump-if-> break/disp8 -1054 89/<- %eax 3/r32/ebx -1055 66 ef/write-ax-into-port-dx -1056 49/decrement-ecx -1057 49/decrement-ecx -1058 } -1059 # pad zeroes -1060 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "P" 7 0) -1061 31/xor %eax 0/r32/eax -1062 { -1063 81 7/subop/compare %ecx 0/imm32 -1064 74/jump-if-= break/disp8 -1065 66 ef/write-ax-into-port-dx + 892 # code disk + 893 # All ports are 8-bit except data-port, which is 16-bit. + 894 Primary-bus-primary-drive: + 895 # command-port: int (write) + 896 0x1f7/imm32 + 897 # status-port: int (read) + 898 0x1f7/imm32 + 899 # alternative-status-port: int (read) + 900 0x3f6/imm32 + 901 # error-port: int (read) + 902 0x1f1/imm32 + 903 # drive-and-head-port: int + 904 0x1f6/imm32 + 905 # sector-count-port: int + 906 0x1f2/imm32 + 907 # lba-low-port: int + 908 0x1f3/imm32 + 909 # lba-mid-port: int + 910 0x1f4/imm32 + 911 # lba-high-port: int + 912 0x1f5/imm32 + 913 # data-port: int + 914 0x1f0/imm32 + 915 # drive-code: byte # only drive-specific field + 916 0xe0/imm32 # LBA mode also enabled + 917 + 918 # data disk + 919 # All ports are 8-bit except data-port, which is 16-bit. + 920 Primary-bus-secondary-drive: + 921 # command-port: int (write) + 922 0x1f7/imm32 + 923 # status-port: int (read) + 924 0x1f7/imm32 + 925 # alternative-status-port: int (read) + 926 0x3f6/imm32 + 927 # error-port: int (read) + 928 0x1f1/imm32 + 929 # drive-and-head-port: int + 930 0x1f6/imm32 + 931 # sector-count-port: int + 932 0x1f2/imm32 + 933 # lba-low-port: int + 934 0x1f3/imm32 + 935 # lba-mid-port: int + 936 0x1f4/imm32 + 937 # lba-high-port: int + 938 0x1f5/imm32 + 939 # data-port: int + 940 0x1f0/imm32 + 941 # drive-code: byte # only drive-specific field + 942 0xf0/imm32 # LBA mode also enabled + 943 + 944 == code + 945 + 946 load-sectors: # disk: (addr disk), lba: int, n: int, out: (addr stream byte) + 947 # . prologue + 948 55/push-ebp + 949 89/<- %ebp 4/r32/esp + 950 # . save registers + 951 50/push-eax + 952 51/push-ecx + 953 52/push-edx + 954 # check for drive + 955 (drive-exists? *(ebp+8)) # => eax + 956 3d/compare-eax-and 0/imm32/false + 957 0f 84/jump-if-= $load-sectors:end/disp32 + 958 # kick off read + 959 (ata-drive-select *(ebp+8) *(ebp+0xc)) + 960 (clear-ata-error *(ebp+8)) + 961 (ata-sector-count *(ebp+8) *(ebp+0x10)) + 962 (ata-lba *(ebp+8) *(ebp+0xc)) + 963 (ata-command *(ebp+8) 0x20) # read sectors with retries + 964 # for each sector + 965 { + 966 # poll for results + 967 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "waiting for sector.." 7 0) + 968 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "." 7 0) + 969 (while-ata-busy *(ebp+8)) + 970 (until-ata-data-available *(ebp+8)) + 971 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "reading\n" 7 0) + 972 # var data-port/edx = disk->data-port + 973 8b/-> *(ebp+8) 0/r32/eax + 974 8b/-> *(eax+0x24) 2/r32/edx + 975 # emit results + 976 31/xor %eax 0/r32/eax + 977 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector + 978 { + 979 81 7/subop/compare %ecx 0/imm32 + 980 74/jump-if-= break/disp8 + 981 66 ed/read-port-dx-into-ax + 982 # write 2 bytes to stream one at a time + 983 (append-byte *(ebp+0x14) %eax) + 984 49/decrement-ecx + 985 c1/shift 5/subop/right-padding-zeroes %eax 8/imm8 + 986 (append-byte *(ebp+0x14) %eax) + 987 49/decrement-ecx + 988 eb/jump loop/disp8 + 989 } + 990 # next sector + 991 ff 1/subop/decrement *(ebp+0x10) + 992 #? (draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen 0 *(ebp+0x10) 0xc 0) + 993 81 7/subop/compare *(ebp+0x10) 0/imm32 + 994 7e/jump-if-<= break/disp8 + 995 (wait-400ns *(ebp+8)) + 996 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "next sector\n" 7 0) + 997 e9/jump loop/disp32 + 998 } + 999 $load-sectors:end: +1000 # . restore registers +1001 5a/pop-to-edx +1002 59/pop-to-ecx +1003 58/pop-to-eax +1004 # . epilogue +1005 89/<- %esp 5/r32/ebp +1006 5d/pop-to-ebp +1007 c3/return +1008 +1009 store-sectors: # disk: (addr disk), lba: int, n: int, in: (addr stream byte) +1010 # . prologue +1011 55/push-ebp +1012 89/<- %ebp 4/r32/esp +1013 # . save registers +1014 50/push-eax +1015 51/push-ecx +1016 52/push-edx +1017 53/push-ebx +1018 # check for drive +1019 (drive-exists? *(ebp+8)) # => eax +1020 3d/compare-eax-and 0/imm32/false +1021 0f 84/jump-if-= $store-sectors:end/disp32 +1022 # kick off write +1023 (ata-drive-select *(ebp+8) *(ebp+0xc)) +1024 (clear-ata-error *(ebp+8)) +1025 (ata-sector-count *(ebp+8) *(ebp+0x10)) +1026 (ata-lba *(ebp+8) *(ebp+0xc)) +1027 (ata-command *(ebp+8) 0x30) # write sectors with retries +1028 # for each sector +1029 #? (set-cursor-position 0 0 0) +1030 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "0" 7 0) +1031 { +1032 # wait +1033 (while-ata-busy *(ebp+8)) +1034 (until-ata-ready-for-data *(ebp+8)) +1035 # var data-port/edx = disk->data-port +1036 8b/-> *(ebp+8) 0/r32/eax +1037 8b/-> *(eax+0x24) 2/r32/edx +1038 # send data +1039 b9/copy-to-ecx 0x200/imm32 # 512 bytes per sector +1040 # . var first-byte/ebx: byte +1041 # . when it's more than 0xff, we're at an even-numbered byte +1042 bb/copy-to-ebx 0xffff/imm32 +1043 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "D" 7 0) +1044 $store-sectors:store-sector: +1045 { +1046 81 7/subop/compare %ecx 0/imm32 +1047 74/jump-if-= break/disp8 +1048 # this loop is slow, but the ATA spec also requires a small delay +1049 (stream-empty? *(ebp+0x14)) # => eax +1050 3d/compare-eax-and 0/imm32/false +1051 75/jump-if-!= break/disp8 +1052 # read byte from stream +1053 (read-byte *(ebp+0x14)) # => eax +1054 # if we're at an odd-numbered byte, save it to first-byte +1055 81 7/subop/compare %ebx 0xff/imm32 +1056 { +1057 7e/jump-if-<= break/disp8 +1058 89/<- %ebx 0/r32/eax +1059 eb/jump $store-sectors:store-sector/disp8 +1060 } +1061 # otherwise OR it with first-byte and write it out +1062 c1/shift 4/subop/left %eax 8/imm8 +1063 09/or %eax 3/r32/ebx +1064 66 ef/write-ax-into-port-dx +1065 49/decrement-ecx 1066 49/decrement-ecx -1067 49/decrement-ecx -1068 eb/jump loop/disp8 -1069 } -1070 # next sector -1071 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "N" 7 0) -1072 ff 1/subop/decrement *(ebp+0x10) -1073 81 7/subop/compare *(ebp+0x10) 0/imm32 -1074 7e/jump-if-<= break/disp8 -1075 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "W" 7 0) -1076 (wait-400ns *(ebp+8)) -1077 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "L" 7 0) -1078 e9/jump loop/disp32 -1079 } -1080 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "F" 7 0) -1081 (flush-ata-cache *(ebp+8)) -1082 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "Y" 7 0) -1083 $store-sectors:end: -1084 # . restore registers -1085 5b/pop-to-ebx -1086 5a/pop-to-edx -1087 59/pop-to-ecx -1088 58/pop-to-eax -1089 # . epilogue -1090 89/<- %esp 5/r32/ebp -1091 5d/pop-to-ebp -1092 c3/return -1093 -1094 +--289 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------ -1383 -1384 ## Controlling a PS/2 mouse -1385 # Uses no IRQs, just polling. -1386 # Thanks Dave Long: https://github.com/jtauber/cleese/blob/master/necco/kernel/bochs/py8042.py -1387 # -1388 # Resources: -1389 # https://wiki.osdev.org/Mouse_Input -1390 -1391 # results x/eax, y/ecx range from -256 to +255 -1392 # See https://wiki.osdev.org/index.php?title=Mouse_Input&oldid=25663#Format_of_First_3_Packet_Bytes -1393 read-mouse-event: # -> _/eax: int, _/ecx: int -1394 # . prologue -1395 55/push-ebp -1396 89/<- %ebp 4/r32/esp -1397 # . save registers -1398 52/push-edx -1399 53/push-ebx -1400 # if no event, return 0, 0 -1401 b8/copy-to-eax 0/imm32 -1402 b9/copy-to-ecx 0/imm32 -1403 (any-mouse-event?) # => eax -1404 3d/compare-eax-and 0/imm32/false -1405 74/jump-if-= $read-mouse-event:end/disp8 -1406 # var f1/edx: byte = inb(0x60) -1407 31/xor %eax 0/r32/eax -1408 e4/read-port-into-al 0x60/imm8 -1409 89/<- %edx 0/r32/eax -1410 (wait-for-mouse-event) -1411 # var dx/ebx: byte = inb(0x60) -1412 31/xor %eax 0/r32/eax -1413 e4/read-port-into-al 0x60/imm8 -1414 89/<- %ebx 0/r32/eax -1415 (wait-for-mouse-event) -1416 # var dy/ecx: byte = inb(0x60) -1417 31/xor %eax 0/r32/eax -1418 e4/read-port-into-al 0x60/imm8 -1419 89/<- %ecx 0/r32/eax -1420 # eax = dx -1421 89/<- %eax 3/r32/ebx -1422 # if (f1 & 0x10) dx = -dx -1423 { -1424 f6 0/subop/test-bits %dl 0x10/imm8 -1425 74/jump-if-zero break/disp8 -1426 0d/or-eax-with 0xffffff00/imm32 -1427 } -1428 # if (f1 & 0x20) dy = -dy -1429 { -1430 f6 0/subop/test-bits %dl 0x20/imm8 -1431 74/jump-if-zero break/disp8 -1432 81 1/subop/or %ecx 0xffffff00/imm32 -1433 } -1434 $read-mouse-event:end: -1435 # . restore registers -1436 5b/pop-to-ebx -1437 5a/pop-to-edx -1438 # . epilogue -1439 89/<- %esp 5/r32/ebp -1440 5d/pop-to-ebp -1441 c3/return -1442 -1443 +--147 lines: # mouse helpers ----------------------------------------------------------------------------------------------------------------------------------------------------------- -1590 -1591 # vim:ft=subx +1067 # reset first-byte +1068 bb/copy-to-ebx 0xffff/imm32 +1069 eb/jump loop/disp8 +1070 } +1071 # write out final first-byte if necessary +1072 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "I" 7 0) +1073 81 7/subop/compare %ebx 0xff/imm32 +1074 { +1075 7f/jump-if-> break/disp8 +1076 89/<- %eax 3/r32/ebx +1077 66 ef/write-ax-into-port-dx +1078 49/decrement-ecx +1079 49/decrement-ecx +1080 } +1081 # pad zeroes +1082 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "P" 7 0) +1083 31/xor %eax 0/r32/eax +1084 { +1085 81 7/subop/compare %ecx 0/imm32 +1086 74/jump-if-= break/disp8 +1087 66 ef/write-ax-into-port-dx +1088 49/decrement-ecx +1089 49/decrement-ecx +1090 eb/jump loop/disp8 +1091 } +1092 # next sector +1093 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "N" 7 0) +1094 ff 1/subop/decrement *(ebp+0x10) +1095 81 7/subop/compare *(ebp+0x10) 0/imm32 +1096 7e/jump-if-<= break/disp8 +1097 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "W" 7 0) +1098 (wait-400ns *(ebp+8)) +1099 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "L" 7 0) +1100 e9/jump loop/disp32 +1101 } +1102 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "F" 7 0) +1103 (flush-ata-cache *(ebp+8)) +1104 #? (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "Y" 7 0) +1105 $store-sectors:end: +1106 # . restore registers +1107 5b/pop-to-ebx +1108 5a/pop-to-edx +1109 59/pop-to-ecx +1110 58/pop-to-eax +1111 # . epilogue +1112 89/<- %esp 5/r32/ebp +1113 5d/pop-to-ebp +1114 c3/return +1115 +1116 +--289 lines: # disk helpers ------------------------------------------------------------------------------------------------------------------------------------------------------------ +1405 +1406 ## Controlling a PS/2 mouse +1407 # Uses no IRQs, just polling. +1408 # Thanks Dave Long: https://github.com/jtauber/cleese/blob/master/necco/kernel/bochs/py8042.py +1409 # +1410 # Resources: +1411 # https://wiki.osdev.org/Mouse_Input +1412 +1413 # results x/eax, y/ecx range from -256 to +255 +1414 # See https://wiki.osdev.org/index.php?title=Mouse_Input&oldid=25663#Format_of_First_3_Packet_Bytes +1415 read-mouse-event: # -> _/eax: int, _/ecx: int +1416 # . prologue +1417 55/push-ebp +1418 89/<- %ebp 4/r32/esp +1419 # . save registers +1420 52/push-edx +1421 53/push-ebx +1422 # if no event, return 0, 0 +1423 b8/copy-to-eax 0/imm32 +1424 b9/copy-to-ecx 0/imm32 +1425 (any-mouse-event?) # => eax +1426 3d/compare-eax-and 0/imm32/false +1427 74/jump-if-= $read-mouse-event:end/disp8 +1428 # var f1/edx: byte = inb(0x60) +1429 31/xor %eax 0/r32/eax +1430 e4/read-port-into-al 0x60/imm8 +1431 89/<- %edx 0/r32/eax +1432 (wait-for-mouse-event) +1433 # var dx/ebx: byte = inb(0x60) +1434 31/xor %eax 0/r32/eax +1435 e4/read-port-into-al 0x60/imm8 +1436 89/<- %ebx 0/r32/eax +1437 (wait-for-mouse-event) +1438 # var dy/ecx: byte = inb(0x60) +1439 31/xor %eax 0/r32/eax +1440 e4/read-port-into-al 0x60/imm8 +1441 89/<- %ecx 0/r32/eax +1442 # eax = dx +1443 89/<- %eax 3/r32/ebx +1444 # if (f1 & 0x10) dx = -dx +1445 { +1446 f6 0/subop/test-bits %dl 0x10/imm8 +1447 74/jump-if-zero break/disp8 +1448 0d/or-eax-with 0xffffff00/imm32 +1449 } +1450 # if (f1 & 0x20) dy = -dy +1451 { +1452 f6 0/subop/test-bits %dl 0x20/imm8 +1453 74/jump-if-zero break/disp8 +1454 81 1/subop/or %ecx 0xffffff00/imm32 +1455 } +1456 $read-mouse-event:end: +1457 # . restore registers +1458 5b/pop-to-ebx +1459 5a/pop-to-edx +1460 # . epilogue +1461 89/<- %esp 5/r32/ebp +1462 5d/pop-to-ebp +1463 c3/return +1464 +1465 +--147 lines: # mouse helpers ----------------------------------------------------------------------------------------------------------------------------------------------------------- +1612 +1613 # vim:ft=subx diff --git a/html/colors.mu.html b/html/colors.mu.html index 25eb4b07..756f0f90 100644 --- a/html/colors.mu.html +++ b/html/colors.mu.html @@ -121,7 +121,7 @@ if ('onhashchange' in window) { 62 var valid?/eax: boolean <- hex-digit? tmp 63 compare valid?, 0/false 64 break-if-!= - 65 abort "invalid byte 0 of r" + 65 abort "invalid byte 0 of r" 66 } 67 tmp <- fast-hex-digit-value tmp 68 var r/ecx: int <- copy tmp @@ -155,7 +155,7 @@ if ('onhashchange' in window) { 96 var valid?/eax: boolean <- hex-digit? tmp 97 compare valid?, 0/false 98 break-if-!= - 99 abort "invalid byte 0 of g" + 99 abort "invalid byte 0 of g" 100 } 101 tmp <- fast-hex-digit-value tmp 102 var g/edx: int <- copy tmp @@ -189,7 +189,7 @@ if ('onhashchange' in window) { 130 var valid?/eax: boolean <- hex-digit? tmp 131 compare valid?, 0/false 132 break-if-!= -133 abort "invalid byte 0 of b" +133 abort "invalid byte 0 of b" 134 } 135 tmp <- fast-hex-digit-value tmp 136 var b/ebx: int <- copy tmp diff --git a/html/ex10.mu.html b/html/ex10.mu.html index ac6dd059..71ede3a0 100644 --- a/html/ex10.mu.html +++ b/html/ex10.mu.html @@ -74,7 +74,7 @@ if ('onhashchange' in window) { 16 $main:event-loop: { 17 var dx/eax: int <- copy 0 18 var dy/ecx: int <- copy 0 -19 dx, dy <- read-mouse-event +19 dx, dy <- read-mouse-event 20 { 21 compare dx, 0 22 break-if-!= diff --git a/html/ex11.mu.html b/html/ex11.mu.html new file mode 100644 index 00000000..853b68d0 --- /dev/null +++ b/html/ex11.mu.html @@ -0,0 +1,323 @@ + + + + +Mu - ex11.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/ex11.mu +
+  1 # Demo of an interactive app: controlling a Bezier curve on screen
+  2 #
+  3 # To build a disk image:
+  4 #   ./translate ex11.mu            # emits code.img
+  5 # To run:
+  6 #   qemu-system-i386 code.img
+  7 # Or:
+  8 #   bochs -f bochsrc               # bochsrc loads code.img
+  9 #
+ 10 # Expected output: a spline with 3 control points. Use `Tab` to switch cursor
+ 11 # between control points, and arrow keys to move the control point at the
+ 12 # cursor.
+ 13 
+ 14 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+ 15   var env-storage: environment
+ 16   var env/esi: (addr environment) <- address env-storage
+ 17   initialize-environment env, 0x200 0x20, 0x180 0x90, 0x180 0x160
+ 18   {
+ 19     render screen, env
+ 20     edit keyboard, env
+ 21     loop
+ 22   }
+ 23 }
+ 24 
+ 25 type environment {
+ 26   p0: (handle point)
+ 27   p1: (handle point)
+ 28   p2: (handle point)
+ 29   cursor: (handle point)  # one of p0, p1 or p2
+ 30 }
+ 31 
+ 32 type point {
+ 33   x: int
+ 34   y: int
+ 35 }
+ 36 
+ 37 fn render screen: (addr screen), _self: (addr environment) {
+ 38   clear-screen screen
+ 39   var self/esi: (addr environment) <- copy _self
+ 40   var tmp-ah/ecx: (addr handle point) <- get self, p0
+ 41   var tmp/eax: (addr point) <- lookup *tmp-ah
+ 42   var p0/ebx: (addr point) <- copy tmp
+ 43   tmp-ah <- get self, p1
+ 44   tmp <- lookup *tmp-ah
+ 45   var p1/edx: (addr point) <- copy tmp
+ 46   tmp-ah <- get self, p2
+ 47   tmp <- lookup *tmp-ah
+ 48   var p2/ecx: (addr point) <- copy tmp
+ 49   # control lines
+ 50   line    screen, p0, p1,                 7/color
+ 51   line    screen, p1, p2,                 7/color
+ 52   # curve above control lines
+ 53   bezier  screen, p0, p1, p2,             0xc/color
+ 54   # points above curve
+ 55   disc    screen, p0,           3/radius, 7/color   0xf/border
+ 56   disc    screen, p1,           3/radius, 7/color   0xf/border
+ 57   disc    screen, p2,           3/radius, 7/color   0xf/border
+ 58   # cursor last of all
+ 59   var cursor-ah/eax: (addr handle point) <- get self, cursor
+ 60   var cursor/eax: (addr point) <- lookup *cursor-ah
+ 61   cursor screen, cursor, 0xa/side, 3/color
+ 62 }
+ 63 
+ 64 fn bezier screen: (addr screen), _p0: (addr point), _p1: (addr point), _p2: (addr point), color: int {
+ 65   var p0/esi: (addr point) <- copy _p0
+ 66   var x0/ecx: (addr int) <- get p0, x
+ 67   var y0/edx: (addr int) <- get p0, y
+ 68   var p1/esi: (addr point) <- copy _p1
+ 69   var x1/ebx: (addr int) <- get p1, x
+ 70   var y1/eax: (addr int) <- get p1, y
+ 71   var p2/esi: (addr point) <- copy _p2
+ 72   var x2/edi: (addr int) <- get p2, x
+ 73   var y2/esi: (addr int) <- get p2, y
+ 74   draw-monotonic-bezier screen, *x0 *y0, *x1 *y1, *x2 *y2, color
+ 75 }
+ 76 
+ 77 fn cursor screen: (addr screen), _p: (addr point), side: int, color: int {
+ 78   var half-side/eax: int <- copy side
+ 79   half-side <- shift-right 1
+ 80   var p/esi: (addr point) <- copy _p
+ 81   var x-a/ecx: (addr int) <- get p, x
+ 82   var left-x/ecx: int <- copy *x-a
+ 83   left-x <- subtract half-side
+ 84   var y-a/edx: (addr int) <- get p, y
+ 85   var top-y/edx: int <- copy *y-a
+ 86   top-y <- subtract half-side
+ 87   var max/eax: int <- copy left-x
+ 88   max <- add side
+ 89   draw-horizontal-line screen, top-y, left-x, max, color
+ 90   max <- copy top-y
+ 91   max <- add side
+ 92   draw-vertical-line screen, left-x, top-y, max, color
+ 93   var right-x/ebx: int <- copy left-x
+ 94   right-x <- add side
+ 95   draw-vertical-line screen, right-x, top-y, max, color
+ 96   var bottom-y/edx: int <- copy top-y
+ 97   bottom-y <- add side
+ 98   draw-horizontal-line screen, bottom-y, left-x, right-x, color
+ 99 }
+100 
+101 fn edit keyboard: (addr keyboard), _self: (addr environment) {
+102   var self/esi: (addr environment) <- copy _self
+103   var key/eax: byte <- read-key keyboard
+104   compare key, 0
+105   loop-if-=
+106   {
+107     compare key, 9/tab
+108     break-if-!=
+109     toggle-cursor self
+110     return
+111   }
+112   {
+113     compare key, 0x80/left-arrow
+114     break-if-!=
+115     cursor-left self
+116     return
+117   }
+118   {
+119     compare key, 0x83/right-arrow
+120     break-if-!=
+121     cursor-right self
+122     return
+123   }
+124   {
+125     compare key, 0x81/down-arrow
+126     break-if-!=
+127     cursor-down self
+128     return
+129   }
+130   {
+131     compare key, 0x82/up-arrow
+132     break-if-!=
+133     cursor-up self
+134     return
+135   }
+136 }
+137 
+138 fn toggle-cursor _self: (addr environment) {
+139   var self/esi: (addr environment) <- copy _self
+140   var cursor-ah/edi: (addr handle point) <- get self, cursor
+141   var p0-ah/ecx: (addr handle point) <- get self, p0
+142   var p1-ah/edx: (addr handle point) <- get self, p1
+143   var p2-ah/ebx: (addr handle point) <- get self, p2
+144   {
+145     var p0?/eax: boolean <- handle-equal? *p0-ah, *cursor-ah
+146     compare p0?, 0/false
+147     break-if-=
+148     copy-object p1-ah, cursor-ah
+149     return
+150   }
+151   {
+152     var p1?/eax: boolean <- handle-equal? *p1-ah, *cursor-ah
+153     compare p1?, 0/false
+154     break-if-=
+155     copy-object p2-ah, cursor-ah
+156     return
+157   }
+158   {
+159     var p2?/eax: boolean <- handle-equal? *p2-ah, *cursor-ah
+160     compare p2?, 0/false
+161     break-if-=
+162     copy-object p0-ah, cursor-ah
+163     return
+164   }
+165   abort "lost cursor"
+166 }
+167 
+168 fn cursor-left _self: (addr environment) {
+169   var self/esi: (addr environment) <- copy _self
+170   var cursor-ah/esi: (addr handle point) <- get self, cursor
+171   var cursor/eax: (addr point) <- lookup *cursor-ah
+172   var cursor-x/eax: (addr int) <- get cursor, x
+173   compare *cursor-x, 0x20
+174   {
+175     break-if-<
+176     subtract-from *cursor-x, 0x20
+177   }
+178 }
+179 
+180 fn cursor-right _self: (addr environment) {
+181   var self/esi: (addr environment) <- copy _self
+182   var cursor-ah/esi: (addr handle point) <- get self, cursor
+183   var cursor/eax: (addr point) <- lookup *cursor-ah
+184   var cursor-x/eax: (addr int) <- get cursor, x
+185   compare *cursor-x, 0x3f0
+186   {
+187     break-if->
+188     add-to *cursor-x, 0x20
+189   }
+190 }
+191 
+192 fn cursor-up _self: (addr environment) {
+193   var self/esi: (addr environment) <- copy _self
+194   var cursor-ah/esi: (addr handle point) <- get self, cursor
+195   var cursor/eax: (addr point) <- lookup *cursor-ah
+196   var cursor-y/eax: (addr int) <- get cursor, y
+197   compare *cursor-y, 0x20
+198   {
+199     break-if-<
+200     subtract-from *cursor-y, 0x20
+201   }
+202 }
+203 
+204 fn cursor-down _self: (addr environment) {
+205   var self/esi: (addr environment) <- copy _self
+206   var cursor-ah/esi: (addr handle point) <- get self, cursor
+207   var cursor/eax: (addr point) <- lookup *cursor-ah
+208   var cursor-y/eax: (addr int) <- get cursor, y
+209   compare *cursor-y, 0x2f0
+210   {
+211     break-if->
+212     add-to *cursor-y, 0x20
+213   }
+214 }
+215 
+216 fn line screen: (addr screen), _p0: (addr point), _p1: (addr point), color: int {
+217   var p0/esi: (addr point) <- copy _p0
+218   var x0/ecx: (addr int) <- get p0, x
+219   var y0/edx: (addr int) <- get p0, y
+220   var p1/esi: (addr point) <- copy _p1
+221   var x1/ebx: (addr int) <- get p1, x
+222   var y1/eax: (addr int) <- get p1, y
+223   draw-line screen, *x0 *y0, *x1 *y1, color
+224 }
+225 
+226 fn disc screen: (addr screen), _p: (addr point), radius: int, color: int, border-color: int {
+227   var p/esi: (addr point) <- copy _p
+228   var x/ecx: (addr int) <- get p, x
+229   var y/edx: (addr int) <- get p, y
+230   draw-disc screen, *x *y, radius, color, border-color
+231 }
+232 
+233 fn initialize-environment _self: (addr environment), x0: int, y0: int, x1: int, y1: int, x2: int, y2: int {
+234   var self/esi: (addr environment) <- copy _self
+235   var p0-ah/eax: (addr handle point) <- get self, p0
+236   allocate p0-ah
+237   var p0/eax: (addr point) <- lookup *p0-ah
+238   initialize-point p0, x0 y0
+239   var p1-ah/eax: (addr handle point) <- get self, p1
+240   allocate p1-ah
+241   var p1/eax: (addr point) <- lookup *p1-ah
+242   initialize-point p1, x1 y1
+243   var p2-ah/eax: (addr handle point) <- get self, p2
+244   allocate p2-ah
+245   var p2/eax: (addr point) <- lookup *p2-ah
+246   initialize-point p2, x2 y2
+247   # cursor initially at p0
+248   var cursor-ah/edi: (addr handle point) <- get self, cursor
+249   var src-ah/esi: (addr handle point) <- get self, p0
+250   copy-object src-ah, cursor-ah
+251 }
+252 
+253 fn initialize-point _p: (addr point), x: int, y: int {
+254   var p/esi: (addr point) <- copy _p
+255   var dest/eax: (addr int) <- get p, x
+256   var src/ecx: int <- copy x
+257   copy-to *dest, src
+258   dest <- get p, y
+259   src <- copy y
+260   copy-to *dest, src
+261 }
+
+ + + diff --git a/html/ex2.mu.html b/html/ex2.mu.html index 66ee63b6..7f3b1d87 100644 --- a/html/ex2.mu.html +++ b/html/ex2.mu.html @@ -83,7 +83,16 @@ if ('onhashchange' in window) { 25 y <- increment 26 loop 27 } -28 } +28 foo +29 } +30 +31 fn foo { +32 bar +33 } +34 +35 fn bar { +36 abort "aaa" +37 } diff --git a/html/ex9.mu.html b/html/ex9.mu.html index 429d788d..c14e8878 100644 --- a/html/ex9.mu.html +++ b/html/ex9.mu.html @@ -76,14 +76,14 @@ if ('onhashchange' in window) { 18 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { 19 var text-storage: (stream byte 0x200) 20 var text/esi: (addr stream byte) <- address text-storage -21 load-sectors data-disk, 0/lba, 1/num-sectors, text +21 load-sectors data-disk, 0/lba, 1/num-sectors, text 22 23 var word-count/eax: int <- word-count text 24 25 var result-storage: (stream byte 0x10) 26 var result/edi: (addr stream byte) <- address result-storage 27 write-int32-decimal result, word-count -28 store-sectors data-disk, 0/lba, 1/num-sectors, result +28 store-sectors data-disk, 0/lba, 1/num-sectors, result 29 } 30 31 fn word-count in: (addr stream byte) -> _/eax: int { diff --git a/html/hest-life.mu.html b/html/hest-life.mu.html new file mode 100644 index 00000000..0dafde10 --- /dev/null +++ b/html/hest-life.mu.html @@ -0,0 +1,1089 @@ + + + + +Mu - hest-life.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/hest-life.mu +
+   1 # Conway's Game of Life in a Hestified way
+   2 #   https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
+   3 #   https://ivanish.ca/hest-podcast
+   4 #
+   5 # To build:
+   6 #   $ ./translate hest-life.mu
+   7 # I run it on my 2.5GHz Linux laptop like this:
+   8 #   $ qemu-system-i386 -enable-kvm code.img
+   9 #
+  10 # If things seem too fast or too slow on your computer, adjust the loop bounds
+  11 # in the function `linger` at the bottom. Its value will depend on how you
+  12 # accelerate Qemu. Mu will eventually get a clock to obviate the need for this
+  13 # tuning.
+  14 #
+  15 # Keyboard shortcuts:
+  16 #   space: pause/resume
+  17 #   0: restart time
+  18 #   l: start looping from 0 to curren time
+  19 #   L: stop looping
+  20 #   +: zoom in
+  21 #   -: zoom out
+  22 
+  23 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) {
+  24   var env-storage: environment
+  25   var env/esi: (addr environment) <- address env-storage
+  26   initialize-environment env
+  27   var second-buffer: screen
+  28   var second-screen/edi: (addr screen) <- address second-buffer
+  29   initialize-screen second-screen, 0x80, 0x30, 1/include-pixels
+  30   render second-screen, env
+  31   copy-pixels second-screen, screen
+  32   {
+  33     edit keyboard, env
+  34     var play?/eax: (addr boolean) <- get env, play?
+  35     compare *play?, 0/false
+  36     {
+  37       break-if-=
+  38       step env
+  39       render second-screen, env
+  40       copy-pixels second-screen, screen
+  41     }
+  42     linger env
+  43     loop
+  44   }
+  45 }
+  46 
+  47 type environment {
+  48   data: (handle array handle array cell)
+  49   zoom: int  # 0 = 1024 px per cell; 5 = 4px per cell; each step adjusts by a factor of 4
+  50   tick: int
+  51   play?: boolean
+  52   loop: int  # if non-zero, return tick to 0 after this point
+  53 }
+  54 
+  55 type cell {
+  56   curr: boolean
+  57   next: boolean
+  58 }
+  59 
+  60 fn render screen: (addr screen), _self: (addr environment) {
+  61   var self/esi: (addr environment) <- copy _self
+  62   var zoom/eax: (addr int) <- get self, zoom
+  63   compare *zoom, 0
+  64   {
+  65     break-if-!=
+  66     clear-screen screen
+  67     render0 screen, self
+  68   }
+  69   compare *zoom, 1
+  70   {
+  71     break-if-!=
+  72     clear-screen screen
+  73     render1 screen, self
+  74   }
+  75   compare *zoom, 4
+  76   {
+  77     break-if-!=
+  78     render4 screen, self
+  79   }
+  80   # clock
+  81   var tick-a/eax: (addr int) <- get self, tick
+  82   set-cursor-position screen, 0x78/x, 0/y
+  83   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, *tick-a, 7/fg 0/bg
+  84 }
+  85 
+  86 # Lots of hardcoded constants for now.
+  87 # TODO: split this up into a primitive to render a single cell and its
+  88 # incoming edges (but not the neighboring nodes they emanate from)
+  89 fn render0 screen: (addr screen), _self: (addr environment) {
+  90   var self/esi: (addr environment) <- copy _self
+  91   # cell border
+  92   draw-vertical-line   screen,  0xc0/x, 0/ymin, 0x300/ymax, 0x16/color=dark-grey
+  93   draw-vertical-line   screen, 0x340/x, 0/ymin, 0x300/ymax, 0x16/color=dark-grey
+  94   draw-horizontal-line screen,  0x40/y, 0/xmin, 0x400/xmax, 0x16/color=dark-grey
+  95   draw-horizontal-line screen, 0x2c0/y, 0/xmin, 0x400/xmax, 0x16/color=dark-grey
+  96   # neighboring inputs, corners
+  97   var color/eax: int <- state-color self, 0x7f/cur-topleftx, 0x5f/cur-toplefty
+  98   draw-rect screen,  0x90/xmin   0x10/ymin,    0xb0/xmax   0x30/ymax,  color
+  99   color <- state-color self, 0x81/cur-toprightx, 0x5f/cur-toprighty
+ 100   draw-rect screen, 0x350/xmin   0x10/ymin,   0x370/xmax   0x30/ymax,  color
+ 101   color <- state-color self, 0x7f/cur-botleftx, 0x61/cur-botlefty
+ 102   draw-rect screen,  0x90/xmin  0x2d0/ymin,    0xb0/xmax  0x2f0/ymax,  color
+ 103   color <- state-color self, 0x81/cur-botrightx, 0x61/cur-botrighty
+ 104   draw-rect screen, 0x350/xmin  0x2d0/ymin,   0x370/xmax  0x2f0/ymax,  color
+ 105   # neighboring inputs, edges
+ 106   color <- state-color self, 0x80/cur-topx, 0x5f/cur-topy
+ 107   draw-rect screen, 0x1f0/xmin   0x10/ymin,   0x210/xmax   0x30/ymax,  color
+ 108   color <- state-color self, 0x7f/cur-leftx, 0x60/cur-lefty
+ 109   draw-rect screen,  0x90/xmin  0x170/ymin,    0xb0/xmax  0x190/ymax,  color
+ 110   color <- state-color self, 0x80/cur-botx, 0x61/cur-boty
+ 111   draw-rect screen, 0x1f0/xmin  0x2d0/ymin,   0x210/xmax  0x2f0/ymax,  color
+ 112   color <- state-color self, 0x81/cur-rightx, 0x60/cur-righty
+ 113   draw-rect screen, 0x350/xmin  0x170/ymin,   0x370/xmax  0x190/ymax,  color
+ 114   # sum node
+ 115   draw-rect screen, 0x170/xsmin 0x140/ysmin,  0x190/xsmax 0x160/ysmax, 0x40/color
+ 116   set-cursor-position screen, 0x2d/scol, 0x13/srow
+ 117   draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "+", 0xf/color, 0/bg
+ 118   # conveyors from neighboring inputs to sum node
+ 119   draw-monotonic-bezier screen,  0xa0/x0  0x20/y0,  0x100/x1 0x150/ys,  0x180/xs 0x150/ys,  4/color
+ 120   draw-monotonic-bezier screen,  0xa0/x0 0x180/y0,   0xc0/x1 0x150/ys,  0x180/xs 0x150/ys,  4/color
+ 121   draw-monotonic-bezier screen,  0xa0/x0 0x2e0/y0,  0x100/x1 0x150/ys,  0x180/xs 0x150/ys,  4/color
+ 122   draw-monotonic-bezier screen, 0x200/x0  0x20/y0,  0x180/x1  0x90/y1,  0x180/xs 0x150/ys,  4/color
+ 123   draw-monotonic-bezier screen, 0x200/x0 0x2e0/y0,  0x180/x1 0x200/y1,  0x180/xs 0x150/ys,  4/color
+ 124   draw-monotonic-bezier screen, 0x360/x0  0x20/y0,  0x180/x1  0xc0/y1,  0x180/xs 0x150/ys,  4/color
+ 125   draw-monotonic-bezier screen, 0x360/x0 0x180/y0,  0x35c/x1 0x150/ys,  0x180/xs 0x150/ys,  4/color
+ 126   draw-monotonic-bezier screen, 0x360/x0 0x2e0/y0,  0x180/x1 0x200/y1,  0x180/xs 0x150/ys,  4/color
+ 127   # filter node
+ 128   draw-rect screen, 0x200/xfmin 0x1c0/yfmin, 0x220/xfmax 0x1e0/yfmax, 0x31/color
+ 129   set-cursor-position screen, 0x40/fcol, 0x1b/frow
+ 130   draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "?", 0xf/color, 0/bg
+ 131   # conveyor from sum node to filter node
+ 132   draw-line screen 0x180/xs, 0x150/ys, 0x210/xf, 0x1d0/yf, 0xa2/color
+ 133   # cell outputs at corners
+ 134   var color/eax: int <- state-color self, 0x80/curx, 0x60/cury
+ 135   draw-rect screen,  0xd0/xmin  0x50/ymin,  0xf0/xmax  0x70/ymax, color
+ 136   draw-rect screen, 0x310/xmin  0x50/ymin, 0x330/xmax  0x70/ymax, color
+ 137   draw-rect screen,  0xd0/xmin 0x290/ymin,  0xf0/xmax 0x2b0/ymax, color
+ 138   draw-rect screen, 0x310/xmin 0x290/ymin, 0x330/xmax 0x2b0/ymax, color
+ 139   # cell outputs at edges
+ 140   draw-rect screen, 0x1f0/xmin  0x50/ymin, 0x210/xmax  0x70/ymax, color
+ 141   draw-rect screen,  0xd0/xmin 0x170/ymin,  0xf0/xmax 0x190/ymax, color
+ 142   draw-rect screen, 0x1f0/xmin 0x290/ymin, 0x210/xmax 0x2b0/ymax, color
+ 143   draw-rect screen, 0x310/xmin 0x170/ymin, 0x330/xmax 0x190/ymax, color
+ 144   # conveyors from filter to outputs
+ 145   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x1c0/x1  0x60/y1,  0xe0/x2   0x60/y2,  0x2a/color
+ 146   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,   0xe0/x1 0x1c0/y1,  0xe0/x2  0x180/y2,  0x2a/color
+ 147   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x1c0/x1 0x2a0/y1,  0xe0/x2  0x2a0/y2,  0x2a/color
+ 148   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x210/x1  0x60/y1, 0x200/x2   0x60/y2,  0x2a/color
+ 149   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x210/x1 0x230/y1, 0x200/x2  0x2a0/y2,  0x2a/color
+ 150   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x320/x1 0x120/y1, 0x320/x2   0x60/y2,  0x2a/color
+ 151   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x320/x1 0x1c0/y1  0x320/x2  0x180/y2,  0x2a/color
+ 152   draw-monotonic-bezier screen, 0x210/xf 0x1d0/yf,  0x320/x1 0x230/y1, 0x320/x2  0x2a0/y2,  0x2a/color
+ 153   # time-variant portion: 16 repeating steps
+ 154   var tick-a/eax: (addr int) <- get self, tick
+ 155   var progress/eax: int <- copy *tick-a
+ 156   progress <- and 0xf
+ 157   # 7 time steps for getting inputs to sum
+ 158   {
+ 159     compare progress, 7
+ 160     break-if->=
+ 161     var u/xmm7: float <- convert progress
+ 162     var six/eax: int <- copy 6
+ 163     var six-f/xmm0: float <- convert six
+ 164     u <- divide six-f
+ 165     # points on conveyors from neighboring cells
+ 166     draw-bezier-point screen, u,  0xa0/x0  0x20/y0, 0x100/x1 0x150/ys, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 167     draw-bezier-point screen, u,  0xa0/x0 0x180/y0,  0xc0/x1 0x150/ys, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 168     draw-bezier-point screen, u,  0xa0/x0 0x2e0/y0, 0x100/x1 0x150/ys, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 169     draw-bezier-point screen, u, 0x200/x0  0x20/y0, 0x180/x1  0x90/y1, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 170     draw-bezier-point screen, u, 0x200/x0 0x2e0/y0, 0x180/x1 0x200/y1, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 171     draw-bezier-point screen, u, 0x360/x0  0x20/y0, 0x180/x1  0xc0/y1, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 172     draw-bezier-point screen, u, 0x360/x0 0x180/y0, 0x35c/x1 0x150/ys, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 173     draw-bezier-point screen, u, 0x360/x0 0x2e0/y0, 0x180/x1 0x200/y1, 0x180/xs 0x150/ys, 7/color, 4/radius
+ 174     return
+ 175   }
+ 176   # two time steps for getting count to filter
+ 177   progress <- subtract 7
+ 178   {
+ 179     compare progress, 2
+ 180     break-if->=
+ 181     progress <- increment  # (0, 1) => (1, 2)
+ 182     var u/xmm7: float <- convert progress
+ 183     var three/eax: int <- copy 3
+ 184     var three-f/xmm0: float <- convert three
+ 185     u <- divide three-f
+ 186     draw-linear-point screen, u, 0x180/xs, 0x150/ys, 0x210/xf, 0x1d0/yf, 7/color, 4/radius
+ 187     set-cursor-position screen, 0x3a/scol, 0x18/srow
+ 188     var n/eax: int <- num-live-neighbors self, 0x80/curx, 0x60/cury
+ 189     draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, n, 0xf/fg 0/bg
+ 190     return
+ 191   }
+ 192   # final 7 time steps for updating output
+ 193   progress <- subtract 2
+ 194   # points on conveyors to outputs
+ 195   var u/xmm7: float <- convert progress
+ 196   var six/eax: int <- copy 6
+ 197   var six-f/xmm0: float <- convert six
+ 198   u <- divide six-f
+ 199   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x1c0/x1  0x60/y1,  0xe0/x2   0x60/y2, 7/color, 4/radius
+ 200   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,   0xe0/x1 0x1c0/y1,  0xe0/x2  0x180/y2, 7/color, 4/radius
+ 201   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x1c0/x1 0x2a0/y1,  0xe0/x2  0x2a0/y2, 7/color, 4/radius
+ 202   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x210/xf  0x60/y1, 0x200/x2   0x60/y2, 7/color, 4/radius
+ 203   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x210/xf 0x230/y1, 0x200/x2  0x2a0/y2, 7/color, 4/radius
+ 204   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x320/x1 0x120/y1, 0x320/x2   0x60/y2, 7/color, 4/radius
+ 205   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x320/x1 0x1c0/y1, 0x320/x2  0x180/y2, 7/color, 4/radius
+ 206   draw-bezier-point screen, u, 0x210/xf 0x1d0/yf,  0x320/x1 0x230/y1, 0x320/x2  0x2a0/y2, 7/color, 4/radius
+ 207 }
+ 208 
+ 209 fn render1 screen: (addr screen), _self: (addr environment) {
+ 210   var self/esi: (addr environment) <- copy _self
+ 211   # cell borders
+ 212   draw-vertical-line   screen,  0xe0/x, 0/ymin, 0x300/ymax, 0x16/color=dark-grey
+ 213   draw-vertical-line   screen, 0x200/x, 0/ymin, 0x300/ymax, 0x16/color=dark-grey
+ 214   draw-vertical-line   screen, 0x320/x, 0/ymin, 0x300/ymax, 0x16/color=dark-grey
+ 215   draw-horizontal-line screen,  0x60/y, 0/xmin, 0x400/xmax, 0x16/color=dark-grey
+ 216   draw-horizontal-line screen, 0x180/y, 0/xmin, 0x400/xmax, 0x16/color=dark-grey
+ 217   draw-horizontal-line screen, 0x2a0/y, 0/xmin, 0x400/xmax, 0x16/color=dark-grey
+ 218   # cell 0: outputs
+ 219   var color/eax: int <- state-color self, 0x80/curx, 0x60/cury
+ 220   draw-rect screen,  0xe8/xmin  0x68/ymin, 0x118/xmax   0x98/ymax, color
+ 221   draw-rect screen,  0xe8/xmin  0xd0/ymin, 0x118/xmax  0x100/ymax, color
+ 222   draw-rect screen,  0xe8/xmin 0x148/ymin, 0x118/xmax  0x178/ymax, color
+ 223   draw-rect screen, 0x158/xmin  0x68/ymin, 0x188/xmax   0x98/ymax, color
+ 224   draw-rect screen, 0x158/xmin 0x148/ymin, 0x188/xmax  0x178/ymax, color
+ 225   draw-rect screen, 0x1c8/xmin  0x68/ymin, 0x1f8/xmax   0x98/ymax, color
+ 226   draw-rect screen, 0x1c8/xmin  0xd0/ymin, 0x1f8/xmax  0x100/ymax, color
+ 227   draw-rect screen, 0x1c8/xmin 0x148/ymin, 0x1f8/xmax  0x178/ymax, color
+ 228   # cell 1: outputs
+ 229   var color/eax: int <- state-color self, 0x81/curx, 0x60/cury
+ 230   draw-rect screen, 0x208/xmin  0x68/ymin, 0x238/xmax   0x98/ymax, color
+ 231   draw-rect screen, 0x208/xmin  0xd0/ymin, 0x238/xmax  0x100/ymax, color
+ 232   draw-rect screen, 0x208/xmin 0x148/ymin, 0x238/xmax  0x178/ymax, color
+ 233   draw-rect screen, 0x278/xmin  0x68/ymin, 0x2a8/xmax   0x98/ymax, color
+ 234   draw-rect screen, 0x278/xmin 0x148/ymin, 0x2a8/xmax  0x178/ymax, color
+ 235   draw-rect screen, 0x2e8/xmin  0x68/ymin, 0x318/xmax   0x98/ymax, color
+ 236   draw-rect screen, 0x2e8/xmin  0xd0/ymin, 0x318/xmax  0x100/ymax, color
+ 237   draw-rect screen, 0x2e8/xmin 0x148/ymin, 0x318/xmax  0x178/ymax, color
+ 238   # cell 2: outputs
+ 239   var color/eax: int <- state-color self, 0x80/curx, 0x61/cury
+ 240   draw-rect screen,  0xe8/xmin 0x188/ymin, 0x118/xmax  0x1b8/ymax, color
+ 241   draw-rect screen,  0xe8/xmin 0x1f0/ymin, 0x118/xmax  0x220/ymax, color
+ 242   draw-rect screen,  0xe8/xmin 0x268/ymin, 0x118/xmax  0x298/ymax, color
+ 243   draw-rect screen, 0x158/xmin 0x188/ymin, 0x188/xmax  0x1b8/ymax, color
+ 244   draw-rect screen, 0x158/xmin 0x268/ymin, 0x188/xmax  0x298/ymax, color
+ 245   draw-rect screen, 0x1c8/xmin 0x188/ymin, 0x1f8/xmax  0x1b8/ymax, color
+ 246   draw-rect screen, 0x1c8/xmin 0x1f0/ymin, 0x1f8/xmax  0x220/ymax, color
+ 247   draw-rect screen, 0x1c8/xmin 0x268/ymin, 0x1f8/xmax  0x298/ymax, color
+ 248   # cell 3: outputs
+ 249   var color/eax: int <- state-color self, 0x81/curx, 0x61/cury
+ 250   draw-rect screen, 0x208/xmin 0x188/ymin, 0x238/xmax  0x1b8/ymax, color
+ 251   draw-rect screen, 0x208/xmin 0x1f0/ymin, 0x238/xmax  0x220/ymax, color
+ 252   draw-rect screen, 0x208/xmin 0x268/ymin, 0x238/xmax  0x298/ymax, color
+ 253   draw-rect screen, 0x278/xmin 0x188/ymin, 0x2a8/xmax  0x1b8/ymax, color
+ 254   draw-rect screen, 0x278/xmin 0x268/ymin, 0x2a8/xmax  0x298/ymax, color
+ 255   draw-rect screen, 0x2e8/xmin 0x188/ymin, 0x318/xmax  0x1b8/ymax, color
+ 256   draw-rect screen, 0x2e8/xmin 0x1f0/ymin, 0x318/xmax  0x220/ymax, color
+ 257   draw-rect screen, 0x2e8/xmin 0x268/ymin, 0x318/xmax  0x298/ymax, color
+ 258   # neighboring nodes
+ 259   var color/eax: int <- state-color self, 0x7f/curx, 0x5f/cury
+ 260   draw-rect screen,  0xa8/xmin  0x28/ymin,  0xd8/xmax   0x58/ymax, color
+ 261   var color/eax: int <- state-color self, 0x80/curx, 0x5f/cury
+ 262   draw-rect screen, 0x158/xmin  0x28/ymin, 0x188/xmax   0x58/ymax, color
+ 263   draw-rect screen, 0x1c8/xmin  0x28/ymin, 0x1f8/xmax   0x58/ymax, color
+ 264   var color/eax: int <- state-color self, 0x81/curx, 0x5f/cury
+ 265   draw-rect screen, 0x208/xmin  0x28/ymin, 0x238/xmax   0x58/ymax, color
+ 266   draw-rect screen, 0x278/xmin  0x28/ymin, 0x2a8/xmax   0x58/ymax, color
+ 267   var color/eax: int <- state-color self, 0x82/curx, 0x5f/cury
+ 268   draw-rect screen, 0x328/xmin  0x28/ymin, 0x358/xmax   0x58/ymax, color
+ 269   var color/eax: int <- state-color self, 0x7f/curx, 0x60/cury
+ 270   draw-rect screen,  0xa8/xmin  0xd0/ymin,  0xd8/xmax  0x100/ymax, color
+ 271   draw-rect screen,  0xa8/xmin 0x148/ymin,  0xd8/xmax  0x178/ymax, color
+ 272   var color/eax: int <- state-color self, 0x82/curx, 0x60/cury
+ 273   draw-rect screen, 0x328/xmin  0xd0/ymin, 0x358/xmax  0x100/ymax, color
+ 274   draw-rect screen, 0x328/xmin 0x148/ymin, 0x358/xmax  0x178/ymax, color
+ 275   var color/eax: int <- state-color self, 0x7f/curx, 0x61/cury
+ 276   draw-rect screen,  0xa8/xmin 0x188/ymin,  0xd8/xmax  0x1b8/ymax, color
+ 277   draw-rect screen,  0xa8/xmin 0x1f0/ymin,  0xd8/xmax  0x220/ymax, color
+ 278   var color/eax: int <- state-color self, 0x82/curx, 0x61/cury
+ 279   draw-rect screen, 0x328/xmin 0x188/ymin, 0x358/xmax  0x1b8/ymax, color
+ 280   draw-rect screen, 0x328/xmin 0x1f0/ymin, 0x358/xmax  0x220/ymax, color
+ 281   var color/eax: int <- state-color self, 0x7f/curx, 0x62/cury
+ 282   draw-rect screen,  0xa8/xmin 0x2a8/ymin,  0xd8/xmax  0x2d8/ymax, color
+ 283   var color/eax: int <- state-color self, 0x80/curx, 0x62/cury
+ 284   draw-rect screen, 0x158/xmin 0x2a8/ymin, 0x188/xmax  0x2d8/ymax, color
+ 285   draw-rect screen, 0x1c8/xmin 0x2a8/ymin, 0x1f8/xmax  0x2d8/ymax, color
+ 286   var color/eax: int <- state-color self, 0x81/curx, 0x62/cury
+ 287   draw-rect screen, 0x208/xmin 0x2a8/ymin, 0x238/xmax  0x2d8/ymax, color
+ 288   draw-rect screen, 0x278/xmin 0x2a8/ymin, 0x2a8/xmax  0x2d8/ymax, color
+ 289   var color/eax: int <- state-color self, 0x82/curx, 0x62/cury
+ 290   draw-rect screen, 0x328/xmin 0x2a8/ymin, 0x358/xmax  0x2d8/ymax, color
+ 291   # cell 0: sum and filter nodes
+ 292   draw-rect screen, 0x148/xsmin  0xc8/ysmin, 0x158/xsmax  0xd8/ysmax, 0x40/color
+ 293   draw-rect screen, 0x180/xfmin  0xf8/yfmin, 0x190/xfmax 0x108/yfmax, 0x31/color
+ 294   # cell 1: sum and filter nodes
+ 295   draw-rect screen, 0x268/xsmin  0xc8/ysmin, 0x278/xsmax  0xd8/ysmax, 0x40/color
+ 296   draw-rect screen, 0x2a0/xfmin  0xf8/yfmin, 0x2b0/xfmax 0x108/yfmax, 0x31/color
+ 297   # cell 2: sum and filter nodes
+ 298   draw-rect screen, 0x148/xsmin 0x1e8/ysmin, 0x158/xsmax 0x1f8/ysmax, 0x40/color
+ 299   draw-rect screen, 0x180/xfmin 0x218/yfmin, 0x190/xfmax 0x228/yfmax, 0x31/color
+ 300   # cell 3: sum and filter nodes
+ 301   draw-rect screen, 0x268/xsmin 0x1e8/ysmin, 0x278/xsmax 0x1f8/ysmax, 0x40/color
+ 302   draw-rect screen, 0x2a0/xfmin 0x218/yfmin, 0x2b0/xfmax 0x228/yfmax, 0x31/color
+ 303   # neighbor counts
+ 304   var n/eax: int <- num-live-neighbors self, 0x80/curx, 0x60/cury
+ 305   set-cursor-position screen, 0x2d, 0xe
+ 306   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, n, 0xf/fg 0/bg
+ 307   var n/eax: int <- num-live-neighbors self, 0x81/curx, 0x60/cury
+ 308   set-cursor-position screen, 0x52, 0xe
+ 309   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, n, 0xf/fg 0/bg
+ 310   var n/eax: int <- num-live-neighbors self, 0x80/curx, 0x61/cury
+ 311   set-cursor-position screen, 0x2d, 0x20
+ 312   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, n, 0xf/fg 0/bg
+ 313   var n/eax: int <- num-live-neighbors self, 0x81/curx, 0x61/cury
+ 314   set-cursor-position screen, 0x52, 0x20
+ 315   draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, n, 0xf/fg 0/bg
+ 316   # cell 0: conveyors from neighboring inputs to sum node
+ 317   draw-monotonic-bezier screen,  0xc0/x0  0x40/y0,  0x100/x1  0xd0/ys, 0x150/xs  0xd0/ys,  4/color
+ 318   draw-monotonic-bezier screen,  0xc0/x0  0xe8/y0,   0xc0/x1  0xd0/ys, 0x150/xs  0xd0/ys,  4/color
+ 319   draw-monotonic-bezier screen,  0xc0/x0 0x1a0/y0,   0xe0/x1  0xd0/ys, 0x150/xs  0xd0/ys,  4/color
+ 320   draw-monotonic-bezier screen, 0x170/x0  0x40/y0,  0x150/x1  0x80/y1, 0x150/xs  0xd0/ys,  4/color
+ 321   draw-monotonic-bezier screen, 0x170/x0 0x1a0/y0,  0x150/x1 0x1a0/y1, 0x150/xs  0xd0/ys,  4/color
+ 322   draw-monotonic-bezier screen, 0x220/x0  0x40/y0,  0x150/x1  0x80/y1, 0x150/xs  0xd0/ys,  4/color
+ 323   draw-monotonic-bezier screen, 0x220/x0  0xe8/y0,  0x220/x1  0xd0/y1, 0x150/xs  0xd0/ys,  4/color
+ 324   draw-monotonic-bezier screen, 0x220/x0 0x1a0/y0,  0x180/x1 0x1a0/y1, 0x150/xs  0xd0/ys,  4/color
+ 325   # cell 0: conveyors from filter to outputs
+ 326   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x160/x1  0x8c/y1, 0x100/x2  0x80/y2,  0x2a/color
+ 327   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x100/x1 0x100/y1, 0x100/x2  0xe8/y2,  0x2a/color
+ 328   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x100/x1 0x100/y1, 0x100/x2 0x160/y2,  0x2a/color
+ 329   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x188/x1  0x80/y1, 0x170/x2  0x80/y2,  0x2a/color
+ 330   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x188/x1 0x160/y1, 0x170/x2 0x160/y2,  0x2a/color
+ 331   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x1e0/x1 0x100/y1, 0x1e0/x2  0x80/y2,  0x2a/color
+ 332   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x1e0/x1 0x100/y1  0x1e0/x2  0xe8/y2,  0x2a/color
+ 333   draw-monotonic-bezier screen, 0x188/xf 0x100/yf,  0x1e0/x1 0x100/y1, 0x1e0/x2 0x160/y2,  0x2a/color
+ 334   # cell 0: time-variant portion: 16 repeating steps
+ 335   $render1:cell0: {
+ 336     var tick-a/eax: (addr int) <- get self, tick
+ 337     var progress/eax: int <- copy *tick-a
+ 338     progress <- and 0xf
+ 339     # cell 0: 7 time steps for getting inputs to sum
+ 340     {
+ 341       compare progress, 7
+ 342       break-if->=
+ 343       var u/xmm7: float <- convert progress
+ 344       var six/eax: int <- copy 6
+ 345       var six-f/xmm0: float <- convert six
+ 346       u <- divide six-f
+ 347       # points on conveyors from neighboring cells
+ 348       draw-bezier-point screen, u,  0xc0/x0  0x40/y0, 0x100/x1  0xd0/ys, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 349       draw-bezier-point screen, u,  0xc0/x0  0xe8/y0,  0xc0/x1  0xd0/ys, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 350       draw-bezier-point screen, u,  0xc0/x0 0x1a0/y0,  0xe0/x1  0xd0/ys, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 351       draw-bezier-point screen, u, 0x170/x0  0x40/y0, 0x150/x1  0x80/y1, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 352       draw-bezier-point screen, u, 0x170/x0 0x1a0/y0, 0x150/x1 0x1a0/y1, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 353       draw-bezier-point screen, u, 0x220/x0  0x40/y0, 0x150/x1  0x80/y1, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 354       draw-bezier-point screen, u, 0x220/x0  0xe8/y0, 0x220/x1  0xd0/y1, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 355       draw-bezier-point screen, u, 0x220/x0 0x1a0/y0, 0x180/x1 0x1a0/y1, 0x150/xs  0xd0/ys, 7/color, 4/radius
+ 356       break $render1:cell0
+ 357     }
+ 358     # cell 0: two time steps for getting count to filter
+ 359     progress <- subtract 7
+ 360     {
+ 361       compare progress, 2
+ 362       break-if->=
+ 363       break $render1:cell0
+ 364     }
+ 365     # cell 0: final 7 time steps for updating output
+ 366     progress <- subtract 2
+ 367     # cell 0: points on conveyors to outputs
+ 368     var u/xmm7: float <- convert progress
+ 369     var six/eax: int <- copy 6
+ 370     var six-f/xmm0: float <- convert six
+ 371     u <- divide six-f
+ 372     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x160/x1  0x8c/y1, 0x100/x2  0x80/y2, 7/color, 4/radius
+ 373     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x100/x1 0x100/y1, 0x100/x2  0xe8/y2, 7/color, 4/radius
+ 374     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x100/x1 0x100/y1, 0x100/x2 0x160/y2, 7/color, 4/radius
+ 375     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x188/xf  0x80/y1, 0x170/x2  0x80/y2, 7/color, 4/radius
+ 376     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x188/xf 0x160/y1, 0x170/x2 0x160/y2, 7/color, 4/radius
+ 377     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x1e0/x1 0x100/y1, 0x1e0/x2  0x80/y2, 7/color, 4/radius
+ 378     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x1e0/x1 0x100/y1, 0x1e0/x2  0xe8/y2, 7/color, 4/radius
+ 379     draw-bezier-point screen, u, 0x188/xf 0x100/yf,  0x1e0/x1 0x100/y1, 0x1e0/x2 0x160/y2, 7/color, 4/radius
+ 380   }
+ 381   # cell 1: conveyors from neighboring inputs to sum node
+ 382   draw-monotonic-bezier screen, 0x1e0/x0  0x40/y0,  0x220/x1  0xd0/ys, 0x270/xs  0xd0/ys,  4/color
+ 383   draw-monotonic-bezier screen, 0x1e0/x0  0xe8/y0,  0x1e0/x1  0xd0/ys, 0x270/xs  0xd0/ys,  4/color
+ 384   draw-monotonic-bezier screen, 0x1e0/x0 0x1a0/y0,  0x200/x1  0xd0/ys, 0x270/xs  0xd0/ys,  4/color
+ 385   draw-monotonic-bezier screen, 0x290/x0  0x40/y0,  0x270/x1  0x80/y1, 0x270/xs  0xd0/ys,  4/color
+ 386   draw-monotonic-bezier screen, 0x290/x0 0x1a0/y0,  0x270/x1 0x1a0/y1, 0x270/xs  0xd0/ys,  4/color
+ 387   draw-monotonic-bezier screen, 0x340/x0  0x40/y0,  0x270/x1  0x80/y1, 0x270/xs  0xd0/ys,  4/color
+ 388   draw-monotonic-bezier screen, 0x340/x0  0xe8/y0,  0x340/x1  0xd0/y1, 0x270/xs  0xd0/ys,  4/color
+ 389   draw-monotonic-bezier screen, 0x340/x0 0x1a0/y0,  0x2a0/x1 0x1a0/y1, 0x270/xs  0xd0/ys,  4/color
+ 390   # cell 1: conveyors from filter to outputs
+ 391   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x280/x1  0x8c/y1, 0x220/x2  0x80/y2,  0x2a/color
+ 392   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x220/x1 0x100/y1, 0x220/x2  0xe8/y2,  0x2a/color
+ 393   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x220/x1 0x100/y1, 0x220/x2 0x160/y2,  0x2a/color
+ 394   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x2a8/x1  0x80/y1, 0x290/x2  0x80/y2,  0x2a/color
+ 395   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x2a8/x1 0x160/y1, 0x290/x2 0x160/y2,  0x2a/color
+ 396   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x300/x1 0x100/y1, 0x300/x2  0x80/y2,  0x2a/color
+ 397   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x300/x1 0x100/y1  0x300/x2  0xe8/y2,  0x2a/color
+ 398   draw-monotonic-bezier screen, 0x2a8/xf 0x100/yf,  0x300/x1 0x100/y1, 0x300/x2 0x160/y2,  0x2a/color
+ 399   # cell 1: time-variant portion: 16 repeating steps
+ 400   $render1:cell1: {
+ 401     var tick-a/eax: (addr int) <- get self, tick
+ 402     var progress/eax: int <- copy *tick-a
+ 403     progress <- and 0xf
+ 404     # cell 1: 7 time steps for getting inputs to sum
+ 405     {
+ 406       compare progress, 7
+ 407       break-if->=
+ 408       var u/xmm7: float <- convert progress
+ 409       var six/eax: int <- copy 6
+ 410       var six-f/xmm0: float <- convert six
+ 411       u <- divide six-f
+ 412       # points on conveyors from neighboring cells
+ 413       draw-bezier-point screen, u, 0x1e0/x0  0x40/y0, 0x220/x1  0xd0/ys, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 414       draw-bezier-point screen, u, 0x1e0/x0  0xe8/y0, 0x1e0/x1  0xd0/ys, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 415       draw-bezier-point screen, u, 0x1e0/x0 0x1a0/y0, 0x200/x1  0xd0/ys, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 416       draw-bezier-point screen, u, 0x290/x0  0x40/y0, 0x270/x1  0x80/y1, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 417       draw-bezier-point screen, u, 0x290/x0 0x1a0/y0, 0x270/x1 0x1a0/y1, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 418       draw-bezier-point screen, u, 0x340/x0  0x40/y0, 0x270/x1  0x80/y1, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 419       draw-bezier-point screen, u, 0x340/x0  0xe8/y0, 0x340/x1  0xd0/y1, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 420       draw-bezier-point screen, u, 0x340/x0 0x1a0/y0, 0x2a0/x1 0x1a0/y1, 0x270/xs  0xd0/ys, 7/color, 4/radius
+ 421       break $render1:cell1
+ 422     }
+ 423     # cell 1: two time steps for getting count to filter
+ 424     progress <- subtract 7
+ 425     {
+ 426       compare progress, 2
+ 427       break-if->=
+ 428       break $render1:cell1
+ 429     }
+ 430     # cell 1: final 7 time steps for updating output
+ 431     progress <- subtract 2
+ 432     # cell 1: points on conveyors to outputs
+ 433     var u/xmm7: float <- convert progress
+ 434     var six/eax: int <- copy 6
+ 435     var six-f/xmm0: float <- convert six
+ 436     u <- divide six-f
+ 437     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x280/x1  0x8c/y1, 0x220/x2  0x80/y2, 7/color, 4/radius
+ 438     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x220/x1 0x100/y1, 0x220/x2  0xe8/y2, 7/color, 4/radius
+ 439     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x220/x1 0x100/y1, 0x220/x2 0x160/y2, 7/color, 4/radius
+ 440     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x2a8/xf  0x80/y1, 0x290/x2  0x80/y2, 7/color, 4/radius
+ 441     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x2a8/xf 0x160/y1, 0x290/x2 0x160/y2, 7/color, 4/radius
+ 442     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x300/x1 0x100/y1, 0x300/x2  0x80/y2, 7/color, 4/radius
+ 443     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x300/x1 0x100/y1, 0x300/x2  0xe8/y2, 7/color, 4/radius
+ 444     draw-bezier-point screen, u, 0x2a8/xf 0x100/yf,  0x300/x1 0x100/y1, 0x300/x2 0x160/y2, 7/color, 4/radius
+ 445   }
+ 446   # cell 2: conveyors from neighboring inputs to sum node
+ 447   draw-monotonic-bezier screen,  0xc0/x0 0x160/y0,  0x100/x1 0x1f0/ys, 0x150/xs 0x1f0/ys,  4/color
+ 448   draw-monotonic-bezier screen,  0xc0/x0 0x208/y0,   0xc0/x1 0x1f0/ys, 0x150/xs 0x1f0/ys,  4/color
+ 449   draw-monotonic-bezier screen,  0xc0/x0 0x2c0/y0,   0xe0/x1 0x1f0/ys, 0x150/xs 0x1f0/ys,  4/color
+ 450   draw-monotonic-bezier screen, 0x170/x0 0x160/y0,  0x150/x1 0x1a0/y1, 0x150/xs 0x1f0/ys,  4/color
+ 451   draw-monotonic-bezier screen, 0x170/x0 0x2c0/y0,  0x150/x1 0x2c0/y1, 0x150/xs 0x1f0/ys,  4/color
+ 452   draw-monotonic-bezier screen, 0x220/x0 0x160/y0,  0x150/x1 0x1a0/y1, 0x150/xs 0x1f0/ys,  4/color
+ 453   draw-monotonic-bezier screen, 0x220/x0 0x208/y0,  0x220/x1 0x1f0/y1, 0x150/xs 0x1f0/ys,  4/color
+ 454   draw-monotonic-bezier screen, 0x220/x0 0x2c0/y0,  0x180/x1 0x2c0/y1, 0x150/xs 0x1f0/ys,  4/color
+ 455   # cell 2: conveyors from filter to outputs
+ 456   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x160/x1 0x1ac/y1, 0x100/x2 0x1a0/y2,  0x2a/color
+ 457   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x100/x1 0x220/y1, 0x100/x2 0x208/y2,  0x2a/color
+ 458   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x100/x1 0x220/y1, 0x100/x2 0x280/y2,  0x2a/color
+ 459   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x188/x1 0x1a0/y1, 0x170/x2 0x1a0/y2,  0x2a/color
+ 460   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x188/x1 0x280/y1, 0x170/x2 0x280/y2,  0x2a/color
+ 461   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x1e0/x1 0x220/y1, 0x1e0/x2 0x1a0/y2,  0x2a/color
+ 462   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x1e0/x1 0x220/y1  0x1e0/x2 0x208/y2,  0x2a/color
+ 463   draw-monotonic-bezier screen, 0x188/xf 0x220/yf,  0x1e0/x1 0x220/y1, 0x1e0/x2 0x280/y2,  0x2a/color
+ 464   # cell 2: time-variant portion: 16 repeating steps
+ 465   $render1:cell2: {
+ 466     var tick-a/eax: (addr int) <- get self, tick
+ 467     var progress/eax: int <- copy *tick-a
+ 468     progress <- and 0xf
+ 469     # cell 2: 7 time steps for getting inputs to sum
+ 470     {
+ 471       compare progress, 7
+ 472       break-if->=
+ 473       var u/xmm7: float <- convert progress
+ 474       var six/eax: int <- copy 6
+ 475       var six-f/xmm0: float <- convert six
+ 476       u <- divide six-f
+ 477       # points on conveyors from neighboring cells
+ 478       draw-bezier-point screen, u,  0xc0/x0 0x160/y0, 0x100/x1 0x1f0/ys, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 479       draw-bezier-point screen, u,  0xc0/x0 0x208/y0,  0xc0/x1 0x1f0/ys, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 480       draw-bezier-point screen, u,  0xc0/x0 0x2c0/y0,  0xe0/x1 0x1f0/ys, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 481       draw-bezier-point screen, u, 0x170/x0 0x160/y0, 0x150/x1 0x1a0/y1, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 482       draw-bezier-point screen, u, 0x170/x0 0x2c0/y0, 0x150/x1 0x2c0/y1, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 483       draw-bezier-point screen, u, 0x220/x0 0x160/y0, 0x150/x1 0x1a0/y1, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 484       draw-bezier-point screen, u, 0x220/x0 0x208/y0, 0x220/x1 0x1f0/y1, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 485       draw-bezier-point screen, u, 0x220/x0 0x2c0/y0, 0x180/x1 0x2c0/y1, 0x150/xs 0x1f0/ys, 7/color, 4/radius
+ 486       break $render1:cell2
+ 487     }
+ 488     # cell 2: two time steps for getting count to filter
+ 489     progress <- subtract 7
+ 490     {
+ 491       compare progress, 2
+ 492       break-if->=
+ 493       break $render1:cell2
+ 494     }
+ 495     # cell 2: final 7 time steps for updating output
+ 496     progress <- subtract 2
+ 497     # cell 2: points on conveyors to outputs
+ 498     var u/xmm7: float <- convert progress
+ 499     var six/eax: int <- copy 6
+ 500     var six-f/xmm0: float <- convert six
+ 501     u <- divide six-f
+ 502     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x160/x1 0x1ac/y1, 0x100/x2 0x1a0/y2, 7/color, 4/radius
+ 503     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x100/x1 0x220/y1, 0x100/x2 0x208/y2, 7/color, 4/radius
+ 504     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x100/x1 0x220/y1, 0x100/x2 0x280/y2, 7/color, 4/radius
+ 505     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x188/xf 0x1a0/y1, 0x170/x2 0x1a0/y2, 7/color, 4/radius
+ 506     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x188/xf 0x280/y1, 0x170/x2 0x280/y2, 7/color, 4/radius
+ 507     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x1e0/x1 0x220/y1, 0x1e0/x2 0x1a0/y2, 7/color, 4/radius
+ 508     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x1e0/x1 0x220/y1, 0x1e0/x2 0x208/y2, 7/color, 4/radius
+ 509     draw-bezier-point screen, u, 0x188/xf 0x220/yf,  0x1e0/x1 0x220/y1, 0x1e0/x2 0x280/y2, 7/color, 4/radius
+ 510   }
+ 511   # cell 3: conveyors from neighboring inputs to sum node
+ 512   draw-monotonic-bezier screen, 0x1e0/x0 0x160/y0,  0x220/x1 0x1f0/ys, 0x270/xs 0x1f0/ys,  4/color
+ 513   draw-monotonic-bezier screen, 0x1e0/x0 0x208/y0,  0x1e0/x1 0x1f0/ys, 0x270/xs 0x1f0/ys,  4/color
+ 514   draw-monotonic-bezier screen, 0x1e0/x0 0x2c0/y0,  0x200/x1 0x1f0/ys, 0x270/xs 0x1f0/ys,  4/color
+ 515   draw-monotonic-bezier screen, 0x290/x0 0x160/y0,  0x270/x1 0x1a0/y1, 0x270/xs 0x1f0/ys,  4/color
+ 516   draw-monotonic-bezier screen, 0x290/x0 0x2c0/y0,  0x270/x1 0x2c0/y1, 0x270/xs 0x1f0/ys,  4/color
+ 517   draw-monotonic-bezier screen, 0x340/x0 0x160/y0,  0x270/x1 0x1a0/y1, 0x270/xs 0x1f0/ys,  4/color
+ 518   draw-monotonic-bezier screen, 0x340/x0 0x208/y0,  0x340/x1 0x1f0/y1, 0x270/xs 0x1f0/ys,  4/color
+ 519   draw-monotonic-bezier screen, 0x340/x0 0x2c0/y0,  0x2a0/x1 0x2c0/y1, 0x270/xs 0x1f0/ys,  4/color
+ 520   # cell 3: conveyors from filter to outputs
+ 521   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x280/x1 0x1ac/y1, 0x220/x2 0x1a0/y2,  0x2a/color
+ 522   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x220/x1 0x220/y1, 0x220/x2 0x208/y2,  0x2a/color
+ 523   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x220/x1 0x220/y1, 0x220/x2 0x280/y2,  0x2a/color
+ 524   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x2a8/x1 0x1a0/y1, 0x290/x2 0x1a0/y2,  0x2a/color
+ 525   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x2a8/x1 0x280/y1, 0x290/x2 0x280/y2,  0x2a/color
+ 526   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x300/x1 0x220/y1, 0x300/x2 0x1a0/y2,  0x2a/color
+ 527   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x300/x1 0x220/y1  0x300/x2 0x208/y2,  0x2a/color
+ 528   draw-monotonic-bezier screen, 0x2a8/xf 0x220/yf,  0x300/x1 0x220/y1, 0x300/x2 0x280/y2,  0x2a/color
+ 529   # cell 3: time-variant portion: 16 repeating steps
+ 530   $render1:cell3: {
+ 531     var tick-a/eax: (addr int) <- get self, tick
+ 532     var progress/eax: int <- copy *tick-a
+ 533     progress <- and 0xf
+ 534     # cell 3: 7 time steps for getting inputs to sum
+ 535     {
+ 536       compare progress, 7
+ 537       break-if->=
+ 538       var u/xmm7: float <- convert progress
+ 539       var six/eax: int <- copy 6
+ 540       var six-f/xmm0: float <- convert six
+ 541       u <- divide six-f
+ 542       # points on conveyors from neighboring cells
+ 543       draw-bezier-point screen, u, 0x1e0/x0 0x160/y0, 0x220/x1 0x1f0/ys, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 544       draw-bezier-point screen, u, 0x1e0/x0 0x208/y0, 0x1e0/x1 0x1f0/ys, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 545       draw-bezier-point screen, u, 0x1e0/x0 0x2c0/y0, 0x200/x1 0x1f0/ys, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 546       draw-bezier-point screen, u, 0x290/x0 0x160/y0, 0x270/x1 0x1a0/y1, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 547       draw-bezier-point screen, u, 0x290/x0 0x2c0/y0, 0x270/x1 0x2c0/y1, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 548       draw-bezier-point screen, u, 0x340/x0 0x160/y0, 0x270/x1 0x1a0/y1, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 549       draw-bezier-point screen, u, 0x340/x0 0x208/y0, 0x340/x1 0x1f0/y1, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 550       draw-bezier-point screen, u, 0x340/x0 0x2c0/y0, 0x2a0/x1 0x2c0/y1, 0x270/xs 0x1f0/ys, 7/color, 4/radius
+ 551       break $render1:cell3
+ 552     }
+ 553     # cell 3: two time steps for getting count to filter
+ 554     progress <- subtract 7
+ 555     {
+ 556       compare progress, 2
+ 557       break-if->=
+ 558       break $render1:cell3
+ 559     }
+ 560     # cell 3: final 7 time steps for updating output
+ 561     progress <- subtract 2
+ 562     # cell 3: points on conveyors to outputs
+ 563     var u/xmm7: float <- convert progress
+ 564     var six/eax: int <- copy 6
+ 565     var six-f/xmm0: float <- convert six
+ 566     u <- divide six-f
+ 567     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x280/x1 0x1ac/y1, 0x220/x2 0x1a0/y2, 7/color, 4/radius
+ 568     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x220/x1 0x220/y1, 0x220/x2 0x208/y2, 7/color, 4/radius
+ 569     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x220/x1 0x220/y1, 0x220/x2 0x280/y2, 7/color, 4/radius
+ 570     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x2a8/xf 0x1a0/y1, 0x290/x2 0x1a0/y2, 7/color, 4/radius
+ 571     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x2a8/xf 0x280/y1, 0x290/x2 0x280/y2, 7/color, 4/radius
+ 572     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x300/x1 0x220/y1, 0x300/x2 0x1a0/y2, 7/color, 4/radius
+ 573     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x300/x1 0x220/y1, 0x300/x2 0x208/y2, 7/color, 4/radius
+ 574     draw-bezier-point screen, u, 0x2a8/xf 0x220/yf,  0x300/x1 0x220/y1, 0x300/x2 0x280/y2, 7/color, 4/radius
+ 575   }
+ 576 }
+ 577 
+ 578 fn draw-bezier-point screen: (addr screen), u: float, x0: int, y0: int, x1: int, y1: int, x2: int, y2: int, color: int, radius: int {
+ 579   var _cy/eax: int <- bezier-point u, y0, y1, y2
+ 580   var cy/ecx: int <- copy _cy
+ 581   var cx/eax: int <- bezier-point u, x0, x1, x2
+ 582   draw-disc screen, cx, cy, radius, color, 0xf/border-color=white
+ 583 }
+ 584 
+ 585 fn draw-linear-point screen: (addr screen), u: float, x0: int, y0: int, x1: int, y1: int, color: int, radius: int {
+ 586   var _cy/eax: int <- line-point u, y0, y1
+ 587   var cy/ecx: int <- copy _cy
+ 588   var cx/eax: int <- line-point u, x0, x1
+ 589   draw-disc screen, cx, cy, radius, color, 0xf/border-color=white
+ 590 }
+ 591 
+ 592 fn edit keyboard: (addr keyboard), _self: (addr environment) {
+ 593   var self/esi: (addr environment) <- copy _self
+ 594   var key/eax: byte <- read-key keyboard
+ 595   # space: play/pause
+ 596   {
+ 597     compare key, 0x20/space
+ 598     break-if-!=
+ 599     var play?/eax: (addr boolean) <- get self, play?
+ 600     compare *play?, 0/false
+ 601     {
+ 602       break-if-=
+ 603       copy-to *play?, 0/false
+ 604       return
+ 605     }
+ 606     copy-to *play?, 1/true
+ 607     return
+ 608   }
+ 609   # 0: back to start
+ 610   {
+ 611     compare key, 0x30/0
+ 612     break-if-!=
+ 613     clear-environment self
+ 614     return
+ 615   }
+ 616   # l: loop from here to start
+ 617   {
+ 618     compare key, 0x6c/l
+ 619     break-if-!=
+ 620     var tick-a/eax: (addr int) <- get self, tick
+ 621     var tick/eax: int <- copy *tick-a
+ 622     var loop/ecx: (addr int) <- get self, loop
+ 623     copy-to *loop, tick
+ 624     return
+ 625   }
+ 626   # L: reset loop
+ 627   {
+ 628     compare key, 0x4c/L
+ 629     break-if-!=
+ 630     var loop/eax: (addr int) <- get self, loop
+ 631     copy-to *loop, 0
+ 632     return
+ 633   }
+ 634   # -: zoom out
+ 635   {
+ 636     compare key, 0x2d/-
+ 637     break-if-!=
+ 638     var zoom/eax: (addr int) <- get self, zoom
+ 639     compare *zoom, 1
+ 640     {
+ 641       break-if-!=
+ 642       copy-to *zoom, 4
+ 643     }
+ 644     compare *zoom, 0
+ 645     {
+ 646       break-if-!=
+ 647       copy-to *zoom, 1
+ 648     }
+ 649     # set tick to a multiple of zoom
+ 650     var tick-a/edx: (addr int) <- get self, tick
+ 651     clear-lowest-bits tick-a, *zoom
+ 652     return
+ 653   }
+ 654   # +: zoom in
+ 655   {
+ 656     compare key, 0x2b/+
+ 657     break-if-!=
+ 658     var zoom/eax: (addr int) <- get self, zoom
+ 659     compare *zoom, 1
+ 660     {
+ 661       break-if-!=
+ 662       copy-to *zoom, 0
+ 663     }
+ 664     compare *zoom, 4
+ 665     {
+ 666       break-if-!=
+ 667       copy-to *zoom, 1
+ 668     }
+ 669     # set tick to a multiple of zoom
+ 670     var tick-a/edx: (addr int) <- get self, tick
+ 671     clear-lowest-bits tick-a, *zoom
+ 672     return
+ 673   }
+ 674 }
+ 675 
+ 676 fn step _self: (addr environment) {
+ 677   var self/esi: (addr environment) <- copy _self
+ 678   var tick-a/ecx: (addr int) <- get self, tick
+ 679   var zoom/edx: (addr int) <- get self, zoom
+ 680   compare *zoom, 0
+ 681   {
+ 682     break-if-!=
+ 683     increment *tick-a
+ 684   }
+ 685   compare *zoom, 1
+ 686   {
+ 687     break-if-!=
+ 688     # I wanted to speed up time, but that doesn't seem very usable.
+ 689 #?     add-to *tick-a, 2
+ 690     increment *tick-a
+ 691   }
+ 692   compare *zoom, 4
+ 693   {
+ 694     break-if-!=
+ 695     add-to *tick-a, 0x10
+ 696   }
+ 697   var tick/eax: int <- copy *tick-a
+ 698   tick <- and 0xf
+ 699   compare tick, 0
+ 700   {
+ 701     break-if-!=
+ 702     step4 self
+ 703   }
+ 704   var loop-a/eax: (addr int) <- get self, loop
+ 705   compare *loop-a, 0
+ 706   {
+ 707     break-if-=
+ 708     var loop/eax: int <- copy *loop-a
+ 709     compare *tick-a, loop
+ 710     break-if-<
+ 711     clear-environment self
+ 712   }
+ 713 }
+ 714 
+ 715 fn initialize-environment _self: (addr environment) {
+ 716   var self/esi: (addr environment) <- copy _self
+ 717   var zoom/eax: (addr int) <- get self, zoom
+ 718   copy-to *zoom, 0
+ 719   var play?/eax: (addr boolean) <- get self, play?
+ 720   copy-to *play?, 1/true
+ 721   var data-ah/eax: (addr handle array handle array cell) <- get self, data
+ 722   populate data-ah, 0x100
+ 723   var data/eax: (addr array handle array cell) <- lookup *data-ah
+ 724   var y/ecx: int <- copy 0
+ 725   {
+ 726     compare y, 0xc0
+ 727     break-if->=
+ 728     var dest-ah/eax: (addr handle array cell) <- index data, y
+ 729     populate dest-ah, 0x100
+ 730     y <- increment
+ 731     loop
+ 732   }
+ 733   set self, 0x80, 0x5f, 1/alive
+ 734   set self, 0x81, 0x5f, 1/alive
+ 735   set self, 0x7f, 0x60, 1/alive
+ 736   set self, 0x80, 0x60, 1/alive
+ 737   set self, 0x80, 0x61, 1/alive
+ 738   flush self
+ 739 }
+ 740 
+ 741 fn clear-environment _self: (addr environment) {
+ 742   var self/esi: (addr environment) <- copy _self
+ 743   var tick/eax: (addr int) <- get self, tick
+ 744   copy-to *tick, 0
+ 745   # don't touch zoom or play settings
+ 746   var data-ah/eax: (addr handle array handle array cell) <- get self, data
+ 747   var data/eax: (addr array handle array cell) <- lookup *data-ah
+ 748   var y/ecx: int <- copy 0
+ 749   {
+ 750     compare y, 0xc0
+ 751     break-if->=
+ 752     var row-ah/eax: (addr handle array cell) <- index data, y
+ 753     var row/eax: (addr array cell) <- lookup *row-ah
+ 754     var x/edx: int <- copy 0
+ 755     {
+ 756       compare x, 0x100
+ 757       break-if->=
+ 758       var dest/eax: (addr cell) <- index row, x
+ 759       clear-object dest
+ 760       x <- increment
+ 761       loop
+ 762     }
+ 763     y <- increment
+ 764     loop
+ 765   }
+ 766   set self, 0x80, 0x5f, 1/alive
+ 767   set self, 0x81, 0x5f, 1/alive
+ 768   set self, 0x7f, 0x60, 1/alive
+ 769   set self, 0x80, 0x60, 1/alive
+ 770   set self, 0x80, 0x61, 1/alive
+ 771   flush self
+ 772 }
+ 773 
+ 774 fn set _self: (addr environment), _x: int, _y: int, _val: boolean {
+ 775   var self/esi: (addr environment) <- copy _self
+ 776   var data-ah/eax: (addr handle array handle array cell) <- get self, data
+ 777   var data/eax: (addr array handle array cell) <- lookup *data-ah
+ 778   var y/ecx: int <- copy _y
+ 779   var row-ah/eax: (addr handle array cell) <- index data, y
+ 780   var row/eax: (addr array cell) <- lookup *row-ah
+ 781   var x/ecx: int <- copy _x
+ 782   var cell/eax: (addr cell) <- index row, x
+ 783   var dest/eax: (addr boolean) <- get cell, next
+ 784   var val/ecx: boolean <- copy _val
+ 785   copy-to *dest, val
+ 786 }
+ 787 
+ 788 fn state _self: (addr environment), _x: int, _y: int -> _/eax: boolean {
+ 789   var self/esi: (addr environment) <- copy _self
+ 790   var x/ecx: int <- copy _x
+ 791   var y/edx: int <- copy _y
+ 792   # clip at the edge
+ 793   compare x, 0
+ 794   {
+ 795     break-if->=
+ 796     return 0/false
+ 797   }
+ 798   compare y, 0
+ 799   {
+ 800     break-if->=
+ 801     return 0/false
+ 802   }
+ 803   compare x, 0x100/width
+ 804   {
+ 805     break-if-<
+ 806     return 0/false
+ 807   }
+ 808   compare y, 0xc0/height
+ 809   {
+ 810     break-if-<
+ 811     return 0/false
+ 812   }
+ 813   var data-ah/eax: (addr handle array handle array cell) <- get self, data
+ 814   var data/eax: (addr array handle array cell) <- lookup *data-ah
+ 815   var row-ah/eax: (addr handle array cell) <- index data, y
+ 816   var row/eax: (addr array cell) <- lookup *row-ah
+ 817   var cell/eax: (addr cell) <- index row, x
+ 818   var src/eax: (addr boolean) <- get cell, curr
+ 819   return *src
+ 820 }
+ 821 
+ 822 fn state-color _self: (addr environment), x: int, y: int -> _/eax: int {
+ 823   var self/esi: (addr environment) <- copy _self
+ 824   var color/ecx: int <- copy 0x1a/dead
+ 825   {
+ 826     var state/eax: boolean <- state self, x, y
+ 827     compare state, 0/dead
+ 828     break-if-=
+ 829     color <- copy 0xf/alive
+ 830   }
+ 831   return color
+ 832 }
+ 833 
+ 834 fn flush  _self: (addr environment) {
+ 835   var self/esi: (addr environment) <- copy _self
+ 836   var data-ah/eax: (addr handle array handle array cell) <- get self, data
+ 837   var _data/eax: (addr array handle array cell) <- lookup *data-ah
+ 838   var data/esi: (addr array handle array cell) <- copy _data
+ 839   var y/ecx: int <- copy 0
+ 840   {
+ 841     compare y, 0xc0/height
+ 842     break-if->=
+ 843     var row-ah/eax: (addr handle array cell) <- index data, y
+ 844     var _row/eax: (addr array cell) <- lookup *row-ah
+ 845     var row/ebx: (addr array cell) <- copy _row
+ 846     var x/edx: int <- copy 0
+ 847     {
+ 848       compare x, 0x100/width
+ 849       break-if->=
+ 850       var cell-a/eax: (addr cell) <- index row, x
+ 851       var curr-a/edi: (addr boolean) <- get cell-a, curr
+ 852       var next-a/esi: (addr boolean) <- get cell-a, next
+ 853       var val/eax: boolean <- copy *next-a
+ 854       copy-to *curr-a, val
+ 855       copy-to *next-a, 0/dead
+ 856       x <- increment
+ 857       loop
+ 858     }
+ 859     y <- increment
+ 860     loop
+ 861   }
+ 862 }
+ 863 
+ 864 fn render4 screen: (addr screen), _self: (addr environment) {
+ 865   var self/esi: (addr environment) <- copy _self
+ 866   var y/ecx: int <- copy 0
+ 867   {
+ 868     compare y, 0xc0/height
+ 869     break-if->=
+ 870     var x/edx: int <- copy 0
+ 871     {
+ 872       compare x, 0x100/width
+ 873       break-if->=
+ 874       var state/eax: boolean <- state self, x, y
+ 875       compare state, 0/false
+ 876       {
+ 877         break-if-=
+ 878         render4-cell screen, x, y, 0xf/alive
+ 879       }
+ 880       compare state, 0/false
+ 881       {
+ 882         break-if-!=
+ 883         render4-cell screen, x, y, 0x1a/dead
+ 884       }
+ 885       x <- increment
+ 886       loop
+ 887     }
+ 888     y <- increment
+ 889     loop
+ 890   }
+ 891 }
+ 892 
+ 893 fn render4-cell screen: (addr screen), x: int, y: int, color: int {
+ 894   var xmin/eax: int <- copy x
+ 895   xmin <- shift-left 2
+ 896   var xmax/ecx: int <- copy xmin
+ 897   xmax <- add 4
+ 898   var ymin/edx: int <- copy y
+ 899   ymin <- shift-left 2
+ 900   var ymax/ebx: int <- copy ymin
+ 901   ymax <- add 4
+ 902   draw-rect screen, xmin ymin, xmax ymax, color
+ 903 }
+ 904 
+ 905 fn step4 _self: (addr environment) {
+ 906   var self/esi: (addr environment) <- copy _self
+ 907   var y/ecx: int <- copy 0
+ 908   {
+ 909     compare y, 0xc0/height
+ 910     break-if->=
+ 911     var x/edx: int <- copy 0
+ 912     {
+ 913       compare x, 0x100/width
+ 914       break-if->=
+ 915       var n/eax: int <- num-live-neighbors self, x, y
+ 916       # if neighbors < 2, die of loneliness
+ 917       {
+ 918         compare n, 2
+ 919         break-if->=
+ 920         set self, x, y, 0/dead
+ 921       }
+ 922       # if neighbors > 3, die of overcrowding
+ 923       {
+ 924         compare n, 3
+ 925         break-if-<=
+ 926         set self, x, y, 0/dead
+ 927       }
+ 928       # if neighbors = 2, preserve state
+ 929       {
+ 930         compare n, 2
+ 931         break-if-!=
+ 932         var old-state/eax: boolean <- state self, x, y
+ 933         set self, x, y, old-state
+ 934       }
+ 935       # if neighbors = 3, cell quickens to life
+ 936       {
+ 937         compare n, 3
+ 938         break-if-!=
+ 939         set self, x, y, 1/live
+ 940       }
+ 941       x <- increment
+ 942       loop
+ 943     }
+ 944     y <- increment
+ 945     loop
+ 946   }
+ 947   flush self
+ 948 }
+ 949 
+ 950 fn num-live-neighbors _self: (addr environment), x: int, y: int -> _/eax: int {
+ 951   var self/esi: (addr environment) <- copy _self
+ 952   var result/edi: int <- copy 0
+ 953   # row above: zig
+ 954   decrement y
+ 955   decrement x
+ 956   var s/eax: boolean <- state self, x, y
+ 957   {
+ 958     compare s, 0/false
+ 959     break-if-=
+ 960     result <- increment
+ 961   }
+ 962   increment x
+ 963   s <- state self, x, y
+ 964   {
+ 965     compare s, 0/false
+ 966     break-if-=
+ 967     result <- increment
+ 968   }
+ 969   increment x
+ 970   s <- state self, x, y
+ 971   {
+ 972     compare s, 0/false
+ 973     break-if-=
+ 974     result <- increment
+ 975   }
+ 976   # curr row: zag
+ 977   increment y
+ 978   s <- state self, x, y
+ 979   {
+ 980     compare s, 0/false
+ 981     break-if-=
+ 982     result <- increment
+ 983   }
+ 984   subtract-from x, 2
+ 985   s <- state self, x, y
+ 986   {
+ 987     compare s, 0/false
+ 988     break-if-=
+ 989     result <- increment
+ 990   }
+ 991   # row below: zig
+ 992   increment y
+ 993   s <- state self, x, y
+ 994   {
+ 995     compare s, 0/false
+ 996     break-if-=
+ 997     result <- increment
+ 998   }
+ 999   increment x
+1000   s <- state self, x, y
+1001   {
+1002     compare s, 0/false
+1003     break-if-=
+1004     result <- increment
+1005   }
+1006   increment x
+1007   s <- state self, x, y
+1008   {
+1009     compare s, 0/false
+1010     break-if-=
+1011     result <- increment
+1012   }
+1013   return result
+1014 }
+1015 
+1016 fn linger _self: (addr environment) {
+1017   var self/esi: (addr environment) <- copy _self
+1018   var i/ecx: int <- copy 0
+1019   {
+1020     compare i, 0x10000000  # Kartik's Linux with -enable-kvm
+1021 #?     compare i, 0x8000000  # Kartik's Mac with -accel tcg
+1022     break-if->=
+1023     i <- increment
+1024     loop
+1025   }
+1026 }
+
+ + + diff --git a/html/life.mu.html b/html/life.mu.html index 3de0b36c..c2bf5faf 100644 --- a/html/life.mu.html +++ b/html/life.mu.html @@ -280,12 +280,12 @@ if ('onhashchange' in window) { 221 var grid1-storage: (handle array boolean) 222 var grid1-ah/eax: (addr handle array boolean) <- address grid1-storage 223 populate grid1-ah, 0xc000 # width * height -224 var _grid1/eax: (addr array boolean) <- lookup *grid1-ah +224 var _grid1/eax: (addr array boolean) <- lookup *grid1-ah 225 var grid1/esi: (addr array boolean) <- copy _grid1 226 var grid2-storage: (handle array boolean) 227 var grid2-ah/eax: (addr handle array boolean) <- address grid2-storage 228 populate grid2-ah, 0xc000 # width * height -229 var _grid2/eax: (addr array boolean) <- lookup *grid2-ah +229 var _grid2/eax: (addr array boolean) <- lookup *grid2-ah 230 var grid2/edi: (addr array boolean) <- copy _grid2 231 # initialize grid1 232 set-state grid1, 0x80, 0x5f, 1/live diff --git a/html/linux/304screen.subx.html b/html/linux/304screen.subx.html index 3ccb5d87..5f362f14 100644 --- a/html/linux/304screen.subx.html +++ b/html/linux/304screen.subx.html @@ -115,7 +115,7 @@ if ('onhashchange' in window) { 56 e8/call syscall_ioctl/disp32 57 # some bitworking to extract 2 16-bit shorts 58 8b/-> *esi 0/r32/eax - 59 81 4/subop/and %eax 0xffff/imm32 + 59 25/and-eax-with 0xffff/imm32 60 8b/-> *esi 1/r32/ecx 61 c1/shift 5/subop/logical-right %ecx 0x10/imm8 62 $real-screen-size:end: diff --git a/html/linux/306files.subx.html b/html/linux/306files.subx.html index 4c930570..bc0d3099 100644 --- a/html/linux/306files.subx.html +++ b/html/linux/306files.subx.html @@ -57,173 +57,171 @@ if ('onhashchange' in window) {
   1 # Methods for constructing buffered-file objects.
   2 #
-  3 # TODO: There are hard-coded parameters here for buffer sizes. When they
-  4 # overflow, tracking down what's going on can get hairy.
-  5 #
-  6 # HACK: buffered-file stores naked addrs. This is safe because buffered-file
-  7 # objects are opaque. But still sub-optimal; they'll be harder to reclaim when
-  8 # we get around to that.
-  9 
- 10 == code
- 11 
- 12 open:  # filename: (addr array byte), write?: boolean, out: (addr handle buffered-file)
- 13     # . prologue
- 14     55/push-ebp
- 15     89/<- %ebp 4/r32/esp
- 16     # . save registers
- 17     50/push-eax
- 18     51/push-ecx
- 19     # var new-fd/ecx: fd
- 20     (open-fd *(ebp+8) *(ebp+0xc))  # => eax
- 21     89/<- %ecx 0/r32/eax
- 22     # if fd < 0 return
- 23     3d/compare-eax-with 0/imm32
- 24     7c/jump-if-< $open:end/disp8
- 25     # allocate a buffered-file
- 26     (allocate Heap 0x1010 *(ebp+0x10))  # file-buffer-size + 16 for other fields
- 27     # var out-addr/eax: (addr buffered-file)
- 28     8b/-> *(ebp+0x10) 0/r32/eax
- 29     (lookup *eax *(eax+4))  # => eax
- 30     # out-addr->size = 4KB
- 31     c7 0/subop/copy *(eax+0xc) 0x1000/imm32/file-buffer-size  # Stream-size + 4 for fd
- 32     # out-addr->fd = fd
- 33     89/<- *eax 1/r32/ecx
- 34 $open:end:
- 35     # . restore registers
- 36     59/pop-to-ecx
- 37     58/pop-to-eax
- 38     # . epilogue
- 39     89/<- %esp 5/r32/ebp
- 40     5d/pop-to-ebp
- 41     c3/return
- 42 
- 43 open-fd:  # filename: (addr array byte), write?: boolean -> result/eax: fd
- 44     # . prologue
- 45     55/push-ebp
- 46     89/<- %ebp 4/r32/esp
- 47     # . save registers
- 48     51/push-ecx
- 49     52/push-edx
- 50     53/push-ebx
- 51     56/push-esi
- 52     # ecx = filename
- 53     8b/-> *(ebp+8) 1/r32/ecx
- 54     # var size/edx: int = filename->length + 1 for the trailing null character
- 55     8b/-> *ecx 2/r32/edx
- 56     42/increment-edx
- 57     # var s/esi: (stream size)
- 58     29/subtract-from %esp 2/r32/edx
- 59     52/push-edx  # size
- 60     68/push 0/imm32/read
- 61     68/push 0/imm32/write
- 62     89/<- %esi 4/r32/esp
- 63     # copy filename and a final null character
- 64     (clear-stream %esi)
- 65     (write %esi %ecx)
- 66     # spill edx
- 67     52/push-edx
- 68     # var fd/eax: fd = open(filename)
- 69     8d/copy-address *(esi+0xc) 3/r32/ebx
- 70     8b/-> *(ebp+0xc) 1/r32/ecx/flags
- 71     ba/copy-to-edx 0x180/imm32/permissions
- 72     e8/call syscall_open/disp32
- 73     # restore edx
- 74     5a/pop-to-edx
- 75 $open-fd:end:
- 76     # . reclaim locals
- 77     01/add-to %esp 2/r32/edx
- 78     81 0/subop/add %esp 0xc/imm32
- 79     # . restore registers
- 80     5e/pop-to-esi
- 81     5b/pop-to-ebx
- 82     5a/pop-to-edx
- 83     59/pop-to-ecx
- 84     # . epilogue
- 85     89/<- %esp 5/r32/ebp
- 86     5d/pop-to-ebp
- 87     c3/return
- 88 
- 89 populate-buffered-file-containing:  # contents: (addr array byte), out: (addr handle buffered-file)
- 90     # . prologue
- 91     55/push-ebp
- 92     89/<- %ebp 4/r32/esp
- 93     # . save registers
- 94     50/push-eax
- 95     51/push-ecx
- 96     56/push-esi
- 97     57/push-edi
- 98     # esi = contents
- 99     8b/-> *(ebp+8) 6/r32/esi
-100     # var n/ecx: int = len(contents)
-101     8b/-> *esi 1/r32/ecx
-102     # var stream/edi: (handle stream byte)
-103     68/push 0/imm32
-104     68/push 0/imm32
-105     89/<- %edi 4/r32/esp
-106     # allocate stream
-107     (new-stream Heap %ecx 1 %edi)
-108     # var stream-addr/edi: (addr stream byte) = lookup(stream)
-109     (lookup *edi *(edi+4))  # => eax
-110     89/<- %edi 0/r32/eax
-111     # write contents to stream
-112     (write %edi %esi)
-113     # allocate buffered-file
-114     (allocate Heap 0x110 *(ebp+0xc))
-115     # var out-addr/eax: (addr buffered-file)
-116     8b/-> *(ebp+0xc) 0/r32/eax
-117     (lookup *eax *(eax+4))  # => eax
-118     # out-addr->size = 256 bytes
-119     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
-120     # out-addr->fd = stream
-121     89/<- *eax 7/r32/edi
-122 $populate-buffered-file-containing:end:
-123     # . reclaim locals
-124     81 0/subop/add %esp 8/imm32
-125     # . restore registers
-126     5f/pop-to-edi
-127     5e/pop-to-esi
-128     59/pop-to-ecx
-129     58/pop-to-eax
-130     # . epilogue
-131     89/<- %esp 5/r32/ebp
-132     5d/pop-to-ebp
-133     c3/return
-134 
-135 new-buffered-file:  # out: (addr handle buffered-file)
-136     # . prologue
-137     55/push-ebp
-138     89/<- %ebp 4/r32/esp
-139     # . save registers
-140     50/push-eax
-141     51/push-ecx
-142     # var stream/ecx: (handle stream byte)
-143     68/push 0/imm32
-144     68/push 0/imm32
-145     89/<- %ecx 4/r32/esp
-146     # allocate stream
-147     (new-stream Heap 0x100 1 %ecx)
-148     # var stream-addr/ecx: (addr stream byte) = lookup(stream)
-149     (lookup *ecx *(ecx+4))  # => eax
-150     89/<- %ecx 0/r32/eax
-151     # allocate buffered-file
-152     (allocate Heap 0x110 *(ebp+8))
-153     # var out-addr/eax: (addr buffered-file)
-154     8b/-> *(ebp+8) 0/r32/eax
-155     (lookup *eax *(eax+4))  # => eax
-156     # out-addr->size = 256 bytes
-157     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
-158     # out-addr->fd = stream
-159     89/<- *eax 1/r32/ecx
-160 $new-buffered-file:end:
-161     # . reclaim locals
-162     81 0/subop/add %esp 8/imm32
-163     # . restore registers
-164     59/pop-to-ecx
-165     58/pop-to-eax
-166     # . epilogue
-167     89/<- %esp 5/r32/ebp
-168     5d/pop-to-ebp
-169     c3/return
+  3 # HACK: buffered-file stores naked addrs. This is safe because buffered-file
+  4 # objects are opaque. But still sub-optimal; they'll be harder to reclaim when
+  5 # we get around to that.
+  6 
+  7 == code
+  8 
+  9 open:  # filename: (addr array byte), write?: boolean, out: (addr handle buffered-file)
+ 10     # . prologue
+ 11     55/push-ebp
+ 12     89/<- %ebp 4/r32/esp
+ 13     # . save registers
+ 14     50/push-eax
+ 15     51/push-ecx
+ 16     # var new-fd/ecx: fd
+ 17     (open-fd *(ebp+8) *(ebp+0xc))  # => eax
+ 18     89/<- %ecx 0/r32/eax
+ 19     # if fd < 0 return
+ 20     3d/compare-eax-with 0/imm32
+ 21     7c/jump-if-< $open:end/disp8
+ 22     # allocate a buffered-file
+ 23     (allocate Heap 0x1010 *(ebp+0x10))  # file-buffer-size + 16 for other fields
+ 24     # var out-addr/eax: (addr buffered-file)
+ 25     8b/-> *(ebp+0x10) 0/r32/eax
+ 26     (lookup *eax *(eax+4))  # => eax
+ 27     # out-addr->size = 4KB
+ 28     c7 0/subop/copy *(eax+0xc) 0x1000/imm32/file-buffer-size  # Stream-size + 4 for fd
+ 29     # out-addr->fd = fd
+ 30     89/<- *eax 1/r32/ecx
+ 31 $open:end:
+ 32     # . restore registers
+ 33     59/pop-to-ecx
+ 34     58/pop-to-eax
+ 35     # . epilogue
+ 36     89/<- %esp 5/r32/ebp
+ 37     5d/pop-to-ebp
+ 38     c3/return
+ 39 
+ 40 open-fd:  # filename: (addr array byte), write?: boolean -> result/eax: fd
+ 41     # . prologue
+ 42     55/push-ebp
+ 43     89/<- %ebp 4/r32/esp
+ 44     # . save registers
+ 45     51/push-ecx
+ 46     52/push-edx
+ 47     53/push-ebx
+ 48     56/push-esi
+ 49     # ecx = filename
+ 50     8b/-> *(ebp+8) 1/r32/ecx
+ 51     # var size/edx: int = filename->length + 1 for the trailing null character
+ 52     8b/-> *ecx 2/r32/edx
+ 53     42/increment-edx
+ 54     # var s/esi: (stream size)
+ 55     29/subtract-from %esp 2/r32/edx
+ 56     52/push-edx  # size
+ 57     68/push 0/imm32/read
+ 58     68/push 0/imm32/write
+ 59     89/<- %esi 4/r32/esp
+ 60     # copy filename and a final null character
+ 61     (clear-stream %esi)
+ 62     (write %esi %ecx)
+ 63     # spill edx
+ 64     52/push-edx
+ 65     # var fd/eax: fd = open(filename)
+ 66     8d/copy-address *(esi+0xc) 3/r32/ebx
+ 67     8b/-> *(ebp+0xc) 1/r32/ecx/flags
+ 68     ba/copy-to-edx 0x180/imm32/permissions
+ 69     e8/call syscall_open/disp32
+ 70     # restore edx
+ 71     5a/pop-to-edx
+ 72 $open-fd:end:
+ 73     # . reclaim locals
+ 74     01/add-to %esp 2/r32/edx
+ 75     81 0/subop/add %esp 0xc/imm32
+ 76     # . restore registers
+ 77     5e/pop-to-esi
+ 78     5b/pop-to-ebx
+ 79     5a/pop-to-edx
+ 80     59/pop-to-ecx
+ 81     # . epilogue
+ 82     89/<- %esp 5/r32/ebp
+ 83     5d/pop-to-ebp
+ 84     c3/return
+ 85 
+ 86 populate-buffered-file-containing:  # contents: (addr array byte), out: (addr handle buffered-file)
+ 87     # . prologue
+ 88     55/push-ebp
+ 89     89/<- %ebp 4/r32/esp
+ 90     # . save registers
+ 91     50/push-eax
+ 92     51/push-ecx
+ 93     56/push-esi
+ 94     57/push-edi
+ 95     # esi = contents
+ 96     8b/-> *(ebp+8) 6/r32/esi
+ 97     # var n/ecx: int = len(contents)
+ 98     8b/-> *esi 1/r32/ecx
+ 99     # var stream/edi: (handle stream byte)
+100     68/push 0/imm32
+101     68/push 0/imm32
+102     89/<- %edi 4/r32/esp
+103     # allocate stream
+104     (new-stream Heap %ecx 1 %edi)
+105     # var stream-addr/edi: (addr stream byte) = lookup(stream)
+106     (lookup *edi *(edi+4))  # => eax
+107     89/<- %edi 0/r32/eax
+108     # write contents to stream
+109     (write %edi %esi)
+110     # allocate buffered-file
+111     (allocate Heap 0x110 *(ebp+0xc))
+112     # var out-addr/eax: (addr buffered-file)
+113     8b/-> *(ebp+0xc) 0/r32/eax
+114     (lookup *eax *(eax+4))  # => eax
+115     # out-addr->size = 256 bytes
+116     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
+117     # out-addr->fd = stream
+118     89/<- *eax 7/r32/edi
+119 $populate-buffered-file-containing:end:
+120     # . reclaim locals
+121     81 0/subop/add %esp 8/imm32
+122     # . restore registers
+123     5f/pop-to-edi
+124     5e/pop-to-esi
+125     59/pop-to-ecx
+126     58/pop-to-eax
+127     # . epilogue
+128     89/<- %esp 5/r32/ebp
+129     5d/pop-to-ebp
+130     c3/return
+131 
+132 # TODO: hard-coded parameter
+133 new-buffered-file:  # out: (addr handle buffered-file)
+134     # . prologue
+135     55/push-ebp
+136     89/<- %ebp 4/r32/esp
+137     # . save registers
+138     50/push-eax
+139     51/push-ecx
+140     # var stream/ecx: (handle stream byte)
+141     68/push 0/imm32
+142     68/push 0/imm32
+143     89/<- %ecx 4/r32/esp
+144     # allocate stream
+145     (new-stream Heap 0x100 1 %ecx)
+146     # var stream-addr/ecx: (addr stream byte) = lookup(stream)
+147     (lookup *ecx *(ecx+4))  # => eax
+148     89/<- %ecx 0/r32/eax
+149     # allocate buffered-file
+150     (allocate Heap 0x110 *(ebp+8))
+151     # var out-addr/eax: (addr buffered-file)
+152     8b/-> *(ebp+8) 0/r32/eax
+153     (lookup *eax *(eax+4))  # => eax
+154     # out-addr->size = 256 bytes
+155     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
+156     # out-addr->fd = stream
+157     89/<- *eax 1/r32/ecx
+158 $new-buffered-file:end:
+159     # . reclaim locals
+160     81 0/subop/add %esp 8/imm32
+161     # . restore registers
+162     59/pop-to-ecx
+163     58/pop-to-eax
+164     # . epilogue
+165     89/<- %esp 5/r32/ebp
+166     5d/pop-to-ebp
+167     c3/return
 
diff --git a/html/linux/311decimal-int.subx.html b/html/linux/311decimal-int.subx.html index fbb70646..ee7b5055 100644 --- a/html/linux/311decimal-int.subx.html +++ b/html/linux/311decimal-int.subx.html @@ -126,7 +126,7 @@ if ('onhashchange' in window) { 66 4a/decrement-edx 67 # if it's a newline, break 68 8a/byte-> *edx 0/r32/eax - 69 81 4/subop/and %eax 0xff/imm32 + 69 25/and-eax-with 0xff/imm32 70 3d/compare-eax-and 0xa/imm32/newline 71 74/jump-if-= break/disp8 72 # not a newline, so restore it diff --git a/html/linux/312copy.subx.html b/html/linux/312copy.subx.html index 7c7ee405..62213681 100644 --- a/html/linux/312copy.subx.html +++ b/html/linux/312copy.subx.html @@ -104,7 +104,7 @@ if ('onhashchange' in window) { 47 89/<- %ecx 0/r32/eax 48 # at this point dest is identical to src, including file descriptor. Now 49 # create an independent copy of the file descriptor -50 (open-fd *(ebp+0x10) 0) # false => eax +50 (open-fd *(ebp+0x10) 0) # false => eax 51 89/<- *edi 0/r32/eax 52 # replicate offset in the new fd 53 89/<- %ebx 0/r32/eax # fd diff --git a/html/linux/313index-bounds-check.subx.html b/html/linux/313index-bounds-check.subx.html index 9eb299b9..07c1e75c 100644 --- a/html/linux/313index-bounds-check.subx.html +++ b/html/linux/313index-bounds-check.subx.html @@ -56,92 +56,108 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/linux/313index-bounds-check.subx
- 1 # Helper to check an array's bounds, and to abort if they're violated.
- 2 # Really only intended to be called from code generated by mu.subx.
- 3 
- 4 == code
- 5 
- 6 __check-mu-array-bounds:  # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
- 7     # . prologue
- 8     55/push-ebp
- 9     89/<- %ebp 4/r32/esp
-10     # . save registers
-11     50/push-eax
-12     51/push-ecx
-13     52/push-edx
-14     # . not bothering saving ebx; it's only clobbered if we're going to abort
-15     # ecx = arr-size
-16     8b/-> *(ebp+0x10) 1/r32/ecx
-17     # var overflow/edx: int = 0
-18     ba/copy-to-edx 0/imm32
-19     # var offset/eax: int = index * elem-size
-20     8b/-> *(ebp+8) 0/r32/eax
-21     f7 4/subop/multiply-eax-with *(ebp+0xc)
-22     # check for overflow
-23     81 7/subop/compare %edx 0/imm32
-24     0f 85/jump-if-!= __check-mu-array-bounds:overflow/disp32
-25     # check bounds
-26     39/compare %eax 1/r32/ecx
-27     0f 82/jump-if-unsigned< $__check-mu-array-bounds:end/disp32  # negative index should always abort
-28     # abort if necessary
-29     (write-buffered Stderr "fn ")
-30     (write-buffered Stderr *(ebp+0x14))
-31     (write-buffered Stderr ": offset ")
-32     (write-int32-hex-buffered Stderr %eax)
-33     (write-buffered Stderr " is too large for array '")
-34     (write-buffered Stderr *(ebp+0x18))
-35     (write-buffered Stderr "'\n")
-36     (flush Stderr)
-37     # exit(1)
-38     bb/copy-to-ebx 1/imm32
-39     e8/call syscall_exit/disp32
-40     # never gets here
-41 $__check-mu-array-bounds:end:
-42     # . restore registers
-43     5a/pop-to-edx
-44     59/pop-to-ecx
-45     58/pop-to-eax
-46     # . epilogue
-47     89/<- %esp 5/r32/ebp
-48     5d/pop-to-ebp
-49     c3/return
-50 
-51 __check-mu-array-bounds:overflow:
-52     # "fn " function-name ": offset to array '" array-name "' overflowed 32 bits\n"
-53     (write-buffered Stderr "fn ")
-54     (write-buffered Stderr *(ebp+0x14))
-55     (write-buffered Stderr ": offset to array '")
-56     (write-buffered Stderr *(ebp+0x18))
-57     (write-buffered Stderr "' overflowed 32 bits\n")
-58     (flush Stderr)
-59     # exit(1)
-60     bb/copy-to-ebx 1/imm32
-61     e8/call syscall_exit/disp32
-62     # never gets here
-63 
-64 # potential alternative
-65 
-66 #? __bounds-check:  # msg: (addr array byte)
-67 #?   (write-buffered Stderr "abort: array bounds exceeded in fn ")
-68 #?   8b/-> *(esp+4) 0/r32/eax  # we're going to abort, so just clobber away
-69 #?   (write-buffered Stderr %eax)
-70 #?   (write-buffered Stderr Newline)
-71 #?   # exit(1)
-72 #?   bb/copy-to-ebx 1/imm32
-73 #?   e8/call syscall_exit/disp32
-74 
-75 # to be called as follows:
-76 #   var/reg <- index arr/rega: (addr array T), idx/regi: int
-77 #     | if size-of(T) is 1, 2, 4 or 8
-78 #         => # temporarily save array size to reg to check bounds
-79 #            "8b/-> *" rega " " reg "/r32"
-80 #            "c1/shift 5/subop/right %" reg " " log2(size-of(T)) "/imm32"
-81 #            "3b/compare " reg "/r32 *" rega
-82 #            "68/push \"" function "\"/imm32"  # pass function name to error message
-83 #            "0f 8d/jump-if->= __bounds_check/disp32"
-84 #            "81 0/subop/add %esp 4/imm32"  # drop function name
-85 #            # actually save the index addr in reg
-86 #            "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"
+  1 # Helper to check an array's bounds, and to abort if they're violated.
+  2 # Really only intended to be called from code generated by mu.subx.
+  3 
+  4 == code
+  5 
+  6 __check-mu-array-bounds:  # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
+  7     # . prologue
+  8     55/push-ebp
+  9     89/<- %ebp 4/r32/esp
+ 10     # . save registers
+ 11     50/push-eax
+ 12     51/push-ecx
+ 13     52/push-edx
+ 14     # . not bothering saving ebx; it's only clobbered if we're going to abort
+ 15     # ecx = arr-size
+ 16     8b/-> *(ebp+0x10) 1/r32/ecx
+ 17     # var overflow/edx: int = 0
+ 18     ba/copy-to-edx 0/imm32
+ 19     # var offset/eax: int = index * elem-size
+ 20     8b/-> *(ebp+8) 0/r32/eax
+ 21     f7 4/subop/multiply-eax-with *(ebp+0xc)
+ 22     # check for overflow
+ 23     81 7/subop/compare %edx 0/imm32
+ 24     0f 85/jump-if-!= __check-mu-array-bounds:overflow/disp32
+ 25     # check bounds
+ 26     39/compare %eax 1/r32/ecx
+ 27     0f 82/jump-if-unsigned< $__check-mu-array-bounds:end/disp32  # negative index should always abort
+ 28     # abort if necessary
+ 29     (write-buffered Stderr "fn ")
+ 30     (write-buffered Stderr *(ebp+0x14))
+ 31     (write-buffered Stderr ": offset ")
+ 32     (write-int32-hex-buffered Stderr %eax)
+ 33     (write-buffered Stderr " is too large for array '")
+ 34     (write-buffered Stderr *(ebp+0x18))
+ 35     (write-buffered Stderr "'\n")
+ 36     (flush Stderr)
+ 37     # exit(1)
+ 38     bb/copy-to-ebx 1/imm32
+ 39     e8/call syscall_exit/disp32
+ 40     # never gets here
+ 41 $__check-mu-array-bounds:end:
+ 42     # . restore registers
+ 43     5a/pop-to-edx
+ 44     59/pop-to-ecx
+ 45     58/pop-to-eax
+ 46     # . epilogue
+ 47     89/<- %esp 5/r32/ebp
+ 48     5d/pop-to-ebp
+ 49     c3/return
+ 50 
+ 51 __check-mu-array-bounds:overflow:
+ 52     # "fn " function-name ": offset to array '" array-name "' overflowed 32 bits\n"
+ 53     (write-buffered Stderr "fn ")
+ 54     (write-buffered Stderr *(ebp+0x14))
+ 55     (write-buffered Stderr ": offset to array '")
+ 56     (write-buffered Stderr *(ebp+0x18))
+ 57     (write-buffered Stderr "' overflowed 32 bits\n")
+ 58     (flush Stderr)
+ 59     # exit(1)
+ 60     bb/copy-to-ebx 1/imm32
+ 61     e8/call syscall_exit/disp32
+ 62     # never gets here
+ 63 
+ 64 # potential alternative
+ 65 
+ 66 #? __bounds-check:  # msg: (addr array byte)
+ 67 #?   (write-buffered Stderr "abort: array bounds exceeded in fn ")
+ 68 #?   8b/-> *(esp+4) 0/r32/eax  # we're going to abort, so just clobber away
+ 69 #?   (write-buffered Stderr %eax)
+ 70 #?   (write-buffered Stderr Newline)
+ 71 #?   # exit(1)
+ 72 #?   bb/copy-to-ebx 1/imm32
+ 73 #?   e8/call syscall_exit/disp32
+ 74 
+ 75 # to be called as follows:
+ 76 #   var/reg <- index arr/rega: (addr array T), idx/regi: int
+ 77 #     | if size-of(T) is 1, 2, 4 or 8
+ 78 #         => # temporarily save array size to reg to check bounds
+ 79 #            "8b/-> *" rega " " reg "/r32"
+ 80 #            "c1/shift 5/subop/right %" reg " " log2(size-of(T)) "/imm32"
+ 81 #            "3b/compare " reg "/r32 *" rega
+ 82 #            "68/push \"" function "\"/imm32"  # pass function name to error message
+ 83 #            "0f 8d/jump-if->= __bounds_check/disp32"
+ 84 #            "81 0/subop/add %esp 4/imm32"  # drop function name
+ 85 #            # actually save the index addr in reg
+ 86 #            "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"
+ 87 
+ 88 __mu-abort-null-index-base-address:
+ 89     (write-buffered Stderr "null address in 'index'\n")
+ 90     (flush Stderr)
+ 91     # exit(1)
+ 92     bb/copy-to-ebx 1/imm32
+ 93     e8/call syscall_exit/disp32
+ 94     # never gets here
+ 95 
+ 96 __mu-abort-null-get-base-address:
+ 97     (write-buffered Stderr "null address in 'get'\n")
+ 98     (flush Stderr)
+ 99     # exit(1)
+100     bb/copy-to-ebx 1/imm32
+101     e8/call syscall_exit/disp32
+102     # never gets here
 
diff --git a/html/linux/400.mu.html b/html/linux/400.mu.html index f8250d21..9b1270b4 100644 --- a/html/linux/400.mu.html +++ b/html/linux/400.mu.html @@ -231,9 +231,9 @@ if ('onhashchange' in window) { 176 sig enable-keyboard-type-mode 177 sig read-key-from-real-keyboard -> _/eax: grapheme 178 sig read-line-from-real-keyboard out: (addr stream byte) -179 sig open filename: (addr array byte), write?: boolean, out: (addr handle buffered-file) -180 sig populate-buffered-file-containing contents: (addr array byte), out: (addr handle buffered-file) -181 sig new-buffered-file out: (addr handle buffered-file) +179 sig open filename: (addr array byte), write?: boolean, out: (addr handle buffered-file) +180 sig populate-buffered-file-containing contents: (addr array byte), out: (addr handle buffered-file) +181 sig new-buffered-file out: (addr handle buffered-file) 182 #sig size in: (addr array _) -> _/eax: int 183 184 sig stream-empty? s: (addr stream _) -> _/eax: boolean diff --git a/html/linux/404stream.mu.html b/html/linux/404stream.mu.html index 77992e5f..a561ca5c 100644 --- a/html/linux/404stream.mu.html +++ b/html/linux/404stream.mu.html @@ -106,7 +106,7 @@ if ('onhashchange' in window) { 48 fn test-fake-input-buffered-file { 49 var foo: (handle buffered-file) 50 var foo-ah/eax: (addr handle buffered-file) <- address foo -51 populate-buffered-file-containing "abc", foo-ah +51 populate-buffered-file-containing "abc", foo-ah 52 var foo-addr/eax: (addr buffered-file) <- lookup foo 53 var s: (stream byte 0x100) 54 var result/ecx: (addr stream byte) <- address s @@ -117,7 +117,7 @@ if ('onhashchange' in window) { 59 fn test-fake-output-buffered-file { 60 var foo: (handle buffered-file) 61 var foo-ah/eax: (addr handle buffered-file) <- address foo -62 new-buffered-file foo-ah +62 new-buffered-file foo-ah 63 var foo-addr/eax: (addr buffered-file) <- lookup foo 64 write-buffered foo-addr, "abc" 65 var s: (stream byte 0x100) diff --git a/html/linux/bootstrap/017jump_disp8.cc.html b/html/linux/bootstrap/017jump_disp8.cc.html index 0c36125f..97457a1f 100644 --- a/html/linux/bootstrap/017jump_disp8.cc.html +++ b/html/linux/bootstrap/017jump_disp8.cc.html @@ -463,6 +463,30 @@ if ('onhashchange' in window) { 405 ); 406 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 407 } +408 +409 //:: jump if overflow +410 +411 :(before "End Initialize Op Names") +412 put_new(Name, "70", "jump disp8 bytes away if OF is set (jcc/jo)"); +413 put_new(Name, "71", "jump disp8 bytes away if OF is unset (jcc/jno)"); +414 +415 :(before "End Single-Byte Opcodes") +416 case 0x70: { // jump disp8 if OF is set +417 const int8_t offset = static_cast<int>(next()); +418 if (OF) { +419 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); +420 EIP += offset; +421 } +422 break; +423 } +424 case 0x71: { // jump disp8 if OF is unset +425 const int8_t offset = static_cast<int>(next()); +426 if (!OF) { +427 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); +428 EIP += offset; +429 } +430 break; +431 } diff --git a/html/linux/bootstrap/018jump_disp32.cc.html b/html/linux/bootstrap/018jump_disp32.cc.html index 2a4e0a3a..2ff5010c 100644 --- a/html/linux/bootstrap/018jump_disp32.cc.html +++ b/html/linux/bootstrap/018jump_disp32.cc.html @@ -463,6 +463,30 @@ if ('onhashchange' in window) { 405 ); 406 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 407 } +408 +409 //:: jump if overflow +410 +411 :(before "End Initialize Op Names") +412 put_new(Name_0f, "80", "jump disp32 bytes away if OF is set (jcc/jo)"); +413 put_new(Name_0f, "81", "jump disp32 bytes away if OF is unset (jcc/jno)"); +414 +415 :(before "End Two-Byte Opcodes Starting With 0f") +416 case 0x80: { // jump disp8 if OF is set +417 const int32_t offset = next32(); +418 if (OF) { +419 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); +420 EIP += offset; +421 } +422 break; +423 } +424 case 0x81: { // jump disp8 if OF is unset +425 const int32_t offset = next32(); +426 if (!OF) { +427 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); +428 EIP += offset; +429 } +430 break; +431 } diff --git a/html/linux/braces.subx.html b/html/linux/braces.subx.html index 77774273..982a1604 100644 --- a/html/linux/braces.subx.html +++ b/html/linux/braces.subx.html @@ -70,10 +70,10 @@ if ('onhashchange' in window) { 11 # 74/jump-if-= loop/disp8 12 # } 13 # $ cat x.subx |braces - 14 # _loop1: - 15 # 7c/jump-if-< _break1/disp8 - 16 # 74/jump-if-= _loop1/disp8 - 17 # _break1: + 14 # @loop1: + 15 # 7c/jump-if-< @break1/disp8 + 16 # 74/jump-if-= @loop1/disp8 + 17 # @break1: 18 # 19 # Example 2: 20 # $ cat x.subx @@ -84,12 +84,12 @@ if ('onhashchange' in window) { 25 # 74/jump-if-= loop/disp8 26 # } 27 # $ cat x.subx |braces - 28 # _loop1: - 29 # 7c/jump-if-< _break1/disp8 - 30 # _break1: - 31 # _loop2: - 32 # 74/jump-if-= _loop2/disp8 - 33 # _break2: + 28 # @loop1: + 29 # 7c/jump-if-< @break1/disp8 + 30 # @break1: + 31 # @loop2: + 32 # 74/jump-if-= @loop2/disp8 + 33 # @break2: 34 # 35 # Example 3: 36 # $ cat x.subx @@ -100,12 +100,12 @@ if ('onhashchange' in window) { 41 # 7c/jump-if-< loop/disp8 42 # } 43 # $ cat x.subx |braces - 44 # _loop1: - 45 # _loop2: - 46 # 74/jump-if-= _loop2/disp8 - 47 # _break2: - 48 # 7c/jump-if-< _loop1/disp8 - 49 # _break1: + 44 # @loop1: + 45 # @loop2: + 46 # 74/jump-if-= @loop2/disp8 + 47 # @break2: + 48 # 7c/jump-if-< @loop1/disp8 + 49 # @break1: 50 51 == code 52 @@ -144,13 +144,13 @@ if ('onhashchange' in window) { 85 # if (line->write == 0) break # end of file 86 # skip-chars-matching-whitespace(line) 87 # if line->data[line->read] == '{' - 88 # print(out, "_loop" next-label-id ":\n") + 88 # print(out, "@loop" next-label-id ":\n") 89 # push(label-stack, next-label-id) 90 # ++next-label-id 91 # continue 92 # if line->data[line->read] == '}' 93 # var top = pop(label-stack) - 94 # print(out, "_break" top ":\n") + 94 # print(out, "@break" top ":\n") 95 # continue 96 # while true 97 # var word-slice: (addr slice) = next-word-or-string(line) @@ -160,11 +160,11 @@ if ('onhashchange' in window) { 101 # continue 102 # if slice-starts-with?(word-slice, "break/") 103 # var top = top(label-stack) -104 # print(out, "_break" top) +104 # print(out, "@break" top) 105 # word-slice->start += len("break") 106 # else if slice-starts-with?(word-slice, "loop/") 107 # var top = top(label-stack) -108 # print(out, "_loop" top) +108 # print(out, "@loop" top) 109 # word-slice->start += len("loop") 110 # print(out, word-slice " ") 111 # print(out, "\n") @@ -211,13 +211,13 @@ if ('onhashchange' in window) { 152 # . eax = line->data[line->read] 153 8b/-> *(ecx+4) 0/r32/eax 154 8a/copy-byte *(ecx+eax+0xc) 0/r32/AL -155 81 4/subop/and %eax 0xff/imm32 +155 25/and-eax-with 0xff/imm32 156 # . if (eax != '{') continue 157 3d/compare-eax-and 0x7b/imm32/open-curly 158 0f 85/jump-if-!= $subx-braces:check-for-curly-closed/disp32 159 $subx-braces:emit-curly-open: -160 # print(out, "_loop" next-label-id ":") -161 (write-buffered *(ebp+0xc) "_loop") +160 # print(out, "@loop" next-label-id ":") +161 (write-buffered *(ebp+0xc) "@loop") 162 (write-int32-hex-buffered *(ebp+0xc) %ebx) 163 (write-buffered *(ebp+0xc) ":") 164 # push(label-stack, next-label-id) @@ -233,8 +233,8 @@ if ('onhashchange' in window) { 174 $subx-braces:emit-curly-closed: 175 # eax = pop(label-stack) 176 (pop %edx) -177 # print(out, "_break" eax ":") -178 (write-buffered *(ebp+0xc) "_break") +177 # print(out, "@break" eax ":") +178 (write-buffered *(ebp+0xc) "@break") 179 (write-int32-hex-buffered *(ebp+0xc) %eax) 180 (write-buffered *(ebp+0xc) ":") 181 # continue @@ -251,7 +251,7 @@ if ('onhashchange' in window) { 192 # . eax = *word-slice->start 193 8b/-> *edi 0/r32/eax 194 8a/copy-byte *eax 0/r32/AL -195 81 4/subop/and %eax 0xff/imm32 +195 25/and-eax-with 0xff/imm32 196 # . if (eax == '#') continue 197 3d/compare-eax-and 0x23/imm32/hash 198 74/jump-if-= $subx-braces:word-loop/disp8 @@ -264,8 +264,8 @@ if ('onhashchange' in window) { 205 74/jump-if-= $subx-braces:check-for-loop/disp8 206 $subx-braces:emit-break: 207 (top %edx) -208 # print(out, "_break" eax) -209 (write-buffered *(ebp+0xc) "_break") +208 # print(out, "@break" eax) +209 (write-buffered *(ebp+0xc) "@break") 210 (write-int32-hex-buffered *(ebp+0xc) %eax) 211 # word-slice->start += len("break") 212 81 0/subop/add *edi 5/imm32/strlen @@ -280,8 +280,8 @@ if ('onhashchange' in window) { 221 74/jump-if-= $subx-braces:emit-word-slice/disp8 222 $subx-braces:emit-loop: 223 (top %edx) -224 # print(out, "_loop" eax) -225 (write-buffered *(ebp+0xc) "_loop") +224 # print(out, "@loop" eax) +225 (write-buffered *(ebp+0xc) "@loop") 226 (write-int32-hex-buffered *(ebp+0xc) %eax) 227 # word-slice->start += len("loop") 228 81 0/subop/add *edi 4/imm32/strlen @@ -343,10 +343,10 @@ if ('onhashchange' in window) { 288 # } 289 # 290 # output: -291 # _loop1: -292 # ab _break1/imm32 -293 # cd _loop1/imm32 -294 # _break1: +291 # @loop1: +292 # ab @break1/imm32 +293 # cd @loop1/imm32 +294 # @break1: 295 # 296 # . prologue 297 55/push-ebp @@ -362,7 +362,7 @@ if ('onhashchange' in window) { 307 # check that the line just passed through 308 (flush _test-output-buffered-file) 309 +-- 5 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -314 (check-stream-equal _test-output-stream "_loop0x00000001:\nab _break0x00000001/imm32 \ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-1") +314 (check-stream-equal _test-output-stream "@loop0x00000001:\nab @break0x00000001/imm32 \ncd @loop0x00000001/imm32 \n@break0x00000001:\n" "F - test-subx-braces-1") 315 # . epilogue 316 89/<- %esp 5/r32/ebp 317 5d/pop-to-ebp @@ -378,12 +378,12 @@ if ('onhashchange' in window) { 327 # } 328 # 329 # output: -330 # _loop1: -331 # _loop2: -332 # ab _break2/imm32 -333 # _break2: -334 # cd _loop1/imm32 -335 # _break1: +330 # @loop1: +331 # @loop2: +332 # ab @break2/imm32 +333 # @break2: +334 # cd @loop1/imm32 +335 # @break1: 336 # 337 # . prologue 338 55/push-ebp @@ -399,7 +399,7 @@ if ('onhashchange' in window) { 348 # check that the line just passed through 349 (flush _test-output-buffered-file) 350 +-- 5 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -355 (check-stream-equal _test-output-stream "_loop0x00000001:\n_loop0x00000002:\nab _break0x00000002/imm32 \n_break0x00000002:\ncd _loop0x00000001/imm32 \n_break0x00000001:\n" "F - test-subx-braces-2") +355 (check-stream-equal _test-output-stream "@loop0x00000001:\n@loop0x00000002:\nab @break0x00000002/imm32 \n@break0x00000002:\ncd @loop0x00000001/imm32 \n@break0x00000001:\n" "F - test-subx-braces-2") 356 # . epilogue 357 89/<- %esp 5/r32/ebp 358 5d/pop-to-ebp diff --git a/html/linux/branches.mu.html b/html/linux/branches.mu.html new file mode 100644 index 00000000..39771bb1 --- /dev/null +++ b/html/linux/branches.mu.html @@ -0,0 +1,99 @@ + + + + +Mu - linux/branches.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/branches.mu +
+ 1 fn foo {
+ 2   $foo: {
+ 3     break-if-=
+ 4     break-if-= $foo
+ 5     break-if-!=
+ 6     break-if-!= $foo
+ 7     break-if-<=
+ 8     break-if-<= $foo
+ 9     break-if->=
+10     break-if->= $foo
+11     break-if-<
+12     break-if-< $foo
+13     break-if->
+14     break-if-> $foo
+15     break-if-carry
+16     break-if-carry $foo
+17     break-if-overflow
+18     break-if-overflow $foo
+19     loop-if-=
+20     loop-if-= $foo
+21     loop-if-!=
+22     loop-if-!= $foo
+23     loop-if-<=
+24     loop-if-<= $foo
+25     loop-if->=
+26     loop-if->= $foo
+27     loop-if-<
+28     loop-if-< $foo
+29     loop-if->
+30     loop-if-> $foo
+31     loop-if-carry
+32     loop-if-carry $foo
+33     loop-if-not-carry
+34     loop-if-not-carry $foo
+35     loop-if-overflow
+36     loop-if-overflow $foo
+37     loop-if-not-overflow
+38     loop-if-not-overflow $foo
+39   }
+40 }
+
+ + + diff --git a/html/linux/calls.subx.html b/html/linux/calls.subx.html index 2c586b7c..f6e181cc 100644 --- a/html/linux/calls.subx.html +++ b/html/linux/calls.subx.html @@ -450,7 +450,7 @@ if ('onhashchange' in window) { 428 # . . eax = *(curr->start+4) 429 8b/-> *ecx 0/r32/eax 430 8a/copy-byte *(eax+4) 0/r32/eax - 431 81 4/subop/and %eax 0xff/imm32 + 431 25/and-eax-with 0xff/imm32 432 # . . push args 433 50/push-eax 434 ff 6/subop/push *(ebp+8) @@ -473,7 +473,7 @@ if ('onhashchange' in window) { 451 8b/-> *ecx 0/r32/eax 452 # . var c/eax: byte = *eax 453 8b/-> *eax 0/r32/eax - 454 81 4/subop/and %eax 0xff/imm32 + 454 25/and-eax-with 0xff/imm32 455 # . if (c == '%') goto push-rm32 456 3d/compare-eax-and 0x25/imm32/percent 457 74/jump-if-= $emit-call:push-rm32/disp8 @@ -1351,7 +1351,7 @@ if ('onhashchange' in window) { 1361 68/push 0xe/imm32 1362 # . . push slice->start - _test-input-stream 1363 8b/-> *ecx 0/r32/eax -1364 81 5/subop/subtract %eax _test-input-stream/imm32 +1364 2d/subtract-from-eax _test-input-stream/imm32 1365 50/push-eax 1366 # . . call 1367 e8/call check-ints-equal/disp32 @@ -1364,7 +1364,7 @@ if ('onhashchange' in window) { 1374 68/push 0x10/imm32 1375 # . . push slice->end - _test-input-stream 1376 8b/-> *(ecx+4) 0/r32/eax -1377 81 5/subop/subtract %eax _test-input-stream/imm32 +1377 2d/subtract-from-eax _test-input-stream/imm32 1378 50/push-eax 1379 # . . call 1380 e8/call check-ints-equal/disp32 @@ -1424,7 +1424,7 @@ if ('onhashchange' in window) { 1434 68/push 0xe/imm32 1435 # . . push slice->start - _test-input-stream 1436 8b/-> *ecx 0/r32/eax -1437 81 5/subop/subtract %eax _test-input-stream/imm32 +1437 2d/subtract-from-eax _test-input-stream/imm32 1438 50/push-eax 1439 # . . call 1440 e8/call check-ints-equal/disp32 @@ -1437,7 +1437,7 @@ if ('onhashchange' in window) { 1447 68/push 0x11/imm32 1448 # . . push slice->end - _test-input-stream 1449 8b/-> *(ecx+4) 0/r32/eax -1450 81 5/subop/subtract %eax _test-input-stream/imm32 +1450 2d/subtract-from-eax _test-input-stream/imm32 1451 50/push-eax 1452 # . . call 1453 e8/call check-ints-equal/disp32 @@ -1487,7 +1487,7 @@ if ('onhashchange' in window) { 1497 68/push 0xd/imm32 1498 # . . push slice->start - _test-input-stream 1499 8b/-> *ecx 0/r32/eax -1500 81 5/subop/subtract %eax _test-input-stream/imm32 +1500 2d/subtract-from-eax _test-input-stream/imm32 1501 50/push-eax 1502 # . . call 1503 e8/call check-ints-equal/disp32 @@ -1500,7 +1500,7 @@ if ('onhashchange' in window) { 1510 68/push 0x12/imm32 1511 # . . push slice->end - _test-input-stream 1512 8b/-> *(ecx+4) 0/r32/eax -1513 81 5/subop/subtract %eax _test-input-stream/imm32 +1513 2d/subtract-from-eax _test-input-stream/imm32 1514 50/push-eax 1515 # . . call 1516 e8/call check-ints-equal/disp32 @@ -1550,7 +1550,7 @@ if ('onhashchange' in window) { 1560 68/push 0xd/imm32 1561 # . . push slice->start - _test-input-stream 1562 8b/-> *ecx 0/r32/eax -1563 81 5/subop/subtract %eax _test-input-stream/imm32 +1563 2d/subtract-from-eax _test-input-stream/imm32 1564 50/push-eax 1565 # . . call 1566 e8/call check-ints-equal/disp32 @@ -1563,7 +1563,7 @@ if ('onhashchange' in window) { 1573 68/push 0x13/imm32 1574 # . . push slice->end - _test-input-stream 1575 8b/-> *(ecx+4) 0/r32/eax -1576 81 5/subop/subtract %eax _test-input-stream/imm32 +1576 2d/subtract-from-eax _test-input-stream/imm32 1577 50/push-eax 1578 # . . call 1579 e8/call check-ints-equal/disp32 @@ -1613,7 +1613,7 @@ if ('onhashchange' in window) { 1623 68/push 0xd/imm32 1624 # . . push slice->start - _test-input-stream 1625 8b/-> *ecx 0/r32/eax -1626 81 5/subop/subtract %eax _test-input-stream/imm32 +1626 2d/subtract-from-eax _test-input-stream/imm32 1627 50/push-eax 1628 # . . call 1629 e8/call check-ints-equal/disp32 @@ -1626,7 +1626,7 @@ if ('onhashchange' in window) { 1636 68/push 0x13/imm32 1637 # . . push slice->end - _test-input-stream 1638 8b/-> *(ecx+4) 0/r32/eax -1639 81 5/subop/subtract %eax _test-input-stream/imm32 +1639 2d/subtract-from-eax _test-input-stream/imm32 1640 50/push-eax 1641 # . . call 1642 e8/call check-ints-equal/disp32 @@ -1841,7 +1841,7 @@ if ('onhashchange' in window) { 1851 68/push 0xd/imm32 1852 # . . push slice->start - _test-input-stream 1853 8b/-> *ecx 0/r32/eax -1854 81 5/subop/subtract %eax _test-input-stream/imm32 +1854 2d/subtract-from-eax _test-input-stream/imm32 1855 50/push-eax 1856 # . . call 1857 e8/call check-ints-equal/disp32 @@ -1854,7 +1854,7 @@ if ('onhashchange' in window) { 1864 68/push 0x10/imm32 1865 # . . push slice->end - _test-input-stream 1866 8b/-> *(ecx+4) 0/r32/eax -1867 81 5/subop/subtract %eax _test-input-stream/imm32 +1867 2d/subtract-from-eax _test-input-stream/imm32 1868 50/push-eax 1869 # . . call 1870 e8/call check-ints-equal/disp32 diff --git a/html/linux/labels_baremetal.subx.html b/html/linux/labels_baremetal.subx.html new file mode 100644 index 00000000..61bdaaa9 --- /dev/null +++ b/html/linux/labels_baremetal.subx.html @@ -0,0 +1,2458 @@ + + + + +Mu - linux/labels_baremetal.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/labels_baremetal.subx +
+   1 # Assign addresses (co-ordinates) to instructions (landmarks) in a program
+   2 # (landscape).
+   3 # Read a list of addresses and labels from a file called 'labels',
+   4 # then replace labels in stdin with their addresses.
+   5 #
+   6 # To build:
+   7 #   $ bootstrap/bootstrap translate [01]*.subx subx-params.subx labels_baremetal.subx  -o labels_baremetal
+   8 #
+   9 # Stdin should be a stream of bytes and some interspersed labels. Comments and
+  10 # '==' segment headers are allowed, but names are ignored. The emitted code
+  11 # will all lie in a single contiguous address range starting at address 0x7c00.
+  12 # Addresses in segment headers are optional. If provided, this program will
+  13 # insert padding in the output until the desired address is reached.
+  14 #
+  15 #   $ cat x
+  16 #   == code
+  17 #   l1:
+  18 #   aa bb l1/imm8
+  19 #   cc dd l2/disp32
+  20 #   l2:
+  21 #   ee foo/imm32
+  22 #   == data 0x7c10
+  23 #   foo:
+  24 #     34
+  25 #
+  26 # The output is the stream of bytes without segment headers or label definitions,
+  27 # and with label references replaced with numeric values/displacements.
+  28 #
+  29 #   $ cat x  |bootstrap/bootstrap run survey_baremetal labels
+  30 #   # 0x7c00
+  31 #   aa bb nn  # some computed address
+  32 #   cc dd nn nn nn nn  # some computed displacement
+  33 #   ee nn nn nn nn  # address right after this instruction
+  34 #   # 0x7c0e
+  35 #   00 00  # padding
+  36 #   # 0x7c10
+  37 #   34  # data segment interleaved with code
+  38 
+  39 == code
+  40 #   instruction                     effective address                                                   register    displacement    immediate
+  41 # . op          subop               mod             rm32          base        index         scale       r32
+  42 # . 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
+  43 
+  44 Entry:  # run tests if necessary, convert stdin if not
+  45     # . prologue
+  46     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+  47 
+  48     # Heap = new-segment(Heap-size)
+  49     # . . push args
+  50     68/push  Heap/imm32
+  51     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Heap-size/disp32                  # push *Heap-size
+  52     # . . call
+  53     e8/call  new-segment/disp32
+  54     # . . discard args
+  55     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+  56     # initialize-trace-stream(Trace-size)
+  57     # . . push args
+  58     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-size/disp32                 # push *Heap-size
+  59     # . . call
+  60     e8/call  initialize-trace-stream/disp32
+  61     # . . discard args
+  62     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+  63 
+  64     # - if argc > 1 and argv[1] == "test", then return run_tests()
+  65     # if (argc <= 1) goto interactive
+  66     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0/disp8         1/imm32           # compare *ebp
+  67     7e/jump-if-<=  $subx-labels-main:interactive/disp8
+  68     # if (!kernel-string-equal?(argv[1], "test")) goto interactive
+  69     # . eax = kernel-string-equal?(argv[1], "test")
+  70     # . . push args
+  71     68/push  "test"/imm32
+  72     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+  73     # . . call
+  74     e8/call  kernel-string-equal?/disp32
+  75     # . . discard args
+  76     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+  77     # . if (eax == false) goto interactive
+  78     3d/compare-eax-and  0/imm32/false
+  79     74/jump-if-=  $subx-labels-main:interactive/disp8
+  80     # run-tests()
+  81 #?     e8/call  test-emit-output-with-padding/disp32
+  82     e8/call  run-tests/disp32
+  83     # syscall(exit, *Num-test-failures)
+  84     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/ebx   Num-test-failures/disp32          # copy *Num-test-failures to ebx
+  85     eb/jump  $subx-labels-main:end/disp8
+  86 $subx-labels-main:interactive:
+  87     # - otherwise convert stdin
+  88     # var labels-file/esi: (addr buffered-file) from syscall_open("labels", READ)
+  89     # . data
+  90     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x1000/imm32      # subtract from esp
+  91     # . size
+  92     68/push  0x1000/imm32
+  93     # . read
+  94     68/push  0/imm32/read
+  95     # . write
+  96     68/push  0/imm32/write
+  97     # . fd = syscall_open("labels", READ)
+  98     bb/copy-to-ebx  Label-file/imm32
+  99     b9/copy-to-ecx  0/imm32/read-mode
+ 100     ba/copy-to-edx  0x180/imm32/permissions
+ 101     e8/call syscall_open/disp32
+ 102     50/push-eax
+ 103     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           4/r32/esp   .               .                 # copy esp to esi
+ 104     # subx-labels(Stdin, label-fd, Stdout)
+ 105     # . . push args
+ 106     68/push  Stdout/imm32
+ 107     56/push-esi
+ 108     68/push  Stdin/imm32
+ 109     # . . call
+ 110     e8/call  subx-labels/disp32
+ 111     # . . discard args
+ 112     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 113 #?     # . write-stream(2/stderr, Trace-stream)
+ 114 #?     # . . push args
+ 115 #?     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+ 116 #?     68/push  2/imm32/stderr
+ 117 #?     # . . call
+ 118 #?     e8/call  write-stream/disp32
+ 119 #?     # . . discard args
+ 120 #?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 121     # syscall(exit, 0)
+ 122     bb/copy-to-ebx  0/imm32
+ 123 $subx-labels-main:end:
+ 124     e8/call  syscall_exit/disp32
+ 125 
+ 126 == data
+ 127 
+ 128 Label-file:
+ 129   6c/l 61/a 62/b 65/e 6c/l 73/s 00/nul
+ 130 
+ 131 == code
+ 132 
+ 133 subx-labels:  # infile: (addr buffered-file), labels-file: (addr buffered-file), out: (addr buffered-file)
+ 134     # pseudocode
+ 135     #   var labels: (stream {label-name, address} Max-labels)
+ 136     #   load-labels(labels-file, labels)
+ 137     #   var in: (stream byte Input-size)
+ 138     #   slurp(infile, in)
+ 139     #   emit-output(in, out, labels)
+ 140     #
+ 141     # . prologue
+ 142     55/push-ebp
+ 143     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 144     # . save registers
+ 145     52/push-edx
+ 146     56/push-esi
+ 147     # var labels/edx: (stream {label-name, address} Max-labels)
+ 148     # (we get more rows than Max-labels advertises because row size is smaller than in survey_elf)
+ 149     # . data
+ 150     2b/subtract                     0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Max-labels/disp32                 # subtract *Max-labels from esp
+ 151     # . size
+ 152     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Max-labels/disp32                 # push *Max-labels
+ 153     # . read
+ 154     68/push  0/imm32/read
+ 155     # . write
+ 156     68/push  0/imm32/write
+ 157     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+ 158     # load-labels(labels-file, labels)
+ 159     # . . push args
+ 160     52/push-edx
+ 161     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 162     # . . call
+ 163     e8/call  load-labels/disp32
+ 164     # . . discard args
+ 165     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 166     # var in/esi: (stream byte Input-size)
+ 167     # . data
+ 168     2b/subtract                     0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Input-size/disp32                 # subtract *Input-size from esp
+ 169     # . size
+ 170     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Input-size/disp32                 # push *Input-size
+ 171     # . read
+ 172     68/push  0/imm32/read
+ 173     # . write
+ 174     68/push  0/imm32/write
+ 175     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           4/r32/esp   .               .                 # copy esp to esi
+ 176     # slurp(infile, in)
+ 177     # . . push args
+ 178     56/push-esi
+ 179     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 180     # . . call
+ 181     e8/call  slurp/disp32
+ 182     # . . discard args
+ 183     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 184     # emit-output(in, out, labels)
+ 185     # . . push args
+ 186     52/push-edx
+ 187     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
+ 188     56/push-esi
+ 189     # . . call
+ 190     e8/call  emit-output/disp32
+ 191     # . . discard args
+ 192     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 193     # flush(out)
+ 194     # . . push args
+ 195     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
+ 196     # . . call
+ 197     e8/call  flush/disp32
+ 198     # . . discard args
+ 199     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 200 $subx-labels:end:
+ 201     # . reclaim locals
+ 202     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x18/imm32        # add to esp
+ 203     03/add                          0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Max-labels/disp32                 # add *Max-labels to esp
+ 204     03/add                          0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Input-size/disp32                 # add *Input-size to esp
+ 205     # . restore registers
+ 206     5e/pop-to-esi
+ 207     5a/pop-to-edx
+ 208     # . epilogue
+ 209     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 210     5d/pop-to-ebp
+ 211     c3/return
+ 212 
+ 213 load-labels:  # in: (addr buffered-file), labels: (stream {label-name, address} Max-labels)
+ 214     # pseudocode
+ 215     #   var line: (stream byte 512)
+ 216     #   while true
+ 217     #     clear-stream(line)
+ 218     #     read-line-buffered(in, line)
+ 219     #     if (line->write == 0) break               # end of file
+ 220     #     var word-slice/ecx: (addr slice) = next-word(line)
+ 221     #     var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row)
+ 222     #     word-slice = next-word(line)
+ 223     #     var address/eax: int = parse-hex-int-from-slice(word-slice)
+ 224     #     *dest = address
+ 225     #
+ 226     # . prologue
+ 227     55/push-ebp
+ 228     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 229     # . save registers
+ 230     50/push-eax
+ 231     51/push-ecx
+ 232     52/push-edx
+ 233     56/push-esi
+ 234     57/push-edi
+ 235     # var line/ecx: (stream byte 512)
+ 236     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x200/imm32       # subtract from esp
+ 237     68/push  0x200/imm32/size
+ 238     68/push  0/imm32/read
+ 239     68/push  0/imm32/write
+ 240     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+ 241     # var word-slice/edx: slice
+ 242     68/push  0/imm32/end
+ 243     68/push  0/imm32/start
+ 244     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+ 245 $load-labels:loop:
+ 246     # clear-stream(line)
+ 247     # . . push args
+ 248     51/push-ecx
+ 249     # . . call
+ 250     e8/call  clear-stream/disp32
+ 251     # . . discard args
+ 252     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 253     # read-line-buffered(in, line)
+ 254     # . . push args
+ 255     51/push-ecx
+ 256     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 257     # . . call
+ 258     e8/call  read-line-buffered/disp32
+ 259     # . . discard args
+ 260     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 261 +-- 33 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
+ 294     # if (line->write == 0) break
+ 295     81          7/subop/compare     0/mod/indirect  1/rm32/ecx    .           .             .           .           .               0/imm32           # compare *ecx
+ 296     0f 84/jump-if-=  $load-labels:end/disp32
+ 297     # next-word(line, word-slice)
+ 298     # . . push args
+ 299     52/push-edx
+ 300     51/push-ecx
+ 301     # . . call
+ 302     e8/call  next-word/disp32
+ 303     # . . discard args
+ 304     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 305 +-- 33 lines: #?     # dump word-slice --------------------------------------------------------------------------------------------------------------------------------------------------
+ 338     # var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap)
+ 339     # . eax = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap)
+ 340     # . . push args
+ 341     68/push  Heap/imm32
+ 342     68/push  0xc/imm32/row-size
+ 343     52/push-edx
+ 344     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 345     # . . call
+ 346     e8/call  get-or-insert-slice/disp32
+ 347     # . . discard args
+ 348     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+ 349     # . edi = eax
+ 350     89/copy                         3/mod/direct    7/rm32/edi    .           .             .           0/r32/eax   .               .                 # copy eax to edi
+ 351     # next-word(line, word-slice)
+ 352     # . . push args
+ 353     52/push-edx
+ 354     51/push-ecx
+ 355     # . . call
+ 356     e8/call  next-word/disp32
+ 357     # . . discard args
+ 358     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 359     # var address/esi: int = parse-hex-int-from-slice(word-slice)
+ 360     # . . push args
+ 361     52/push-edx
+ 362     # . . call
+ 363     e8/call  parse-hex-int-from-slice/disp32
+ 364     # . . discard args
+ 365     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 366     # . esi = eax
+ 367     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy eax to esi
+ 368     # *dest = address
+ 369     89/copy                         0/mod/indirect  7/rm32/edi    .           .                         6/r32/esi   .               .                 # copy esi to *edi
+ 370     #
+ 371     e9/jump  $load-labels:loop/disp32
+ 372 $load-labels:end:
+ 373     # . reclaim locals
+ 374     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x214/imm32       # add to esp
+ 375     # . restore registers
+ 376     5f/pop-to-edi
+ 377     5e/pop-to-esi
+ 378     5a/pop-to-edx
+ 379     59/pop-to-ecx
+ 380     58/pop-to-eax
+ 381     # . epilogue
+ 382     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 383     5d/pop-to-ebp
+ 384     c3/return
+ 385 
+ 386 # global scratch space for emit-output
+ 387 == data
+ 388 
+ 389 emit-output:datum:  # slice
+ 390   0/imm32/start
+ 391   0/imm32/end
+ 392 
+ 393 == code
+ 394 
+ 395 emit-output:  # in: (addr stream byte), out: (addr buffered-file), labels: (addr stream {(handle array byte), address})
+ 396     # pseudocode:
+ 397     #   var address-of-next-instruction = 0x7c00
+ 398     #   var line: (stream byte 512)
+ 399     #   line-loop:
+ 400     #   while true
+ 401     #     clear-stream(line)
+ 402     #     read-line(in, line)
+ 403     #     if (line->write == 0) break               # end of file
+ 404     #     address-of-next-instruction += num-bytes(line)
+ 405     #     var far-jump-or-call? = far-jump-or-call?(line)
+ 406     #     rewind-stream(line)
+ 407     #     while true
+ 408     #       var word-slice = next-word(line)
+ 409     #       if slice-empty?(word-slice)             # end of line
+ 410     #         break
+ 411     #       if slice-starts-with?(word-slice, "#")  # comment
+ 412     #         break
+ 413     #       if label?(word-slice)                # no need for label declarations anymore
+ 414     #         goto line-loop                        # don't insert empty lines
+ 415     #       if slice-equal?(word-slice, "==")       # no need for segment header lines
+ 416     #         word-slice = next-word(line)          # skip segment name
+ 417     #         word-slice = next-word(line)
+ 418     #         if !slice-empty?(word-slice)
+ 419     #           new-address = parse-hex-int-from-slice(word-slice)
+ 420     #           write-buffered(out, "# " address-of-next-instruction "\n")
+ 421     #           while address-of-next-instruction < new-address
+ 422     #             write-buffered("00")
+ 423     #             ++address-of-next-instruction
+ 424     #           write-buffered(out, "# " address-of-next-instruction "\n")
+ 425     #           goto line-loop                      # don't insert empty lines
+ 426     #       if length(word-slice) == 2
+ 427     #         write-slice-buffered(out, word-slice)
+ 428     #         write-buffered(out, " ")
+ 429     #         continue
+ 430     #       var datum: (addr slice) = next-token-from-slice(word-slice->start, word-slice->end, "/")
+ 431     #       var address: (addr int) = get-slice(labels, datum)
+ 432     #       if has-metadata?(word-slice, "imm8")
+ 433     #         emit(out, *address, 1)
+ 434     #       else if has-metadata?(word-slice, "imm16")
+ 435     #         emit(out, *address, 2)
+ 436     #       else if has-metadata?(word-slice, "imm32")
+ 437     #         emit(out, *address, 4)
+ 438     #       else if has-metadata?(word-slice, "disp8")
+ 439     #         value = *address - address-of-next-instruction
+ 440     #         emit(out, value, 1)
+ 441     #       else if has-metadata?(word-slice, "disp32")
+ 442     #         if far-jump-or-call?
+ 443     #           value = *address - address-of-next-instruction
+ 444     #         else
+ 445     #           value = *address
+ 446     #         emit(out, value, 4)
+ 447     #       else
+ 448     #         abort
+ 449     #     write-buffered(out, "\n")
+ 450     #
+ 451     # registers:
+ 452     #   line: ecx
+ 453     #   word-slice: edx
+ 454     #   address-of-next-instruction: ebx
+ 455     #   far-jump-or-call?: edi
+ 456     #   address: esi (inner loop only)
+ 457     #   temporaries: eax, esi (outer loop)
+ 458     #
+ 459     # . prologue
+ 460     55/push-ebp
+ 461     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 462     # . save registers
+ 463     50/push-eax
+ 464     51/push-ecx
+ 465     52/push-edx
+ 466     53/push-ebx
+ 467     56/push-esi
+ 468     57/push-edi
+ 469     # var line/ecx: (stream byte 512)
+ 470     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x200/imm32       # subtract from esp
+ 471     68/push  0x200/imm32/size
+ 472     68/push  0/imm32/read
+ 473     68/push  0/imm32/write
+ 474     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+ 475     # var word-slice/edx: slice
+ 476     68/push  0/imm32/end
+ 477     68/push  0/imm32/start
+ 478     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+ 479     # var address-of-next-instruction/ebx = 0x7c00
+ 480     bb/copy-to-ebx  0x7c00/imm32
+ 481 $emit-output:line-loop:
+ 482     # clear-stream(line)
+ 483     # . . push args
+ 484     51/push-ecx
+ 485     # . . call
+ 486     e8/call  clear-stream/disp32
+ 487     # . . discard args
+ 488     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 489     # read-line(in, line)
+ 490     # . . push args
+ 491     51/push-ecx
+ 492     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 493     # . . call
+ 494     e8/call  read-line/disp32
+ 495     # . . discard args
+ 496     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 497 +-- 33 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
+ 530 $emit-output:check-for-end-of-input:
+ 531     # if (line->write == 0) break
+ 532     81          7/subop/compare     0/mod/indirect  1/rm32/ecx    .           .             .           .           .               0/imm32           # compare *ecx
+ 533     0f 84/jump-if-=  $emit-output:end/disp32
+ 534     # address-of-next-instruction += num-bytes(line)
+ 535     # . eax = num-bytes(line)
+ 536     # . . push args
+ 537     51/push-ecx
+ 538     # . . call
+ 539     e8/call  num-bytes/disp32
+ 540     # . . discard args
+ 541     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 542     # . ebx += eax
+ 543     01/add                          3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # add eax to ebx
+ 544     # var far-jump-or-call?/edi: boolean = far-jump-or-call?(line)
+ 545     # . . push args
+ 546     51/push-ecx
+ 547     # . . call
+ 548     e8/call  far-jump-or-call?/disp32
+ 549     # . . discard args
+ 550     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 551     # rewind-stream(line)
+ 552     # . . push args
+ 553     51/push-ecx
+ 554     # . . call
+ 555     e8/call  rewind-stream/disp32
+ 556     # . . discard args
+ 557     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 558 $emit-output:word-loop:
+ 559     # next-word(line, word-slice)
+ 560     # . . push args
+ 561     52/push-edx
+ 562     51/push-ecx
+ 563     # . . call
+ 564     e8/call  next-word/disp32
+ 565     # . . discard args
+ 566     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 567 +-- 33 lines: #?     # dump word-slice --------------------------------------------------------------------------------------------------------------------------------------------------
+ 600 $emit-output:check-for-end-of-line:
+ 601     # if (slice-empty?(word-slice)) break
+ 602     # . eax = slice-empty?(word-slice)
+ 603     # . . push args
+ 604     52/push-edx
+ 605     # . . call
+ 606     e8/call  slice-empty?/disp32
+ 607     # . . discard args
+ 608     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 609     # . if (eax != 0) break
+ 610     3d/compare-eax-and  0/imm32/false
+ 611     0f 85/jump-if-!=  $emit-output:next-line/disp32
+ 612 $emit-output:check-for-comment:
+ 613     # if (slice-starts-with?(word-slice, "#")) break
+ 614     # . start/esi = word-slice->start
+ 615     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           6/r32/esi   .               .                 # copy *edx to esi
+ 616     # . c/eax = *start
+ 617     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
+ 618     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           0/r32/AL    .               .                 # copy byte at *esi to AL
+ 619     # . if (eax == '#') break
+ 620     3d/compare-eax-and  0x23/imm32/hash
+ 621     0f 84/jump-if-=  $emit-output:next-line/disp32
+ 622 $emit-output:check-for-label:
+ 623     # if label?(word-slice) break
+ 624     # . eax = label?(word-slice)
+ 625     # . . push args
+ 626     52/push-edx
+ 627     # . . call
+ 628     e8/call  label?/disp32
+ 629     # . . discard args
+ 630     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 631     # . if (eax != false) break
+ 632     3d/compare-eax-and  0/imm32/false
+ 633     0f 85/jump-if-!=  $emit-output:line-loop/disp32
+ 634 $emit-output:check-for-segment-header:
+ 635     # if !slice-equal?(word-slice, "==") goto next check
+ 636     # . eax = slice-equal?(word-slice, "==")
+ 637     # . . push args
+ 638     68/push  "=="/imm32
+ 639     52/push-edx
+ 640     # . . call
+ 641     e8/call  slice-equal?/disp32
+ 642     # . . discard args
+ 643     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 644     # . if (eax == false) goto next check
+ 645     3d/compare-eax-and  0/imm32/false
+ 646     0f 84/jump-if-=  $emit-output:2-character/disp32
+ 647     # skip segment name
+ 648     # . next-word(line, word-slice)
+ 649     # . . push args
+ 650     52/push-edx
+ 651     51/push-ecx
+ 652     # . . call
+ 653     e8/call  next-word/disp32
+ 654     # . . discard args
+ 655     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 656     # compute segment address if it exists
+ 657     # . next-word(line, word-slice)
+ 658     # . . push args
+ 659     52/push-edx
+ 660     51/push-ecx
+ 661     # . . call
+ 662     e8/call  next-word/disp32
+ 663     # . . discard args
+ 664     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 665     # . if slice-empty?(word-slice) goto padding-done
+ 666     # . . push args
+ 667     52/push-edx
+ 668     # . . call
+ 669     e8/call  slice-empty?/disp32
+ 670     # . . discard args
+ 671     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 672     # . .
+ 673     3d/compare-eax-and  0/imm32/false
+ 674     0f 85/jump-if-!=  $emit-output:padding-done/disp32
+ 675     # . var new-address/eax: int = parse-hex-int-from-slice(word-slice)
+ 676     # . . push args
+ 677     52/push-edx
+ 678     # . . call
+ 679     e8/call  parse-hex-int-from-slice/disp32
+ 680     # . . discard args
+ 681     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 682     # write-buffered(out, "# " address-of-next-instruction "\n")
+ 683     # . write-buffered(out, "# ")
+ 684     # . . push args
+ 685     68/push  "# "/imm32
+ 686     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 687     # . . call
+ 688     e8/call  write-buffered/disp32
+ 689     # . . discard args
+ 690     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 691     # . write-int32-hex-buffered(out, address-of-next-instruction)
+ 692     # . . push args
+ 693     53/push-ebx
+ 694     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 695     # . . call
+ 696     e8/call  write-int32-hex-buffered/disp32
+ 697     # . . discard args
+ 698     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 699     # . write-buffered(out, "\n")
+ 700     # . . push args
+ 701     68/push  Newline/imm32
+ 702     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 703     # . . call
+ 704     e8/call  write-buffered/disp32
+ 705     # . . discard args
+ 706     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 707 $emit-output:padding-loop:
+ 708     # if (address-of-next-instruction >= new-address) goto padding-loop-done
+ 709     39/compare                      3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # compare ebx with eax
+ 710     73/jump-if-addr>=  $emit-output:padding-loop-done/disp8
+ 711     # if (address-of-next-instruction % 8 == 0) write-buffered("\n")
+ 712     53/push-ebx
+ 713     81          4/subop/and         3/mod/direct    3/rm32/ebx    .           .             .           .           .               7/imm32           # bitwise and of ebx
+ 714     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0/imm32           # compare ebx
+ 715     5b/pop-to-ebx
+ 716     75/jump-if-!=  $emit-output:padding-core/disp8
+ 717     # . write-buffered(out, "\n")
+ 718     # . . push args
+ 719     68/push  Newline/imm32
+ 720     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 721     # . . call
+ 722     e8/call  write-buffered/disp32
+ 723     # . . discard args
+ 724     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 725 $emit-output:padding-core:
+ 726     # write-buffered("00")
+ 727     # . . push args
+ 728     68/push  "00 "/imm32
+ 729     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 730     # . . call
+ 731     e8/call  write-buffered/disp32
+ 732     # . . discard args
+ 733     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 734     # ++address-of-next-instruction
+ 735     43/increment-ebx
+ 736     # loop
+ 737     eb/jump $emit-output:padding-loop/disp8
+ 738 $emit-output:padding-loop-done:
+ 739     # . write-buffered(out, "\n")
+ 740     # . . push args
+ 741     68/push  Newline/imm32
+ 742     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 743     # . . call
+ 744     e8/call  write-buffered/disp32
+ 745     # . . discard args
+ 746     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 747 $emit-output:padding-done:
+ 748     # write-buffered(out, "# " address-of-next-instruction "\n")
+ 749     # . write-buffered(out, "# ")
+ 750     # . . push args
+ 751     68/push  "# "/imm32
+ 752     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 753     # . . call
+ 754     e8/call  write-buffered/disp32
+ 755     # . . discard args
+ 756     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 757     # . write-int32-hex-buffered(out, address-of-next-instruction)
+ 758     # . . push args
+ 759     53/push-ebx
+ 760     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 761     # . . call
+ 762     e8/call  write-int32-hex-buffered/disp32
+ 763     # . . discard args
+ 764     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 765     # . write-buffered(out, "\n")
+ 766     # . . push args
+ 767     68/push  Newline/imm32
+ 768     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 769     # . . call
+ 770     e8/call  write-buffered/disp32
+ 771     # . . discard args
+ 772     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 773     #
+ 774     e9/jump  $emit-output:line-loop/disp32
+ 775 $emit-output:2-character:
+ 776     # if (size(word-slice) != 2) goto next check
+ 777     # . eax = size(word-slice)
+ 778     8b/copy                         1/mod/*+disp8   2/rm32/edx    .           .             .           0/r32/eax   4/disp8         .                 # copy *(edx+4) to eax
+ 779     2b/subtract                     0/mod/indirect  2/rm32/edx    .           .             .           0/r32/eax   .               .                 # subtract *edx from eax
+ 780     # . if (eax != 2) goto next check
+ 781     3d/compare-eax-and  2/imm32
+ 782     75/jump-if-!=  $emit-output:check-metadata/disp8
+ 783     # write-slice-buffered(out, word-slice)
+ 784     # . . push args
+ 785     52/push-edx
+ 786     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 787     # . . call
+ 788     e8/call  write-slice-buffered/disp32
+ 789     # . . discard args
+ 790     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 791     # write-buffered(out, " ")
+ 792     # . . push args
+ 793     68/push  Space/imm32
+ 794     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 795     # . . call
+ 796     e8/call  write-buffered/disp32
+ 797     # . . discard args
+ 798     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 799     # continue
+ 800     e9/jump  $emit-output:word-loop/disp32
+ 801 $emit-output:check-metadata:
+ 802     # - if we get here, 'word-slice' must be a label to be looked up
+ 803     # datum = next-token-from-slice(word-slice->start, word-slice->end, "/")
+ 804     # . . push args
+ 805     68/push  emit-output:datum/imm32
+ 806     68/push  0x2f/imm32/slash
+ 807     ff          6/subop/push        1/mod/*+disp8   2/rm32/edx    .           .             .           .           4/disp8         .                 # push *(edx+4)
+ 808     ff          6/subop/push        0/mod/indirect  2/rm32/edx    .           .             .           .           .               .                 # push *edx
+ 809     # . . call
+ 810     e8/call  next-token-from-slice/disp32
+ 811     # . . discard args
+ 812     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+ 813 +-- 33 lines: #?     # dump datum -------------------------------------------------------------------------------------------------------------------------------------------------------
+ 846     # address/esi: (addr int) = get-slice(labels, datum, row-size=12, "label table")
+ 847     # . eax = get-slice(labels, datum, row-size=24, "label table")
+ 848     # . . push args
+ 849     68/push  "label table"/imm32
+ 850     68/push  0xc/imm32/row-size
+ 851     68/push  emit-output:datum/imm32
+ 852     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
+ 853     # . . call
+ 854     e8/call  get-slice/disp32
+ 855     # . . discard args
+ 856     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+ 857     # . esi = eax
+ 858     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy eax to esi
+ 859 $emit-output:check-imm8:
+ 860     # if (!has-metadata?(word-slice, "imm8")) goto next check
+ 861     # . eax = has-metadata?(edx, "imm8")
+ 862     # . . push args
+ 863     68/push  "imm8"/imm32
+ 864     52/push-edx
+ 865     # . . call
+ 866     e8/call  has-metadata?/disp32
+ 867     # . . discard args
+ 868     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 869     # . if (eax != false) abort
+ 870     3d/compare-eax-and  0/imm32/false
+ 871     74/jump-if-=  $emit-output:check-imm16/disp8
+ 872 $emit-output:emit-imm8:
+ 873     # emit-hex(out, *address, 1)
+ 874     # . . push args
+ 875     68/push  1/imm32
+ 876     ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
+ 877     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 878     # . . call
+ 879     e8/call  emit-hex/disp32
+ 880     # . . discard args
+ 881     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 882     # continue
+ 883     e9/jump  $emit-output:word-loop/disp32
+ 884 $emit-output:check-imm16:
+ 885     # if (!has-metadata?(word-slice, "imm16")) goto next check
+ 886     # . eax = has-metadata?(edx, "imm16")
+ 887     # . . push args
+ 888     68/push  "imm16"/imm32
+ 889     52/push-edx
+ 890     # . . call
+ 891     e8/call  has-metadata?/disp32
+ 892     # . . discard args
+ 893     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 894     # . if (eax == false) goto next check
+ 895     3d/compare-eax-and  0/imm32/false
+ 896     74/jump-if-=  $emit-output:check-imm32/disp8
+ 897 +-- 33 lines: #?     # dump *address ----------------------------------------------------------------------------------------------------------------------------------------------------
+ 930 $emit-output:emit-imm16:
+ 931     # emit-hex(out, *address, 2)
+ 932     # . . push args
+ 933     68/push  2/imm32
+ 934     ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
+ 935     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 936     # . . call
+ 937     e8/call  emit-hex/disp32
+ 938     # . . discard args
+ 939     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 940     # TODO: ensure that the higher 2 bytes are zero
+ 941     # continue
+ 942     e9/jump  $emit-output:word-loop/disp32
+ 943 $emit-output:check-imm32:
+ 944     # if (!has-metadata?(word-slice, "imm32")) goto next check
+ 945     # . eax = has-metadata?(edx, "imm32")
+ 946     # . . push args
+ 947     68/push  "imm32"/imm32
+ 948     52/push-edx
+ 949     # . . call
+ 950     e8/call  has-metadata?/disp32
+ 951     # . . discard args
+ 952     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 953     # . if (eax == false) goto next check
+ 954     3d/compare-eax-and  0/imm32/false
+ 955     74/jump-if-=  $emit-output:check-disp8/disp8
+ 956 +-- 33 lines: #?     # dump *address ----------------------------------------------------------------------------------------------------------------------------------------------------
+ 989 $emit-output:emit-imm32:
+ 990     # emit-hex(out, *address, 4)
+ 991     # . . push args
+ 992     68/push  4/imm32
+ 993     ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
+ 994     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 995     # . . call
+ 996     e8/call  emit-hex/disp32
+ 997     # . . discard args
+ 998     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 999     # continue
+1000     e9/jump  $emit-output:word-loop/disp32
+1001 $emit-output:check-disp8:
+1002     # if (!has-metadata?(word-slice, "disp8")) goto next check
+1003     # . eax = has-metadata?(edx, "disp8")
+1004     # . . push args
+1005     68/push  "disp8"/imm32
+1006     52/push-edx
+1007     # . . call
+1008     e8/call  has-metadata?/disp32
+1009     # . . discard args
+1010     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1011     # . if (eax == false) goto next check
+1012     3d/compare-eax-and  0/imm32/false
+1013     74/jump-if-=  $emit-output:check-disp16/disp8
+1014 $emit-output:emit-disp8:
+1015     # emit-hex(out, *address - address-of-next-instruction, 1)
+1016     # . . push args
+1017     68/push  1/imm32
+1018     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
+1019     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
+1020     50/push-eax
+1021     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+1022     # . . call
+1023     e8/call  emit-hex/disp32
+1024     # . . discard args
+1025     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1026     # continue
+1027     e9/jump  $emit-output:word-loop/disp32
+1028 $emit-output:check-disp16:
+1029     # if (!has-metadata?(word-slice, "disp16")) goto next check
+1030     # . eax = has-metadata?(edx, "disp16")
+1031     # . . push args
+1032     68/push  "disp16"/imm32
+1033     52/push-edx
+1034     # . . call
+1035     e8/call  has-metadata?/disp32
+1036     # . . discard args
+1037     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1038     # . if (eax == false) goto next check
+1039     3d/compare-eax-and  0/imm32/false
+1040     74/jump-if-=  $emit-output:check-disp32/disp8
+1041 $emit-output:emit-disp16:
+1042     # emit-hex(out, *address - address-of-next-instruction, 2)
+1043     # . . push args
+1044     68/push  2/imm32
+1045     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
+1046     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
+1047     50/push-eax
+1048     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+1049     # . . call
+1050     e8/call  emit-hex/disp32
+1051     # . . discard args
+1052     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1053     # continue
+1054     e9/jump  $emit-output:word-loop/disp32
+1055 $emit-output:check-disp32:
+1056     # if (!has-metadata?(word-slice, "disp32")) abort
+1057     # . eax = has-metadata?(edx, "disp32")
+1058     # . . push args
+1059     68/push  "disp32"/imm32
+1060     52/push-edx
+1061     # . . call
+1062     e8/call  has-metadata?/disp32
+1063     # . . discard args
+1064     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1065     # . if (eax == false) abort
+1066     3d/compare-eax-and  0/imm32/false
+1067     0f 84/jump-if-=  $emit-output:abort/disp32
+1068 $emit-output:emit-disp32:
+1069     # var value/eax = *address
+1070     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
+1071     # if (far-jump-or-call?) value -= address-of-next-instruction
+1072     81          7/subop/compare     3/mod/direct    7/rm32/edi    .           .             .           .           .               0/imm32/false     # compare edi
+1073     74/jump-if-=  $emit-output:really-emit-disp32/disp8
+1074     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
+1075 $emit-output:really-emit-disp32:
+1076     # emit-hex(out, value, 4)
+1077     # . . push args
+1078     68/push  4/imm32
+1079     50/push-eax
+1080     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+1081     # . . call
+1082     e8/call  emit-hex/disp32
+1083     # . . discard args
+1084     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1085     # continue
+1086     e9/jump  $emit-output:word-loop/disp32
+1087 $emit-output:next-line:
+1088     # write-buffered(out, "\n")
+1089     # . . push args
+1090     68/push  Newline/imm32
+1091     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+1092     # . . call
+1093     e8/call  write-buffered/disp32
+1094     # . . discard args
+1095     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1096     # loop
+1097     e9/jump  $emit-output:line-loop/disp32
+1098 $emit-output:end:
+1099     # . reclaim locals
+1100     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x214/imm32       # add to esp
+1101     # . restore registers
+1102     5f/pop-to-edi
+1103     5e/pop-to-esi
+1104     5b/pop-to-ebx
+1105     5a/pop-to-edx
+1106     59/pop-to-ecx
+1107     58/pop-to-eax
+1108     # . epilogue
+1109     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1110     5d/pop-to-ebp
+1111     c3/return
+1112 
+1113 $emit-output:abort:
+1114     # print(stderr, "missing metadata in " word-slice)
+1115     # . _write(2/stderr, "missing metadata in word ")
+1116     # . . push args
+1117     68/push  "emit-output: missing metadata in "/imm32
+1118     68/push  2/imm32/stderr
+1119     # . . call
+1120     e8/call  _write/disp32
+1121     # . . discard args
+1122     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1123     # . write-slice-buffered(Stderr, word-slice)
+1124     # . . push args
+1125     52/push-edx
+1126     68/push  Stderr/imm32
+1127     # . . call
+1128     e8/call  write-slice-buffered/disp32
+1129     # . . discard args
+1130     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1131     # . flush(Stderr)
+1132     # . . push args
+1133     68/push  Stderr/imm32
+1134     # . . call
+1135     e8/call  flush/disp32
+1136     # . . discard args
+1137     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1138     # . syscall(exit, 1)
+1139     bb/copy-to-ebx  1/imm32
+1140     e8/call  syscall_exit/disp32
+1141     # never gets here
+1142 
+1143 test-emit-output-non-far-control-flow:
+1144     # labels turn into absolute addresses if opcodes are not far jumps or calls
+1145     #
+1146     # input:
+1147     #   in:
+1148     #     == code
+1149     #     ab cd ef gh
+1150     #     ij x/disp32
+1151     #     == data
+1152     #     00
+1153     #     34
+1154     #   labels:
+1155     #     - 'x': 0x11223344
+1156     #
+1157     # output:
+1158     #   ab cd ef gh
+1159     #   ij 44 33 22 11
+1160     #   00
+1161     #   34
+1162     #
+1163     # . prologue
+1164     55/push-ebp
+1165     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1166     # setup
+1167     # . clear-stream(_test-input-stream)
+1168     # . . push args
+1169     68/push  _test-input-stream/imm32
+1170     # . . call
+1171     e8/call  clear-stream/disp32
+1172     # . . discard args
+1173     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1174     # . clear-stream(_test-output-stream)
+1175     # . . push args
+1176     68/push  _test-output-stream/imm32
+1177     # . . call
+1178     e8/call  clear-stream/disp32
+1179     # . . discard args
+1180     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1181     # . clear-stream($_test-output-buffered-file->buffer)
+1182     # . . push args
+1183     68/push  $_test-output-buffered-file->buffer/imm32
+1184     # . . call
+1185     e8/call  clear-stream/disp32
+1186     # . . discard args
+1187     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1188     # . var labels/edx: (stream byte 8*24)
+1189     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
+1190     68/push  0xc0/imm32/size
+1191     68/push  0/imm32/read
+1192     68/push  0/imm32/write
+1193     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+1194     # . var h/ebx: (handle array byte)
+1195     68/push  0/imm32
+1196     68/push  0/imm32
+1197     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+1198     # initialize input
+1199     # . write(_test-input-stream, "== code\n")
+1200     # . . push args
+1201     68/push  "== code\n"/imm32
+1202     68/push  _test-input-stream/imm32
+1203     # . . call
+1204     e8/call  write/disp32
+1205     # . . discard args
+1206     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1207     # . write(_test-input-stream, "ab cd ef gh\n")
+1208     # . . push args
+1209     68/push  "ab cd ef gh\n"/imm32
+1210     68/push  _test-input-stream/imm32
+1211     # . . call
+1212     e8/call  write/disp32
+1213     # . . discard args
+1214     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1215     # . write(_test-input-stream, "ij x/disp32\n")
+1216     # . . push args
+1217     68/push  "ij x/disp32\n"/imm32
+1218     68/push  _test-input-stream/imm32
+1219     # . . call
+1220     e8/call  write/disp32
+1221     # . . discard args
+1222     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1223     # . write(_test-input-stream, "== data\n")
+1224     # . . push args
+1225     68/push  "== data\n"/imm32
+1226     68/push  _test-input-stream/imm32
+1227     # . . call
+1228     e8/call  write/disp32
+1229     # . . discard args
+1230     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1231     # . write(_test-input-stream, "00\n")
+1232     # . . push args
+1233     68/push  "00\n"/imm32
+1234     68/push  _test-input-stream/imm32
+1235     # . . call
+1236     e8/call  write/disp32
+1237     # . . discard args
+1238     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1239     # . write(_test-input-stream, "34\n")
+1240     # . . push args
+1241     68/push  "34\n"/imm32
+1242     68/push  _test-input-stream/imm32
+1243     # . . call
+1244     e8/call  write/disp32
+1245     # . . discard args
+1246     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1247     # . stream-add2(labels, "x", 0x11223344)
+1248     68/push  0x11223344/imm32/label-address
+1249     # . . push handle for "x"
+1250     53/push-ebx
+1251     68/push  "x"/imm32
+1252     68/push  Heap/imm32
+1253     e8/call  copy-array/disp32
+1254     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1255     ff          6/subop/push        1/mod/*+disp8   3/rm32/ebx    .           .             .           .           4/disp8         .                 # push *(ebx+4)
+1256     ff          6/subop/push        0/mod/indirect  3/rm32/ebx    .           .             .           .           .               .                 # push *ebx
+1257     # . . push labels
+1258     52/push-edx
+1259     # . . call
+1260     e8/call  stream-add2/disp32
+1261     # . . discard args
+1262     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+1263     # component under test
+1264     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
+1265     # . . push args
+1266     52/push-edx
+1267     68/push  _test-output-buffered-file/imm32
+1268     68/push  _test-input-stream/imm32
+1269     # . . call
+1270     e8/call  emit-output/disp32
+1271     # . . discard args
+1272     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1273     # checks
+1274     # . flush(_test-output-buffered-file)
+1275     # . . push args
+1276     68/push  _test-output-buffered-file/imm32
+1277     # . . call
+1278     e8/call  flush/disp32
+1279     # . . discard args
+1280     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1281 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
+1314     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
+1315     # . . push args
+1316     68/push  "F - test-emit-output-non-far-control-flow/0"/imm32
+1317     68/push  "# 0x00007c00"/imm32
+1318     68/push  _test-output-stream/imm32
+1319     # . . call
+1320     e8/call  check-next-stream-line-equal/disp32
+1321     # . . discard args
+1322     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1323     # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg)
+1324     # . . push args
+1325     68/push  "F - test-emit-output-non-far-control-flow/1"/imm32
+1326     68/push  "ab cd ef gh "/imm32
+1327     68/push  _test-output-stream/imm32
+1328     # . . call
+1329     e8/call  check-next-stream-line-equal/disp32
+1330     # . . discard args
+1331     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1332     # . check-next-stream-line-equal(_test-output-stream, "ij 44 33 22 11 ", msg)
+1333     # . . push args
+1334     68/push  "F - test-emit-output-non-far-control-flow/2"/imm32
+1335     68/push  "ij 44 33 22 11 "/imm32
+1336     68/push  _test-output-stream/imm32
+1337     # . . call
+1338     e8/call  check-next-stream-line-equal/disp32
+1339     # . . discard args
+1340     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1341     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c09", msg)
+1342     # . . push args
+1343     68/push  "F - test-emit-output-non-far-control-flow/3"/imm32
+1344     68/push  "# 0x00007c09"/imm32
+1345     68/push  _test-output-stream/imm32
+1346     # . . call
+1347     e8/call  check-next-stream-line-equal/disp32
+1348     # . . discard args
+1349     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1350     # . check-next-stream-line-equal(_test-output-stream, "00 ", msg)
+1351     # . . push args
+1352     68/push  "F - test-emit-output-non-far-control-flow/3"/imm32
+1353     68/push  "00 "/imm32
+1354     68/push  _test-output-stream/imm32
+1355     # . . call
+1356     e8/call  check-next-stream-line-equal/disp32
+1357     # . . discard args
+1358     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1359     # . check-next-stream-line-equal(_test-output-stream, "34 ", msg)
+1360     # . . push args
+1361     68/push  "F - test-emit-output-non-far-control-flow/4"/imm32
+1362     68/push  "34 "/imm32
+1363     68/push  _test-output-stream/imm32
+1364     # . . call
+1365     e8/call  check-next-stream-line-equal/disp32
+1366     # . . discard args
+1367     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1368     # . epilogue
+1369     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1370     5d/pop-to-ebp
+1371     c3/return
+1372 
+1373 test-emit-output-with-padding:
+1374     # labels turn into absolute addresses if opcodes are not far jumps or calls
+1375     #
+1376     # input:
+1377     #   in:
+1378     #     == code
+1379     #     ab cd ef gh
+1380     #     == data 0x7c10
+1381     #     34
+1382     #
+1383     # output:
+1384     #   ab cd ef gh
+1385     #   # 0x7c04
+1386     #   00 00 00 00
+1387     #   00 00 00 00 00 00 00 00
+1388     #   # 0x7c10
+1389     #   34
+1390     #
+1391     # . prologue
+1392     55/push-ebp
+1393     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1394     # setup
+1395     # . clear-stream(_test-input-stream)
+1396     # . . push args
+1397     68/push  _test-input-stream/imm32
+1398     # . . call
+1399     e8/call  clear-stream/disp32
+1400     # . . discard args
+1401     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1402     # . clear-stream(_test-output-stream)
+1403     # . . push args
+1404     68/push  _test-output-stream/imm32
+1405     # . . call
+1406     e8/call  clear-stream/disp32
+1407     # . . discard args
+1408     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1409     # . clear-stream($_test-output-buffered-file->buffer)
+1410     # . . push args
+1411     68/push  $_test-output-buffered-file->buffer/imm32
+1412     # . . call
+1413     e8/call  clear-stream/disp32
+1414     # . . discard args
+1415     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1416     # . var labels/edx: (stream byte 8*24)
+1417     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
+1418     68/push  0xc0/imm32/size
+1419     68/push  0/imm32/read
+1420     68/push  0/imm32/write
+1421     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+1422     # . var h/ebx: (handle array byte)
+1423     68/push  0/imm32
+1424     68/push  0/imm32
+1425     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+1426     # initialize input
+1427     # . write(_test-input-stream, "== code\n")
+1428     # . . push args
+1429     68/push  "== code\n"/imm32
+1430     68/push  _test-input-stream/imm32
+1431     # . . call
+1432     e8/call  write/disp32
+1433     # . . discard args
+1434     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1435     # . write(_test-input-stream, "ab cd ef gh\n")
+1436     # . . push args
+1437     68/push  "ab cd ef gh\n"/imm32
+1438     68/push  _test-input-stream/imm32
+1439     # . . call
+1440     e8/call  write/disp32
+1441     # . . discard args
+1442     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1443     # . write(_test-input-stream, "== data 0x7c10\n")
+1444     # . . push args
+1445     68/push  "== data 0x7c10\n"/imm32
+1446     68/push  _test-input-stream/imm32
+1447     # . . call
+1448     e8/call  write/disp32
+1449     # . . discard args
+1450     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1451     # . write(_test-input-stream, "34\n")
+1452     # . . push args
+1453     68/push  "34\n"/imm32
+1454     68/push  _test-input-stream/imm32
+1455     # . . call
+1456     e8/call  write/disp32
+1457     # . . discard args
+1458     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1459     # component under test
+1460     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
+1461     # . . push args
+1462     52/push-edx
+1463     68/push  _test-output-buffered-file/imm32
+1464     68/push  _test-input-stream/imm32
+1465     # . . call
+1466     e8/call  emit-output/disp32
+1467     # . . discard args
+1468     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1469     # checks
+1470     # . flush(_test-output-buffered-file)
+1471     # . . push args
+1472     68/push  _test-output-buffered-file/imm32
+1473     # . . call
+1474     e8/call  flush/disp32
+1475     # . . discard args
+1476     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1477 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
+1510     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
+1511     # . . push args
+1512     68/push  "F - test-emit-output-with-padding/0"/imm32
+1513     68/push  "# 0x00007c00"/imm32
+1514     68/push  _test-output-stream/imm32
+1515     # . . call
+1516     e8/call  check-next-stream-line-equal/disp32
+1517     # . . discard args
+1518     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1519     # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg)
+1520     # . . push args
+1521     68/push  "F - test-emit-output-with-padding/1"/imm32
+1522     68/push  "ab cd ef gh "/imm32
+1523     68/push  _test-output-stream/imm32
+1524     # . . call
+1525     e8/call  check-next-stream-line-equal/disp32
+1526     # . . discard args
+1527     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1528     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c04", msg)
+1529     # . . push args
+1530     68/push  "F - test-emit-output-with-padding/0"/imm32
+1531     68/push  "# 0x00007c04"/imm32
+1532     68/push  _test-output-stream/imm32
+1533     # . . call
+1534     e8/call  check-next-stream-line-equal/disp32
+1535     # . . discard args
+1536     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1537     # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg)
+1538     # . . push args
+1539     68/push  "F - test-emit-output-with-padding/2"/imm32
+1540     68/push  "00 00 00 00 "/imm32
+1541     68/push  _test-output-stream/imm32
+1542     # . . call
+1543     e8/call  check-next-stream-line-equal/disp32
+1544     # . . discard args
+1545     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1546     # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg)
+1547     # . . push args
+1548     68/push  "F - test-emit-output-with-padding/3"/imm32
+1549     68/push  "00 00 00 00 00 00 00 00 "/imm32
+1550     68/push  _test-output-stream/imm32
+1551     # . . call
+1552     e8/call  check-next-stream-line-equal/disp32
+1553     # . . discard args
+1554     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1555     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c10", msg)
+1556     # . . push args
+1557     68/push  "F - test-emit-output-with-padding/0"/imm32
+1558     68/push  "# 0x00007c10"/imm32
+1559     68/push  _test-output-stream/imm32
+1560     # . . call
+1561     e8/call  check-next-stream-line-equal/disp32
+1562     # . . discard args
+1563     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1564     # . check-next-stream-line-equal(_test-output-stream, "34 ", msg)
+1565     # . . push args
+1566     68/push  "F - test-emit-output-with-padding/4"/imm32
+1567     68/push  "34 "/imm32
+1568     68/push  _test-output-stream/imm32
+1569     # . . call
+1570     e8/call  check-next-stream-line-equal/disp32
+1571     # . . discard args
+1572     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1573     # . epilogue
+1574     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1575     5d/pop-to-ebp
+1576     c3/return
+1577 
+1578 test-emit-output-code-label:
+1579     # labels turn into PC-relative addresses if opcodes are far jumps or calls
+1580     #
+1581     # input:
+1582     #   in:
+1583     #     == code
+1584     #     ab cd
+1585     #     ef gh
+1586     #     e8 l1/disp32
+1587     #   labels:
+1588     #     - 'l1': 0x7c10
+1589     #
+1590     # output:
+1591     #   ab cd
+1592     #   ef gh
+1593     #   e8 07 00 00 00  # 0x7c10 - 0x7c09 = 7
+1594     #
+1595     # . prologue
+1596     55/push-ebp
+1597     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1598     # setup
+1599     # . clear-stream(_test-input-stream)
+1600     # . . push args
+1601     68/push  _test-input-stream/imm32
+1602     # . . call
+1603     e8/call  clear-stream/disp32
+1604     # . . discard args
+1605     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1606     # . clear-stream(_test-output-stream)
+1607     # . . push args
+1608     68/push  _test-output-stream/imm32
+1609     # . . call
+1610     e8/call  clear-stream/disp32
+1611     # . . discard args
+1612     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1613     # . clear-stream($_test-output-buffered-file->buffer)
+1614     # . . push args
+1615     68/push  $_test-output-buffered-file->buffer/imm32
+1616     # . . call
+1617     e8/call  clear-stream/disp32
+1618     # . . discard args
+1619     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1620     # . var labels/edx: (stream byte 8*24)
+1621     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
+1622     68/push  0xc0/imm32/size
+1623     68/push  0/imm32/read
+1624     68/push  0/imm32/write
+1625     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+1626     # . var h/ebx: (handle array byte)
+1627     68/push  0/imm32
+1628     68/push  0/imm32
+1629     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+1630     # initialize input
+1631     # . write(_test-input-stream, "== code\n")
+1632     # . . push args
+1633     68/push  "== code\n"/imm32
+1634     68/push  _test-input-stream/imm32
+1635     # . . call
+1636     e8/call  write/disp32
+1637     # . . discard args
+1638     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1639     # . write(_test-input-stream, "ab cd\n")
+1640     # . . push args
+1641     68/push  "ab cd\n"/imm32
+1642     68/push  _test-input-stream/imm32
+1643     # . . call
+1644     e8/call  write/disp32
+1645     # . . discard args
+1646     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1647     # . write(_test-input-stream, "ef gh\n")
+1648     # . . push args
+1649     68/push  "ef gh\n"/imm32
+1650     68/push  _test-input-stream/imm32
+1651     # . . call
+1652     e8/call  write/disp32
+1653     # . . discard args
+1654     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1655     # . write(_test-input-stream, "e8 l1/disp32\n")
+1656     # . . push args
+1657     68/push  "e8 l1/disp32\n"/imm32
+1658     68/push  _test-input-stream/imm32
+1659     # . . call
+1660     e8/call  write/disp32
+1661     # . . discard args
+1662     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1663     # . stream-add2(labels, "l1", 0x7c10)
+1664     68/push  0x7c10/imm32/label-address
+1665     # . . push handle for "l1"
+1666     53/push-ebx
+1667     68/push  "l1"/imm32
+1668     68/push  Heap/imm32
+1669     e8/call  copy-array/disp32
+1670     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1671     ff          6/subop/push        1/mod/*+disp8   3/rm32/ebx    .           .             .           .           4/disp8         .                 # push *(ebx+4)
+1672     ff          6/subop/push        0/mod/indirect  3/rm32/ebx    .           .             .           .           .               .                 # push *ebx
+1673     # . . push labels
+1674     52/push-edx
+1675     # . . call
+1676     e8/call  stream-add2/disp32
+1677     # . . discard args
+1678     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+1679     # component under test
+1680     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
+1681     # . . push args
+1682     52/push-edx
+1683     68/push  _test-output-buffered-file/imm32
+1684     68/push  _test-input-stream/imm32
+1685     # . . call
+1686     e8/call  emit-output/disp32
+1687     # . . discard args
+1688     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1689     # checks
+1690     # . flush(_test-output-buffered-file)
+1691     # . . push args
+1692     68/push  _test-output-buffered-file/imm32
+1693     # . . call
+1694     e8/call  flush/disp32
+1695     # . . discard args
+1696     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1697 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
+1730     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
+1731     # . . push args
+1732     68/push  "F - test-emit-output-code-label/0"/imm32
+1733     68/push  "# 0x00007c00"/imm32
+1734     68/push  _test-output-stream/imm32
+1735     # . . call
+1736     e8/call  check-next-stream-line-equal/disp32
+1737     # . . discard args
+1738     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1739     # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg)
+1740     # . . push args
+1741     68/push  "F - test-emit-output-code-label/1"/imm32
+1742     68/push  "ab cd "/imm32
+1743     68/push  _test-output-stream/imm32
+1744     # . . call
+1745     e8/call  check-next-stream-line-equal/disp32
+1746     # . . discard args
+1747     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1748     # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg)
+1749     # . . push args
+1750     68/push  "F - test-emit-output-code-label/2"/imm32
+1751     68/push  "ef gh "/imm32
+1752     68/push  _test-output-stream/imm32
+1753     # . . call
+1754     e8/call  check-next-stream-line-equal/disp32
+1755     # . . discard args
+1756     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1757     # . check-next-stream-line-equal(_test-output-stream, "e8 07 00 00 00 ", msg)
+1758     # . . push args
+1759     68/push  "F - test-emit-output-code-label/3"/imm32
+1760     68/push  "e8 07 00 00 00 "/imm32
+1761     68/push  _test-output-stream/imm32
+1762     # . . call
+1763     e8/call  check-next-stream-line-equal/disp32
+1764     # . . discard args
+1765     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1766     # . epilogue
+1767     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1768     5d/pop-to-ebp
+1769     c3/return
+1770 
+1771 test-emit-output-code-label-absolute:
+1772     # labels can also convert to absolute addresses
+1773     #
+1774     # input:
+1775     #   in:
+1776     #     == code
+1777     #     ab cd
+1778     #     ef gh
+1779     #     ij l1/imm32
+1780     #   labels:
+1781     #     - 'l1': 0x1056
+1782     #
+1783     # output:
+1784     #   ab cd
+1785     #   ef gh
+1786     #   ij 56 10 00 00
+1787     #
+1788     # . prologue
+1789     55/push-ebp
+1790     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1791     # setup
+1792     # . clear-stream(_test-input-stream)
+1793     # . . push args
+1794     68/push  _test-input-stream/imm32
+1795     # . . call
+1796     e8/call  clear-stream/disp32
+1797     # . . discard args
+1798     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1799     # . clear-stream(_test-output-stream)
+1800     # . . push args
+1801     68/push  _test-output-stream/imm32
+1802     # . . call
+1803     e8/call  clear-stream/disp32
+1804     # . . discard args
+1805     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1806     # . clear-stream($_test-output-buffered-file->buffer)
+1807     # . . push args
+1808     68/push  $_test-output-buffered-file->buffer/imm32
+1809     # . . call
+1810     e8/call  clear-stream/disp32
+1811     # . . discard args
+1812     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1813     # . var labels/edx: (stream byte 8*24)
+1814     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
+1815     68/push  0xc0/imm32/size
+1816     68/push  0/imm32/read
+1817     68/push  0/imm32/write
+1818     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+1819     # . var h/ebx: (handle array byte)
+1820     68/push  0/imm32
+1821     68/push  0/imm32
+1822     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+1823     # initialize input
+1824     # . write(_test-input-stream, "== code 0x1000\n")
+1825     # . . push args
+1826     68/push  "== code\n"/imm32
+1827     68/push  _test-input-stream/imm32
+1828     # . . call
+1829     e8/call  write/disp32
+1830     # . . discard args
+1831     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1832     # . write(_test-input-stream, "ab cd\n")
+1833     # . . push args
+1834     68/push  "ab cd\n"/imm32
+1835     68/push  _test-input-stream/imm32
+1836     # . . call
+1837     e8/call  write/disp32
+1838     # . . discard args
+1839     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1840     # . write(_test-input-stream, "ef gh\n")
+1841     # . . push args
+1842     68/push  "ef gh\n"/imm32
+1843     68/push  _test-input-stream/imm32
+1844     # . . call
+1845     e8/call  write/disp32
+1846     # . . discard args
+1847     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1848     # . write(_test-input-stream, "ij l1/imm32\n")
+1849     # . . push args
+1850     68/push  "ij l1/imm32\n"/imm32
+1851     68/push  _test-input-stream/imm32
+1852     # . . call
+1853     e8/call  write/disp32
+1854     # . . discard args
+1855     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1856     # . stream-add2(labels, "l1", 0x1056)
+1857     68/push  0x1056/imm32/label-address
+1858     # . . push handle for "l1"
+1859     53/push-ebx
+1860     68/push  "l1"/imm32
+1861     68/push  Heap/imm32
+1862     e8/call  copy-array/disp32
+1863     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1864     ff          6/subop/push        1/mod/*+disp8   3/rm32/ebx    .           .             .           .           4/disp8         .                 # push *(ebx+4)
+1865     ff          6/subop/push        0/mod/indirect  3/rm32/ebx    .           .             .           .           .               .                 # push *ebx
+1866     # . . push labels
+1867     52/push-edx
+1868     # . . call
+1869     e8/call  stream-add2/disp32
+1870     # . . discard args
+1871     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+1872     # component under test
+1873     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
+1874     # . . push args
+1875     52/push-edx
+1876     68/push  _test-output-buffered-file/imm32
+1877     68/push  _test-input-stream/imm32
+1878     # . . call
+1879     e8/call  emit-output/disp32
+1880     # . . discard args
+1881     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1882     # checks
+1883     # . flush(_test-output-buffered-file)
+1884     # . . push args
+1885     68/push  _test-output-buffered-file/imm32
+1886     # . . call
+1887     e8/call  flush/disp32
+1888     # . . discard args
+1889     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1890 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
+1923     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
+1924     # . . push args
+1925     68/push  "F - test-emit-output-code-label-absolute/0"/imm32
+1926     68/push  "# 0x00007c00"/imm32
+1927     68/push  _test-output-stream/imm32
+1928     # . . call
+1929     e8/call  check-next-stream-line-equal/disp32
+1930     # . . discard args
+1931     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1932     # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg)
+1933     # . . push args
+1934     68/push  "F - test-emit-output-code-label-absolute/1"/imm32
+1935     68/push  "ab cd "/imm32
+1936     68/push  _test-output-stream/imm32
+1937     # . . call
+1938     e8/call  check-next-stream-line-equal/disp32
+1939     # . . discard args
+1940     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1941     # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg)
+1942     # . . push args
+1943     68/push  "F - test-emit-output-code-label-absolute/2"/imm32
+1944     68/push  "ef gh "/imm32
+1945     68/push  _test-output-stream/imm32
+1946     # . . call
+1947     e8/call  check-next-stream-line-equal/disp32
+1948     # . . discard args
+1949     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1950     # . check-next-stream-line-equal(_test-output-stream, "ij f9 ff ff ff ", msg)
+1951     # . . push args
+1952     68/push  "F - test-emit-output-code-label-absolute/3"/imm32
+1953     68/push  "ij 56 10 00 00 "/imm32
+1954     68/push  _test-output-stream/imm32
+1955     # . . call
+1956     e8/call  check-next-stream-line-equal/disp32
+1957     # . . discard args
+1958     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+1959     # . epilogue
+1960     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1961     5d/pop-to-ebp
+1962     c3/return
+1963 
+1964 # reads line to make some checks
+1965 # don't assume the read state of line after calling this function
+1966 far-jump-or-call?:  # line: (addr stream byte) -> result/edi: boolean
+1967     # . prologue
+1968     55/push-ebp
+1969     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1970     # . save registers
+1971     50/push-eax
+1972     51/push-ecx
+1973     52/push-edx
+1974     53/push-ebx
+1975     # ecx = line
+1976     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
+1977     # var word-slice/edx: slice
+1978     68/push  0/imm32/end
+1979     68/push  0/imm32/start
+1980     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+1981     # var datum-slice/ebx: slice
+1982     68/push  0/imm32/end
+1983     68/push  0/imm32/start
+1984     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+1985     # result = false
+1986     bf/copy-to-edi  0/imm32/false
+1987 $far-jump-or-call?:check-first-word:
+1988     # next-word(line, word-slice)
+1989     # . . push args
+1990     52/push-edx
+1991     51/push-ecx
+1992     # . . call
+1993     e8/call  next-word/disp32
+1994     # . . discard args
+1995     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1996     # if (slice-empty?(word-slice)) return false
+1997     # . eax = slice-empty?(word-slice)
+1998     # . . push args
+1999     52/push-edx
+2000     # . . call
+2001     e8/call  slice-empty?/disp32
+2002     # . . discard args
+2003     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2004     # . if (eax != 0) return
+2005     3d/compare-eax-and  0/imm32/false
+2006     0f 85/jump-if-!=  $far-jump-or-call?:end/disp32
+2007     # datum = next-token-from-slice(word-slice->start, word-slice->end, "/")
+2008     # . . push args
+2009     53/push-ebx
+2010     68/push  0x2f/imm32/slash
+2011     ff          6/subop/push        1/mod/*+disp8   2/rm32/edx    .           .             .           .           4/disp8         .                 # push *(edx+4)
+2012     ff          6/subop/push        0/mod/indirect  2/rm32/edx    .           .             .           .           .               .                 # push *edx
+2013     # . . call
+2014     e8/call  next-token-from-slice/disp32
+2015     # . . discard args
+2016     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+2017     # if (datum-slice == "e8") return true
+2018     # . eax = slice-equal?(datum-slice, "e8")
+2019     # . . push args
+2020     68/push  "e8"/imm32
+2021     53/push-ebx
+2022     # . . call
+2023     e8/call  slice-equal?/disp32
+2024     # . . discard args
+2025     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2026     # . if (eax != false) return true
+2027     3d/compare-eax-and  0/imm32/false
+2028     75/jump-if-!=  $far-jump-or-call?:return-true/disp8
+2029     # if (datum-slice == "e9") return true
+2030     # . eax = slice-equal?(datum-slice, "e9")
+2031     # . . push args
+2032     68/push  "e9"/imm32
+2033     53/push-ebx
+2034     # . . call
+2035     e8/call  slice-equal?/disp32
+2036     # . . discard args
+2037     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2038     # . if (eax != false) return true
+2039     3d/compare-eax-and  0/imm32/false
+2040     75/jump-if-!=  $far-jump-or-call?:return-true/disp8
+2041     # if (datum-slice != "0f") return false
+2042     # . eax = slice-equal?(datum-slice, "0f")
+2043     # . . push args
+2044     68/push  "0f"/imm32
+2045     53/push-ebx
+2046     # . . call
+2047     e8/call  slice-equal?/disp32
+2048     # . . discard args
+2049     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2050     # . if (eax == false) return
+2051     3d/compare-eax-and  0/imm32/false
+2052     74/jump-if-=  $far-jump-or-call?:end/disp8
+2053 $far-jump-or-call?:check-second-word:
+2054     # next-word(line, word-slice)
+2055     # . . push args
+2056     52/push-edx
+2057     51/push-ecx
+2058     # . . call
+2059     e8/call  next-word/disp32
+2060     # . . discard args
+2061     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2062     # if (slice-empty?(word-slice)) return false
+2063     # . eax = slice-empty?(word-slice)
+2064     # . . push args
+2065     52/push-edx
+2066     # . . call
+2067     e8/call  slice-empty?/disp32
+2068     # . . discard args
+2069     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2070     # . if (eax != 0) return
+2071     3d/compare-eax-and  0/imm32/false
+2072     75/jump-if-!=  $far-jump-or-call?:end/disp8
+2073     # if datum of word-slice does not start with "8", return false
+2074     # . start/eax = word-slice->start
+2075     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           0/r32/eax   .               .                 # copy *edx to eax
+2076     # . c/eax = *start
+2077     8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           0/r32/AL    .               .                 # copy byte at *eax to AL
+2078     25/and-eax-with  0xff/imm32
+2079     # . if (eax != '8') return
+2080     3d/compare-eax-and  0x38/imm32/8
+2081     75/jump-if-!=  $far-jump-or-call?:end/disp8
+2082     # otherwise return true
+2083 $far-jump-or-call?:return-true:
+2084     bf/copy-to-edi  1/imm32/true
+2085 $far-jump-or-call?:end:
+2086     # . reclaim locals
+2087     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+2088     # . restore registers
+2089     5b/pop-to-ebx
+2090     5a/pop-to-edx
+2091     59/pop-to-ecx
+2092     58/pop-to-eax
+2093     # . epilogue
+2094     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2095     5d/pop-to-ebp
+2096     c3/return
+2097 
+2098 # - some helpers for tests
+2099 
+2100 stream-add2:  # in: (addr stream byte), key: handle, val: int
+2101     # . prologue
+2102     55/push-ebp
+2103     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2104     # . save registers
+2105     50/push-eax
+2106     51/push-ecx
+2107     52/push-edx
+2108     56/push-esi
+2109     # esi = in
+2110     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+2111     # curr/eax = &in->data[in->write]
+2112     # . eax = in->write
+2113     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
+2114     # . eax = esi+eax+12
+2115     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
+2116     # max/edx = &in->data[in->size]
+2117     # . edx = in->size
+2118     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           2/r32/edx   8/disp8         .                 # copy *(esi+8) to edx
+2119     # . edx = esi+edx+12
+2120     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  2/index/edx   .           2/r32/edx   0xc/disp8       .                 # copy esi+edx+12 to edx
+2121     # if (curr >= max) abort
+2122     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax with edx
+2123     73/jump-if-addr>=  $stream-add2:abort/disp8
+2124     # *curr = key->alloc-id
+2125     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
+2126     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
+2127     # curr += 4
+2128     05/add-to-eax  4/imm32
+2129     # if (curr >= max) abort
+2130     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax with edx
+2131     73/jump-if-addr>=  $stream-add2:abort/disp8
+2132     # *curr = key->payload
+2133     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   0x10/disp8      .                 # copy *(ebp+16) to ecx
+2134     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
+2135     # curr += 4
+2136     05/add-to-eax  4/imm32
+2137     # if (curr >= max) abort
+2138     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax with edx
+2139     73/jump-if-addr>=  $stream-add2:abort/disp8
+2140     # *curr = val
+2141     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   0x14/disp8      .                 # copy *(ebp+20) to ecx
+2142     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
+2143     # in->write += 0xc
+2144     81          0/subop/add         0/mod/indirect  6/rm32/esi    .           .             .           .           .               0xc/imm32         # add to *esi
+2145 $stream-add2:end:
+2146     # . restore registers
+2147     5e/pop-to-esi
+2148     5a/pop-to-edx
+2149     59/pop-to-ecx
+2150     58/pop-to-eax
+2151     # . epilogue
+2152     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2153     5d/pop-to-ebp
+2154     c3/return
+2155 
+2156 $stream-add2:abort:
+2157     # . _write(2/stderr, error)
+2158     # . . push args
+2159     68/push  "overflow in stream-add2\n"/imm32
+2160     68/push  2/imm32/stderr
+2161     # . . call
+2162     e8/call  _write/disp32
+2163     # . . discard args
+2164     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2165     # . syscall(exit, 1)
+2166     bb/copy-to-ebx  1/imm32
+2167     e8/call  syscall_exit/disp32
+2168     # never gets here
+2169 
+2170 # some variants of 'trace' that take multiple arguments in different combinations of types:
+2171 #   n: int
+2172 #   c: character [4-bytes, will eventually be UTF-8]
+2173 #   s: (addr array byte)
+2174 #   l: (addr slice)
+2175 # one gotcha: 's5' must not be empty
+2176 
+2177 trace-slsns:  # s1: (addr array byte), l2: (addr slice), s3: (addr array byte), n4: int, s5: (addr array byte)
+2178     # . prologue
+2179     55/push-ebp
+2180     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2181     # write(*Trace-stream, s1)
+2182     # . . push args
+2183     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+2184     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+2185     # . . call
+2186     e8/call  write/disp32
+2187     # . . discard args
+2188     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2189     # write-slice(*Trace-stream, l2)
+2190     # . . push args
+2191     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+2192     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+2193     # . . call
+2194     e8/call  write-slice/disp32
+2195     # . . discard args
+2196     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2197     # write(*Trace-stream, s3)
+2198     # . . push args
+2199     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
+2200     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+2201     # . . call
+2202     e8/call  write/disp32
+2203     # . . discard args
+2204     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2205     # write-int32-hex(*Trace-stream, n4)
+2206     # . . push args
+2207     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x14/disp8      .                 # push *(ebp+20)
+2208     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+2209     # . . call
+2210     e8/call  write-int32-hex/disp32
+2211     # . . discard args
+2212     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2213     # trace(s5)  # implicitly adds a newline and finalizes the trace line
+2214     # . . push args
+2215     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x18/disp8      .                 # push *(ebp+24)
+2216     # . . call
+2217     e8/call  trace/disp32
+2218     # . . discard args
+2219     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2220 $trace-slsns:end:
+2221     # . epilogue
+2222     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2223     5d/pop-to-ebp
+2224     c3/return
+2225 
+2226 test-trace-slsns:
+2227     # . prologue
+2228     55/push-ebp
+2229     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2230     # setup
+2231     # . *Trace-stream->write = 0
+2232     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/eax   Trace-stream/disp32               # copy *Trace-stream to eax
+2233     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm32           # clear *eax
+2234     # (eax..ecx) = "b"
+2235     b8/copy-to-eax  "b"/imm32
+2236     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
+2237     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
+2238     05/add-to-eax  4/imm32
+2239     # var b/ebx: slice = {eax, ecx}
+2240     51/push-ecx
+2241     50/push-eax
+2242     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+2243     # trace-slsls("A" b "c " 3 " e")
+2244     # . . push args
+2245     68/push  " e"/imm32
+2246     68/push  3/imm32
+2247     68/push  "c "/imm32
+2248     53/push-ebx
+2249     68/push  "A"/imm32
+2250     # . . call
+2251     e8/call  trace-slsns/disp32
+2252     # . . discard args
+2253     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
+2254 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
+2280     # check-trace-contains("Abc 0x00000003 e")
+2281     # . . push args
+2282     68/push  "F - test-trace-slsls"/imm32
+2283     68/push  "Abc 0x00000003 e"/imm32
+2284     # . . call
+2285     e8/call  check-trace-contains/disp32
+2286     # . . discard args
+2287     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2288     # . epilogue
+2289     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2290     5d/pop-to-ebp
+2291     c3/return
+2292 
+2293 num-bytes:  # line: (addr stream byte) -> eax: int
+2294     # pseudocode:
+2295     #   result = 0
+2296     #   while true
+2297     #     var word-slice = next-word(line)
+2298     #     if slice-empty?(word-slice)             # end of line
+2299     #       break
+2300     #     if slice-starts-with?(word-slice, "#")  # comment
+2301     #       break
+2302     #     if label?(word-slice)                # no need for label declarations anymore
+2303     #       break
+2304     #     if slice-equal?(word-slice, "==")
+2305     #       break                                 # no need for segment header lines
+2306     #     result += compute-width(word-slice)
+2307     #   return result
+2308     #
+2309     # . prologue
+2310     55/push-ebp
+2311     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2312     # . save registers
+2313     51/push-ecx
+2314     52/push-edx
+2315     53/push-ebx
+2316     # var result/eax = 0
+2317     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
+2318     # var word-slice/ecx: slice
+2319     68/push  0/imm32/end
+2320     68/push  0/imm32/start
+2321     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+2322 +-- 26 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
+2348     # . rewind-stream(line)
+2349     # . . push args
+2350     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+2351     # . . call
+2352     e8/call  rewind-stream/disp32
+2353     # . . discard args
+2354     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2355 $num-bytes:loop:
+2356     # next-word(line, word-slice)
+2357     # . . push args
+2358     51/push-ecx
+2359     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+2360     # . . call
+2361     e8/call  next-word/disp32
+2362     # . . discard args
+2363     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2364 +-- 40 lines: #?     # dump word-slice --------------------------------------------------------------------------------------------------------------------------------------------------
+2404 $num-bytes:check0:
+2405     # if (slice-empty?(word-slice)) break
+2406     # . save result
+2407     50/push-eax
+2408     # . eax = slice-empty?(word-slice)
+2409     # . . push args
+2410     51/push-ecx
+2411     # . . call
+2412     e8/call  slice-empty?/disp32
+2413     # . . discard args
+2414     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2415     # . if (eax != false) break
+2416     3d/compare-eax-and  0/imm32/false
+2417     # . restore result now that ZF is set
+2418     58/pop-to-eax
+2419     75/jump-if-!=  $num-bytes:end/disp8
+2420 $num-bytes:check-for-comment:
+2421     # if (slice-starts-with?(word-slice, "#")) break
+2422     # . start/edx = word-slice->start
+2423     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # copy *ecx to edx
+2424     # . c/ebx = *start
+2425     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
+2426     8a/copy-byte                    0/mod/indirect  2/rm32/edx    .           .             .           3/r32/BL    .               .                 # copy byte at *edx to BL
+2427     # . if (ebx == '#') break
+2428     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x23/imm32/hash   # compare ebx
+2429     74/jump-if-=  $num-bytes:end/disp8
+2430 $num-bytes:check-for-label:
+2431     # if (slice-ends-with?(word-slice, ":")) break
+2432     # . end/edx = word-slice->end
+2433     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .             .           2/r32/edx   4/disp8         .                 # copy *(ecx+4) to edx
+2434     # . c/ebx = *(end-1)
+2435     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
+2436     8a/copy-byte                    1/mod/*+disp8   2/rm32/edx    .           .             .           3/r32/BL    -1/disp8        .                 # copy byte at *ecx to BL
+2437     # . if (ebx == ':') break
+2438     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x3a/imm32/colon  # compare ebx
+2439     74/jump-if-=  $num-bytes:end/disp8
+2440 $num-bytes:check-for-segment-header:
+2441     # if (slice-equal?(word-slice, "==")) break
+2442     # . push result
+2443     50/push-eax
+2444     # . eax = slice-equal?(word-slice, "==")
+2445     # . . push args
+2446     68/push  "=="/imm32
+2447     51/push-ecx
+2448     # . . call
+2449     e8/call  slice-equal?/disp32
+2450     # . . discard args
+2451     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2452     # . if (eax != false) break
+2453     3d/compare-eax-and  0/imm32/false
+2454     # . restore result now that ZF is set
+2455     58/pop-to-eax
+2456     75/jump-if-!=  $num-bytes:end/disp8
+2457 $num-bytes:loop-body:
+2458     # result += compute-width-of-slice(word-slice)
+2459     # . copy result to edx
+2460     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           0/r32/eax   .               .                 # copy eax to edx
+2461     # . eax = compute-width-of-slice(word-slice)
+2462     # . . push args
+2463     51/push-ecx
+2464     # . . call
+2465     e8/call compute-width-of-slice/disp32
+2466     # . . discard args
+2467     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2468     # . eax += result
+2469     01/add                          3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # add edx to eax
+2470     e9/jump  $num-bytes:loop/disp32
+2471 $num-bytes:end:
+2472     # . rewind-stream(line)
+2473     # . . push args
+2474     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+2475     # . . call
+2476     e8/call  rewind-stream/disp32
+2477     # . . discard args
+2478     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2479     # . reclaim locals
+2480     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2481     # . restore registers
+2482     5b/pop-to-ebx
+2483     5a/pop-to-edx
+2484     59/pop-to-ecx
+2485     # . epilogue
+2486     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2487     5d/pop-to-ebp
+2488     c3/return
+2489 
+2490 test-num-bytes-handles-empty-string:
+2491     # if a line starts with '#', return 0
+2492     # . prologue
+2493     55/push-ebp
+2494     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2495     # setup
+2496     # . clear-stream(_test-input-stream)
+2497     # . . push args
+2498     68/push  _test-input-stream/imm32
+2499     # . . call
+2500     e8/call  clear-stream/disp32
+2501     # . . discard args
+2502     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2503     # . clear-stream(_test-output-stream)
+2504     # . . push args
+2505     68/push  _test-output-stream/imm32
+2506     # . . call
+2507     e8/call  clear-stream/disp32
+2508     # . . discard args
+2509     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2510     # no contents in input
+2511     # eax = num-bytes(_test-input-stream)
+2512     # . . push args
+2513     68/push  _test-input-stream/imm32
+2514     # . . call
+2515     e8/call  num-bytes/disp32
+2516     # . . discard args
+2517     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2518     # check-ints-equal(eax, 0, msg)
+2519     # . . push args
+2520     68/push  "F - test-num-bytes-handles-empty-string"/imm32
+2521     68/push  0/imm32/true
+2522     50/push-eax
+2523     # . . call
+2524     e8/call  check-ints-equal/disp32
+2525     # . . discard args
+2526     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2527     # . epilogue
+2528     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2529     5d/pop-to-ebp
+2530     c3/return
+2531 
+2532 test-num-bytes-ignores-comments:
+2533     # if a line starts with '#', return 0
+2534     # . prologue
+2535     55/push-ebp
+2536     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2537     # setup
+2538     # . clear-stream(_test-input-stream)
+2539     # . . push args
+2540     68/push  _test-input-stream/imm32
+2541     # . . call
+2542     e8/call  clear-stream/disp32
+2543     # . . discard args
+2544     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2545     # . clear-stream(_test-output-stream)
+2546     # . . push args
+2547     68/push  _test-output-stream/imm32
+2548     # . . call
+2549     e8/call  clear-stream/disp32
+2550     # . . discard args
+2551     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2552     # initialize input
+2553     # . write(_test-input-stream, "# abcd")
+2554     # . . push args
+2555     68/push  "# abcd"/imm32
+2556     68/push  _test-input-stream/imm32
+2557     # . . call
+2558     e8/call  write/disp32
+2559     # . . discard args
+2560     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2561     # eax = num-bytes(_test-input-stream)
+2562     # . . push args
+2563     68/push  _test-input-stream/imm32
+2564     # . . call
+2565     e8/call  num-bytes/disp32
+2566     # . . discard args
+2567     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2568     # check-ints-equal(eax, 0, msg)
+2569     # . . push args
+2570     68/push  "F - test-num-bytes-ignores-comments"/imm32
+2571     68/push  0/imm32/true
+2572     50/push-eax
+2573     # . . call
+2574     e8/call  check-ints-equal/disp32
+2575     # . . discard args
+2576     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2577     # . epilogue
+2578     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2579     5d/pop-to-ebp
+2580     c3/return
+2581 
+2582 test-num-bytes-ignores-labels:
+2583     # if the first word ends with ':', return 0
+2584     # . prologue
+2585     55/push-ebp
+2586     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2587     # setup
+2588     # . clear-stream(_test-input-stream)
+2589     # . . push args
+2590     68/push  _test-input-stream/imm32
+2591     # . . call
+2592     e8/call  clear-stream/disp32
+2593     # . . discard args
+2594     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2595     # . clear-stream(_test-output-stream)
+2596     # . . push args
+2597     68/push  _test-output-stream/imm32
+2598     # . . call
+2599     e8/call  clear-stream/disp32
+2600     # . . discard args
+2601     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2602     # initialize input
+2603     # . write(_test-input-stream, "ab: # cd")
+2604     # . . push args
+2605     68/push  "ab: # cd"/imm32
+2606     68/push  _test-input-stream/imm32
+2607     # . . call
+2608     e8/call  write/disp32
+2609     # . . discard args
+2610     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2611     # eax = num-bytes(_test-input-stream)
+2612     # . . push args
+2613     68/push  _test-input-stream/imm32
+2614     # . . call
+2615     e8/call  num-bytes/disp32
+2616     # . . discard args
+2617     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2618     # check-ints-equal(eax, 0, msg)
+2619     # . . push args
+2620     68/push  "F - test-num-bytes-ignores-labels"/imm32
+2621     68/push  0/imm32/true
+2622     50/push-eax
+2623     # . . call
+2624     e8/call  check-ints-equal/disp32
+2625     # . . discard args
+2626     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2627     # . epilogue
+2628     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2629     5d/pop-to-ebp
+2630     c3/return
+2631 
+2632 test-num-bytes-ignores-segment-headers:
+2633     # if the first word is '==', return 0
+2634     # . prologue
+2635     55/push-ebp
+2636     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2637     # setup
+2638     # . clear-stream(_test-input-stream)
+2639     # . . push args
+2640     68/push  _test-input-stream/imm32
+2641     # . . call
+2642     e8/call  clear-stream/disp32
+2643     # . . discard args
+2644     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2645     # . clear-stream(_test-output-stream)
+2646     # . . push args
+2647     68/push  _test-output-stream/imm32
+2648     # . . call
+2649     e8/call  clear-stream/disp32
+2650     # . . discard args
+2651     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2652     # initialize input
+2653     # . write(_test-input-stream, "== ab cd")
+2654     # . . push args
+2655     68/push  "== ab cd"/imm32
+2656     68/push  _test-input-stream/imm32
+2657     # . . call
+2658     e8/call  write/disp32
+2659     # . . discard args
+2660     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2661     # eax = num-bytes(_test-input-stream)
+2662     # . . push args
+2663     68/push  _test-input-stream/imm32
+2664     # . . call
+2665     e8/call  num-bytes/disp32
+2666     # . . discard args
+2667     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2668     # check-ints-equal(eax, 0, msg)
+2669     # . . push args
+2670     68/push  "F - test-num-bytes-ignores-segment-headers"/imm32
+2671     68/push  0/imm32/true
+2672     50/push-eax
+2673     # . . call
+2674     e8/call  check-ints-equal/disp32
+2675     # . . discard args
+2676     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2677     # . epilogue
+2678     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2679     5d/pop-to-ebp
+2680     c3/return
+2681 
+2682 test-num-bytes-counts-words-by-default:
+2683     # without metadata, count words
+2684     # . prologue
+2685     55/push-ebp
+2686     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2687     # setup
+2688     # . clear-stream(_test-input-stream)
+2689     # . . push args
+2690     68/push  _test-input-stream/imm32
+2691     # . . call
+2692     e8/call  clear-stream/disp32
+2693     # . . discard args
+2694     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2695     # . clear-stream(_test-output-stream)
+2696     # . . push args
+2697     68/push  _test-output-stream/imm32
+2698     # . . call
+2699     e8/call  clear-stream/disp32
+2700     # . . discard args
+2701     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2702     # initialize input
+2703     # . write(_test-input-stream, "ab cd ef")
+2704     # . . push args
+2705     68/push  "ab cd ef"/imm32
+2706     68/push  _test-input-stream/imm32
+2707     # . . call
+2708     e8/call  write/disp32
+2709     # . . discard args
+2710     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2711     # eax = num-bytes(_test-input-stream)
+2712     # . . push args
+2713     68/push  _test-input-stream/imm32
+2714     # . . call
+2715     e8/call  num-bytes/disp32
+2716     # . . discard args
+2717     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2718     # check-ints-equal(eax, 3, msg)
+2719     # . . push args
+2720     68/push  "F - test-num-bytes-counts-words-by-default"/imm32
+2721     68/push  3/imm32/true
+2722     50/push-eax
+2723     # . . call
+2724     e8/call  check-ints-equal/disp32
+2725     # . . discard args
+2726     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2727     # . epilogue
+2728     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2729     5d/pop-to-ebp
+2730     c3/return
+2731 
+2732 test-num-bytes-ignores-trailing-comment:
+2733     # trailing comments appropriately ignored
+2734     # . prologue
+2735     55/push-ebp
+2736     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2737     # setup
+2738     # . clear-stream(_test-input-stream)
+2739     # . . push args
+2740     68/push  _test-input-stream/imm32
+2741     # . . call
+2742     e8/call  clear-stream/disp32
+2743     # . . discard args
+2744     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2745     # . clear-stream(_test-output-stream)
+2746     # . . push args
+2747     68/push  _test-output-stream/imm32
+2748     # . . call
+2749     e8/call  clear-stream/disp32
+2750     # . . discard args
+2751     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2752     # initialize input
+2753     # . write(_test-input-stream, "ab cd # ef")
+2754     # . . push args
+2755     68/push  "ab cd # ef"/imm32
+2756     68/push  _test-input-stream/imm32
+2757     # . . call
+2758     e8/call  write/disp32
+2759     # . . discard args
+2760     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2761     # eax = num-bytes(_test-input-stream)
+2762     # . . push args
+2763     68/push  _test-input-stream/imm32
+2764     # . . call
+2765     e8/call  num-bytes/disp32
+2766     # . . discard args
+2767     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2768     # check-ints-equal(eax, 2, msg)
+2769     # . . push args
+2770     68/push  "F - test-num-bytes-ignores-trailing-comment"/imm32
+2771     68/push  2/imm32/true
+2772     50/push-eax
+2773     # . . call
+2774     e8/call  check-ints-equal/disp32
+2775     # . . discard args
+2776     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2777     # . epilogue
+2778     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2779     5d/pop-to-ebp
+2780     c3/return
+2781 
+2782 test-num-bytes-handles-imm32:
+2783     # if a word has the /imm32 metadata, count it as 4 bytes
+2784     # . prologue
+2785     55/push-ebp
+2786     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+2787     # setup
+2788     # . clear-stream(_test-input-stream)
+2789     # . . push args
+2790     68/push  _test-input-stream/imm32
+2791     # . . call
+2792     e8/call  clear-stream/disp32
+2793     # . . discard args
+2794     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2795     # . clear-stream(_test-output-stream)
+2796     # . . push args
+2797     68/push  _test-output-stream/imm32
+2798     # . . call
+2799     e8/call  clear-stream/disp32
+2800     # . . discard args
+2801     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2802     # initialize input
+2803     # . write(_test-input-stream, "ab cd/imm32 ef")
+2804     # . . push args
+2805     68/push  "ab cd/imm32 ef"/imm32
+2806     68/push  _test-input-stream/imm32
+2807     # . . call
+2808     e8/call  write/disp32
+2809     # . . discard args
+2810     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+2811     # eax = num-bytes(_test-input-stream)
+2812     # . . push args
+2813     68/push  _test-input-stream/imm32
+2814     # . . call
+2815     e8/call  num-bytes/disp32
+2816     # . . discard args
+2817     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+2818     # check-ints-equal(eax, 6, msg)
+2819     # . . push args
+2820     68/push  "F - test-num-bytes-handles-imm32"/imm32
+2821     68/push  6/imm32/true
+2822     50/push-eax
+2823     # . . call
+2824     e8/call  check-ints-equal/disp32
+2825     # . . discard args
+2826     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+2827     # . epilogue
+2828     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+2829     5d/pop-to-ebp
+2830     c3/return
+2831 
+2832 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/linux/mu.subx.html b/html/linux/mu.subx.html index 38561550..e9b68096 100644 --- a/html/linux/mu.subx.html +++ b/html/linux/mu.subx.html @@ -575,7 +575,7 @@ if ('onhashchange' in window) { 513 # . save registers 514 50/push-eax 515 # initialize global data structures - 516 c7 0/subop/copy *Next-block-index 1/imm32 + 516 c7 0/subop/copy *Next-block-index 1/imm32 517 8b/-> *Primitive-type-ids 0/r32/eax 518 89/<- *Type-id 0/r32/eax # stream-write 519 c7 0/subop/copy *_Program-functions 0/imm32 @@ -585,11 +585,11 @@ if ('onhashchange' in window) { 523 c7 0/subop/copy *_Program-signatures 0/imm32 524 c7 0/subop/copy *_Program-signatures->payload 0/imm32 525 # - 526 (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14)) - 527 (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14)) + 526 (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14)) + 527 (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14)) 528 #? (dump-typeinfos "=== typeinfos\n") - 529 (check-mu-types *(ebp+0x10) *(ebp+0x14)) - 530 (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) + 529 (check-mu-types *(ebp+0x10) *(ebp+0x14)) + 530 (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) 531 $convert-mu:end: 532 # . restore registers 533 58/pop-to-eax @@ -5776,7519 +5776,7519 @@ if ('onhashchange' in window) { 6309 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array/8") 6310 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array/9") 6311 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array/10") - 6312 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/11") - 6313 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/12") - 6314 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/13") - 6315 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/14") - 6316 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/15") - 6317 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/16") - 6318 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/17") - 6319 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/18") - 6320 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/19") - 6321 # . epilogue - 6322 89/<- %esp 5/r32/ebp - 6323 5d/pop-to-ebp - 6324 c3/return - 6325 - 6326 test-convert-index-into-array-of-bytes: - 6327 # . prologue - 6328 55/push-ebp - 6329 89/<- %ebp 4/r32/esp - 6330 # setup - 6331 (clear-stream _test-input-stream) - 6332 (clear-stream $_test-input-buffered-file->buffer) - 6333 (clear-stream _test-output-stream) - 6334 (clear-stream $_test-output-buffered-file->buffer) - 6335 # - 6336 (write _test-input-stream "fn foo {\n") - 6337 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") - 6338 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 6339 (write _test-input-stream " var x/eax: (addr byte) <- index arr, idx\n") - 6340 (write _test-input-stream "}\n") - 6341 # convert - 6342 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6343 (flush _test-output-buffered-file) - 6344 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6350 # check output - 6351 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes/0") - 6352 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes/1") - 6353 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes/2") - 6354 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes/3") - 6355 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes/4") - 6356 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes/5") - 6357 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes/6") - 6358 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes/7") - 6359 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes/8") - 6360 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-of-bytes/9") - 6361 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes/10") - 6362 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes/11") - 6363 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes/12") - 6364 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes/13") - 6365 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes/14") - 6366 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes/15") - 6367 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes/16") - 6368 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes/17") - 6369 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes/18") - 6370 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes/19") - 6371 # . epilogue - 6372 89/<- %esp 5/r32/ebp - 6373 5d/pop-to-ebp - 6374 c3/return - 6375 - 6376 test-convert-index-into-array-with-literal: - 6377 # . prologue - 6378 55/push-ebp - 6379 89/<- %ebp 4/r32/esp - 6380 # setup - 6381 (clear-stream _test-input-stream) - 6382 (clear-stream $_test-input-buffered-file->buffer) - 6383 (clear-stream _test-output-stream) - 6384 (clear-stream $_test-output-buffered-file->buffer) - 6385 # - 6386 (write _test-input-stream "fn foo {\n") - 6387 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 6388 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") - 6389 (write _test-input-stream "}\n") - 6390 # convert - 6391 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6392 (flush _test-output-buffered-file) - 6393 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6399 # check output - 6400 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-with-literal/0") - 6401 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-with-literal/1") - 6402 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-with-literal/2") - 6403 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-with-literal/3") - 6404 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-with-literal/4") - 6405 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5") - 6406 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6") - 6407 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7") - 6408 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-with-literal/8") - 6409 # 2 * 4 bytes/elem + 4 bytes for size = offset 12 - 6410 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/9") - 6411 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/10") - 6412 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/11") - 6413 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/12") - 6414 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/13") - 6415 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/14") - 6416 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/15") - 6417 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/16") - 6418 # . epilogue - 6419 89/<- %esp 5/r32/ebp - 6420 5d/pop-to-ebp - 6421 c3/return - 6422 - 6423 test-convert-index-into-array-of-bytes-with-literal: - 6424 # . prologue - 6425 55/push-ebp - 6426 89/<- %ebp 4/r32/esp - 6427 # setup - 6428 (clear-stream _test-input-stream) - 6429 (clear-stream $_test-input-buffered-file->buffer) - 6430 (clear-stream _test-output-stream) - 6431 (clear-stream $_test-output-buffered-file->buffer) - 6432 # - 6433 (write _test-input-stream "fn foo {\n") - 6434 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") - 6435 (write _test-input-stream " var x/eax: (addr byte) <- index arr, 2\n") - 6436 (write _test-input-stream "}\n") - 6437 # convert - 6438 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6439 (flush _test-output-buffered-file) - 6440 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6446 # check output - 6447 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-with-literal/0") - 6448 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-with-literal/1") - 6449 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-with-literal/2") - 6450 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-with-literal/3") - 6451 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-with-literal/4") - 6452 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-with-literal/5") - 6453 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-with-literal/6") - 6454 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-with-literal/7") - 6455 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-with-literal/8") - 6456 # 2 * 1 byte/elem + 4 bytes for size = offset 6 - 6457 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000006) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-with-literal/8") - 6458 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-with-literal/9") - 6459 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-with-literal/10") - 6460 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-with-literal/11") - 6461 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-with-literal/12") - 6462 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-with-literal/13") - 6463 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-with-literal/14") - 6464 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-with-literal/15") - 6465 # . epilogue - 6466 89/<- %esp 5/r32/ebp - 6467 5d/pop-to-ebp - 6468 c3/return - 6469 - 6470 test-convert-index-into-array-on-stack: - 6471 # . prologue - 6472 55/push-ebp - 6473 89/<- %ebp 4/r32/esp - 6474 # setup - 6475 (clear-stream _test-input-stream) - 6476 (clear-stream $_test-input-buffered-file->buffer) - 6477 (clear-stream _test-output-stream) - 6478 (clear-stream $_test-output-buffered-file->buffer) - 6479 # - 6480 (write _test-input-stream "fn foo {\n") - 6481 (write _test-input-stream " var arr: (array int 3)\n") - 6482 (write _test-input-stream " var idx/eax: int <- copy 2\n") - 6483 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") - 6484 (write _test-input-stream "}\n") - 6485 # convert - 6486 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6487 (flush _test-output-buffered-file) - 6488 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6494 # check output - 6495 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack/0") - 6496 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack/1") - 6497 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack/2") - 6498 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack/3") - 6499 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack/4") - 6500 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack/5") - 6501 # var arr - 6502 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack/6") - 6503 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack/7") - 6504 # var idx - 6505 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8") - 6506 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9") - 6507 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")" "F - test-convert-index-into-array-on-stack/10") - 6508 # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc - 6509 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/11") - 6510 # reclaim idx - 6511 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/12") - 6512 # reclaim arr - 6513 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/13") - 6514 # - 6515 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/14") - 6516 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/15") - 6517 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/16") - 6518 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/17") - 6519 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/18") - 6520 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/19") - 6521 # . epilogue - 6522 89/<- %esp 5/r32/ebp - 6523 5d/pop-to-ebp - 6524 c3/return - 6525 - 6526 test-convert-index-into-array-on-stack-with-literal: - 6527 # . prologue - 6528 55/push-ebp - 6529 89/<- %ebp 4/r32/esp - 6530 # setup - 6531 (clear-stream _test-input-stream) - 6532 (clear-stream $_test-input-buffered-file->buffer) - 6533 (clear-stream _test-output-stream) - 6534 (clear-stream $_test-output-buffered-file->buffer) - 6535 # - 6536 (write _test-input-stream "fn foo {\n") - 6537 (write _test-input-stream " var arr: (array int 3)\n") - 6538 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") - 6539 (write _test-input-stream "}\n") - 6540 # convert - 6541 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6542 (flush _test-output-buffered-file) - 6543 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6549 # check output - 6550 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack-with-literal/0") - 6551 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack-with-literal/1") - 6552 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack-with-literal/2") - 6553 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack-with-literal/3") - 6554 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack-with-literal/4") - 6555 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack-with-literal/5") - 6556 # var arr - 6557 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack-with-literal/6") - 6558 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7") - 6559 # var x - 6560 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8") - 6561 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")" "F - test-convert-index-into-array-on-stack-with-literal/9") - 6562 # x is at (ebp-0x10) + 4 + 2*4 = ebp-4 - 6563 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/10") - 6564 # reclaim x - 6565 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/11") - 6566 # reclaim arr - 6567 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/12") - 6568 # - 6569 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/13") - 6570 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/14") - 6571 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/15") - 6572 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/16") - 6573 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/17") - 6574 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/18") - 6575 # . epilogue - 6576 89/<- %esp 5/r32/ebp - 6577 5d/pop-to-ebp - 6578 c3/return - 6579 - 6580 test-convert-index-into-array-of-bytes-on-stack-with-literal: - 6581 # . prologue - 6582 55/push-ebp - 6583 89/<- %ebp 4/r32/esp - 6584 # setup - 6585 (clear-stream _test-input-stream) - 6586 (clear-stream $_test-input-buffered-file->buffer) - 6587 (clear-stream _test-output-stream) - 6588 (clear-stream $_test-output-buffered-file->buffer) - 6589 # - 6590 (write _test-input-stream "fn foo {\n") - 6591 (write _test-input-stream " var arr: (array byte 3)\n") - 6592 (write _test-input-stream " var x/eax: (addr byte) <- index arr, 2\n") - 6593 (write _test-input-stream "}\n") - 6594 # convert - 6595 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6596 (flush _test-output-buffered-file) - 6597 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6603 # check output - 6604 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0") - 6605 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1") - 6606 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2") - 6607 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/3") - 6608 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4") - 6609 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5") - 6610 # var arr - 6611 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x00000003)" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/6") - 6612 (check-next-stream-line-equal _test-output-stream " 68/push 0x00000003/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/7") - 6613 # var x - 6614 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/8") - 6615 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9") - 6616 # x is at (ebp-7) + 4 + 2 = ebp-1 - 6617 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10") - 6618 # reclaim x - 6619 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11") - 6620 # reclaim arr - 6621 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000007/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12") - 6622 # - 6623 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13") - 6624 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14") - 6625 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15") - 6626 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16") - 6627 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17") - 6628 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18") - 6629 # . epilogue - 6630 89/<- %esp 5/r32/ebp - 6631 5d/pop-to-ebp - 6632 c3/return - 6633 - 6634 test-convert-index-into-array-using-offset: - 6635 # . prologue - 6636 55/push-ebp - 6637 89/<- %ebp 4/r32/esp - 6638 # setup - 6639 (clear-stream _test-input-stream) - 6640 (clear-stream $_test-input-buffered-file->buffer) - 6641 (clear-stream _test-output-stream) - 6642 (clear-stream $_test-output-buffered-file->buffer) - 6643 # - 6644 (write _test-input-stream "fn foo {\n") - 6645 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 6646 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 6647 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") - 6648 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") - 6649 (write _test-input-stream "}\n") - 6650 # convert - 6651 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6652 (flush _test-output-buffered-file) - 6653 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6659 # check output - 6660 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset/0") - 6661 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset/1") - 6662 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset/2") - 6663 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset/3") - 6664 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset/4") - 6665 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset/5") - 6666 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset/6") - 6667 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset/7") - 6668 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8") - 6669 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9") - 6670 (check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10") - 6671 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-using-offset/11") - 6672 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/12") - 6673 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/13") - 6674 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/14") - 6675 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/15") - 6676 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/16") - 6677 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/17") - 6678 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/18") - 6679 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/19") - 6680 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/20") - 6681 # . epilogue - 6682 89/<- %esp 5/r32/ebp - 6683 5d/pop-to-ebp - 6684 c3/return - 6685 - 6686 test-convert-index-into-array-of-bytes-using-offset: - 6687 # . prologue - 6688 55/push-ebp - 6689 89/<- %ebp 4/r32/esp - 6690 # setup - 6691 (clear-stream _test-input-stream) - 6692 (clear-stream $_test-input-buffered-file->buffer) - 6693 (clear-stream _test-output-stream) - 6694 (clear-stream $_test-output-buffered-file->buffer) - 6695 # - 6696 (write _test-input-stream "fn foo {\n") - 6697 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") - 6698 (write _test-input-stream " var idx/ecx: int <- copy 3\n") - 6699 (write _test-input-stream " var off/ecx: (offset byte) <- compute-offset arr, idx\n") - 6700 (write _test-input-stream " var x/eax: (addr byte) <- index arr, off\n") - 6701 (write _test-input-stream "}\n") - 6702 # convert - 6703 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6704 (flush _test-output-buffered-file) - 6705 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6711 # check output - 6712 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-using-offset/0") - 6713 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-using-offset/1") - 6714 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-using-offset/2") - 6715 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-using-offset/3") - 6716 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-using-offset/4") - 6717 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-using-offset/5") - 6718 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-using-offset/6") - 6719 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset/7") - 6720 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/8") - 6721 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-of-bytes-using-offset/9") - 6722 (check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000001/imm32 0x00000001/r32" "F - test-convert-index-into-array-of-bytes-using-offset/10") - 6723 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-using-offset/11") - 6724 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset/12") - 6725 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/13") - 6726 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset/14") - 6727 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset/15") - 6728 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset/16") - 6729 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset/17") - 6730 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset/18") - 6731 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset/19") - 6732 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset/20") - 6733 # . epilogue - 6734 89/<- %esp 5/r32/ebp - 6735 5d/pop-to-ebp - 6736 c3/return - 6737 - 6738 test-convert-index-into-array-using-offset-on-stack: - 6739 # . prologue - 6740 55/push-ebp - 6741 89/<- %ebp 4/r32/esp - 6742 # setup - 6743 (clear-stream _test-input-stream) - 6744 (clear-stream $_test-input-buffered-file->buffer) - 6745 (clear-stream _test-output-stream) - 6746 (clear-stream $_test-output-buffered-file->buffer) - 6747 # - 6748 (write _test-input-stream "fn foo {\n") - 6749 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") - 6750 (write _test-input-stream " var idx: int\n") - 6751 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") - 6752 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") - 6753 (write _test-input-stream "}\n") - 6754 # convert - 6755 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6756 (flush _test-output-buffered-file) - 6757 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6763 # check output - 6764 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset-on-stack/0") - 6765 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset-on-stack/1") - 6766 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset-on-stack/2") - 6767 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset-on-stack/3") - 6768 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset-on-stack/4") - 6769 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset-on-stack/5") - 6770 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset-on-stack/6") - 6771 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/7") - 6772 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8") - 6773 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9") - 6774 (check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10") - 6775 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-using-offset-on-stack/11") - 6776 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/12") - 6777 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/13") - 6778 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/14") - 6779 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/15") - 6780 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/16") - 6781 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/17") - 6782 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/18") - 6783 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/19") - 6784 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/20") - 6785 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/21") - 6786 # . epilogue - 6787 89/<- %esp 5/r32/ebp - 6788 5d/pop-to-ebp - 6789 c3/return - 6790 - 6791 test-convert-index-into-array-of-bytes-using-offset-on-stack: - 6792 # . prologue - 6793 55/push-ebp - 6794 89/<- %ebp 4/r32/esp - 6795 # setup - 6796 (clear-stream _test-input-stream) - 6797 (clear-stream $_test-input-buffered-file->buffer) - 6798 (clear-stream _test-output-stream) - 6799 (clear-stream $_test-output-buffered-file->buffer) - 6800 # - 6801 (write _test-input-stream "fn foo {\n") - 6802 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") - 6803 (write _test-input-stream " var idx: int\n") - 6804 (write _test-input-stream " var off/ecx: (offset byte) <- compute-offset arr, idx\n") - 6805 (write _test-input-stream " var x/eax: (addr byte) <- index arr, off\n") - 6806 (write _test-input-stream "}\n") - 6807 # convert - 6808 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6809 (flush _test-output-buffered-file) - 6810 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6816 # check output - 6817 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0") - 6818 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1") - 6819 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2") - 6820 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/3") - 6821 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4") - 6822 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5") - 6823 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/6") - 6824 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/7") - 6825 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/8") - 6826 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9") - 6827 (check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10") - 6828 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11") - 6829 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12") - 6830 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13") - 6831 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14") - 6832 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15") - 6833 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16") - 6834 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17") - 6835 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18") - 6836 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19") - 6837 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20") - 6838 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21") - 6839 # . epilogue - 6840 89/<- %esp 5/r32/ebp - 6841 5d/pop-to-ebp - 6842 c3/return - 6843 - 6844 test-convert-function-and-type-definition: - 6845 # . prologue - 6846 55/push-ebp - 6847 89/<- %ebp 4/r32/esp - 6848 # setup - 6849 (clear-stream _test-input-stream) - 6850 (clear-stream $_test-input-buffered-file->buffer) - 6851 (clear-stream _test-output-stream) - 6852 (clear-stream $_test-output-buffered-file->buffer) - 6853 # - 6854 (write _test-input-stream "fn foo a: (addr t) {\n") - 6855 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") - 6856 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") - 6857 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") - 6858 (write _test-input-stream "}\n") - 6859 (write _test-input-stream "type t {\n") - 6860 (write _test-input-stream " x: int\n") - 6861 (write _test-input-stream " y: int\n") - 6862 (write _test-input-stream "}\n") - 6863 # convert - 6864 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 6865 (flush _test-output-buffered-file) - 6866 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 6872 # check output - 6873 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-and-type-definition/0") - 6874 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-and-type-definition/1") - 6875 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-and-type-definition/2") - 6876 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-and-type-definition/3") - 6877 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-and-type-definition/4") - 6878 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-and-type-definition/5") - 6879 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") - 6880 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") - 6881 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") - 6882 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/9") - 6883 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") - 6884 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13") - 6885 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14") - 6886 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/15") - 6887 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/16") - 6888 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/17") - 6889 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/18") - 6890 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/19") - 6891 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/20") - 6892 # . epilogue - 6893 89/<- %esp 5/r32/ebp - 6894 5d/pop-to-ebp - 6895 c3/return - 6896 - 6897 test-type-definition-with-array: - 6898 # . prologue - 6899 55/push-ebp - 6900 89/<- %ebp 4/r32/esp - 6901 # setup - 6902 (clear-stream _test-input-stream) - 6903 (clear-stream $_test-input-buffered-file->buffer) - 6904 (clear-stream _test-output-stream) - 6905 (clear-stream $_test-output-buffered-file->buffer) - 6906 (clear-stream _test-error-stream) - 6907 (clear-stream $_test-error-buffered-file->buffer) - 6908 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 6909 68/push 0/imm32 - 6910 68/push 0/imm32 - 6911 89/<- %edx 4/r32/esp - 6912 (tailor-exit-descriptor %edx 0x10) - 6913 # - 6914 (write _test-input-stream "type t {\n") - 6915 (write _test-input-stream " a: (array int 3)\n") - 6916 (write _test-input-stream "}\n") - 6917 # convert - 6918 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 6919 # registers except esp clobbered at this point - 6920 # restore ed - 6921 89/<- %edx 4/r32/esp - 6922 (flush _test-output-buffered-file) - 6923 (flush _test-error-buffered-file) - 6924 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 6930 # check output - 6931 (check-stream-equal _test-output-stream "" "F - test-type-definition-with-array: output should be empty") - 6932 (check-next-stream-line-equal _test-error-stream "type t: 'array' elements not allowed for now" "F - test-type-definition-with-array: error message") - 6933 # check that stop(1) was called - 6934 (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status") - 6935 # don't restore from ebp - 6936 81 0/subop/add %esp 8/imm32 - 6937 # . epilogue - 6938 5d/pop-to-ebp - 6939 c3/return - 6940 - 6941 test-type-definition-with-addr: - 6942 # . prologue - 6943 55/push-ebp - 6944 89/<- %ebp 4/r32/esp - 6945 # setup - 6946 (clear-stream _test-input-stream) - 6947 (clear-stream $_test-input-buffered-file->buffer) - 6948 (clear-stream _test-output-stream) - 6949 (clear-stream $_test-output-buffered-file->buffer) - 6950 (clear-stream _test-error-stream) - 6951 (clear-stream $_test-error-buffered-file->buffer) - 6952 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 6953 68/push 0/imm32 - 6954 68/push 0/imm32 - 6955 89/<- %edx 4/r32/esp - 6956 (tailor-exit-descriptor %edx 0x10) - 6957 # - 6958 (write _test-input-stream "type t {\n") - 6959 (write _test-input-stream " a: (addr int)\n") - 6960 (write _test-input-stream "}\n") - 6961 # convert - 6962 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 6963 # registers except esp clobbered at this point - 6964 # restore ed - 6965 89/<- %edx 4/r32/esp - 6966 (flush _test-output-buffered-file) - 6967 (flush _test-error-buffered-file) - 6968 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 6974 # check output - 6975 (check-stream-equal _test-output-stream "" "F - test-type-definition-with-addr: output should be empty") - 6976 (check-next-stream-line-equal _test-error-stream "type t: 'addr' elements not allowed" "F - test-type-definition-with-addr: error message") - 6977 # check that stop(1) was called - 6978 (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status") - 6979 # don't restore from ebp - 6980 81 0/subop/add %esp 8/imm32 - 6981 # . epilogue - 6982 5d/pop-to-ebp - 6983 c3/return - 6984 - 6985 test-convert-function-with-local-var-with-user-defined-type: - 6986 # . prologue - 6987 55/push-ebp - 6988 89/<- %ebp 4/r32/esp - 6989 # setup - 6990 (clear-stream _test-input-stream) - 6991 (clear-stream $_test-input-buffered-file->buffer) - 6992 (clear-stream _test-output-stream) - 6993 (clear-stream $_test-output-buffered-file->buffer) - 6994 # - 6995 (write _test-input-stream "fn foo {\n") - 6996 (write _test-input-stream " var a: t\n") - 6997 (write _test-input-stream "}\n") - 6998 (write _test-input-stream "type t {\n") - 6999 (write _test-input-stream " x: int\n") - 7000 (write _test-input-stream " y: int\n") - 7001 (write _test-input-stream "}\n") - 7002 # convert - 7003 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7004 (flush _test-output-buffered-file) - 7005 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7011 # check output - 7012 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type/0") - 7013 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type/1") - 7014 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/2") - 7015 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type/3") - 7016 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type/4") - 7017 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type/5") - 7018 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/6") - 7019 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/7") - 7020 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/8") - 7021 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type/9") - 7022 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type/10") - 7023 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type/11") - 7024 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type/12") - 7025 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/13") - 7026 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type/14") - 7027 # . epilogue - 7028 89/<- %esp 5/r32/ebp - 7029 5d/pop-to-ebp - 7030 c3/return - 7031 - 7032 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type: - 7033 # . prologue - 7034 55/push-ebp - 7035 89/<- %ebp 4/r32/esp - 7036 # setup - 7037 (clear-stream _test-input-stream) - 7038 (clear-stream $_test-input-buffered-file->buffer) - 7039 (clear-stream _test-output-stream) - 7040 (clear-stream $_test-output-buffered-file->buffer) - 7041 # - 7042 (write _test-input-stream "fn foo {\n") - 7043 (write _test-input-stream " var a: t\n") - 7044 (write _test-input-stream "}\n") - 7045 (write _test-input-stream "type t {\n") - 7046 (write _test-input-stream " x: s\n") - 7047 (write _test-input-stream "}\n") - 7048 (write _test-input-stream "type s {\n") - 7049 (write _test-input-stream " z: int\n") - 7050 (write _test-input-stream "}\n") - 7051 # convert - 7052 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7053 (flush _test-output-buffered-file) - 7054 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7060 # check output - 7061 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/0") - 7062 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/1") - 7063 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/2") - 7064 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/3") - 7065 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4") - 7066 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/5") - 7067 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/7") - 7068 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/8") - 7069 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9") - 7070 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/10") - 7071 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/11") - 7072 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/12") - 7073 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/13") - 7074 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/14") - 7075 # . epilogue - 7076 89/<- %esp 5/r32/ebp - 7077 5d/pop-to-ebp - 7078 c3/return - 7079 - 7080 test-convert-function-call-with-arg-of-user-defined-type: - 7081 # . prologue - 7082 55/push-ebp - 7083 89/<- %ebp 4/r32/esp - 7084 # setup - 7085 (clear-stream _test-input-stream) - 7086 (clear-stream $_test-input-buffered-file->buffer) - 7087 (clear-stream _test-output-stream) - 7088 (clear-stream $_test-output-buffered-file->buffer) - 7089 # - 7090 (write _test-input-stream "fn f {\n") - 7091 (write _test-input-stream " var a: t\n") - 7092 (write _test-input-stream " foo a\n") - 7093 (write _test-input-stream "}\n") - 7094 (write _test-input-stream "fn foo x: t {\n") - 7095 (write _test-input-stream "}\n") - 7096 (write _test-input-stream "type t {\n") - 7097 (write _test-input-stream " x: int\n") - 7098 (write _test-input-stream " y: int\n") - 7099 (write _test-input-stream "}\n") - 7100 # convert - 7101 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7102 (flush _test-output-buffered-file) - 7103 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7109 # check output - 7110 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type/0") - 7111 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/1") - 7112 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/2") - 7113 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/3") - 7114 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type/4") - 7115 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type/5") - 7116 # var a: t - 7117 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/6") - 7118 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/7") - 7119 # foo a - 7120 (check-next-stream-line-equal _test-output-stream " (foo *(ebp+0xfffffff8) *(ebp+0xfffffffc))" "F - test-convert-function-call-with-arg-of-user-defined-type/8") - 7121 # - 7122 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/9") - 7123 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type/10") - 7124 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type/11") - 7125 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/12") - 7126 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/13") - 7127 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/14") - 7128 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/15") - 7129 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type/16") - 7130 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/17") - 7131 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/18") - 7132 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/19") - 7133 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/20") - 7134 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/21") - 7135 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/22") - 7136 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/23") - 7137 # . epilogue - 7138 89/<- %esp 5/r32/ebp - 7139 5d/pop-to-ebp - 7140 c3/return - 7141 - 7142 test-convert-function-call-with-arg-of-user-defined-type-register-indirect: - 7143 # . prologue - 7144 55/push-ebp - 7145 89/<- %ebp 4/r32/esp - 7146 # setup - 7147 (clear-stream _test-input-stream) - 7148 (clear-stream $_test-input-buffered-file->buffer) - 7149 (clear-stream _test-output-stream) - 7150 (clear-stream $_test-output-buffered-file->buffer) - 7151 # - 7152 (write _test-input-stream "fn f {\n") - 7153 (write _test-input-stream " var a/eax: (addr t) <- copy 0\n") - 7154 (write _test-input-stream " foo *a\n") - 7155 (write _test-input-stream "}\n") - 7156 (write _test-input-stream "fn foo x: t {\n") - 7157 (write _test-input-stream "}\n") - 7158 (write _test-input-stream "type t {\n") - 7159 (write _test-input-stream " x: int\n") - 7160 (write _test-input-stream " y: int\n") - 7161 (write _test-input-stream "}\n") - 7162 # convert - 7163 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7164 (flush _test-output-buffered-file) - 7165 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7171 # check output - 7172 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type/0") - 7173 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/1") - 7174 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/2") - 7175 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/3") - 7176 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type/4") - 7177 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type/5") - 7178 # var a - 7179 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/6") - 7180 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/7") - 7181 # foo a - 7182 (check-next-stream-line-equal _test-output-stream " (foo *(eax+0x00000000) *(eax+0x00000004))" "F - test-convert-function-call-with-arg-of-user-defined-type/8") - 7183 # - 7184 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/9") - 7185 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type/10") - 7186 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type/11") - 7187 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/12") - 7188 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/13") - 7189 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/14") - 7190 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/15") - 7191 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type/16") - 7192 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/17") - 7193 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/18") - 7194 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/19") - 7195 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/20") - 7196 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/21") - 7197 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/22") - 7198 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/23") - 7199 # . epilogue - 7200 89/<- %esp 5/r32/ebp - 7201 5d/pop-to-ebp - 7202 c3/return - 7203 - 7204 # we don't have special support for call-by-reference; just explicitly create - 7205 # a new variable with the address of the arg - 7206 test-convert-function-call-with-arg-of-user-defined-type-by-reference: - 7207 # . prologue - 7208 55/push-ebp - 7209 89/<- %ebp 4/r32/esp - 7210 # setup - 7211 (clear-stream _test-input-stream) - 7212 (clear-stream $_test-input-buffered-file->buffer) - 7213 (clear-stream _test-output-stream) - 7214 (clear-stream $_test-output-buffered-file->buffer) - 7215 # - 7216 (write _test-input-stream "fn f {\n") - 7217 (write _test-input-stream " var a: t\n") - 7218 (write _test-input-stream " var b/eax: (addr t) <- address a\n") - 7219 (write _test-input-stream " foo b\n") - 7220 (write _test-input-stream "}\n") - 7221 (write _test-input-stream "fn foo x: (addr t) {\n") - 7222 (write _test-input-stream " var x/ecx: (addr t) <- copy x\n") - 7223 (write _test-input-stream "}\n") - 7224 (write _test-input-stream "type t {\n") - 7225 (write _test-input-stream " x: int\n") - 7226 (write _test-input-stream " y: int\n") - 7227 (write _test-input-stream "}\n") - 7228 # convert - 7229 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7230 (flush _test-output-buffered-file) - 7231 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7237 # check output - 7238 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0") - 7239 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1") - 7240 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/2") - 7241 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/3") - 7242 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4") - 7243 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/5") - 7244 # var a: t - 7245 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/6") - 7246 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/7") - 7247 # var b/eax: (addr t) - 7248 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/8") - 7249 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/9") - 7250 # foo a - 7251 (check-next-stream-line-equal _test-output-stream " (foo %eax)" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10") - 7252 # - 7253 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/11") - 7254 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/12") - 7255 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13") - 7256 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/14") - 7257 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15") - 7258 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/16") - 7259 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/17") - 7260 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18") - 7261 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19") - 7262 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20") - 7263 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/21") - 7264 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/22") - 7265 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23") - 7266 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/24") - 7267 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/25") - 7268 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000001/r32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/26") - 7269 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27") - 7270 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28") - 7271 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29") - 7272 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30") - 7273 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31") - 7274 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32") - 7275 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33") - 7276 # . epilogue - 7277 89/<- %esp 5/r32/ebp - 7278 5d/pop-to-ebp - 7279 c3/return - 7280 - 7281 test-convert-get-on-local-variable: - 7282 # . prologue - 7283 55/push-ebp - 7284 89/<- %ebp 4/r32/esp - 7285 # setup - 7286 (clear-stream _test-input-stream) - 7287 (clear-stream $_test-input-buffered-file->buffer) - 7288 (clear-stream _test-output-stream) - 7289 (clear-stream $_test-output-buffered-file->buffer) - 7290 # - 7291 (write _test-input-stream "fn foo {\n") - 7292 (write _test-input-stream " var a: t\n") - 7293 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") - 7294 (write _test-input-stream "}\n") - 7295 (write _test-input-stream "type t {\n") - 7296 (write _test-input-stream " x: int\n") - 7297 (write _test-input-stream " y: int\n") - 7298 (write _test-input-stream "}\n") - 7299 # convert - 7300 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7301 (flush _test-output-buffered-file) - 7302 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7308 # check output - 7309 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-on-local-variable/0") - 7310 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-on-local-variable/1") - 7311 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-on-local-variable/2") - 7312 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-on-local-variable/3") - 7313 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-on-local-variable/4") - 7314 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-on-local-variable/5") - 7315 # var a - 7316 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-on-local-variable/6") - 7317 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-on-local-variable/7") - 7318 # var c - 7319 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-on-local-variable/8") - 7320 # get - 7321 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32" "F - test-convert-get-on-local-variable/9") - 7322 # reclaim c - 7323 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10") - 7324 # reclaim a - 7325 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-get-on-local-variable/11") - 7326 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-on-local-variable/12") - 7327 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-on-local-variable/13") - 7328 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-on-local-variable/14") - 7329 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-on-local-variable/15") - 7330 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-on-local-variable/16") - 7331 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-on-local-variable/17") - 7332 # . epilogue - 7333 89/<- %esp 5/r32/ebp - 7334 5d/pop-to-ebp - 7335 c3/return - 7336 - 7337 test-convert-get-on-function-argument: - 7338 # . prologue - 7339 55/push-ebp - 7340 89/<- %ebp 4/r32/esp - 7341 # setup - 7342 (clear-stream _test-input-stream) - 7343 (clear-stream $_test-input-buffered-file->buffer) - 7344 (clear-stream _test-output-stream) - 7345 (clear-stream $_test-output-buffered-file->buffer) - 7346 # - 7347 (write _test-input-stream "fn foo a: t {\n") - 7348 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") - 7349 (write _test-input-stream "}\n") - 7350 (write _test-input-stream "type t {\n") - 7351 (write _test-input-stream " x: int\n") - 7352 (write _test-input-stream " y: int\n") - 7353 (write _test-input-stream "}\n") - 7354 # convert - 7355 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7356 (flush _test-output-buffered-file) - 7357 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7363 # check output - 7364 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-on-function-argument/0") - 7365 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-on-function-argument/1") - 7366 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-on-function-argument/2") - 7367 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-on-function-argument/3") - 7368 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-on-function-argument/4") - 7369 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-on-function-argument/5") - 7370 # var c - 7371 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-on-function-argument/6") - 7372 # get - 7373 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0x0000000c) 0x00000001/r32" "F - test-convert-get-on-function-argument/7") - 7374 # reclaim c - 7375 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8") - 7376 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-on-function-argument/9") - 7377 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-on-function-argument/10") - 7378 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-on-function-argument/11") - 7379 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-on-function-argument/12") - 7380 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-on-function-argument/13") - 7381 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-on-function-argument/14") - 7382 # . epilogue - 7383 89/<- %esp 5/r32/ebp - 7384 5d/pop-to-ebp - 7385 c3/return - 7386 - 7387 test-convert-get-on-function-argument-with-known-type: - 7388 # . prologue - 7389 55/push-ebp - 7390 89/<- %ebp 4/r32/esp - 7391 # setup - 7392 (clear-stream _test-input-stream) - 7393 (clear-stream $_test-input-buffered-file->buffer) - 7394 (clear-stream _test-output-stream) - 7395 (clear-stream $_test-output-buffered-file->buffer) - 7396 # - 7397 (write _test-input-stream "type t {\n") - 7398 (write _test-input-stream " x: int\n") - 7399 (write _test-input-stream " y: int\n") - 7400 (write _test-input-stream "}\n") - 7401 (write _test-input-stream "fn foo a: t {\n") - 7402 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") - 7403 (write _test-input-stream "}\n") - 7404 # convert - 7405 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7406 (flush _test-output-buffered-file) - 7407 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 7413 # check output - 7414 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-on-function-argument-with-known-type/0") - 7415 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-on-function-argument-with-known-type/1") - 7416 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-on-function-argument-with-known-type/2") - 7417 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-on-function-argument-with-known-type/3") - 7418 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-on-function-argument-with-known-type/4") - 7419 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-on-function-argument-with-known-type/5") - 7420 # var c - 7421 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-on-function-argument-with-known-type/6") - 7422 # get - 7423 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0x0000000c) 0x00000001/r32" "F - test-convert-get-on-function-argument-with-known-type/7") - 7424 # reclaim c - 7425 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8") - 7426 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-on-function-argument-with-known-type/9") - 7427 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-on-function-argument-with-known-type/10") - 7428 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-on-function-argument-with-known-type/11") - 7429 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-on-function-argument-with-known-type/12") - 7430 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-on-function-argument-with-known-type/13") - 7431 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-on-function-argument-with-known-type/14") - 7432 # . epilogue - 7433 89/<- %esp 5/r32/ebp - 7434 5d/pop-to-ebp - 7435 c3/return - 7436 - 7437 test-add-with-too-many-inouts: - 7438 # . prologue - 7439 55/push-ebp - 7440 89/<- %ebp 4/r32/esp - 7441 # setup - 7442 (clear-stream _test-input-stream) - 7443 (clear-stream $_test-input-buffered-file->buffer) - 7444 (clear-stream _test-output-stream) - 7445 (clear-stream $_test-output-buffered-file->buffer) - 7446 (clear-stream _test-error-stream) - 7447 (clear-stream $_test-error-buffered-file->buffer) - 7448 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7449 68/push 0/imm32 - 7450 68/push 0/imm32 - 7451 89/<- %edx 4/r32/esp - 7452 (tailor-exit-descriptor %edx 0x10) - 7453 # - 7454 (write _test-input-stream "fn foo {\n") - 7455 (write _test-input-stream " var a: int\n") - 7456 (write _test-input-stream " var b/ecx: int <- add a, 0\n") - 7457 (write _test-input-stream "}\n") - 7458 # convert - 7459 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7460 # registers except esp clobbered at this point - 7461 # restore ed - 7462 89/<- %edx 4/r32/esp - 7463 (flush _test-output-buffered-file) - 7464 (flush _test-error-buffered-file) - 7465 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7471 # check output - 7472 (check-stream-equal _test-output-stream "" "F - test-add-with-too-many-inouts: output should be empty") - 7473 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: too many inouts; most primitives support at most two arguments, across inouts and outputs" "F - test-add-with-too-many-inouts: error message") - 7474 # check that stop(1) was called - 7475 (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status") - 7476 # don't restore from ebp - 7477 81 0/subop/add %esp 8/imm32 - 7478 # . epilogue - 7479 5d/pop-to-ebp - 7480 c3/return - 7481 - 7482 test-add-with-too-many-inouts-2: - 7483 # . prologue - 7484 55/push-ebp - 7485 89/<- %ebp 4/r32/esp - 7486 # setup - 7487 (clear-stream _test-input-stream) - 7488 (clear-stream $_test-input-buffered-file->buffer) - 7489 (clear-stream _test-output-stream) - 7490 (clear-stream $_test-output-buffered-file->buffer) - 7491 (clear-stream _test-error-stream) - 7492 (clear-stream $_test-error-buffered-file->buffer) - 7493 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7494 68/push 0/imm32 - 7495 68/push 0/imm32 - 7496 89/<- %edx 4/r32/esp - 7497 (tailor-exit-descriptor %edx 0x10) - 7498 # - 7499 (write _test-input-stream "fn foo {\n") - 7500 (write _test-input-stream " var a: int\n") - 7501 (write _test-input-stream " add-to a, 0, 1\n") - 7502 (write _test-input-stream "}\n") - 7503 # convert - 7504 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7505 # registers except esp clobbered at this point - 7506 # restore ed - 7507 89/<- %edx 4/r32/esp - 7508 (flush _test-output-buffered-file) - 7509 (flush _test-error-buffered-file) - 7510 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7516 # check output - 7517 (check-stream-equal _test-output-stream "" "F - test-add-with-too-many-inouts-2: output should be empty") - 7518 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add-to: too many inouts; most primitives support at most two arguments, across inouts and outputs" "F - test-add-with-too-many-inouts-2: error message") - 7519 # check that stop(1) was called - 7520 (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status") - 7521 # don't restore from ebp - 7522 81 0/subop/add %esp 8/imm32 - 7523 # . epilogue - 7524 5d/pop-to-ebp - 7525 c3/return - 7526 - 7527 test-add-with-too-many-outputs: - 7528 # . prologue - 7529 55/push-ebp - 7530 89/<- %ebp 4/r32/esp - 7531 # setup - 7532 (clear-stream _test-input-stream) - 7533 (clear-stream $_test-input-buffered-file->buffer) - 7534 (clear-stream _test-output-stream) - 7535 (clear-stream $_test-output-buffered-file->buffer) - 7536 (clear-stream _test-error-stream) - 7537 (clear-stream $_test-error-buffered-file->buffer) - 7538 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7539 68/push 0/imm32 - 7540 68/push 0/imm32 - 7541 89/<- %edx 4/r32/esp - 7542 (tailor-exit-descriptor %edx 0x10) - 7543 # - 7544 (write _test-input-stream "fn foo {\n") - 7545 (write _test-input-stream " var a/eax: int <- copy 0\n") - 7546 (write _test-input-stream " var b/ebx: int <- copy 0\n") - 7547 (write _test-input-stream " var c/ecx: int <- copy 0\n") - 7548 (write _test-input-stream " c, b <- add a\n") - 7549 (write _test-input-stream "}\n") - 7550 # convert - 7551 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7552 # registers except esp clobbered at this point - 7553 # restore ed - 7554 89/<- %edx 4/r32/esp - 7555 (flush _test-output-buffered-file) - 7556 (flush _test-error-buffered-file) - 7557 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7563 # check output - 7564 (check-stream-equal _test-output-stream "" "F - test-add-with-too-many-outputs: output should be empty") - 7565 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: too many outputs; most primitives support at most one output" "F - test-add-with-too-many-outputs: error message") - 7566 # check that stop(1) was called - 7567 (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status") - 7568 # don't restore from ebp - 7569 81 0/subop/add %esp 8/imm32 - 7570 # . epilogue - 7571 5d/pop-to-ebp - 7572 c3/return - 7573 - 7574 test-add-with-non-number: - 7575 # . prologue - 7576 55/push-ebp - 7577 89/<- %ebp 4/r32/esp - 7578 # setup - 7579 (clear-stream _test-input-stream) - 7580 (clear-stream $_test-input-buffered-file->buffer) - 7581 (clear-stream _test-output-stream) - 7582 (clear-stream $_test-output-buffered-file->buffer) - 7583 (clear-stream _test-error-stream) - 7584 (clear-stream $_test-error-buffered-file->buffer) - 7585 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7586 68/push 0/imm32 - 7587 68/push 0/imm32 - 7588 89/<- %edx 4/r32/esp - 7589 (tailor-exit-descriptor %edx 0x10) - 7590 # - 7591 (write _test-input-stream "fn foo {\n") - 7592 (write _test-input-stream " var a: int\n") - 7593 (write _test-input-stream " var b/ecx: (addr int) <- add a\n") - 7594 (write _test-input-stream "}\n") - 7595 # convert - 7596 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7597 # registers except esp clobbered at this point - 7598 # restore ed - 7599 89/<- %edx 4/r32/esp - 7600 (flush _test-output-buffered-file) - 7601 (flush _test-error-buffered-file) - 7602 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7608 # check output - 7609 (check-stream-equal _test-output-stream "" "F - test-add-with-non-number: output should be empty") - 7610 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: 'b' must be a non-addr non-offset scalar" "F - test-add-with-non-number: error message") - 7611 # check that stop(1) was called - 7612 (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status") - 7613 # don't restore from ebp - 7614 81 0/subop/add %esp 8/imm32 - 7615 # . epilogue - 7616 5d/pop-to-ebp - 7617 c3/return - 7618 - 7619 test-add-with-addr-dereferenced: - 7620 # . prologue - 7621 55/push-ebp - 7622 89/<- %ebp 4/r32/esp - 7623 # setup - 7624 (clear-stream _test-input-stream) - 7625 (clear-stream $_test-input-buffered-file->buffer) - 7626 (clear-stream _test-output-stream) - 7627 (clear-stream $_test-output-buffered-file->buffer) - 7628 # - 7629 (write _test-input-stream "fn foo {\n") - 7630 (write _test-input-stream " var a/eax: (addr int) <- copy 0\n") - 7631 (write _test-input-stream " add-to *a, 1\n") - 7632 (write _test-input-stream "}\n") - 7633 # convert - 7634 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7635 (flush _test-output-buffered-file) - 7636 # no error - 7637 # . epilogue - 7638 89/<- %esp 5/r32/ebp - 7639 5d/pop-to-ebp - 7640 c3/return - 7641 - 7642 test-copy-with-no-inout: - 7643 # . prologue - 7644 55/push-ebp - 7645 89/<- %ebp 4/r32/esp - 7646 # setup - 7647 (clear-stream _test-input-stream) - 7648 (clear-stream $_test-input-buffered-file->buffer) - 7649 (clear-stream _test-output-stream) - 7650 (clear-stream $_test-output-buffered-file->buffer) - 7651 (clear-stream _test-error-stream) - 7652 (clear-stream $_test-error-buffered-file->buffer) - 7653 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7654 68/push 0/imm32 - 7655 68/push 0/imm32 - 7656 89/<- %edx 4/r32/esp - 7657 (tailor-exit-descriptor %edx 0x10) - 7658 # - 7659 (write _test-input-stream "fn foo {\n") - 7660 (write _test-input-stream " var x/eax: boolean <- copy\n") - 7661 (write _test-input-stream "}\n") - 7662 # convert - 7663 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7664 # registers except esp clobbered at this point - 7665 # restore ed - 7666 89/<- %edx 4/r32/esp - 7667 (flush _test-output-buffered-file) - 7668 (flush _test-error-buffered-file) - 7669 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7675 # check output - 7676 (check-stream-equal _test-output-stream "" "F - test-copy-with-no-inout: output should be empty") - 7677 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' expects an inout" "F - test-copy-with-no-inout: error message") - 7678 # check that stop(1) was called - 7679 (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status") - 7680 # don't restore from ebp - 7681 81 0/subop/add %esp 8/imm32 - 7682 # . epilogue - 7683 5d/pop-to-ebp - 7684 c3/return - 7685 - 7686 test-copy-with-multiple-inouts: - 7687 # . prologue - 7688 55/push-ebp - 7689 89/<- %ebp 4/r32/esp - 7690 # setup - 7691 (clear-stream _test-input-stream) - 7692 (clear-stream $_test-input-buffered-file->buffer) - 7693 (clear-stream _test-output-stream) - 7694 (clear-stream $_test-output-buffered-file->buffer) - 7695 (clear-stream _test-error-stream) - 7696 (clear-stream $_test-error-buffered-file->buffer) - 7697 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7698 68/push 0/imm32 - 7699 68/push 0/imm32 - 7700 89/<- %edx 4/r32/esp - 7701 (tailor-exit-descriptor %edx 0x10) - 7702 # - 7703 (write _test-input-stream "fn foo {\n") - 7704 (write _test-input-stream " var x/eax: boolean <- copy 0, 0\n") - 7705 (write _test-input-stream "}\n") - 7706 # convert - 7707 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7708 # registers except esp clobbered at this point - 7709 # restore ed - 7710 89/<- %edx 4/r32/esp - 7711 (flush _test-output-buffered-file) - 7712 (flush _test-error-buffered-file) - 7713 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7719 # check output - 7720 (check-stream-equal _test-output-stream "" "F - test-copy-with-multiple-inouts: output should be empty") - 7721 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' must have just one inout" "F - test-copy-with-multiple-inouts: error message") - 7722 # check that stop(1) was called - 7723 (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status") - 7724 # don't restore from ebp - 7725 81 0/subop/add %esp 8/imm32 - 7726 # . epilogue - 7727 5d/pop-to-ebp - 7728 c3/return - 7729 - 7730 test-copy-with-no-output: - 7731 # . prologue - 7732 55/push-ebp - 7733 89/<- %ebp 4/r32/esp - 7734 # setup - 7735 (clear-stream _test-input-stream) - 7736 (clear-stream $_test-input-buffered-file->buffer) - 7737 (clear-stream _test-output-stream) - 7738 (clear-stream $_test-output-buffered-file->buffer) - 7739 (clear-stream _test-error-stream) - 7740 (clear-stream $_test-error-buffered-file->buffer) - 7741 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7742 68/push 0/imm32 - 7743 68/push 0/imm32 - 7744 89/<- %edx 4/r32/esp - 7745 (tailor-exit-descriptor %edx 0x10) - 7746 # - 7747 (write _test-input-stream "fn foo {\n") - 7748 (write _test-input-stream " copy 0\n") - 7749 (write _test-input-stream "}\n") - 7750 # convert - 7751 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7752 # registers except esp clobbered at this point - 7753 # restore ed - 7754 89/<- %edx 4/r32/esp - 7755 (flush _test-output-buffered-file) - 7756 (flush _test-error-buffered-file) - 7757 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7763 # check output - 7764 (check-stream-equal _test-output-stream "" "F - test-copy-with-no-output: output should be empty") - 7765 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' expects an output" "F - test-copy-with-no-output: error message") - 7766 # check that stop(1) was called - 7767 (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status") - 7768 # don't restore from ebp - 7769 81 0/subop/add %esp 8/imm32 - 7770 # . epilogue - 7771 5d/pop-to-ebp - 7772 c3/return - 7773 - 7774 test-copy-with-multiple-outputs: - 7775 # . prologue - 7776 55/push-ebp - 7777 89/<- %ebp 4/r32/esp - 7778 # setup - 7779 (clear-stream _test-input-stream) - 7780 (clear-stream $_test-input-buffered-file->buffer) - 7781 (clear-stream _test-output-stream) - 7782 (clear-stream $_test-output-buffered-file->buffer) - 7783 (clear-stream _test-error-stream) - 7784 (clear-stream $_test-error-buffered-file->buffer) - 7785 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7786 68/push 0/imm32 - 7787 68/push 0/imm32 - 7788 89/<- %edx 4/r32/esp - 7789 (tailor-exit-descriptor %edx 0x10) - 7790 # - 7791 (write _test-input-stream "fn foo {\n") - 7792 (write _test-input-stream " var x/eax: boolean <- copy 0\n") - 7793 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") - 7794 (write _test-input-stream " x, y <- copy 0\n") - 7795 (write _test-input-stream "}\n") - 7796 # convert - 7797 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7798 # registers except esp clobbered at this point - 7799 # restore ed - 7800 89/<- %edx 4/r32/esp - 7801 (flush _test-output-buffered-file) - 7802 (flush _test-error-buffered-file) - 7803 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7809 # check output - 7810 (check-stream-equal _test-output-stream "" "F - test-copy-with-multiple-outputs: output should be empty") - 7811 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' must have just one output" "F - test-copy-with-multiple-outputs: error message") - 7812 # check that stop(1) was called - 7813 (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status") - 7814 # don't restore from ebp - 7815 81 0/subop/add %esp 8/imm32 - 7816 # . epilogue - 7817 5d/pop-to-ebp - 7818 c3/return - 7819 - 7820 test-copy-invalid-value-to-address: - 7821 # . prologue - 7822 55/push-ebp - 7823 89/<- %ebp 4/r32/esp - 7824 # setup - 7825 (clear-stream _test-input-stream) - 7826 (clear-stream $_test-input-buffered-file->buffer) - 7827 (clear-stream _test-output-stream) - 7828 (clear-stream $_test-output-buffered-file->buffer) - 7829 (clear-stream _test-error-stream) - 7830 (clear-stream $_test-error-buffered-file->buffer) - 7831 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7832 68/push 0/imm32 - 7833 68/push 0/imm32 - 7834 89/<- %edx 4/r32/esp - 7835 (tailor-exit-descriptor %edx 0x10) - 7836 # - 7837 (write _test-input-stream "fn foo {\n") - 7838 (write _test-input-stream " var x/eax: int <- copy 0\n") - 7839 (write _test-input-stream " var y/ecx: (addr int) <- copy x\n") - 7840 (write _test-input-stream "}\n") - 7841 # convert - 7842 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7843 # registers except esp clobbered at this point - 7844 # restore ed - 7845 89/<- %edx 4/r32/esp - 7846 (flush _test-output-buffered-file) - 7847 (flush _test-error-buffered-file) - 7848 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7854 # check output - 7855 (check-stream-equal _test-output-stream "" "F - test-copy-invalid-value-to-address: output should be empty") - 7856 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar" "F - test-copy-invalid-value-to-address: error message") - 7857 # check that stop(1) was called - 7858 (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status") - 7859 # don't restore from ebp - 7860 81 0/subop/add %esp 8/imm32 - 7861 # . epilogue - 7862 5d/pop-to-ebp - 7863 c3/return - 7864 - 7865 test-copy-null-value-to-address: - 7866 # . prologue - 7867 55/push-ebp - 7868 89/<- %ebp 4/r32/esp - 7869 # setup - 7870 (clear-stream _test-input-stream) - 7871 (clear-stream $_test-input-buffered-file->buffer) - 7872 (clear-stream _test-output-stream) - 7873 (clear-stream $_test-output-buffered-file->buffer) - 7874 # - 7875 (write _test-input-stream "fn foo {\n") - 7876 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") - 7877 (write _test-input-stream "}\n") - 7878 # convert - 7879 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7880 (flush _test-output-buffered-file) - 7881 # no errors - 7882 # . epilogue - 7883 89/<- %esp 5/r32/ebp - 7884 5d/pop-to-ebp - 7885 c3/return - 7886 - 7887 test-copy-invalid-value-to-offset: - 7888 # . prologue - 7889 55/push-ebp - 7890 89/<- %ebp 4/r32/esp - 7891 # setup - 7892 (clear-stream _test-input-stream) - 7893 (clear-stream $_test-input-buffered-file->buffer) - 7894 (clear-stream _test-output-stream) - 7895 (clear-stream $_test-output-buffered-file->buffer) - 7896 (clear-stream _test-error-stream) - 7897 (clear-stream $_test-error-buffered-file->buffer) - 7898 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7899 68/push 0/imm32 - 7900 68/push 0/imm32 - 7901 89/<- %edx 4/r32/esp - 7902 (tailor-exit-descriptor %edx 0x10) - 7903 # - 7904 (write _test-input-stream "fn foo {\n") - 7905 (write _test-input-stream " var x/eax: int <- copy 0\n") - 7906 (write _test-input-stream " var y/ecx: (offset int) <- copy x\n") - 7907 (write _test-input-stream "}\n") - 7908 # convert - 7909 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7910 # registers except esp clobbered at this point - 7911 # restore ed - 7912 89/<- %edx 4/r32/esp - 7913 (flush _test-output-buffered-file) - 7914 (flush _test-error-buffered-file) - 7915 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7921 # check output - 7922 (check-stream-equal _test-output-stream "" "F - test-copy-invalid-value-to-address: output should be empty") - 7923 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar" "F - test-copy-invalid-value-to-address: error message") - 7924 # check that stop(1) was called - 7925 (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status") - 7926 # don't restore from ebp - 7927 81 0/subop/add %esp 8/imm32 - 7928 # . epilogue - 7929 5d/pop-to-ebp - 7930 c3/return - 7931 - 7932 test-copy-null-value-to-offset: - 7933 # . prologue - 7934 55/push-ebp - 7935 89/<- %ebp 4/r32/esp - 7936 # setup - 7937 (clear-stream _test-input-stream) - 7938 (clear-stream $_test-input-buffered-file->buffer) - 7939 (clear-stream _test-output-stream) - 7940 (clear-stream $_test-output-buffered-file->buffer) - 7941 # - 7942 (write _test-input-stream "fn foo {\n") - 7943 (write _test-input-stream " var y/ecx: (offset int) <- copy 0\n") - 7944 (write _test-input-stream "}\n") - 7945 # convert - 7946 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 7947 (flush _test-output-buffered-file) - 7948 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7954 # no errors - 7955 # . epilogue - 7956 89/<- %esp 5/r32/ebp - 7957 5d/pop-to-ebp - 7958 c3/return - 7959 - 7960 test-copy-non-literal-to-byte: - 7961 # . prologue - 7962 55/push-ebp - 7963 89/<- %ebp 4/r32/esp - 7964 # setup - 7965 (clear-stream _test-input-stream) - 7966 (clear-stream $_test-input-buffered-file->buffer) - 7967 (clear-stream _test-output-stream) - 7968 (clear-stream $_test-output-buffered-file->buffer) - 7969 (clear-stream _test-error-stream) - 7970 (clear-stream $_test-error-buffered-file->buffer) - 7971 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 7972 68/push 0/imm32 - 7973 68/push 0/imm32 - 7974 89/<- %edx 4/r32/esp - 7975 (tailor-exit-descriptor %edx 0x10) - 7976 # - 7977 (write _test-input-stream "fn foo {\n") - 7978 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 7979 (write _test-input-stream " var y/ecx: byte <- copy x\n") - 7980 (write _test-input-stream "}\n") - 7981 # convert - 7982 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 7983 # registers except esp clobbered at this point - 7984 # restore ed - 7985 89/<- %edx 4/r32/esp - 7986 (flush _test-output-buffered-file) - 7987 (flush _test-error-buffered-file) - 7988 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 7994 # check output - 7995 (check-stream-equal _test-output-stream "" "F - test-copy-non-literal-to-byte: output should be empty") - 7996 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte" "F - test-copy-non-literal-to-byte: error message") - 7997 # check that stop(1) was called - 7998 (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status") - 7999 # don't restore from ebp - 8000 81 0/subop/add %esp 8/imm32 - 8001 # . epilogue - 8002 5d/pop-to-ebp - 8003 c3/return - 8004 - 8005 test-copy-deref-address: - 8006 # . prologue - 8007 55/push-ebp - 8008 89/<- %ebp 4/r32/esp - 8009 # setup - 8010 (clear-stream _test-input-stream) - 8011 (clear-stream $_test-input-buffered-file->buffer) - 8012 (clear-stream _test-output-stream) - 8013 (clear-stream $_test-output-buffered-file->buffer) - 8014 # - 8015 (write _test-input-stream "fn foo {\n") - 8016 (write _test-input-stream " var x/eax: (addr addr int) <- copy 0\n") - 8017 (write _test-input-stream " var y/ecx: (addr int) <- copy *x\n") - 8018 (write _test-input-stream "}\n") - 8019 # convert - 8020 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 8021 (flush _test-output-buffered-file) - 8022 # no errors - 8023 # . epilogue - 8024 5d/pop-to-ebp - 8025 c3/return - 8026 - 8027 test-copy-to-non-register: - 8028 # . prologue - 8029 55/push-ebp - 8030 89/<- %ebp 4/r32/esp - 8031 # setup - 8032 (clear-stream _test-input-stream) - 8033 (clear-stream $_test-input-buffered-file->buffer) - 8034 (clear-stream _test-output-stream) - 8035 (clear-stream $_test-output-buffered-file->buffer) - 8036 (clear-stream _test-error-stream) - 8037 (clear-stream $_test-error-buffered-file->buffer) - 8038 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8039 68/push 0/imm32 - 8040 68/push 0/imm32 - 8041 89/<- %edx 4/r32/esp - 8042 (tailor-exit-descriptor %edx 0x10) - 8043 # - 8044 (write _test-input-stream "fn foo {\n") - 8045 (write _test-input-stream " var x: int\n") - 8046 (write _test-input-stream " x <- copy 0\n") - 8047 (write _test-input-stream "}\n") - 8048 # convert - 8049 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8050 # registers except esp clobbered at this point - 8051 # restore ed - 8052 89/<- %edx 4/r32/esp - 8053 (flush _test-output-buffered-file) - 8054 (flush _test-error-buffered-file) - 8055 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8061 # check output - 8062 (check-stream-equal _test-output-stream "" "F - test-copy-to-non-register: output should be empty") - 8063 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: output 'x' not in a register" "F - test-copy-to-non-register: error message") - 8064 # check that stop(1) was called - 8065 (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status") - 8066 # don't restore from ebp - 8067 81 0/subop/add %esp 8/imm32 - 8068 # . epilogue - 8069 5d/pop-to-ebp - 8070 c3/return - 8071 - 8072 test-copy-from-non-scalar-inout: - 8073 # . prologue - 8074 55/push-ebp - 8075 89/<- %ebp 4/r32/esp - 8076 # setup - 8077 (clear-stream _test-input-stream) - 8078 (clear-stream $_test-input-buffered-file->buffer) - 8079 (clear-stream _test-output-stream) - 8080 (clear-stream $_test-output-buffered-file->buffer) - 8081 (clear-stream _test-error-stream) - 8082 (clear-stream $_test-error-buffered-file->buffer) - 8083 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8084 68/push 0/imm32 - 8085 68/push 0/imm32 - 8086 89/<- %edx 4/r32/esp - 8087 (tailor-exit-descriptor %edx 0x10) - 8088 # - 8089 (write _test-input-stream "fn foo {\n") - 8090 (write _test-input-stream " var x: (handle int)\n") - 8091 (write _test-input-stream " var y/eax: int <- copy x\n") - 8092 (write _test-input-stream "}\n") - 8093 # convert - 8094 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8095 # registers except esp clobbered at this point - 8096 # restore ed - 8097 89/<- %edx 4/r32/esp - 8098 (flush _test-output-buffered-file) - 8099 (flush _test-error-buffered-file) - 8100 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8106 # check output - 8107 (check-stream-equal _test-output-stream "" "F - test-copy-from-non-scalar-inout: output should be empty") - 8108 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: 'x' is too large to fit in a register" "F - test-copy-from-non-scalar-inout: error message") - 8109 # check that stop(1) was called - 8110 (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status") - 8111 # don't restore from ebp - 8112 81 0/subop/add %esp 8/imm32 - 8113 # . epilogue - 8114 5d/pop-to-ebp - 8115 c3/return - 8116 - 8117 test-copy-to-with-no-inout: - 8118 # . prologue - 8119 55/push-ebp - 8120 89/<- %ebp 4/r32/esp - 8121 # setup - 8122 (clear-stream _test-input-stream) - 8123 (clear-stream $_test-input-buffered-file->buffer) - 8124 (clear-stream _test-output-stream) - 8125 (clear-stream $_test-output-buffered-file->buffer) - 8126 (clear-stream _test-error-stream) - 8127 (clear-stream $_test-error-buffered-file->buffer) - 8128 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8129 68/push 0/imm32 - 8130 68/push 0/imm32 - 8131 89/<- %edx 4/r32/esp - 8132 (tailor-exit-descriptor %edx 0x10) - 8133 # - 8134 (write _test-input-stream "fn foo {\n") - 8135 (write _test-input-stream " copy-to\n") - 8136 (write _test-input-stream "}\n") - 8137 # convert - 8138 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8139 # registers except esp clobbered at this point - 8140 # restore ed - 8141 89/<- %edx 4/r32/esp - 8142 (flush _test-output-buffered-file) - 8143 (flush _test-error-buffered-file) - 8144 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8150 # check output - 8151 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-no-inout: output should be empty") - 8152 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must have two inouts" "F - test-copy-to-with-no-inout: error message") - 8153 # check that stop(1) was called - 8154 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status") - 8155 # don't restore from ebp - 8156 81 0/subop/add %esp 8/imm32 - 8157 # . epilogue - 8158 5d/pop-to-ebp - 8159 c3/return - 8160 - 8161 test-copy-to-with-no-source: - 8162 # . prologue - 8163 55/push-ebp - 8164 89/<- %ebp 4/r32/esp - 8165 # setup - 8166 (clear-stream _test-input-stream) - 8167 (clear-stream $_test-input-buffered-file->buffer) - 8168 (clear-stream _test-output-stream) - 8169 (clear-stream $_test-output-buffered-file->buffer) - 8170 (clear-stream _test-error-stream) - 8171 (clear-stream $_test-error-buffered-file->buffer) - 8172 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8173 68/push 0/imm32 - 8174 68/push 0/imm32 - 8175 89/<- %edx 4/r32/esp - 8176 (tailor-exit-descriptor %edx 0x10) - 8177 # - 8178 (write _test-input-stream "fn foo {\n") - 8179 (write _test-input-stream " var x: boolean\n") - 8180 (write _test-input-stream " copy-to x\n") - 8181 (write _test-input-stream "}\n") - 8182 # convert - 8183 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8184 # registers except esp clobbered at this point - 8185 # restore ed - 8186 89/<- %edx 4/r32/esp - 8187 (flush _test-output-buffered-file) - 8188 (flush _test-error-buffered-file) - 8189 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8195 # check output - 8196 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-no-source: output should be empty") - 8197 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must have two inouts" "F - test-copy-to-with-no-source: error message") - 8198 # check that stop(1) was called - 8199 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status") - 8200 # don't restore from ebp - 8201 81 0/subop/add %esp 8/imm32 - 8202 # . epilogue - 8203 5d/pop-to-ebp - 8204 c3/return - 8205 - 8206 test-copy-to-with-no-register: - 8207 # . prologue - 8208 55/push-ebp - 8209 89/<- %ebp 4/r32/esp - 8210 # setup - 8211 (clear-stream _test-input-stream) - 8212 (clear-stream $_test-input-buffered-file->buffer) - 8213 (clear-stream _test-output-stream) - 8214 (clear-stream $_test-output-buffered-file->buffer) - 8215 (clear-stream _test-error-stream) - 8216 (clear-stream $_test-error-buffered-file->buffer) - 8217 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8218 68/push 0/imm32 - 8219 68/push 0/imm32 - 8220 89/<- %edx 4/r32/esp - 8221 (tailor-exit-descriptor %edx 0x10) - 8222 # - 8223 (write _test-input-stream "fn foo {\n") - 8224 (write _test-input-stream " var x: boolean\n") - 8225 (write _test-input-stream " copy-to x, x\n") - 8226 (write _test-input-stream "}\n") - 8227 # convert - 8228 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8229 # registers except esp clobbered at this point - 8230 # restore ed - 8231 89/<- %edx 4/r32/esp - 8232 (flush _test-output-buffered-file) - 8233 (flush _test-error-buffered-file) - 8234 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8240 # check output - 8241 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-no-register: output should be empty") - 8242 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: source (second inout) is in memory" "F - test-copy-to-with-no-register: error message") - 8243 # check that stop(1) was called - 8244 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status") - 8245 # don't restore from ebp - 8246 81 0/subop/add %esp 8/imm32 - 8247 # . epilogue - 8248 5d/pop-to-ebp - 8249 c3/return - 8250 - 8251 test-copy-to-with-too-many-inouts: - 8252 # . prologue - 8253 55/push-ebp - 8254 89/<- %ebp 4/r32/esp - 8255 # setup - 8256 (clear-stream _test-input-stream) - 8257 (clear-stream $_test-input-buffered-file->buffer) - 8258 (clear-stream _test-output-stream) - 8259 (clear-stream $_test-output-buffered-file->buffer) - 8260 (clear-stream _test-error-stream) - 8261 (clear-stream $_test-error-buffered-file->buffer) - 8262 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8263 68/push 0/imm32 - 8264 68/push 0/imm32 - 8265 89/<- %edx 4/r32/esp - 8266 (tailor-exit-descriptor %edx 0x10) - 8267 # - 8268 (write _test-input-stream "fn foo {\n") - 8269 (write _test-input-stream " var x: boolean\n") - 8270 (write _test-input-stream " copy-to x, 0, 0\n") - 8271 (write _test-input-stream "}\n") - 8272 # convert - 8273 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8274 # registers except esp clobbered at this point - 8275 # restore ed - 8276 89/<- %edx 4/r32/esp - 8277 (flush _test-output-buffered-file) - 8278 (flush _test-error-buffered-file) - 8279 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8285 # check output - 8286 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-too-many-inouts: output should be empty") - 8287 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must have two inouts" "F - test-copy-to-with-too-many-inouts: error message") - 8288 # check that stop(1) was called - 8289 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status") - 8290 # don't restore from ebp - 8291 81 0/subop/add %esp 8/imm32 - 8292 # . epilogue - 8293 5d/pop-to-ebp - 8294 c3/return - 8295 - 8296 test-copy-to-with-output: - 8297 # . prologue - 8298 55/push-ebp - 8299 89/<- %ebp 4/r32/esp - 8300 # setup - 8301 (clear-stream _test-input-stream) - 8302 (clear-stream $_test-input-buffered-file->buffer) - 8303 (clear-stream _test-output-stream) - 8304 (clear-stream $_test-output-buffered-file->buffer) - 8305 (clear-stream _test-error-stream) - 8306 (clear-stream $_test-error-buffered-file->buffer) - 8307 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8308 68/push 0/imm32 - 8309 68/push 0/imm32 - 8310 89/<- %edx 4/r32/esp - 8311 (tailor-exit-descriptor %edx 0x10) - 8312 # - 8313 (write _test-input-stream "fn foo {\n") - 8314 (write _test-input-stream " var x/eax: boolean <- copy 0\n") - 8315 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") - 8316 (write _test-input-stream " x <- copy-to y, 0\n") - 8317 (write _test-input-stream "}\n") - 8318 # convert - 8319 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8320 # registers except esp clobbered at this point - 8321 # restore ed - 8322 89/<- %edx 4/r32/esp - 8323 (flush _test-output-buffered-file) - 8324 (flush _test-error-buffered-file) - 8325 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8331 # check output - 8332 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-output: output should be empty") - 8333 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must not have any outputs" "F - test-copy-to-with-output: error message") - 8334 # check that stop(1) was called - 8335 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status") - 8336 # don't restore from ebp - 8337 81 0/subop/add %esp 8/imm32 - 8338 # . epilogue - 8339 5d/pop-to-ebp - 8340 c3/return - 8341 - 8342 test-copy-to-invalid-value-to-address: - 8343 # . prologue - 8344 55/push-ebp - 8345 89/<- %ebp 4/r32/esp - 8346 # setup - 8347 (clear-stream _test-input-stream) - 8348 (clear-stream $_test-input-buffered-file->buffer) - 8349 (clear-stream _test-output-stream) - 8350 (clear-stream $_test-output-buffered-file->buffer) - 8351 (clear-stream _test-error-stream) - 8352 (clear-stream $_test-error-buffered-file->buffer) - 8353 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8354 68/push 0/imm32 - 8355 68/push 0/imm32 - 8356 89/<- %edx 4/r32/esp - 8357 (tailor-exit-descriptor %edx 0x10) - 8358 # - 8359 (write _test-input-stream "fn foo {\n") - 8360 (write _test-input-stream " var x/eax: int <- copy 0\n") - 8361 (write _test-input-stream " var y: (addr int)\n") - 8362 (write _test-input-stream " copy-to y, x\n") - 8363 (write _test-input-stream "}\n") - 8364 # convert - 8365 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8366 # registers except esp clobbered at this point - 8367 # restore ed - 8368 89/<- %edx 4/r32/esp - 8369 (flush _test-output-buffered-file) - 8370 (flush _test-error-buffered-file) - 8371 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8377 # check output - 8378 (check-stream-equal _test-output-stream "" "F - test-copy-to-invalid-value-to-address: output should be empty") - 8379 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar" "F - test-copy-to-invalid-value-to-address: error message") - 8380 # check that stop(1) was called - 8381 (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status") - 8382 # don't restore from ebp - 8383 81 0/subop/add %esp 8/imm32 - 8384 # . epilogue - 8385 5d/pop-to-ebp - 8386 c3/return - 8387 - 8388 test-copy-to-null-value-to-address: - 8389 # . prologue - 8390 55/push-ebp - 8391 89/<- %ebp 4/r32/esp - 8392 # setup - 8393 (clear-stream _test-input-stream) - 8394 (clear-stream $_test-input-buffered-file->buffer) - 8395 (clear-stream _test-output-stream) - 8396 (clear-stream $_test-output-buffered-file->buffer) - 8397 # - 8398 (write _test-input-stream "fn foo {\n") - 8399 (write _test-input-stream " var y: (addr int)\n") - 8400 (write _test-input-stream " copy-to y, 0\n") - 8401 (write _test-input-stream "}\n") - 8402 # convert - 8403 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 8404 (flush _test-output-buffered-file) - 8405 # no errors - 8406 # . epilogue - 8407 89/<- %esp 5/r32/ebp - 8408 5d/pop-to-ebp - 8409 c3/return - 8410 - 8411 test-copy-to-invalid-value-to-offset: - 8412 # . prologue - 8413 55/push-ebp - 8414 89/<- %ebp 4/r32/esp - 8415 # setup - 8416 (clear-stream _test-input-stream) - 8417 (clear-stream $_test-input-buffered-file->buffer) - 8418 (clear-stream _test-output-stream) - 8419 (clear-stream $_test-output-buffered-file->buffer) - 8420 (clear-stream _test-error-stream) - 8421 (clear-stream $_test-error-buffered-file->buffer) - 8422 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8423 68/push 0/imm32 - 8424 68/push 0/imm32 - 8425 89/<- %edx 4/r32/esp - 8426 (tailor-exit-descriptor %edx 0x10) - 8427 # - 8428 (write _test-input-stream "fn foo {\n") - 8429 (write _test-input-stream " var x/eax: int <- copy 0\n") - 8430 (write _test-input-stream " var y: (offset int)\n") - 8431 (write _test-input-stream " copy-to y, x\n") - 8432 (write _test-input-stream "}\n") - 8433 # convert - 8434 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8435 # registers except esp clobbered at this point - 8436 # restore ed - 8437 89/<- %edx 4/r32/esp - 8438 (flush _test-output-buffered-file) - 8439 (flush _test-error-buffered-file) - 8440 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8446 # check output - 8447 (check-stream-equal _test-output-stream "" "F - test-copy-to-invalid-value-to-offset: output should be empty") - 8448 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar" "F - test-copy-to-invalid-value-to-offset: error message") - 8449 # check that stop(1) was called - 8450 (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status") - 8451 # don't restore from ebp - 8452 81 0/subop/add %esp 8/imm32 - 8453 # . epilogue - 8454 5d/pop-to-ebp - 8455 c3/return - 8456 - 8457 test-copy-to-null-value-to-offset: - 8458 # . prologue - 8459 55/push-ebp - 8460 89/<- %ebp 4/r32/esp - 8461 # setup - 8462 (clear-stream _test-input-stream) - 8463 (clear-stream $_test-input-buffered-file->buffer) - 8464 (clear-stream _test-output-stream) - 8465 (clear-stream $_test-output-buffered-file->buffer) - 8466 # - 8467 (write _test-input-stream "fn foo {\n") - 8468 (write _test-input-stream " var y: (offset int)\n") - 8469 (write _test-input-stream " copy-to y, 0\n") - 8470 (write _test-input-stream "}\n") - 8471 # convert - 8472 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 8473 (flush _test-output-buffered-file) - 8474 # no errors - 8475 # . epilogue - 8476 89/<- %esp 5/r32/ebp - 8477 5d/pop-to-ebp - 8478 c3/return - 8479 - 8480 test-copy-to-non-literal-to-byte: - 8481 # . prologue - 8482 55/push-ebp - 8483 89/<- %ebp 4/r32/esp - 8484 # setup - 8485 (clear-stream _test-input-stream) - 8486 (clear-stream $_test-input-buffered-file->buffer) - 8487 (clear-stream _test-output-stream) - 8488 (clear-stream $_test-output-buffered-file->buffer) - 8489 (clear-stream _test-error-stream) - 8490 (clear-stream $_test-error-buffered-file->buffer) - 8491 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8492 68/push 0/imm32 - 8493 68/push 0/imm32 - 8494 89/<- %edx 4/r32/esp - 8495 (tailor-exit-descriptor %edx 0x10) - 8496 # - 8497 (write _test-input-stream "fn foo {\n") - 8498 (write _test-input-stream " var x/ecx: byte <- copy 3\n") - 8499 (write _test-input-stream " var y/eax: (addr byte) <- copy 0\n") - 8500 (write _test-input-stream " copy-to *y, x\n") - 8501 (write _test-input-stream "}\n") - 8502 # convert - 8503 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8504 # registers except esp clobbered at this point - 8505 # restore ed - 8506 89/<- %edx 4/r32/esp - 8507 (flush _test-output-buffered-file) - 8508 (flush _test-error-buffered-file) - 8509 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8515 # check output - 8516 (check-stream-equal _test-output-stream "" "F - test-copy-to-non-literal-to-byte: output should be empty") - 8517 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to" "F - test-copy-to-non-literal-to-byte: error message") - 8518 # check that stop(1) was called - 8519 (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status") - 8520 # don't restore from ebp - 8521 81 0/subop/add %esp 8/imm32 - 8522 # . epilogue - 8523 5d/pop-to-ebp - 8524 c3/return - 8525 - 8526 test-copy-to-deref-address: - 8527 # . prologue - 8528 55/push-ebp - 8529 89/<- %ebp 4/r32/esp - 8530 # setup - 8531 (clear-stream _test-input-stream) - 8532 (clear-stream $_test-input-buffered-file->buffer) - 8533 (clear-stream _test-output-stream) - 8534 (clear-stream $_test-output-buffered-file->buffer) - 8535 # - 8536 (write _test-input-stream "fn foo {\n") - 8537 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") - 8538 (write _test-input-stream " var y/ecx: (addr addr int) <- copy 0\n") - 8539 (write _test-input-stream " copy-to *y, x\n") - 8540 (write _test-input-stream "}\n") - 8541 # convert - 8542 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 8543 (flush _test-output-buffered-file) - 8544 # no errors - 8545 # . epilogue - 8546 5d/pop-to-ebp - 8547 c3/return - 8548 - 8549 test-copy-to-from-non-scalar-inout: - 8550 # . prologue - 8551 55/push-ebp - 8552 89/<- %ebp 4/r32/esp - 8553 # setup - 8554 (clear-stream _test-input-stream) - 8555 (clear-stream $_test-input-buffered-file->buffer) - 8556 (clear-stream _test-output-stream) - 8557 (clear-stream $_test-output-buffered-file->buffer) - 8558 (clear-stream _test-error-stream) - 8559 (clear-stream $_test-error-buffered-file->buffer) - 8560 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8561 68/push 0/imm32 - 8562 68/push 0/imm32 - 8563 89/<- %edx 4/r32/esp - 8564 (tailor-exit-descriptor %edx 0x10) - 8565 # - 8566 (write _test-input-stream "fn foo {\n") - 8567 (write _test-input-stream " var x: (handle int)\n") - 8568 (write _test-input-stream " var y: int\n") - 8569 (write _test-input-stream " copy-to y, x\n") - 8570 (write _test-input-stream "}\n") - 8571 # convert - 8572 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8573 # registers except esp clobbered at this point - 8574 # restore ed - 8575 89/<- %edx 4/r32/esp - 8576 (flush _test-output-buffered-file) - 8577 (flush _test-error-buffered-file) - 8578 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8584 # check output - 8585 (check-stream-equal _test-output-stream "" "F - test-copy-to-from-non-scalar-inout: output should be empty") - 8586 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: 'x' is too large to copy" "F - test-copy-to-from-non-scalar-inout: error message") - 8587 # check that stop(1) was called - 8588 (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status") - 8589 # don't restore from ebp - 8590 81 0/subop/add %esp 8/imm32 - 8591 # . epilogue - 8592 5d/pop-to-ebp - 8593 c3/return - 8594 - 8595 test-copy-byte-with-no-inout: - 8596 # . prologue - 8597 55/push-ebp - 8598 89/<- %ebp 4/r32/esp - 8599 # setup - 8600 (clear-stream _test-input-stream) - 8601 (clear-stream $_test-input-buffered-file->buffer) - 8602 (clear-stream _test-output-stream) - 8603 (clear-stream $_test-output-buffered-file->buffer) - 8604 (clear-stream _test-error-stream) - 8605 (clear-stream $_test-error-buffered-file->buffer) - 8606 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8607 68/push 0/imm32 - 8608 68/push 0/imm32 - 8609 89/<- %edx 4/r32/esp - 8610 (tailor-exit-descriptor %edx 0x10) - 8611 # - 8612 (write _test-input-stream "fn foo {\n") - 8613 (write _test-input-stream " var x/eax: byte <- copy-byte\n") - 8614 (write _test-input-stream "}\n") - 8615 # convert - 8616 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8617 # registers except esp clobbered at this point - 8618 # restore ed - 8619 89/<- %edx 4/r32/esp - 8620 (flush _test-output-buffered-file) - 8621 (flush _test-error-buffered-file) - 8622 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8628 # check output - 8629 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-no-inout: output should be empty") - 8630 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' expects an inout" "F - test-copy-byte-with-no-inout: error message") - 8631 # check that stop(1) was called - 8632 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status") - 8633 # don't restore from ebp - 8634 81 0/subop/add %esp 8/imm32 - 8635 # . epilogue - 8636 5d/pop-to-ebp - 8637 c3/return - 8638 - 8639 test-copy-byte-with-multiple-inouts: - 8640 # . prologue - 8641 55/push-ebp - 8642 89/<- %ebp 4/r32/esp - 8643 # setup - 8644 (clear-stream _test-input-stream) - 8645 (clear-stream $_test-input-buffered-file->buffer) - 8646 (clear-stream _test-output-stream) - 8647 (clear-stream $_test-output-buffered-file->buffer) - 8648 (clear-stream _test-error-stream) - 8649 (clear-stream $_test-error-buffered-file->buffer) - 8650 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8651 68/push 0/imm32 - 8652 68/push 0/imm32 - 8653 89/<- %edx 4/r32/esp - 8654 (tailor-exit-descriptor %edx 0x10) - 8655 # - 8656 (write _test-input-stream "fn foo {\n") - 8657 (write _test-input-stream " var x/eax: byte <- copy-byte 0, 0\n") - 8658 (write _test-input-stream "}\n") - 8659 # convert - 8660 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8661 # registers except esp clobbered at this point - 8662 # restore ed - 8663 89/<- %edx 4/r32/esp - 8664 (flush _test-output-buffered-file) - 8665 (flush _test-error-buffered-file) - 8666 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8672 # check output - 8673 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-multiple-inouts: output should be empty") - 8674 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' must have just one inout" "F - test-copy-byte-with-multiple-inouts: error message") - 8675 # check that stop(1) was called - 8676 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status") - 8677 # don't restore from ebp - 8678 81 0/subop/add %esp 8/imm32 - 8679 # . epilogue - 8680 5d/pop-to-ebp - 8681 c3/return - 8682 - 8683 test-copy-byte-with-no-output: - 8684 # . prologue - 8685 55/push-ebp - 8686 89/<- %ebp 4/r32/esp - 8687 # setup - 8688 (clear-stream _test-input-stream) - 8689 (clear-stream $_test-input-buffered-file->buffer) - 8690 (clear-stream _test-output-stream) - 8691 (clear-stream $_test-output-buffered-file->buffer) - 8692 (clear-stream _test-error-stream) - 8693 (clear-stream $_test-error-buffered-file->buffer) - 8694 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8695 68/push 0/imm32 - 8696 68/push 0/imm32 - 8697 89/<- %edx 4/r32/esp - 8698 (tailor-exit-descriptor %edx 0x10) - 8699 # - 8700 (write _test-input-stream "fn foo {\n") - 8701 (write _test-input-stream " copy-byte 0\n") - 8702 (write _test-input-stream "}\n") - 8703 # convert - 8704 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8705 # registers except esp clobbered at this point - 8706 # restore ed - 8707 89/<- %edx 4/r32/esp - 8708 (flush _test-output-buffered-file) - 8709 (flush _test-error-buffered-file) - 8710 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8716 # check output - 8717 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-no-output: output should be empty") - 8718 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' expects an output" "F - test-copy-byte-with-no-output: error message") - 8719 # check that stop(1) was called - 8720 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status") - 8721 # don't restore from ebp - 8722 81 0/subop/add %esp 8/imm32 - 8723 # . epilogue - 8724 5d/pop-to-ebp - 8725 c3/return - 8726 - 8727 test-copy-byte-with-multiple-outputs: - 8728 # . prologue - 8729 55/push-ebp - 8730 89/<- %ebp 4/r32/esp - 8731 # setup - 8732 (clear-stream _test-input-stream) - 8733 (clear-stream $_test-input-buffered-file->buffer) - 8734 (clear-stream _test-output-stream) - 8735 (clear-stream $_test-output-buffered-file->buffer) - 8736 (clear-stream _test-error-stream) - 8737 (clear-stream $_test-error-buffered-file->buffer) - 8738 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8739 68/push 0/imm32 - 8740 68/push 0/imm32 - 8741 89/<- %edx 4/r32/esp - 8742 (tailor-exit-descriptor %edx 0x10) - 8743 # - 8744 (write _test-input-stream "fn foo {\n") - 8745 (write _test-input-stream " var x/eax: byte <- copy 0\n") - 8746 (write _test-input-stream " var y/ecx: byte <- copy 0\n") - 8747 (write _test-input-stream " x, y <- copy-byte 0\n") - 8748 (write _test-input-stream "}\n") - 8749 # convert - 8750 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8751 # registers except esp clobbered at this point - 8752 # restore ed - 8753 89/<- %edx 4/r32/esp - 8754 (flush _test-output-buffered-file) - 8755 (flush _test-error-buffered-file) - 8756 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8762 # check output - 8763 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-multiple-outputs: output should be empty") - 8764 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' must have just one output" "F - test-copy-byte-with-multiple-outputs: error message") - 8765 # check that stop(1) was called - 8766 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status") - 8767 # don't restore from ebp - 8768 81 0/subop/add %esp 8/imm32 - 8769 # . epilogue - 8770 5d/pop-to-ebp - 8771 c3/return - 8772 - 8773 test-copy-byte-deref-address: - 8774 # . prologue - 8775 55/push-ebp - 8776 89/<- %ebp 4/r32/esp - 8777 # setup - 8778 (clear-stream _test-input-stream) - 8779 (clear-stream $_test-input-buffered-file->buffer) - 8780 (clear-stream _test-output-stream) - 8781 (clear-stream $_test-output-buffered-file->buffer) - 8782 # - 8783 (write _test-input-stream "fn foo {\n") - 8784 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") - 8785 (write _test-input-stream " var y/ecx: byte <- copy-byte *x\n") - 8786 (write _test-input-stream "}\n") - 8787 # convert - 8788 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 8789 (flush _test-output-buffered-file) - 8790 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8796 # not bothering checking output - 8797 (check-next-stream-line-equal _test-error-stream "" "F - test-copy-byte-deref-address: error message") - 8798 # . epilogue - 8799 5d/pop-to-ebp - 8800 c3/return - 8801 - 8802 test-copy-byte-with-invalid-output-type: - 8803 # . prologue - 8804 55/push-ebp - 8805 89/<- %ebp 4/r32/esp - 8806 # setup - 8807 (clear-stream _test-input-stream) - 8808 (clear-stream $_test-input-buffered-file->buffer) - 8809 (clear-stream _test-output-stream) - 8810 (clear-stream $_test-output-buffered-file->buffer) - 8811 (clear-stream _test-error-stream) - 8812 (clear-stream $_test-error-buffered-file->buffer) - 8813 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8814 68/push 0/imm32 - 8815 68/push 0/imm32 - 8816 89/<- %edx 4/r32/esp - 8817 (tailor-exit-descriptor %edx 0x10) - 8818 # - 8819 (write _test-input-stream "fn foo {\n") - 8820 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") - 8821 (write _test-input-stream " var y/eax: int <- copy-byte *x\n") - 8822 (write _test-input-stream "}\n") - 8823 # convert - 8824 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8825 # registers except esp clobbered at this point - 8826 # restore ed - 8827 89/<- %edx 4/r32/esp - 8828 (flush _test-output-buffered-file) - 8829 (flush _test-error-buffered-file) - 8830 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8836 # check output - 8837 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-invalid-output-type: output should be empty") - 8838 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' must write to output of type byte" "F - test-copy-byte-with-invalid-output-type: error message") - 8839 # check that stop(1) was called - 8840 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status") - 8841 # don't restore from ebp - 8842 81 0/subop/add %esp 8/imm32 - 8843 # . epilogue - 8844 5d/pop-to-ebp - 8845 c3/return - 8846 - 8847 test-copy-byte-from-non-scalar-inout: - 8848 # . prologue - 8849 55/push-ebp - 8850 89/<- %ebp 4/r32/esp - 8851 # setup - 8852 (clear-stream _test-input-stream) - 8853 (clear-stream $_test-input-buffered-file->buffer) - 8854 (clear-stream _test-output-stream) - 8855 (clear-stream $_test-output-buffered-file->buffer) - 8856 (clear-stream _test-error-stream) - 8857 (clear-stream $_test-error-buffered-file->buffer) - 8858 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8859 68/push 0/imm32 - 8860 68/push 0/imm32 - 8861 89/<- %edx 4/r32/esp - 8862 (tailor-exit-descriptor %edx 0x10) - 8863 # - 8864 (write _test-input-stream "fn foo {\n") - 8865 (write _test-input-stream " var x: (handle int)\n") - 8866 (write _test-input-stream " var y/eax: byte <- copy-byte x\n") - 8867 (write _test-input-stream "}\n") - 8868 # convert - 8869 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8870 # registers except esp clobbered at this point - 8871 # restore ed - 8872 89/<- %edx 4/r32/esp - 8873 (flush _test-output-buffered-file) - 8874 (flush _test-error-buffered-file) - 8875 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8881 # check output - 8882 (check-stream-equal _test-output-stream "" "F - test-copy-byte-from-non-scalar-inout: output should be empty") - 8883 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte: 'x' is too large to fit in a register" "F - test-copy-byte-from-non-scalar-inout: error message") - 8884 # check that stop(1) was called - 8885 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status") - 8886 # don't restore from ebp - 8887 81 0/subop/add %esp 8/imm32 - 8888 # . epilogue - 8889 5d/pop-to-ebp - 8890 c3/return - 8891 - 8892 test-copy-byte-to-with-no-inout: - 8893 # . prologue - 8894 55/push-ebp - 8895 89/<- %ebp 4/r32/esp - 8896 # setup - 8897 (clear-stream _test-input-stream) - 8898 (clear-stream $_test-input-buffered-file->buffer) - 8899 (clear-stream _test-output-stream) - 8900 (clear-stream $_test-output-buffered-file->buffer) - 8901 (clear-stream _test-error-stream) - 8902 (clear-stream $_test-error-buffered-file->buffer) - 8903 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8904 68/push 0/imm32 - 8905 68/push 0/imm32 - 8906 89/<- %edx 4/r32/esp - 8907 (tailor-exit-descriptor %edx 0x10) - 8908 # - 8909 (write _test-input-stream "fn foo {\n") - 8910 (write _test-input-stream " copy-byte-to\n") - 8911 (write _test-input-stream "}\n") - 8912 # convert - 8913 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8914 # registers except esp clobbered at this point - 8915 # restore ed - 8916 89/<- %edx 4/r32/esp - 8917 (flush _test-output-buffered-file) - 8918 (flush _test-error-buffered-file) - 8919 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8925 # check output - 8926 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-no-inout: output should be empty") - 8927 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must have two inouts" "F - test-copy-byte-to-with-no-inout: error message") - 8928 # check that stop(1) was called - 8929 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status") - 8930 # don't restore from ebp - 8931 81 0/subop/add %esp 8/imm32 - 8932 # . epilogue - 8933 5d/pop-to-ebp - 8934 c3/return - 8935 - 8936 test-copy-byte-to-with-no-source: - 8937 # . prologue - 8938 55/push-ebp - 8939 89/<- %ebp 4/r32/esp - 8940 # setup - 8941 (clear-stream _test-input-stream) - 8942 (clear-stream $_test-input-buffered-file->buffer) - 8943 (clear-stream _test-output-stream) - 8944 (clear-stream $_test-output-buffered-file->buffer) - 8945 (clear-stream _test-error-stream) - 8946 (clear-stream $_test-error-buffered-file->buffer) - 8947 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8948 68/push 0/imm32 - 8949 68/push 0/imm32 - 8950 89/<- %edx 4/r32/esp - 8951 (tailor-exit-descriptor %edx 0x10) - 8952 # - 8953 (write _test-input-stream "fn foo {\n") - 8954 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") - 8955 (write _test-input-stream " copy-byte-to *x\n") - 8956 (write _test-input-stream "}\n") - 8957 # convert - 8958 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 8959 # registers except esp clobbered at this point - 8960 # restore ed - 8961 89/<- %edx 4/r32/esp - 8962 (flush _test-output-buffered-file) - 8963 (flush _test-error-buffered-file) - 8964 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 8970 # check output - 8971 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-no-source: output should be empty") - 8972 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must have two inouts" "F - test-copy-byte-to-with-no-source: error message") - 8973 # check that stop(1) was called - 8974 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status") - 8975 # don't restore from ebp - 8976 81 0/subop/add %esp 8/imm32 - 8977 # . epilogue - 8978 5d/pop-to-ebp - 8979 c3/return - 8980 - 8981 test-copy-byte-to-with-too-many-inouts: - 8982 # . prologue - 8983 55/push-ebp - 8984 89/<- %ebp 4/r32/esp - 8985 # setup - 8986 (clear-stream _test-input-stream) - 8987 (clear-stream $_test-input-buffered-file->buffer) - 8988 (clear-stream _test-output-stream) - 8989 (clear-stream $_test-output-buffered-file->buffer) - 8990 (clear-stream _test-error-stream) - 8991 (clear-stream $_test-error-buffered-file->buffer) - 8992 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 8993 68/push 0/imm32 - 8994 68/push 0/imm32 - 8995 89/<- %edx 4/r32/esp - 8996 (tailor-exit-descriptor %edx 0x10) - 8997 # - 8998 (write _test-input-stream "fn foo {\n") - 8999 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") - 9000 (write _test-input-stream " copy-byte-to *x, 0, 0\n") - 9001 (write _test-input-stream "}\n") - 9002 # convert - 9003 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9004 # registers except esp clobbered at this point - 9005 # restore ed - 9006 89/<- %edx 4/r32/esp - 9007 (flush _test-output-buffered-file) - 9008 (flush _test-error-buffered-file) - 9009 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9015 # check output - 9016 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-too-many-inouts: output should be empty") - 9017 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must have two inouts" "F - test-copy-byte-to-with-too-many-inouts: error message") - 9018 # check that stop(1) was called - 9019 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status") - 9020 # don't restore from ebp - 9021 81 0/subop/add %esp 8/imm32 - 9022 # . epilogue - 9023 5d/pop-to-ebp - 9024 c3/return - 9025 - 9026 test-copy-byte-to-with-output: - 9027 # . prologue - 9028 55/push-ebp - 9029 89/<- %ebp 4/r32/esp - 9030 # setup - 9031 (clear-stream _test-input-stream) - 9032 (clear-stream $_test-input-buffered-file->buffer) - 9033 (clear-stream _test-output-stream) - 9034 (clear-stream $_test-output-buffered-file->buffer) - 9035 (clear-stream _test-error-stream) - 9036 (clear-stream $_test-error-buffered-file->buffer) - 9037 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9038 68/push 0/imm32 - 9039 68/push 0/imm32 - 9040 89/<- %edx 4/r32/esp - 9041 (tailor-exit-descriptor %edx 0x10) - 9042 # - 9043 (write _test-input-stream "fn foo {\n") - 9044 (write _test-input-stream " var x/eax: byte <- copy 0\n") - 9045 (write _test-input-stream " var y/ecx: (addr byte) <- copy 0\n") - 9046 (write _test-input-stream " x <- copy-byte-to *y, 0\n") - 9047 (write _test-input-stream "}\n") - 9048 # convert - 9049 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9050 # registers except esp clobbered at this point - 9051 # restore ed - 9052 89/<- %edx 4/r32/esp - 9053 (flush _test-output-buffered-file) - 9054 (flush _test-error-buffered-file) - 9055 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9061 # check output - 9062 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-output: output should be empty") - 9063 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must not have any outputs" "F - test-copy-byte-to-with-output: error message") - 9064 # check that stop(1) was called - 9065 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status") - 9066 # don't restore from ebp - 9067 81 0/subop/add %esp 8/imm32 - 9068 # . epilogue - 9069 5d/pop-to-ebp - 9070 c3/return - 9071 - 9072 test-copy-byte-to-with-invalid-output-type: - 9073 # . prologue - 9074 55/push-ebp - 9075 89/<- %ebp 4/r32/esp - 9076 # setup - 9077 (clear-stream _test-input-stream) - 9078 (clear-stream $_test-input-buffered-file->buffer) - 9079 (clear-stream _test-output-stream) - 9080 (clear-stream $_test-output-buffered-file->buffer) - 9081 (clear-stream _test-error-stream) - 9082 (clear-stream $_test-error-buffered-file->buffer) - 9083 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9084 68/push 0/imm32 - 9085 68/push 0/imm32 - 9086 89/<- %edx 4/r32/esp - 9087 (tailor-exit-descriptor %edx 0x10) - 9088 # - 9089 (write _test-input-stream "fn foo {\n") - 9090 (write _test-input-stream " var x/eax: byte <- copy 0\n") - 9091 (write _test-input-stream " var y: int\n") - 9092 (write _test-input-stream " copy-byte-to y, x\n") - 9093 (write _test-input-stream "}\n") - 9094 # convert - 9095 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9096 # registers except esp clobbered at this point - 9097 # restore ed - 9098 89/<- %edx 4/r32/esp - 9099 (flush _test-output-buffered-file) - 9100 (flush _test-error-buffered-file) - 9101 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9107 # check output - 9108 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-invalid-output-type: output should be empty") - 9109 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte-to: 'y' must be a byte" "F - test-copy-byte-to-with-invalid-output-type: error message") - 9110 # check that stop(1) was called - 9111 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status") - 9112 # don't restore from ebp - 9113 81 0/subop/add %esp 8/imm32 - 9114 # . epilogue - 9115 5d/pop-to-ebp - 9116 c3/return - 9117 - 9118 test-copy-byte-to-with-literal-inout: - 9119 # . prologue - 9120 55/push-ebp - 9121 89/<- %ebp 4/r32/esp - 9122 # setup - 9123 (clear-stream _test-input-stream) - 9124 (clear-stream $_test-input-buffered-file->buffer) - 9125 (clear-stream _test-output-stream) - 9126 (clear-stream $_test-output-buffered-file->buffer) - 9127 (clear-stream _test-error-stream) - 9128 (clear-stream $_test-error-buffered-file->buffer) - 9129 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9130 68/push 0/imm32 - 9131 68/push 0/imm32 - 9132 89/<- %edx 4/r32/esp - 9133 (tailor-exit-descriptor %edx 0x10) - 9134 # - 9135 (write _test-input-stream "fn foo {\n") - 9136 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") - 9137 (write _test-input-stream " copy-byte-to *x, 0\n") - 9138 (write _test-input-stream "}\n") - 9139 # convert - 9140 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9141 # registers except esp clobbered at this point - 9142 # restore ed - 9143 89/<- %edx 4/r32/esp - 9144 (flush _test-output-buffered-file) - 9145 (flush _test-error-buffered-file) - 9146 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9152 # check output - 9153 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-literal-inout: output should be empty") - 9154 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte-to: source (second inout) must be in a register" "F - test-copy-byte-to-with-literal-inout: error message") - 9155 # check that stop(1) was called - 9156 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status") - 9157 # don't restore from ebp - 9158 81 0/subop/add %esp 8/imm32 - 9159 # . epilogue - 9160 5d/pop-to-ebp - 9161 c3/return - 9162 - 9163 test-copy-byte-to-deref-address: - 9164 # . prologue - 9165 55/push-ebp - 9166 89/<- %ebp 4/r32/esp - 9167 # setup - 9168 (clear-stream _test-input-stream) - 9169 (clear-stream $_test-input-buffered-file->buffer) - 9170 (clear-stream _test-output-stream) - 9171 (clear-stream $_test-output-buffered-file->buffer) - 9172 # - 9173 (write _test-input-stream "fn foo {\n") - 9174 (write _test-input-stream " var x/eax: byte <- copy 0\n") - 9175 (write _test-input-stream " var y/ecx: (addr byte) <- copy 0\n") - 9176 (write _test-input-stream " copy-byte-to *y, x\n") - 9177 (write _test-input-stream "}\n") - 9178 # convert - 9179 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 9180 (flush _test-output-buffered-file) - 9181 # no errors - 9182 # . epilogue - 9183 5d/pop-to-ebp - 9184 c3/return - 9185 - 9186 test-copy-byte-to-from-non-scalar-inout: - 9187 # . prologue - 9188 55/push-ebp - 9189 89/<- %ebp 4/r32/esp - 9190 # setup - 9191 (clear-stream _test-input-stream) - 9192 (clear-stream $_test-input-buffered-file->buffer) - 9193 (clear-stream _test-output-stream) - 9194 (clear-stream $_test-output-buffered-file->buffer) - 9195 (clear-stream _test-error-stream) - 9196 (clear-stream $_test-error-buffered-file->buffer) - 9197 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9198 68/push 0/imm32 - 9199 68/push 0/imm32 - 9200 89/<- %edx 4/r32/esp - 9201 (tailor-exit-descriptor %edx 0x10) - 9202 # - 9203 (write _test-input-stream "fn foo {\n") - 9204 (write _test-input-stream " var x: (handle int)\n") - 9205 (write _test-input-stream " var y/eax: (addr byte) <- copy 0\n") - 9206 (write _test-input-stream " copy-byte-to *y, x\n") - 9207 (write _test-input-stream "}\n") - 9208 # convert - 9209 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9210 # registers except esp clobbered at this point - 9211 # restore ed - 9212 89/<- %edx 4/r32/esp - 9213 (flush _test-output-buffered-file) - 9214 (flush _test-error-buffered-file) - 9215 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9221 # check output - 9222 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-from-non-scalar-inout: output should be empty") - 9223 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte-to: 'x' is too large to copy" "F - test-copy-byte-to-from-non-scalar-inout: error message") - 9224 # check that stop(1) was called - 9225 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status") - 9226 # don't restore from ebp - 9227 81 0/subop/add %esp 8/imm32 - 9228 # . epilogue - 9229 5d/pop-to-ebp - 9230 c3/return - 9231 - 9232 test-compare-with-no-inout: - 9233 # . prologue - 9234 55/push-ebp - 9235 89/<- %ebp 4/r32/esp - 9236 # setup - 9237 (clear-stream _test-input-stream) - 9238 (clear-stream $_test-input-buffered-file->buffer) - 9239 (clear-stream _test-output-stream) - 9240 (clear-stream $_test-output-buffered-file->buffer) - 9241 (clear-stream _test-error-stream) - 9242 (clear-stream $_test-error-buffered-file->buffer) - 9243 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9244 68/push 0/imm32 - 9245 68/push 0/imm32 - 9246 89/<- %edx 4/r32/esp - 9247 (tailor-exit-descriptor %edx 0x10) - 9248 # - 9249 (write _test-input-stream "fn foo {\n") - 9250 (write _test-input-stream " var x: boolean\n") - 9251 (write _test-input-stream " compare\n") - 9252 (write _test-input-stream "}\n") - 9253 # convert - 9254 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9255 # registers except esp clobbered at this point - 9256 # restore ed - 9257 89/<- %edx 4/r32/esp - 9258 (flush _test-output-buffered-file) - 9259 (flush _test-error-buffered-file) - 9260 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9266 # check output - 9267 (check-stream-equal _test-output-stream "" "F - test-compare-with-no-inout: output should be empty") - 9268 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must have two inouts" "F - test-compare-with-no-inout: error message") - 9269 # check that stop(1) was called - 9270 (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status") - 9271 # don't restore from ebp - 9272 81 0/subop/add %esp 8/imm32 - 9273 # . epilogue - 9274 5d/pop-to-ebp - 9275 c3/return - 9276 - 9277 test-compare-with-just-one-inout: - 9278 # . prologue - 9279 55/push-ebp - 9280 89/<- %ebp 4/r32/esp - 9281 # setup - 9282 (clear-stream _test-input-stream) - 9283 (clear-stream $_test-input-buffered-file->buffer) - 9284 (clear-stream _test-output-stream) - 9285 (clear-stream $_test-output-buffered-file->buffer) - 9286 (clear-stream _test-error-stream) - 9287 (clear-stream $_test-error-buffered-file->buffer) - 9288 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9289 68/push 0/imm32 - 9290 68/push 0/imm32 - 9291 89/<- %edx 4/r32/esp - 9292 (tailor-exit-descriptor %edx 0x10) - 9293 # - 9294 (write _test-input-stream "fn foo {\n") - 9295 (write _test-input-stream " var x: boolean\n") - 9296 (write _test-input-stream " compare x\n") - 9297 (write _test-input-stream "}\n") - 9298 # convert - 9299 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9300 # registers except esp clobbered at this point - 9301 # restore ed - 9302 89/<- %edx 4/r32/esp - 9303 (flush _test-output-buffered-file) - 9304 (flush _test-error-buffered-file) - 9305 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9311 # check output - 9312 (check-stream-equal _test-output-stream "" "F - test-compare-with-just-one-inout: output should be empty") - 9313 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must have two inouts" "F - test-compare-with-just-one-inout: error message") - 9314 # check that stop(1) was called - 9315 (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status") - 9316 # don't restore from ebp - 9317 81 0/subop/add %esp 8/imm32 - 9318 # . epilogue - 9319 5d/pop-to-ebp - 9320 c3/return - 9321 - 9322 test-compare-with-too-many-inouts: - 9323 # . prologue - 9324 55/push-ebp - 9325 89/<- %ebp 4/r32/esp - 9326 # setup - 9327 (clear-stream _test-input-stream) - 9328 (clear-stream $_test-input-buffered-file->buffer) - 9329 (clear-stream _test-output-stream) - 9330 (clear-stream $_test-output-buffered-file->buffer) - 9331 (clear-stream _test-error-stream) - 9332 (clear-stream $_test-error-buffered-file->buffer) - 9333 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9334 68/push 0/imm32 - 9335 68/push 0/imm32 - 9336 89/<- %edx 4/r32/esp - 9337 (tailor-exit-descriptor %edx 0x10) - 9338 # - 9339 (write _test-input-stream "fn foo {\n") - 9340 (write _test-input-stream " var x: boolean\n") - 9341 (write _test-input-stream " compare x, 0, 0\n") - 9342 (write _test-input-stream "}\n") - 9343 # convert - 9344 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9345 # registers except esp clobbered at this point - 9346 # restore ed - 9347 89/<- %edx 4/r32/esp - 9348 (flush _test-output-buffered-file) - 9349 (flush _test-error-buffered-file) - 9350 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9356 # check output - 9357 (check-stream-equal _test-output-stream "" "F - test-compare-with-too-many-inouts: output should be empty") - 9358 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must have two inouts" "F - test-compare-with-too-many-inouts: error message") - 9359 # check that stop(1) was called - 9360 (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status") - 9361 # don't restore from ebp - 9362 81 0/subop/add %esp 8/imm32 - 9363 # . epilogue - 9364 5d/pop-to-ebp - 9365 c3/return - 9366 - 9367 test-compare-with-output: - 9368 # . prologue - 9369 55/push-ebp - 9370 89/<- %ebp 4/r32/esp - 9371 # setup - 9372 (clear-stream _test-input-stream) - 9373 (clear-stream $_test-input-buffered-file->buffer) - 9374 (clear-stream _test-output-stream) - 9375 (clear-stream $_test-output-buffered-file->buffer) - 9376 (clear-stream _test-error-stream) - 9377 (clear-stream $_test-error-buffered-file->buffer) - 9378 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9379 68/push 0/imm32 - 9380 68/push 0/imm32 - 9381 89/<- %edx 4/r32/esp - 9382 (tailor-exit-descriptor %edx 0x10) - 9383 # - 9384 (write _test-input-stream "fn foo {\n") - 9385 (write _test-input-stream " var x/eax: boolean <- copy 0\n") - 9386 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") - 9387 (write _test-input-stream " x <- compare y, 0\n") - 9388 (write _test-input-stream "}\n") - 9389 # convert - 9390 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9391 # registers except esp clobbered at this point - 9392 # restore ed - 9393 89/<- %edx 4/r32/esp - 9394 (flush _test-output-buffered-file) - 9395 (flush _test-error-buffered-file) - 9396 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9402 # check output - 9403 (check-stream-equal _test-output-stream "" "F - test-compare-with-output: output should be empty") - 9404 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must not have any outputs" "F - test-compare-with-output: error message") - 9405 # check that stop(1) was called - 9406 (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status") - 9407 # don't restore from ebp - 9408 81 0/subop/add %esp 8/imm32 - 9409 # . epilogue - 9410 5d/pop-to-ebp - 9411 c3/return - 9412 - 9413 test-compare-invalid-value-to-address: - 9414 # . prologue - 9415 55/push-ebp - 9416 89/<- %ebp 4/r32/esp - 9417 # setup - 9418 (clear-stream _test-input-stream) - 9419 (clear-stream $_test-input-buffered-file->buffer) - 9420 (clear-stream _test-output-stream) - 9421 (clear-stream $_test-output-buffered-file->buffer) - 9422 (clear-stream _test-error-stream) - 9423 (clear-stream $_test-error-buffered-file->buffer) - 9424 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9425 68/push 0/imm32 - 9426 68/push 0/imm32 - 9427 89/<- %edx 4/r32/esp - 9428 (tailor-exit-descriptor %edx 0x10) - 9429 # - 9430 (write _test-input-stream "fn foo {\n") - 9431 (write _test-input-stream " var x/eax: int <- copy 0\n") - 9432 (write _test-input-stream " var y: (addr int)\n") - 9433 (write _test-input-stream " compare y, x\n") - 9434 (write _test-input-stream "}\n") - 9435 # convert - 9436 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9437 # registers except esp clobbered at this point - 9438 # restore ed - 9439 89/<- %edx 4/r32/esp - 9440 (flush _test-output-buffered-file) - 9441 (flush _test-error-buffered-file) - 9442 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9448 # check output - 9449 (check-stream-equal _test-output-stream "" "F - test-compare-invalid-value-to-address: output should be empty") - 9450 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar" "F - test-compare-invalid-value-to-address: error message") - 9451 # check that stop(1) was called - 9452 (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status") - 9453 # don't restore from ebp - 9454 81 0/subop/add %esp 8/imm32 - 9455 # . epilogue - 9456 5d/pop-to-ebp - 9457 c3/return - 9458 - 9459 test-compare-address: - 9460 # . prologue - 9461 55/push-ebp - 9462 89/<- %ebp 4/r32/esp - 9463 # setup - 9464 (clear-stream _test-input-stream) - 9465 (clear-stream $_test-input-buffered-file->buffer) - 9466 (clear-stream _test-output-stream) - 9467 (clear-stream $_test-output-buffered-file->buffer) - 9468 # - 9469 (write _test-input-stream "fn foo {\n") - 9470 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") - 9471 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") - 9472 (write _test-input-stream " compare y, x\n") - 9473 (write _test-input-stream "}\n") - 9474 # convert - 9475 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 9476 (flush _test-output-buffered-file) - 9477 # no errors - 9478 # . epilogue - 9479 5d/pop-to-ebp - 9480 c3/return - 9481 - 9482 test-compare-deref-address: - 9483 # . prologue - 9484 55/push-ebp - 9485 89/<- %ebp 4/r32/esp - 9486 # setup - 9487 (clear-stream _test-input-stream) - 9488 (clear-stream $_test-input-buffered-file->buffer) - 9489 (clear-stream _test-output-stream) - 9490 (clear-stream $_test-output-buffered-file->buffer) - 9491 # - 9492 (write _test-input-stream "fn foo {\n") - 9493 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") - 9494 (write _test-input-stream " var y/ecx: (addr addr int) <- copy 0\n") - 9495 (write _test-input-stream " compare *y, x\n") - 9496 (write _test-input-stream "}\n") - 9497 # convert - 9498 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 9499 (flush _test-output-buffered-file) - 9500 # no errors - 9501 # . epilogue - 9502 5d/pop-to-ebp - 9503 c3/return - 9504 - 9505 test-compare-two-vars-in-memory: - 9506 # . prologue - 9507 55/push-ebp - 9508 89/<- %ebp 4/r32/esp - 9509 # setup - 9510 (clear-stream _test-input-stream) - 9511 (clear-stream $_test-input-buffered-file->buffer) - 9512 (clear-stream _test-output-stream) - 9513 (clear-stream $_test-output-buffered-file->buffer) - 9514 (clear-stream _test-error-stream) - 9515 (clear-stream $_test-error-buffered-file->buffer) - 9516 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9517 68/push 0/imm32 - 9518 68/push 0/imm32 - 9519 89/<- %edx 4/r32/esp - 9520 (tailor-exit-descriptor %edx 0x10) - 9521 # - 9522 (write _test-input-stream "fn foo {\n") - 9523 (write _test-input-stream " var x: boolean\n") - 9524 (write _test-input-stream " compare x, x\n") - 9525 (write _test-input-stream "}\n") - 9526 # convert - 9527 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9528 # registers except esp clobbered at this point - 9529 # restore ed - 9530 89/<- %edx 4/r32/esp - 9531 (flush _test-output-buffered-file) - 9532 (flush _test-error-buffered-file) - 9533 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9539 # check output - 9540 (check-stream-equal _test-output-stream "" "F - test-compare-two-vars-in-memory: output should be empty") - 9541 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: both inouts are in memory" "F - test-compare-two-vars-in-memory: error message") - 9542 # check that stop(1) was called - 9543 (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status") - 9544 # don't restore from ebp - 9545 81 0/subop/add %esp 8/imm32 - 9546 # . epilogue - 9547 5d/pop-to-ebp - 9548 c3/return - 9549 - 9550 test-compare-non-scalar: - 9551 # . prologue - 9552 55/push-ebp - 9553 89/<- %ebp 4/r32/esp - 9554 # setup - 9555 (clear-stream _test-input-stream) - 9556 (clear-stream $_test-input-buffered-file->buffer) - 9557 (clear-stream _test-output-stream) - 9558 (clear-stream $_test-output-buffered-file->buffer) - 9559 (clear-stream _test-error-stream) - 9560 (clear-stream $_test-error-buffered-file->buffer) - 9561 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9562 68/push 0/imm32 - 9563 68/push 0/imm32 - 9564 89/<- %edx 4/r32/esp - 9565 (tailor-exit-descriptor %edx 0x10) - 9566 # - 9567 (write _test-input-stream "fn foo {\n") - 9568 (write _test-input-stream " var x: (handle int)\n") - 9569 (write _test-input-stream " var y: int\n") - 9570 (write _test-input-stream " compare y, x\n") - 9571 (write _test-input-stream "}\n") - 9572 # convert - 9573 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9574 # registers except esp clobbered at this point - 9575 # restore ed - 9576 89/<- %edx 4/r32/esp - 9577 (flush _test-output-buffered-file) - 9578 (flush _test-error-buffered-file) - 9579 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9585 # check output - 9586 (check-stream-equal _test-output-stream "" "F - test-compare-non-scalar: output should be empty") - 9587 #? (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: 'x' is too large to compare" "F - test-compare-non-scalar: error message") - 9588 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: both inouts are in memory" "F - test-compare-non-scalar: error message") - 9589 # check that stop(1) was called - 9590 (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status") - 9591 # don't restore from ebp - 9592 81 0/subop/add %esp 8/imm32 - 9593 # . epilogue - 9594 5d/pop-to-ebp - 9595 c3/return - 9596 - 9597 test-compare-with-string-literal: - 9598 # . prologue - 9599 55/push-ebp - 9600 89/<- %ebp 4/r32/esp - 9601 # setup - 9602 (clear-stream _test-input-stream) - 9603 (clear-stream $_test-input-buffered-file->buffer) - 9604 (clear-stream _test-output-stream) - 9605 (clear-stream $_test-output-buffered-file->buffer) - 9606 (clear-stream _test-error-stream) - 9607 (clear-stream $_test-error-buffered-file->buffer) - 9608 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9609 68/push 0/imm32 - 9610 68/push 0/imm32 - 9611 89/<- %edx 4/r32/esp - 9612 (tailor-exit-descriptor %edx 0x10) - 9613 # - 9614 (write _test-input-stream "fn foo {\n") - 9615 (write _test-input-stream " var x/eax: (addr array byte) <- copy 0\n") - 9616 (write _test-input-stream " compare x, \"abc\"\n") - 9617 (write _test-input-stream "}\n") - 9618 # convert - 9619 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9620 # registers except esp clobbered at this point - 9621 # restore ed - 9622 89/<- %edx 4/r32/esp - 9623 (flush _test-output-buffered-file) - 9624 (flush _test-error-buffered-file) - 9625 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9631 # check output - 9632 (check-stream-equal _test-output-stream "" "F - test-compare-with-string-literal: output should be empty") - 9633 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: string literal \"abc\" is not supported; use the string-equal? function" "F - test-compare-with-string-literal: error message") - 9634 # check that stop(1) was called - 9635 (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status") - 9636 # don't restore from ebp - 9637 81 0/subop/add %esp 8/imm32 - 9638 # . epilogue - 9639 5d/pop-to-ebp - 9640 c3/return - 9641 - 9642 test-address-with-no-inout: - 9643 # . prologue - 9644 55/push-ebp - 9645 89/<- %ebp 4/r32/esp - 9646 # setup - 9647 (clear-stream _test-input-stream) - 9648 (clear-stream $_test-input-buffered-file->buffer) - 9649 (clear-stream _test-output-stream) - 9650 (clear-stream $_test-output-buffered-file->buffer) - 9651 (clear-stream _test-error-stream) - 9652 (clear-stream $_test-error-buffered-file->buffer) - 9653 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9654 68/push 0/imm32 - 9655 68/push 0/imm32 - 9656 89/<- %edx 4/r32/esp - 9657 (tailor-exit-descriptor %edx 0x10) - 9658 # - 9659 (write _test-input-stream "fn foo {\n") - 9660 (write _test-input-stream " var x/eax: boolean <- address\n") - 9661 (write _test-input-stream "}\n") - 9662 # convert - 9663 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9664 # registers except esp clobbered at this point - 9665 # restore ed - 9666 89/<- %edx 4/r32/esp - 9667 (flush _test-output-buffered-file) - 9668 (flush _test-error-buffered-file) - 9669 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9675 # check output - 9676 (check-stream-equal _test-output-stream "" "F - test-address-with-no-inout: output should be empty") - 9677 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' expects an inout" "F - test-address-with-no-inout: error message") - 9678 # check that stop(1) was called - 9679 (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status") - 9680 # don't restore from ebp - 9681 81 0/subop/add %esp 8/imm32 - 9682 # . epilogue - 9683 5d/pop-to-ebp - 9684 c3/return - 9685 - 9686 test-address-with-multiple-inouts: - 9687 # . prologue - 9688 55/push-ebp - 9689 89/<- %ebp 4/r32/esp - 9690 # setup - 9691 (clear-stream _test-input-stream) - 9692 (clear-stream $_test-input-buffered-file->buffer) - 9693 (clear-stream _test-output-stream) - 9694 (clear-stream $_test-output-buffered-file->buffer) - 9695 (clear-stream _test-error-stream) - 9696 (clear-stream $_test-error-buffered-file->buffer) - 9697 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9698 68/push 0/imm32 - 9699 68/push 0/imm32 - 9700 89/<- %edx 4/r32/esp - 9701 (tailor-exit-descriptor %edx 0x10) - 9702 # - 9703 (write _test-input-stream "fn foo {\n") - 9704 (write _test-input-stream " var x/eax: boolean <- address 0, 0\n") - 9705 (write _test-input-stream "}\n") - 9706 # convert - 9707 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9708 # registers except esp clobbered at this point - 9709 # restore ed - 9710 89/<- %edx 4/r32/esp - 9711 (flush _test-output-buffered-file) - 9712 (flush _test-error-buffered-file) - 9713 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9719 # check output - 9720 (check-stream-equal _test-output-stream "" "F - test-address-with-multiple-inouts: output should be empty") - 9721 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' must have just one inout" "F - test-address-with-multiple-inouts: error message") - 9722 # check that stop(1) was called - 9723 (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status") - 9724 # don't restore from ebp - 9725 81 0/subop/add %esp 8/imm32 - 9726 # . epilogue - 9727 5d/pop-to-ebp - 9728 c3/return - 9729 - 9730 test-address-with-no-output: - 9731 # . prologue - 9732 55/push-ebp - 9733 89/<- %ebp 4/r32/esp - 9734 # setup - 9735 (clear-stream _test-input-stream) - 9736 (clear-stream $_test-input-buffered-file->buffer) - 9737 (clear-stream _test-output-stream) - 9738 (clear-stream $_test-output-buffered-file->buffer) - 9739 (clear-stream _test-error-stream) - 9740 (clear-stream $_test-error-buffered-file->buffer) - 9741 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9742 68/push 0/imm32 - 9743 68/push 0/imm32 - 9744 89/<- %edx 4/r32/esp - 9745 (tailor-exit-descriptor %edx 0x10) - 9746 # - 9747 (write _test-input-stream "fn foo {\n") - 9748 (write _test-input-stream " address 0\n") - 9749 (write _test-input-stream "}\n") - 9750 # convert - 9751 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9752 # registers except esp clobbered at this point - 9753 # restore ed - 9754 89/<- %edx 4/r32/esp - 9755 (flush _test-output-buffered-file) - 9756 (flush _test-error-buffered-file) - 9757 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9763 # check output - 9764 (check-stream-equal _test-output-stream "" "F - test-address-with-no-output: output should be empty") - 9765 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' expects an output" "F - test-address-with-no-output: error message") - 9766 # check that stop(1) was called - 9767 (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status") - 9768 # don't restore from ebp - 9769 81 0/subop/add %esp 8/imm32 - 9770 # . epilogue - 9771 5d/pop-to-ebp - 9772 c3/return - 9773 - 9774 test-address-with-multiple-outputs: - 9775 # . prologue - 9776 55/push-ebp - 9777 89/<- %ebp 4/r32/esp - 9778 # setup - 9779 (clear-stream _test-input-stream) - 9780 (clear-stream $_test-input-buffered-file->buffer) - 9781 (clear-stream _test-output-stream) - 9782 (clear-stream $_test-output-buffered-file->buffer) - 9783 (clear-stream _test-error-stream) - 9784 (clear-stream $_test-error-buffered-file->buffer) - 9785 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9786 68/push 0/imm32 - 9787 68/push 0/imm32 - 9788 89/<- %edx 4/r32/esp - 9789 (tailor-exit-descriptor %edx 0x10) - 9790 # - 9791 (write _test-input-stream "fn foo {\n") - 9792 (write _test-input-stream " var x/eax: boolean <- copy 0\n") - 9793 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") - 9794 (write _test-input-stream " x, y <- address 0\n") - 9795 (write _test-input-stream "}\n") - 9796 # convert - 9797 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9798 # registers except esp clobbered at this point - 9799 # restore ed - 9800 89/<- %edx 4/r32/esp - 9801 (flush _test-output-buffered-file) - 9802 (flush _test-error-buffered-file) - 9803 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9809 # check output - 9810 (check-stream-equal _test-output-stream "" "F - test-address-with-multiple-outputs: output should be empty") - 9811 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' must have just one output" "F - test-address-with-multiple-outputs: error message") - 9812 # check that stop(1) was called - 9813 (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status") - 9814 # don't restore from ebp - 9815 81 0/subop/add %esp 8/imm32 - 9816 # . epilogue - 9817 5d/pop-to-ebp - 9818 c3/return - 9819 - 9820 # silly but it works - 9821 test-address-of-deref: - 9822 # . prologue - 9823 55/push-ebp - 9824 89/<- %ebp 4/r32/esp - 9825 # setup - 9826 (clear-stream _test-input-stream) - 9827 (clear-stream $_test-input-buffered-file->buffer) - 9828 (clear-stream _test-output-stream) - 9829 (clear-stream $_test-output-buffered-file->buffer) - 9830 # - 9831 (write _test-input-stream "fn foo {\n") - 9832 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") - 9833 (write _test-input-stream " var y/ecx: (addr int) <- address *x\n") - 9834 (write _test-input-stream "}\n") - 9835 # convert - 9836 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 9837 (flush _test-output-buffered-file) - 9838 # no errors - 9839 # . epilogue - 9840 5d/pop-to-ebp - 9841 c3/return - 9842 - 9843 test-address-to-non-register: - 9844 # . prologue - 9845 55/push-ebp - 9846 89/<- %ebp 4/r32/esp - 9847 # setup - 9848 (clear-stream _test-input-stream) - 9849 (clear-stream $_test-input-buffered-file->buffer) - 9850 (clear-stream _test-output-stream) - 9851 (clear-stream $_test-output-buffered-file->buffer) - 9852 (clear-stream _test-error-stream) - 9853 (clear-stream $_test-error-buffered-file->buffer) - 9854 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9855 68/push 0/imm32 - 9856 68/push 0/imm32 - 9857 89/<- %edx 4/r32/esp - 9858 (tailor-exit-descriptor %edx 0x10) - 9859 # - 9860 (write _test-input-stream "fn foo {\n") - 9861 (write _test-input-stream " var x: (addr int)\n") - 9862 (write _test-input-stream " x <- address 0\n") - 9863 (write _test-input-stream "}\n") - 9864 # convert - 9865 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9866 # registers except esp clobbered at this point - 9867 # restore ed - 9868 89/<- %edx 4/r32/esp - 9869 (flush _test-output-buffered-file) - 9870 (flush _test-error-buffered-file) - 9871 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9877 # check output - 9878 (check-stream-equal _test-output-stream "" "F - test-address-to-non-register: output should be empty") - 9879 (check-next-stream-line-equal _test-error-stream "fn foo: stmt address: output 'x' not in a register" "F - test-address-to-non-register: error message") - 9880 # check that stop(1) was called - 9881 (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status") - 9882 # don't restore from ebp - 9883 81 0/subop/add %esp 8/imm32 - 9884 # . epilogue - 9885 5d/pop-to-ebp - 9886 c3/return - 9887 - 9888 test-address-with-wrong-type: - 9889 # . prologue - 9890 55/push-ebp - 9891 89/<- %ebp 4/r32/esp - 9892 # setup - 9893 (clear-stream _test-input-stream) - 9894 (clear-stream $_test-input-buffered-file->buffer) - 9895 (clear-stream _test-output-stream) - 9896 (clear-stream $_test-output-buffered-file->buffer) - 9897 (clear-stream _test-error-stream) - 9898 (clear-stream $_test-error-buffered-file->buffer) - 9899 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9900 68/push 0/imm32 - 9901 68/push 0/imm32 - 9902 89/<- %edx 4/r32/esp - 9903 (tailor-exit-descriptor %edx 0x10) - 9904 # - 9905 (write _test-input-stream "fn foo {\n") - 9906 (write _test-input-stream " var x: int\n") - 9907 (write _test-input-stream " var y/eax: (addr boolean) <- address x\n") - 9908 (write _test-input-stream "}\n") - 9909 # convert - 9910 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) - 9911 # registers except esp clobbered at this point - 9912 # restore ed - 9913 89/<- %edx 4/r32/esp - 9914 (flush _test-output-buffered-file) - 9915 (flush _test-error-buffered-file) - 9916 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ - 9922 # check output - 9923 (check-stream-equal _test-output-stream "" "F - test-address-with-wrong-type: output should be empty") - 9924 (check-next-stream-line-equal _test-error-stream "fn foo: stmt address: output 'y' cannot hold address of 'x'" "F - test-address-with-wrong-type: error message") - 9925 # check that stop(1) was called - 9926 (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status") - 9927 # don't restore from ebp - 9928 81 0/subop/add %esp 8/imm32 - 9929 # . epilogue - 9930 5d/pop-to-ebp - 9931 c3/return - 9932 - 9933 test-address-with-right-type-for-array: - 9934 # . prologue - 9935 55/push-ebp - 9936 89/<- %ebp 4/r32/esp - 9937 # setup - 9938 (clear-stream _test-input-stream) - 9939 (clear-stream $_test-input-buffered-file->buffer) - 9940 (clear-stream _test-output-stream) - 9941 (clear-stream $_test-output-buffered-file->buffer) - 9942 # - 9943 (write _test-input-stream "fn foo {\n") - 9944 (write _test-input-stream " var x: (array int 3)\n") - 9945 (write _test-input-stream " var y/eax: (addr array int) <- address x\n") - 9946 (write _test-input-stream "}\n") - 9947 # convert - 9948 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 9949 (flush _test-output-buffered-file) - 9950 # no errors - 9951 # . epilogue - 9952 89/<- %esp 5/r32/ebp - 9953 5d/pop-to-ebp - 9954 c3/return - 9955 - 9956 test-address-with-right-type-for-stream: - 9957 # . prologue - 9958 55/push-ebp - 9959 89/<- %ebp 4/r32/esp - 9960 # setup - 9961 (clear-stream _test-input-stream) - 9962 (clear-stream $_test-input-buffered-file->buffer) - 9963 (clear-stream _test-output-stream) - 9964 (clear-stream $_test-output-buffered-file->buffer) - 9965 # - 9966 (write _test-input-stream "fn foo {\n") - 9967 (write _test-input-stream " var x: (stream int 3)\n") - 9968 (write _test-input-stream " var y/eax: (addr stream int) <- address x\n") - 9969 (write _test-input-stream "}\n") - 9970 # convert - 9971 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) - 9972 (flush _test-output-buffered-file) - 9973 # no errors - 9974 # . epilogue - 9975 89/<- %esp 5/r32/ebp - 9976 5d/pop-to-ebp - 9977 c3/return - 9978 - 9979 test-get-with-wrong-field: - 9980 # . prologue - 9981 55/push-ebp - 9982 89/<- %ebp 4/r32/esp - 9983 # setup - 9984 (clear-stream _test-input-stream) - 9985 (clear-stream $_test-input-buffered-file->buffer) - 9986 (clear-stream _test-output-stream) - 9987 (clear-stream $_test-output-buffered-file->buffer) - 9988 (clear-stream _test-error-stream) - 9989 (clear-stream $_test-error-buffered-file->buffer) - 9990 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) - 9991 68/push 0/imm32 - 9992 68/push 0/imm32 - 9993 89/<- %edx 4/r32/esp - 9994 (tailor-exit-descriptor %edx 0x10) - 9995 # - 9996 (write _test-input-stream "fn foo {\n") - 9997 (write _test-input-stream " var a: t\n") - 9998 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") - 9999 (write _test-input-stream "}\n") -10000 (write _test-input-stream "type t {\n") -10001 (write _test-input-stream " x: int\n") -10002 (write _test-input-stream "}\n") -10003 # convert -10004 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10005 # registers except esp clobbered at this point -10006 # restore ed -10007 89/<- %edx 4/r32/esp -10008 (flush _test-output-buffered-file) -10009 (flush _test-error-buffered-file) -10010 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10016 # check output -10017 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-field: output should be empty") -10018 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: type 't' has no member called 'y'" "F - test-get-with-wrong-field: error message") -10019 # check that stop(1) was called -10020 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status") -10021 # don't restore from ebp -10022 81 0/subop/add %esp 8/imm32 -10023 # . epilogue -10024 5d/pop-to-ebp -10025 c3/return -10026 -10027 test-get-with-wrong-base-type: -10028 # . prologue -10029 55/push-ebp -10030 89/<- %ebp 4/r32/esp -10031 # setup -10032 (clear-stream _test-input-stream) -10033 (clear-stream $_test-input-buffered-file->buffer) -10034 (clear-stream _test-output-stream) -10035 (clear-stream $_test-output-buffered-file->buffer) -10036 (clear-stream _test-error-stream) -10037 (clear-stream $_test-error-buffered-file->buffer) -10038 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10039 68/push 0/imm32 -10040 68/push 0/imm32 -10041 89/<- %edx 4/r32/esp -10042 (tailor-exit-descriptor %edx 0x10) -10043 # -10044 (write _test-input-stream "fn foo {\n") -10045 (write _test-input-stream " var a: int\n") -10046 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") -10047 (write _test-input-stream "}\n") -10048 # convert -10049 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10050 # registers except esp clobbered at this point -10051 # restore ed -10052 89/<- %edx 4/r32/esp -10053 (flush _test-output-buffered-file) -10054 (flush _test-error-buffered-file) -10055 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10061 # check output -10062 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-base-type: output should be empty") -10063 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' must have a 'type' definition" "F - test-get-with-wrong-base-type: error message") -10064 # check that stop(1) was called -10065 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status") -10066 # don't restore from ebp -10067 81 0/subop/add %esp 8/imm32 -10068 # . epilogue -10069 5d/pop-to-ebp -10070 c3/return -10071 -10072 test-get-with-wrong-base-type-2: -10073 # . prologue -10074 55/push-ebp -10075 89/<- %ebp 4/r32/esp -10076 # setup -10077 (clear-stream _test-input-stream) -10078 (clear-stream $_test-input-buffered-file->buffer) -10079 (clear-stream _test-output-stream) -10080 (clear-stream $_test-output-buffered-file->buffer) -10081 (clear-stream _test-error-stream) -10082 (clear-stream $_test-error-buffered-file->buffer) -10083 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10084 68/push 0/imm32 -10085 68/push 0/imm32 -10086 89/<- %edx 4/r32/esp -10087 (tailor-exit-descriptor %edx 0x10) -10088 # -10089 (write _test-input-stream "fn foo {\n") -10090 (write _test-input-stream " var a: (addr t)\n") -10091 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") -10092 (write _test-input-stream "}\n") -10093 (write _test-input-stream "type t {\n") -10094 (write _test-input-stream " x: int\n") -10095 (write _test-input-stream "}\n") -10096 # convert -10097 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10098 # registers except esp clobbered at this point -10099 # restore ed -10100 89/<- %edx 4/r32/esp -10101 (flush _test-output-buffered-file) -10102 (flush _test-error-buffered-file) -10103 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10109 # check output -10110 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-base-type-2: output should be empty") -10111 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' is an 'addr' type, and so must live in a register" "F - test-get-with-wrong-base-type-2: error message") -10112 # check that stop(1) was called -10113 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status") -10114 # don't restore from ebp -10115 81 0/subop/add %esp 8/imm32 -10116 # . epilogue -10117 5d/pop-to-ebp -10118 c3/return -10119 -10120 test-get-with-wrong-base-type-3: -10121 # . prologue -10122 55/push-ebp -10123 89/<- %ebp 4/r32/esp -10124 # setup -10125 (clear-stream _test-input-stream) -10126 (clear-stream $_test-input-buffered-file->buffer) -10127 (clear-stream _test-output-stream) -10128 (clear-stream $_test-output-buffered-file->buffer) -10129 (clear-stream _test-error-stream) -10130 (clear-stream $_test-error-buffered-file->buffer) -10131 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10132 68/push 0/imm32 -10133 68/push 0/imm32 -10134 89/<- %edx 4/r32/esp -10135 (tailor-exit-descriptor %edx 0x10) -10136 # -10137 (write _test-input-stream "fn foo {\n") -10138 (write _test-input-stream " var a: (handle int)\n") -10139 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") -10140 (write _test-input-stream "}\n") -10141 # convert -10142 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10143 # registers except esp clobbered at this point -10144 # restore ed -10145 89/<- %edx 4/r32/esp -10146 (flush _test-output-buffered-file) -10147 (flush _test-error-buffered-file) -10148 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10154 # check output -10155 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-base-type-3: output should be empty") -10156 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' must have a 'type' definition" "F - test-get-with-wrong-base-type-3: error message") -10157 # check that stop(1) was called -10158 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status") -10159 # don't restore from ebp -10160 81 0/subop/add %esp 8/imm32 -10161 # . epilogue -10162 5d/pop-to-ebp -10163 c3/return -10164 -10165 test-get-with-wrong-offset-type: -10166 # . prologue -10167 55/push-ebp -10168 89/<- %ebp 4/r32/esp -10169 # setup -10170 (clear-stream _test-input-stream) -10171 (clear-stream $_test-input-buffered-file->buffer) -10172 (clear-stream _test-output-stream) -10173 (clear-stream $_test-output-buffered-file->buffer) -10174 (clear-stream _test-error-stream) -10175 (clear-stream $_test-error-buffered-file->buffer) -10176 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10177 68/push 0/imm32 -10178 68/push 0/imm32 -10179 89/<- %edx 4/r32/esp -10180 (tailor-exit-descriptor %edx 0x10) -10181 # -10182 (write _test-input-stream "fn foo {\n") -10183 (write _test-input-stream " var a: t\n") -10184 (write _test-input-stream " var b: int\n") -10185 (write _test-input-stream " var c/ecx: (addr int) <- get a, b\n") -10186 (write _test-input-stream "}\n") -10187 (write _test-input-stream "type t {\n") -10188 (write _test-input-stream " x: int\n") -10189 (write _test-input-stream "}\n") -10190 # convert -10191 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10192 # registers except esp clobbered at this point -10193 # restore ed -10194 89/<- %edx 4/r32/esp -10195 (flush _test-output-buffered-file) -10196 (flush _test-error-buffered-file) -10197 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10203 # check output -10204 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-offset-type: output should be empty") -10205 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: type 't' has no member called 'b'" "F - test-get-with-wrong-offset-type: error message") -10206 # check that stop(1) was called -10207 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status") -10208 # don't restore from ebp -10209 81 0/subop/add %esp 8/imm32 -10210 # . epilogue -10211 5d/pop-to-ebp -10212 c3/return -10213 -10214 test-get-with-wrong-output-type: -10215 # . prologue -10216 55/push-ebp -10217 89/<- %ebp 4/r32/esp -10218 # setup -10219 (clear-stream _test-input-stream) -10220 (clear-stream $_test-input-buffered-file->buffer) -10221 (clear-stream _test-output-stream) -10222 (clear-stream $_test-output-buffered-file->buffer) -10223 (clear-stream _test-error-stream) -10224 (clear-stream $_test-error-buffered-file->buffer) -10225 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10226 68/push 0/imm32 -10227 68/push 0/imm32 -10228 89/<- %edx 4/r32/esp -10229 (tailor-exit-descriptor %edx 0x10) -10230 # -10231 (write _test-input-stream "fn foo {\n") -10232 (write _test-input-stream " var a: t\n") -10233 (write _test-input-stream " var c: (addr int)\n") -10234 (write _test-input-stream " c <- get a, x\n") -10235 (write _test-input-stream "}\n") -10236 (write _test-input-stream "type t {\n") -10237 (write _test-input-stream " x: int\n") -10238 (write _test-input-stream "}\n") -10239 # convert -10240 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10241 # registers except esp clobbered at this point -10242 # restore ed -10243 89/<- %edx 4/r32/esp -10244 (flush _test-output-buffered-file) -10245 (flush _test-error-buffered-file) -10246 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10252 # check output -10253 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type: output should be empty") -10254 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: output 'c' is not in a register" "F - test-get-with-wrong-output-type: error message") -10255 # check that stop(1) was called -10256 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status") -10257 # don't restore from ebp -10258 81 0/subop/add %esp 8/imm32 -10259 # . epilogue -10260 5d/pop-to-ebp -10261 c3/return -10262 -10263 test-get-with-wrong-output-type-2: -10264 # . prologue -10265 55/push-ebp -10266 89/<- %ebp 4/r32/esp -10267 # setup -10268 (clear-stream _test-input-stream) -10269 (clear-stream $_test-input-buffered-file->buffer) -10270 (clear-stream _test-output-stream) -10271 (clear-stream $_test-output-buffered-file->buffer) -10272 (clear-stream _test-error-stream) -10273 (clear-stream $_test-error-buffered-file->buffer) -10274 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10275 68/push 0/imm32 -10276 68/push 0/imm32 -10277 89/<- %edx 4/r32/esp -10278 (tailor-exit-descriptor %edx 0x10) -10279 # -10280 (write _test-input-stream "fn foo {\n") -10281 (write _test-input-stream " var a: t\n") -10282 (write _test-input-stream " var c/ecx: int <- get a, x\n") -10283 (write _test-input-stream "}\n") -10284 (write _test-input-stream "type t {\n") -10285 (write _test-input-stream " x: int\n") -10286 (write _test-input-stream "}\n") -10287 # convert -10288 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10289 # registers except esp clobbered at this point -10290 # restore ed -10291 89/<- %edx 4/r32/esp -10292 (flush _test-output-buffered-file) -10293 (flush _test-error-buffered-file) -10294 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10300 # check output -10301 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type-2: output should be empty") -10302 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: output must be an addr" "F - test-get-with-wrong-output-type-2: error message") -10303 # check that stop(1) was called -10304 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status") -10305 # don't restore from ebp -10306 81 0/subop/add %esp 8/imm32 -10307 # . epilogue -10308 5d/pop-to-ebp -10309 c3/return -10310 -10311 test-get-with-wrong-output-type-3: -10312 # . prologue -10313 55/push-ebp -10314 89/<- %ebp 4/r32/esp -10315 # setup -10316 (clear-stream _test-input-stream) -10317 (clear-stream $_test-input-buffered-file->buffer) -10318 (clear-stream _test-output-stream) -10319 (clear-stream $_test-output-buffered-file->buffer) -10320 (clear-stream _test-error-stream) -10321 (clear-stream $_test-error-buffered-file->buffer) -10322 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10323 68/push 0/imm32 -10324 68/push 0/imm32 -10325 89/<- %edx 4/r32/esp -10326 (tailor-exit-descriptor %edx 0x10) -10327 # -10328 (write _test-input-stream "fn foo {\n") -10329 (write _test-input-stream " var a: t\n") -10330 (write _test-input-stream " var c/ecx: (array int) <- get a, x\n") -10331 (write _test-input-stream "}\n") -10332 (write _test-input-stream "type t {\n") -10333 (write _test-input-stream " x: int\n") -10334 (write _test-input-stream "}\n") -10335 # convert -10336 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10337 # registers except esp clobbered at this point -10338 # restore ed -10339 89/<- %edx 4/r32/esp -10340 (flush _test-output-buffered-file) -10341 (flush _test-error-buffered-file) -10342 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10348 # check output -10349 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type-3: output should be empty") -10350 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: output must be an addr" "F - test-get-with-wrong-output-type-3: error message") -10351 # check that stop(1) was called -10352 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status") -10353 # don't restore from ebp -10354 81 0/subop/add %esp 8/imm32 -10355 # . epilogue -10356 5d/pop-to-ebp -10357 c3/return -10358 -10359 test-get-with-wrong-output-type-4: -10360 # . prologue -10361 55/push-ebp -10362 89/<- %ebp 4/r32/esp -10363 # setup -10364 (clear-stream _test-input-stream) -10365 (clear-stream $_test-input-buffered-file->buffer) -10366 (clear-stream _test-output-stream) -10367 (clear-stream $_test-output-buffered-file->buffer) -10368 (clear-stream _test-error-stream) -10369 (clear-stream $_test-error-buffered-file->buffer) -10370 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10371 68/push 0/imm32 -10372 68/push 0/imm32 -10373 89/<- %edx 4/r32/esp -10374 (tailor-exit-descriptor %edx 0x10) -10375 # -10376 (write _test-input-stream "fn foo {\n") -10377 (write _test-input-stream " var a: t\n") -10378 (write _test-input-stream " var c/ecx: (addr boolean) <- get a, x\n") -10379 (write _test-input-stream "}\n") -10380 (write _test-input-stream "type t {\n") -10381 (write _test-input-stream " x: int\n") -10382 (write _test-input-stream "}\n") -10383 # convert -10384 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10385 # registers except esp clobbered at this point -10386 # restore ed -10387 89/<- %edx 4/r32/esp -10388 (flush _test-output-buffered-file) -10389 (flush _test-error-buffered-file) -10390 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10396 # check output -10397 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type-4: output should be empty") -10398 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: wrong output type for member 'x' of type 't'" "F - test-get-with-wrong-output-type-4: error message") -10399 # check that stop(1) was called -10400 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status") -10401 # don't restore from ebp -10402 81 0/subop/add %esp 8/imm32 -10403 # . epilogue -10404 5d/pop-to-ebp -10405 c3/return -10406 -10407 test-get-with-wrong-output-type-5: -10408 # . prologue -10409 55/push-ebp -10410 89/<- %ebp 4/r32/esp -10411 # setup -10412 (clear-stream _test-input-stream) -10413 (clear-stream $_test-input-buffered-file->buffer) -10414 (clear-stream _test-output-stream) -10415 (clear-stream $_test-output-buffered-file->buffer) -10416 # -10417 (write _test-input-stream "fn foo {\n") -10418 (write _test-input-stream " var a: t\n") -10419 (write _test-input-stream " var c/ecx: (addr handle int) <- get a, x\n") -10420 (write _test-input-stream "}\n") -10421 (write _test-input-stream "type t {\n") -10422 (write _test-input-stream " x: (handle int)\n") -10423 (write _test-input-stream "}\n") -10424 # convert -10425 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -10426 (flush _test-output-buffered-file) -10427 # no errors -10428 # . epilogue -10429 89/<- %esp 5/r32/ebp -10430 5d/pop-to-ebp -10431 c3/return -10432 -10433 test-get-with-too-few-inouts: -10434 # . prologue -10435 55/push-ebp -10436 89/<- %ebp 4/r32/esp -10437 # setup -10438 (clear-stream _test-input-stream) -10439 (clear-stream $_test-input-buffered-file->buffer) -10440 (clear-stream _test-output-stream) -10441 (clear-stream $_test-output-buffered-file->buffer) -10442 (clear-stream _test-error-stream) -10443 (clear-stream $_test-error-buffered-file->buffer) -10444 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10445 68/push 0/imm32 -10446 68/push 0/imm32 -10447 89/<- %edx 4/r32/esp -10448 (tailor-exit-descriptor %edx 0x10) -10449 # -10450 (write _test-input-stream "fn foo {\n") -10451 (write _test-input-stream " var a: t\n") -10452 (write _test-input-stream " var c/ecx: (addr int) <- get a\n") -10453 (write _test-input-stream "}\n") -10454 (write _test-input-stream "type t {\n") -10455 (write _test-input-stream " x: int\n") -10456 (write _test-input-stream "}\n") -10457 # convert -10458 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10459 # registers except esp clobbered at this point -10460 # restore ed -10461 89/<- %edx 4/r32/esp -10462 (flush _test-output-buffered-file) -10463 (flush _test-error-buffered-file) -10464 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10470 # check output -10471 (check-stream-equal _test-output-stream "" "F - test-get-with-too-few-inouts: output should be empty") -10472 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: too few inouts (2 required)" "F - test-get-with-too-few-inouts: error message") -10473 # check that stop(1) was called -10474 (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status") -10475 # don't restore from ebp -10476 81 0/subop/add %esp 8/imm32 -10477 # . epilogue -10478 5d/pop-to-ebp -10479 c3/return -10480 -10481 test-get-with-too-many-inouts: -10482 # . prologue -10483 55/push-ebp -10484 89/<- %ebp 4/r32/esp -10485 # setup -10486 (clear-stream _test-input-stream) -10487 (clear-stream $_test-input-buffered-file->buffer) -10488 (clear-stream _test-output-stream) -10489 (clear-stream $_test-output-buffered-file->buffer) -10490 (clear-stream _test-error-stream) -10491 (clear-stream $_test-error-buffered-file->buffer) -10492 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10493 68/push 0/imm32 -10494 68/push 0/imm32 -10495 89/<- %edx 4/r32/esp -10496 (tailor-exit-descriptor %edx 0x10) -10497 # -10498 (write _test-input-stream "fn foo {\n") -10499 (write _test-input-stream " var a: t\n") -10500 (write _test-input-stream " var c/ecx: (addr int) <- get a, x, 0\n") -10501 (write _test-input-stream "}\n") -10502 (write _test-input-stream "type t {\n") -10503 (write _test-input-stream " x: int\n") -10504 (write _test-input-stream "}\n") -10505 # convert -10506 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10507 # registers except esp clobbered at this point -10508 # restore ed -10509 89/<- %edx 4/r32/esp -10510 (flush _test-output-buffered-file) -10511 (flush _test-error-buffered-file) -10512 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10518 # check output -10519 (check-stream-equal _test-output-stream "" "F - test-get-with-too-many-inouts: output should be empty") -10520 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: too many inouts (2 required)" "F - test-get-with-too-many-inouts: error message") -10521 # check that stop(1) was called -10522 (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status") -10523 # don't restore from ebp -10524 81 0/subop/add %esp 8/imm32 -10525 # . epilogue -10526 5d/pop-to-ebp -10527 c3/return -10528 -10529 test-get-with-no-output: -10530 # . prologue -10531 55/push-ebp -10532 89/<- %ebp 4/r32/esp -10533 # setup -10534 (clear-stream _test-input-stream) -10535 (clear-stream $_test-input-buffered-file->buffer) -10536 (clear-stream _test-output-stream) -10537 (clear-stream $_test-output-buffered-file->buffer) -10538 (clear-stream _test-error-stream) -10539 (clear-stream $_test-error-buffered-file->buffer) -10540 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10541 68/push 0/imm32 -10542 68/push 0/imm32 -10543 89/<- %edx 4/r32/esp -10544 (tailor-exit-descriptor %edx 0x10) -10545 # -10546 (write _test-input-stream "fn foo {\n") -10547 (write _test-input-stream " var a: t\n") -10548 (write _test-input-stream " get a, x\n") -10549 (write _test-input-stream "}\n") -10550 (write _test-input-stream "type t {\n") -10551 (write _test-input-stream " x: int\n") -10552 (write _test-input-stream "}\n") -10553 # convert -10554 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10555 # registers except esp clobbered at this point -10556 # restore ed -10557 89/<- %edx 4/r32/esp -10558 (flush _test-output-buffered-file) -10559 (flush _test-error-buffered-file) -10560 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10566 # check output -10567 (check-stream-equal _test-output-stream "" "F - test-get-with-no-output: output should be empty") -10568 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: must have an output" "F - test-get-with-no-output: error message") -10569 # check that stop(1) was called -10570 (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status") -10571 # don't restore from ebp -10572 81 0/subop/add %esp 8/imm32 -10573 # . epilogue -10574 5d/pop-to-ebp -10575 c3/return -10576 -10577 test-get-with-too-many-outputs: -10578 # . prologue -10579 55/push-ebp -10580 89/<- %ebp 4/r32/esp -10581 # setup -10582 (clear-stream _test-input-stream) -10583 (clear-stream $_test-input-buffered-file->buffer) -10584 (clear-stream _test-output-stream) -10585 (clear-stream $_test-output-buffered-file->buffer) -10586 (clear-stream _test-error-stream) -10587 (clear-stream $_test-error-buffered-file->buffer) -10588 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10589 68/push 0/imm32 -10590 68/push 0/imm32 -10591 89/<- %edx 4/r32/esp -10592 (tailor-exit-descriptor %edx 0x10) -10593 # -10594 (write _test-input-stream "fn foo {\n") -10595 (write _test-input-stream " var a: t\n") -10596 (write _test-input-stream " var b: int\n") -10597 (write _test-input-stream " var c/eax: (addr int) <- copy 0\n") -10598 (write _test-input-stream " c, b <- get a, x\n") -10599 (write _test-input-stream "}\n") -10600 (write _test-input-stream "type t {\n") -10601 (write _test-input-stream " x: int\n") -10602 (write _test-input-stream "}\n") -10603 # convert -10604 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10605 # registers except esp clobbered at this point -10606 # restore ed -10607 89/<- %edx 4/r32/esp -10608 (flush _test-output-buffered-file) -10609 (flush _test-error-buffered-file) -10610 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10616 # check output -10617 (check-stream-equal _test-output-stream "" "F - test-get-with-too-many-outputs: output should be empty") -10618 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: too many outputs (1 required)" "F - test-get-with-too-many-outputs: error message") -10619 # check that stop(1) was called -10620 (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status") -10621 # don't restore from ebp -10622 81 0/subop/add %esp 8/imm32 -10623 # . epilogue -10624 5d/pop-to-ebp -10625 c3/return -10626 -10627 test-convert-array-of-user-defined-types: -10628 # . prologue -10629 55/push-ebp -10630 89/<- %ebp 4/r32/esp -10631 # setup -10632 (clear-stream _test-input-stream) -10633 (clear-stream $_test-input-buffered-file->buffer) -10634 (clear-stream _test-output-stream) -10635 (clear-stream $_test-output-buffered-file->buffer) -10636 # -10637 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 -10638 (write _test-input-stream " x: int\n") -10639 (write _test-input-stream " y: int\n") -10640 (write _test-input-stream "}\n") -10641 (write _test-input-stream "fn foo {\n") -10642 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") -10643 (write _test-input-stream " var idx/ecx: int <- copy 3\n") -10644 (write _test-input-stream " var x/eax: (addr t) <- index arr, idx\n") -10645 (write _test-input-stream "}\n") -10646 # convert -10647 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -10648 (flush _test-output-buffered-file) -10649 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10655 # check output -10656 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-array-of-user-defined-types/0") -10657 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-array-of-user-defined-types/1") -10658 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-array-of-user-defined-types/2") -10659 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-array-of-user-defined-types/3") -10660 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-array-of-user-defined-types/4") -10661 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-array-of-user-defined-types/5") -10662 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-array-of-user-defined-types/6") -10663 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7") -10664 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8") -10665 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9") -10666 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")" "F - test-convert-array-of-user-defined-types/10") -10667 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/11") -10668 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/12") -10669 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/13") -10670 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/14") -10671 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/15") -10672 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/16") -10673 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/17") -10674 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/18") -10675 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/19") -10676 # . epilogue -10677 89/<- %esp 5/r32/ebp -10678 5d/pop-to-ebp -10679 c3/return -10680 -10681 test-convert-length-of-array-of-user-defined-types-to-eax: -10682 # . prologue -10683 55/push-ebp -10684 89/<- %ebp 4/r32/esp -10685 # setup -10686 (clear-stream _test-input-stream) -10687 (clear-stream $_test-input-buffered-file->buffer) -10688 (clear-stream _test-output-stream) -10689 (clear-stream $_test-output-buffered-file->buffer) -10690 # -10691 (write _test-input-stream "type t {\n") # size = 12, which is not a power of 2 -10692 (write _test-input-stream " x: int\n") -10693 (write _test-input-stream " y: int\n") -10694 (write _test-input-stream " z: int\n") -10695 (write _test-input-stream "}\n") -10696 (write _test-input-stream "fn foo {\n") -10697 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") -10698 (write _test-input-stream " var x/eax: int <- length arr\n") -10699 (write _test-input-stream "}\n") -10700 # convert -10701 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -10702 (flush _test-output-buffered-file) -10703 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10709 # check output -10710 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types-to-eax/0") -10711 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types-to-eax/1") -10712 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/2") -10713 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/3") -10714 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types-to-eax/4") -10715 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types-to-eax/5") -10716 # var arr -10717 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types-to-eax/6") -10718 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-eax/7") -10719 # length instruction -10720 (check-next-stream-line-equal _test-output-stream " 51/push-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/8") -10721 (check-next-stream-line-equal _test-output-stream " 52/push-edx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/9") -10722 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types-to-eax/10") -10723 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/11") -10724 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-eax/12") -10725 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/13") -10726 (check-next-stream-line-equal _test-output-stream " 5a/pop-to-edx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/14") -10727 (check-next-stream-line-equal _test-output-stream " 59/pop-to-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/15") -10728 # reclaim arr -10729 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types-to-eax/16") -10730 # -10731 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types-to-eax/17") -10732 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types-to-eax/18") -10733 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types-to-eax/19") -10734 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/20") -10735 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/21") -10736 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types-to-eax/22") -10737 # . epilogue -10738 89/<- %esp 5/r32/ebp -10739 5d/pop-to-ebp -10740 c3/return -10741 -10742 test-convert-length-of-array-of-user-defined-types-to-ecx: -10743 # . prologue -10744 55/push-ebp -10745 89/<- %ebp 4/r32/esp -10746 # setup -10747 (clear-stream _test-input-stream) -10748 (clear-stream $_test-input-buffered-file->buffer) -10749 (clear-stream _test-output-stream) -10750 (clear-stream $_test-output-buffered-file->buffer) -10751 # -10752 (write _test-input-stream "type t {\n") # size = 12, which is not a power of 2 -10753 (write _test-input-stream " x: int\n") -10754 (write _test-input-stream " y: int\n") -10755 (write _test-input-stream " z: int\n") -10756 (write _test-input-stream "}\n") -10757 (write _test-input-stream "fn foo {\n") -10758 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") -10759 (write _test-input-stream " var x/ecx: int <- length arr\n") -10760 (write _test-input-stream "}\n") -10761 # convert -10762 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -10763 (flush _test-output-buffered-file) -10764 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10770 # check output -10771 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0") -10772 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1") -10773 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2") -10774 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/3") -10775 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4") -10776 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5") -10777 # var a -10778 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/6") -10779 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/7") -10780 # var x -10781 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/8") -10782 # length instruction -10783 (check-next-stream-line-equal _test-output-stream " 50/push-eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9") -10784 (check-next-stream-line-equal _test-output-stream " 52/push-edx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10") -10785 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/11") -10786 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/12") -10787 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/13") -10788 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/14") -10789 (check-next-stream-line-equal _test-output-stream " 89/<- %ecx 0/r32/eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/15") -10790 (check-next-stream-line-equal _test-output-stream " 5a/pop-to-edx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/16") -10791 (check-next-stream-line-equal _test-output-stream " 58/pop-to-eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/17") -10792 # reclaim x -10793 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/18") -10794 # reclaim a -10795 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/19") -10796 # -10797 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20") -10798 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21") -10799 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22") -10800 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/23") -10801 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/24") -10802 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25") -10803 # . epilogue -10804 89/<- %esp 5/r32/ebp -10805 5d/pop-to-ebp -10806 c3/return -10807 -10808 test-convert-length-of-array-of-user-defined-types-to-edx: -10809 # . prologue -10810 55/push-ebp -10811 89/<- %ebp 4/r32/esp -10812 # setup -10813 (clear-stream _test-input-stream) -10814 (clear-stream $_test-input-buffered-file->buffer) -10815 (clear-stream _test-output-stream) -10816 (clear-stream $_test-output-buffered-file->buffer) -10817 # -10818 (write _test-input-stream "type t {\n") # size = 12, which is not a power of 2 -10819 (write _test-input-stream " x: int\n") -10820 (write _test-input-stream " y: int\n") -10821 (write _test-input-stream " z: int\n") -10822 (write _test-input-stream "}\n") -10823 (write _test-input-stream "fn foo {\n") -10824 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") -10825 (write _test-input-stream " var x/edx: int <- length arr\n") -10826 (write _test-input-stream "}\n") -10827 # convert -10828 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -10829 (flush _test-output-buffered-file) -10830 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10836 # check output -10837 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types-to-edx/0") -10838 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types-to-edx/1") -10839 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/2") -10840 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/3") -10841 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types-to-edx/4") -10842 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types-to-edx/5") -10843 # var a -10844 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/6") -10845 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-edx/7") -10846 # var x -10847 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %edx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/8") -10848 # length instruction -10849 (check-next-stream-line-equal _test-output-stream " 50/push-eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/9") -10850 (check-next-stream-line-equal _test-output-stream " 51/push-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/10") -10851 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types-to-edx/11") -10852 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/12") -10853 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-edx/13") -10854 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/14") -10855 (check-next-stream-line-equal _test-output-stream " 89/<- %edx 0/r32/eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/15") -10856 (check-next-stream-line-equal _test-output-stream " 59/pop-to-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/16") -10857 (check-next-stream-line-equal _test-output-stream " 58/pop-to-eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/17") -10858 # reclaim x -10859 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %edx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/18") -10860 # reclaim a -10861 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/19") -10862 # -10863 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types-to-edx/20") -10864 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types-to-edx/21") -10865 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types-to-edx/22") -10866 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/23") -10867 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/24") -10868 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types-to-edx/25") -10869 # . epilogue -10870 89/<- %esp 5/r32/ebp -10871 5d/pop-to-ebp -10872 c3/return -10873 -10874 test-convert-length-of-array-of-user-defined-types: -10875 # . prologue -10876 55/push-ebp -10877 89/<- %ebp 4/r32/esp -10878 # setup -10879 (clear-stream _test-input-stream) -10880 (clear-stream $_test-input-buffered-file->buffer) -10881 (clear-stream _test-output-stream) -10882 (clear-stream $_test-output-buffered-file->buffer) -10883 # -10884 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 -10885 (write _test-input-stream " x: int\n") -10886 (write _test-input-stream " y: int\n") -10887 (write _test-input-stream " z: int\n") -10888 (write _test-input-stream "}\n") -10889 (write _test-input-stream "fn foo {\n") -10890 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") -10891 (write _test-input-stream " var x/ebx: int <- length arr\n") -10892 (write _test-input-stream "}\n") -10893 # convert -10894 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -10895 (flush _test-output-buffered-file) -10896 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -10902 # check output -10903 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types/0") -10904 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types/1") -10905 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types/2") -10906 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types/3") -10907 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types/4") -10908 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types/5") -10909 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types/6") -10910 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types/7") -10911 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ebx" "F - test-convert-length-of-array-of-user-defined-types/8") -10912 (check-next-stream-line-equal _test-output-stream " 50/push-eax" "F - test-convert-length-of-array-of-user-defined-types/9") -10913 (check-next-stream-line-equal _test-output-stream " 51/push-ecx" "F - test-convert-length-of-array-of-user-defined-types/10") -10914 (check-next-stream-line-equal _test-output-stream " 52/push-edx" "F - test-convert-length-of-array-of-user-defined-types/11") -10915 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types/12") -10916 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types/13") -10917 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types/14") -10918 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types/15") -10919 (check-next-stream-line-equal _test-output-stream " 89/<- %ebx 0/r32/eax" "F - test-convert-length-of-array-of-user-defined-types/16") -10920 (check-next-stream-line-equal _test-output-stream " 5a/pop-to-edx" "F - test-convert-length-of-array-of-user-defined-types/17") -10921 (check-next-stream-line-equal _test-output-stream " 59/pop-to-ecx" "F - test-convert-length-of-array-of-user-defined-types/18") -10922 (check-next-stream-line-equal _test-output-stream " 58/pop-to-eax" "F - test-convert-length-of-array-of-user-defined-types/19") -10923 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ebx" "F - test-convert-length-of-array-of-user-defined-types/20") -10924 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types/21") -10925 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types/22") -10926 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types/23") -10927 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types/24") -10928 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types/25") -10929 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types/26") -10930 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types/27") -10931 # . epilogue -10932 89/<- %esp 5/r32/ebp -10933 5d/pop-to-ebp -10934 c3/return -10935 -10936 test-index-with-non-array-atom-base-type: -10937 # . prologue -10938 55/push-ebp -10939 89/<- %ebp 4/r32/esp -10940 # setup -10941 (clear-stream _test-input-stream) -10942 (clear-stream $_test-input-buffered-file->buffer) -10943 (clear-stream _test-output-stream) -10944 (clear-stream $_test-output-buffered-file->buffer) -10945 (clear-stream _test-error-stream) -10946 (clear-stream $_test-error-buffered-file->buffer) -10947 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10948 68/push 0/imm32 -10949 68/push 0/imm32 -10950 89/<- %edx 4/r32/esp -10951 (tailor-exit-descriptor %edx 0x10) -10952 # -10953 (write _test-input-stream "fn foo {\n") -10954 (write _test-input-stream " var a: int\n") -10955 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") -10956 (write _test-input-stream "}\n") -10957 # convert -10958 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -10959 # registers except esp clobbered at this point -10960 # restore ed -10961 89/<- %edx 4/r32/esp -10962 (flush _test-output-buffered-file) -10963 (flush _test-error-buffered-file) -10964 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -10970 # check output -10971 (check-stream-equal _test-output-stream "" "F - test-index-with-non-array-atom-base-type: output should be empty") -10972 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is not an array" "F - test-index-with-non-array-atom-base-type: error message") -10973 # check that stop(1) was called -10974 (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status") -10975 # don't restore from ebp -10976 81 0/subop/add %esp 8/imm32 -10977 # . epilogue -10978 5d/pop-to-ebp -10979 c3/return -10980 -10981 test-index-with-non-array-compound-base-type: -10982 # . prologue -10983 55/push-ebp -10984 89/<- %ebp 4/r32/esp -10985 # setup -10986 (clear-stream _test-input-stream) -10987 (clear-stream $_test-input-buffered-file->buffer) -10988 (clear-stream _test-output-stream) -10989 (clear-stream $_test-output-buffered-file->buffer) -10990 (clear-stream _test-error-stream) -10991 (clear-stream $_test-error-buffered-file->buffer) -10992 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -10993 68/push 0/imm32 -10994 68/push 0/imm32 -10995 89/<- %edx 4/r32/esp -10996 (tailor-exit-descriptor %edx 0x10) -10997 # -10998 (write _test-input-stream "fn foo {\n") -10999 (write _test-input-stream " var a: (handle int)\n") -11000 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") -11001 (write _test-input-stream "}\n") -11002 # convert -11003 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11004 # registers except esp clobbered at this point -11005 # restore ed -11006 89/<- %edx 4/r32/esp -11007 (flush _test-output-buffered-file) -11008 (flush _test-error-buffered-file) -11009 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11015 # check output -11016 (check-stream-equal _test-output-stream "" "F - test-index-with-non-array-compound-base-type: output should be empty") -11017 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is not an array" "F - test-index-with-non-array-compound-base-type: error message") -11018 # check that stop(1) was called -11019 (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status") -11020 # don't restore from ebp -11021 81 0/subop/add %esp 8/imm32 -11022 # . epilogue -11023 5d/pop-to-ebp -11024 c3/return -11025 -11026 test-index-with-non-array-compound-base-type-2: -11027 # . prologue -11028 55/push-ebp -11029 89/<- %ebp 4/r32/esp -11030 # setup -11031 (clear-stream _test-input-stream) -11032 (clear-stream $_test-input-buffered-file->buffer) -11033 (clear-stream _test-output-stream) -11034 (clear-stream $_test-output-buffered-file->buffer) -11035 (clear-stream _test-error-stream) -11036 (clear-stream $_test-error-buffered-file->buffer) -11037 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11038 68/push 0/imm32 -11039 68/push 0/imm32 -11040 89/<- %edx 4/r32/esp -11041 (tailor-exit-descriptor %edx 0x10) -11042 # -11043 (write _test-input-stream "fn foo {\n") -11044 (write _test-input-stream " var a: (addr int)\n") -11045 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") -11046 (write _test-input-stream "}\n") -11047 # convert -11048 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11049 # registers except esp clobbered at this point -11050 # restore ed -11051 89/<- %edx 4/r32/esp -11052 (flush _test-output-buffered-file) -11053 (flush _test-error-buffered-file) -11054 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11060 # check output -11061 (check-stream-equal _test-output-stream "" "F - test-index-with-non-array-compound-base-type-2: output should be empty") -11062 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is not an array" "F - test-index-with-non-array-compound-base-type-2: error message") -11063 # check that stop(1) was called -11064 (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status") -11065 # don't restore from ebp -11066 81 0/subop/add %esp 8/imm32 -11067 # . epilogue -11068 5d/pop-to-ebp -11069 c3/return -11070 -11071 test-index-with-array-atom-base-type: -11072 # . prologue -11073 55/push-ebp -11074 89/<- %ebp 4/r32/esp -11075 # setup -11076 (clear-stream _test-input-stream) -11077 (clear-stream $_test-input-buffered-file->buffer) -11078 (clear-stream _test-output-stream) -11079 (clear-stream $_test-output-buffered-file->buffer) -11080 (clear-stream _test-error-stream) -11081 (clear-stream $_test-error-buffered-file->buffer) -11082 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11083 68/push 0/imm32 -11084 68/push 0/imm32 -11085 89/<- %edx 4/r32/esp -11086 (tailor-exit-descriptor %edx 0x10) -11087 # -11088 (write _test-input-stream "fn foo {\n") -11089 (write _test-input-stream " var a: array\n") -11090 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") -11091 (write _test-input-stream "}\n") -11092 # convert -11093 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11094 # registers except esp clobbered at this point -11095 # restore ed -11096 89/<- %edx 4/r32/esp -11097 (flush _test-output-buffered-file) -11098 (flush _test-error-buffered-file) -11099 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11105 # check output -11106 (check-stream-equal _test-output-stream "" "F - test-index-with-array-atom-base-type: output should be empty") -11107 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: array 'a' must specify the type of its elements" "F - test-index-with-array-atom-base-type: error message") -11108 # check that stop(1) was called -11109 (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status") -11110 # don't restore from ebp -11111 81 0/subop/add %esp 8/imm32 -11112 # . epilogue -11113 5d/pop-to-ebp -11114 c3/return -11115 -11116 test-index-with-addr-base-on-stack: -11117 # . prologue -11118 55/push-ebp -11119 89/<- %ebp 4/r32/esp -11120 # setup -11121 (clear-stream _test-input-stream) -11122 (clear-stream $_test-input-buffered-file->buffer) -11123 (clear-stream _test-output-stream) -11124 (clear-stream $_test-output-buffered-file->buffer) -11125 (clear-stream _test-error-stream) -11126 (clear-stream $_test-error-buffered-file->buffer) -11127 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11128 68/push 0/imm32 -11129 68/push 0/imm32 -11130 89/<- %edx 4/r32/esp -11131 (tailor-exit-descriptor %edx 0x10) -11132 # -11133 (write _test-input-stream "fn foo {\n") -11134 (write _test-input-stream " var a: (addr array int)\n") -11135 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") -11136 (write _test-input-stream "}\n") -11137 # convert -11138 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11139 # registers except esp clobbered at this point -11140 # restore ed -11141 89/<- %edx 4/r32/esp -11142 (flush _test-output-buffered-file) -11143 (flush _test-error-buffered-file) -11144 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11150 # check output -11151 (check-stream-equal _test-output-stream "" "F - test-index-with-addr-base-on-stack: output should be empty") -11152 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is an addr to an array, and so must live in a register" "F - test-index-with-addr-base-on-stack: error message") -11153 # check that stop(1) was called -11154 (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status") -11155 # don't restore from ebp -11156 81 0/subop/add %esp 8/imm32 -11157 # . epilogue -11158 5d/pop-to-ebp -11159 c3/return -11160 -11161 test-index-with-wrong-index-type: -11162 # . prologue -11163 55/push-ebp -11164 89/<- %ebp 4/r32/esp -11165 # setup -11166 (clear-stream _test-input-stream) -11167 (clear-stream $_test-input-buffered-file->buffer) -11168 (clear-stream _test-output-stream) -11169 (clear-stream $_test-output-buffered-file->buffer) -11170 (clear-stream _test-error-stream) -11171 (clear-stream $_test-error-buffered-file->buffer) -11172 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11173 68/push 0/imm32 -11174 68/push 0/imm32 -11175 89/<- %edx 4/r32/esp -11176 (tailor-exit-descriptor %edx 0x10) -11177 # -11178 (write _test-input-stream "fn foo {\n") -11179 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") -11180 (write _test-input-stream " var b: boolean\n") -11181 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") -11182 (write _test-input-stream "}\n") -11183 # convert -11184 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11185 # registers except esp clobbered at this point -11186 # restore ed -11187 89/<- %edx 4/r32/esp -11188 (flush _test-output-buffered-file) -11189 (flush _test-error-buffered-file) -11190 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11196 # check output -11197 (check-stream-equal _test-output-stream "" "F - test-index-with-wrong-index-type: output should be empty") -11198 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: second argument 'b' must be an int or offset" "F - test-index-with-wrong-index-type: error message") -11199 # check that stop(1) was called -11200 (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status") -11201 # don't restore from ebp -11202 81 0/subop/add %esp 8/imm32 -11203 # . epilogue -11204 5d/pop-to-ebp -11205 c3/return -11206 -11207 test-index-with-offset-atom-index-type: -11208 # . prologue -11209 55/push-ebp -11210 89/<- %ebp 4/r32/esp -11211 # setup -11212 (clear-stream _test-input-stream) -11213 (clear-stream $_test-input-buffered-file->buffer) -11214 (clear-stream _test-output-stream) -11215 (clear-stream $_test-output-buffered-file->buffer) -11216 (clear-stream _test-error-stream) -11217 (clear-stream $_test-error-buffered-file->buffer) -11218 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11219 68/push 0/imm32 -11220 68/push 0/imm32 -11221 89/<- %edx 4/r32/esp -11222 (tailor-exit-descriptor %edx 0x10) -11223 # -11224 (write _test-input-stream "fn foo {\n") -11225 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") -11226 (write _test-input-stream " var b: offset\n") -11227 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") -11228 (write _test-input-stream "}\n") -11229 # convert -11230 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11231 # registers except esp clobbered at this point -11232 # restore ed -11233 89/<- %edx 4/r32/esp -11234 (flush _test-output-buffered-file) -11235 (flush _test-error-buffered-file) -11236 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11242 # check output -11243 (check-stream-equal _test-output-stream "" "F - test-index-with-offset-atom-index-type: output should be empty") -11244 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: offset 'b' must specify the type of array elements" "F - test-index-with-offset-atom-index-type: error message") -11245 # check that stop(1) was called -11246 (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status") -11247 # don't restore from ebp -11248 81 0/subop/add %esp 8/imm32 -11249 # . epilogue -11250 5d/pop-to-ebp -11251 c3/return -11252 -11253 test-index-with-offset-on-stack: -11254 # . prologue -11255 55/push-ebp -11256 89/<- %ebp 4/r32/esp -11257 # setup -11258 (clear-stream _test-input-stream) -11259 (clear-stream $_test-input-buffered-file->buffer) -11260 (clear-stream _test-output-stream) -11261 (clear-stream $_test-output-buffered-file->buffer) -11262 (clear-stream _test-error-stream) -11263 (clear-stream $_test-error-buffered-file->buffer) -11264 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11265 68/push 0/imm32 -11266 68/push 0/imm32 -11267 89/<- %edx 4/r32/esp -11268 (tailor-exit-descriptor %edx 0x10) -11269 # -11270 (write _test-input-stream "fn foo {\n") -11271 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") -11272 (write _test-input-stream " var b: int\n") -11273 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") -11274 (write _test-input-stream "}\n") -11275 # convert -11276 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11277 # registers except esp clobbered at this point -11278 # restore ed -11279 89/<- %edx 4/r32/esp -11280 (flush _test-output-buffered-file) -11281 (flush _test-error-buffered-file) -11282 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11288 # check output -11289 (check-stream-equal _test-output-stream "" "F - test-index-with-offset-on-stack: output should be empty") -11290 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: second argument 'b' must be in a register" "F - test-index-with-offset-on-stack: error message") -11291 # check that stop(1) was called -11292 (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status") -11293 # don't restore from ebp -11294 81 0/subop/add %esp 8/imm32 -11295 # . epilogue -11296 5d/pop-to-ebp -11297 c3/return -11298 -11299 test-index-needs-offset-type: -11300 # . prologue -11301 55/push-ebp -11302 89/<- %ebp 4/r32/esp -11303 # setup -11304 (clear-stream _test-input-stream) -11305 (clear-stream $_test-input-buffered-file->buffer) -11306 (clear-stream _test-output-stream) -11307 (clear-stream $_test-output-buffered-file->buffer) -11308 (clear-stream _test-error-stream) -11309 (clear-stream $_test-error-buffered-file->buffer) -11310 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11311 68/push 0/imm32 -11312 68/push 0/imm32 -11313 89/<- %edx 4/r32/esp -11314 (tailor-exit-descriptor %edx 0x10) -11315 # -11316 (write _test-input-stream "fn foo {\n") -11317 (write _test-input-stream " var a/eax: (addr array t) <- copy 0\n") -11318 (write _test-input-stream " var b/ebx: int <- copy 0\n") -11319 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") -11320 (write _test-input-stream "}\n") -11321 (write _test-input-stream "type t {\n") # size 12 is not a power of two -11322 (write _test-input-stream " x: int\n") -11323 (write _test-input-stream " y: int\n") -11324 (write _test-input-stream " z: int\n") -11325 (write _test-input-stream "}\n") -11326 # convert -11327 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11328 # registers except esp clobbered at this point -11329 # restore ed -11330 89/<- %edx 4/r32/esp -11331 (flush _test-output-buffered-file) -11332 (flush _test-error-buffered-file) -11333 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11339 # check output -11340 (check-stream-equal _test-output-stream "" "F - test-index-needs-offset-type: output should be empty") -11341 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: cannot take an int for array 'a'; create an offset instead. See mu.md for details." "F - test-index-needs-offset-type: error message") -11342 # check that stop(1) was called -11343 (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status") -11344 # don't restore from ebp -11345 81 0/subop/add %esp 8/imm32 -11346 # . epilogue -11347 5d/pop-to-ebp -11348 c3/return -11349 -11350 test-index-with-output-not-address: -11351 # . prologue -11352 55/push-ebp -11353 89/<- %ebp 4/r32/esp -11354 # setup -11355 (clear-stream _test-input-stream) -11356 (clear-stream $_test-input-buffered-file->buffer) -11357 (clear-stream _test-output-stream) -11358 (clear-stream $_test-output-buffered-file->buffer) -11359 (clear-stream _test-error-stream) -11360 (clear-stream $_test-error-buffered-file->buffer) -11361 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11362 68/push 0/imm32 -11363 68/push 0/imm32 -11364 89/<- %edx 4/r32/esp -11365 (tailor-exit-descriptor %edx 0x10) -11366 # -11367 (write _test-input-stream "fn foo {\n") -11368 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -11369 (write _test-input-stream " var o/edi: int <- index a, 0\n") -11370 (write _test-input-stream "}\n") -11371 # convert -11372 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11373 # registers except esp clobbered at this point -11374 # restore ed -11375 89/<- %edx 4/r32/esp -11376 (flush _test-output-buffered-file) -11377 (flush _test-error-buffered-file) -11378 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11384 # check output -11385 (check-stream-equal _test-output-stream "" "F - test-index-with-output-not-address: output should be empty") -11386 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' must be an addr" "F - test-index-with-output-not-address: error message") -11387 # check that stop(1) was called -11388 (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status") -11389 # don't restore from ebp -11390 81 0/subop/add %esp 8/imm32 -11391 # . epilogue -11392 5d/pop-to-ebp -11393 c3/return -11394 -11395 test-index-with-output-not-address-2: -11396 # . prologue -11397 55/push-ebp -11398 89/<- %ebp 4/r32/esp -11399 # setup -11400 (clear-stream _test-input-stream) -11401 (clear-stream $_test-input-buffered-file->buffer) -11402 (clear-stream _test-output-stream) -11403 (clear-stream $_test-output-buffered-file->buffer) -11404 (clear-stream _test-error-stream) -11405 (clear-stream $_test-error-buffered-file->buffer) -11406 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11407 68/push 0/imm32 -11408 68/push 0/imm32 -11409 89/<- %edx 4/r32/esp -11410 (tailor-exit-descriptor %edx 0x10) -11411 # -11412 (write _test-input-stream "fn foo {\n") -11413 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -11414 (write _test-input-stream " var o/edi: (int) <- index a, 0\n") -11415 (write _test-input-stream "}\n") -11416 # convert -11417 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11418 # registers except esp clobbered at this point -11419 # restore ed -11420 89/<- %edx 4/r32/esp -11421 (flush _test-output-buffered-file) -11422 (flush _test-error-buffered-file) -11423 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11429 # check output -11430 (check-stream-equal _test-output-stream "" "F - test-index-with-output-not-address-2: output should be empty") -11431 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' must be an addr" "F - test-index-with-output-not-address-2: error message") -11432 # check that stop(1) was called -11433 (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status") -11434 # don't restore from ebp -11435 81 0/subop/add %esp 8/imm32 -11436 # . epilogue -11437 5d/pop-to-ebp -11438 c3/return -11439 -11440 test-index-with-wrong-output-type: -11441 # . prologue -11442 55/push-ebp -11443 89/<- %ebp 4/r32/esp -11444 # setup -11445 (clear-stream _test-input-stream) -11446 (clear-stream $_test-input-buffered-file->buffer) -11447 (clear-stream _test-output-stream) -11448 (clear-stream $_test-output-buffered-file->buffer) -11449 (clear-stream _test-error-stream) -11450 (clear-stream $_test-error-buffered-file->buffer) -11451 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11452 68/push 0/imm32 -11453 68/push 0/imm32 -11454 89/<- %edx 4/r32/esp -11455 (tailor-exit-descriptor %edx 0x10) -11456 # -11457 (write _test-input-stream "fn foo {\n") -11458 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -11459 (write _test-input-stream " var o/edi: (addr int) <- index a, 0\n") -11460 (write _test-input-stream "}\n") -11461 # convert -11462 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11463 # registers except esp clobbered at this point -11464 # restore ed -11465 89/<- %edx 4/r32/esp -11466 (flush _test-output-buffered-file) -11467 (flush _test-error-buffered-file) -11468 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11474 # check output -11475 (check-stream-equal _test-output-stream "" "F - test-index-with-wrong-output-type: output should be empty") -11476 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' does not have the right type" "F - test-index-with-wrong-output-type: error message") -11477 # check that stop(1) was called -11478 (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status") -11479 # don't restore from ebp -11480 81 0/subop/add %esp 8/imm32 -11481 # . epilogue -11482 5d/pop-to-ebp -11483 c3/return -11484 -11485 test-index-with-wrong-output-compound-type: -11486 # . prologue -11487 55/push-ebp -11488 89/<- %ebp 4/r32/esp -11489 # setup -11490 (clear-stream _test-input-stream) -11491 (clear-stream $_test-input-buffered-file->buffer) -11492 (clear-stream _test-output-stream) -11493 (clear-stream $_test-output-buffered-file->buffer) -11494 (clear-stream _test-error-stream) -11495 (clear-stream $_test-error-buffered-file->buffer) -11496 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11497 68/push 0/imm32 -11498 68/push 0/imm32 -11499 89/<- %edx 4/r32/esp -11500 (tailor-exit-descriptor %edx 0x10) -11501 # -11502 (write _test-input-stream "fn foo {\n") -11503 (write _test-input-stream " var a/ebx: (addr array handle boolean) <- copy 0\n") -11504 (write _test-input-stream " var o/edi: (addr handle int) <- index a, 0\n") -11505 (write _test-input-stream "}\n") -11506 # convert -11507 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11508 # registers except esp clobbered at this point -11509 # restore ed -11510 89/<- %edx 4/r32/esp -11511 (flush _test-output-buffered-file) -11512 (flush _test-error-buffered-file) -11513 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11519 # check output -11520 (check-stream-equal _test-output-stream "" "F - test-index-with-wrong-output-compound-type: output should be empty") -11521 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' does not have the right type" "F - test-index-with-wrong-output-compound-type: error message") -11522 # check that stop(1) was called -11523 (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status") -11524 # don't restore from ebp -11525 81 0/subop/add %esp 8/imm32 -11526 # . epilogue -11527 5d/pop-to-ebp -11528 c3/return -11529 -11530 test-index-with-no-inouts: -11531 # . prologue -11532 55/push-ebp -11533 89/<- %ebp 4/r32/esp -11534 # setup -11535 (clear-stream _test-input-stream) -11536 (clear-stream $_test-input-buffered-file->buffer) -11537 (clear-stream _test-output-stream) -11538 (clear-stream $_test-output-buffered-file->buffer) -11539 (clear-stream _test-error-stream) -11540 (clear-stream $_test-error-buffered-file->buffer) -11541 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11542 68/push 0/imm32 -11543 68/push 0/imm32 -11544 89/<- %edx 4/r32/esp -11545 (tailor-exit-descriptor %edx 0x10) -11546 # -11547 (write _test-input-stream "fn foo {\n") -11548 (write _test-input-stream " var c/ecx: (addr int) <- index\n") -11549 (write _test-input-stream "}\n") -11550 # convert -11551 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11552 # registers except esp clobbered at this point -11553 # restore ed -11554 89/<- %edx 4/r32/esp -11555 (flush _test-output-buffered-file) -11556 (flush _test-error-buffered-file) -11557 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11563 # check output -11564 (check-stream-equal _test-output-stream "" "F - test-index-with-no-inouts: output should be empty") -11565 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too few inouts (2 required)" "F - test-index-with-no-inouts: error message") -11566 # check that stop(1) was called -11567 (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status") -11568 # don't restore from ebp -11569 81 0/subop/add %esp 8/imm32 -11570 # . epilogue -11571 5d/pop-to-ebp -11572 c3/return -11573 -11574 test-index-with-too-few-inouts: -11575 # . prologue -11576 55/push-ebp -11577 89/<- %ebp 4/r32/esp -11578 # setup -11579 (clear-stream _test-input-stream) -11580 (clear-stream $_test-input-buffered-file->buffer) -11581 (clear-stream _test-output-stream) -11582 (clear-stream $_test-output-buffered-file->buffer) -11583 (clear-stream _test-error-stream) -11584 (clear-stream $_test-error-buffered-file->buffer) -11585 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11586 68/push 0/imm32 -11587 68/push 0/imm32 -11588 89/<- %edx 4/r32/esp -11589 (tailor-exit-descriptor %edx 0x10) -11590 # -11591 (write _test-input-stream "fn foo {\n") -11592 (write _test-input-stream " var a: (array int 3)\n") -11593 (write _test-input-stream " var c/ecx: (addr int) <- index a\n") -11594 (write _test-input-stream "}\n") -11595 # convert -11596 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11597 # registers except esp clobbered at this point -11598 # restore ed -11599 89/<- %edx 4/r32/esp -11600 (flush _test-output-buffered-file) -11601 (flush _test-error-buffered-file) -11602 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11608 # check output -11609 (check-stream-equal _test-output-stream "" "F - test-index-with-too-few-inouts: output should be empty") -11610 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too few inouts (2 required)" "F - test-index-with-too-few-inouts: error message") -11611 # check that stop(1) was called -11612 (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status") -11613 # don't restore from ebp -11614 81 0/subop/add %esp 8/imm32 -11615 # . epilogue -11616 5d/pop-to-ebp -11617 c3/return -11618 -11619 test-index-with-too-many-inouts: -11620 # . prologue -11621 55/push-ebp -11622 89/<- %ebp 4/r32/esp -11623 # setup -11624 (clear-stream _test-input-stream) -11625 (clear-stream $_test-input-buffered-file->buffer) -11626 (clear-stream _test-output-stream) -11627 (clear-stream $_test-output-buffered-file->buffer) -11628 (clear-stream _test-error-stream) -11629 (clear-stream $_test-error-buffered-file->buffer) -11630 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11631 68/push 0/imm32 -11632 68/push 0/imm32 -11633 89/<- %edx 4/r32/esp -11634 (tailor-exit-descriptor %edx 0x10) -11635 # -11636 (write _test-input-stream "fn foo {\n") -11637 (write _test-input-stream " var a: (array int 3)\n") -11638 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0, 0\n") -11639 (write _test-input-stream "}\n") -11640 # convert -11641 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11642 # registers except esp clobbered at this point -11643 # restore ed -11644 89/<- %edx 4/r32/esp -11645 (flush _test-output-buffered-file) -11646 (flush _test-error-buffered-file) -11647 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11653 # check output -11654 (check-stream-equal _test-output-stream "" "F - test-index-with-too-many-inouts: output should be empty") -11655 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too many inouts (2 required)" "F - test-index-with-too-many-inouts: error message") -11656 # check that stop(1) was called -11657 (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status") -11658 # don't restore from ebp -11659 81 0/subop/add %esp 8/imm32 -11660 # . epilogue -11661 5d/pop-to-ebp -11662 c3/return -11663 -11664 test-index-with-no-output: -11665 # . prologue -11666 55/push-ebp -11667 89/<- %ebp 4/r32/esp -11668 # setup -11669 (clear-stream _test-input-stream) -11670 (clear-stream $_test-input-buffered-file->buffer) -11671 (clear-stream _test-output-stream) -11672 (clear-stream $_test-output-buffered-file->buffer) -11673 (clear-stream _test-error-stream) -11674 (clear-stream $_test-error-buffered-file->buffer) -11675 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11676 68/push 0/imm32 -11677 68/push 0/imm32 -11678 89/<- %edx 4/r32/esp -11679 (tailor-exit-descriptor %edx 0x10) -11680 # -11681 (write _test-input-stream "fn foo {\n") -11682 (write _test-input-stream " var a: (array int 3)\n") -11683 (write _test-input-stream " index a, 0\n") -11684 (write _test-input-stream "}\n") -11685 # convert -11686 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11687 # registers except esp clobbered at this point -11688 # restore ed -11689 89/<- %edx 4/r32/esp -11690 (flush _test-output-buffered-file) -11691 (flush _test-error-buffered-file) -11692 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11698 # check output -11699 (check-stream-equal _test-output-stream "" "F - test-index-with-no-output: output should be empty") -11700 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: must have an output" "F - test-index-with-no-output: error message") -11701 # check that stop(1) was called -11702 (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status") -11703 # don't restore from ebp -11704 81 0/subop/add %esp 8/imm32 -11705 # . epilogue -11706 5d/pop-to-ebp -11707 c3/return -11708 -11709 test-index-with-too-many-outputs: -11710 # . prologue -11711 55/push-ebp -11712 89/<- %ebp 4/r32/esp -11713 # setup -11714 (clear-stream _test-input-stream) -11715 (clear-stream $_test-input-buffered-file->buffer) -11716 (clear-stream _test-output-stream) -11717 (clear-stream $_test-output-buffered-file->buffer) -11718 (clear-stream _test-error-stream) -11719 (clear-stream $_test-error-buffered-file->buffer) -11720 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11721 68/push 0/imm32 -11722 68/push 0/imm32 -11723 89/<- %edx 4/r32/esp -11724 (tailor-exit-descriptor %edx 0x10) -11725 # -11726 (write _test-input-stream "fn foo {\n") -11727 (write _test-input-stream " var a: (array int 3)\n") -11728 (write _test-input-stream " var b/eax: (addr int) <- copy 0\n") -11729 (write _test-input-stream " var c/ecx: (addr int) <- copy 0\n") -11730 (write _test-input-stream " b, c <- index a, 0\n") -11731 (write _test-input-stream "}\n") -11732 # convert -11733 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11734 # registers except esp clobbered at this point -11735 # restore ed -11736 89/<- %edx 4/r32/esp -11737 (flush _test-output-buffered-file) -11738 (flush _test-error-buffered-file) -11739 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11745 # check output -11746 (check-stream-equal _test-output-stream "" "F - test-index-with-too-many-outputs: output should be empty") -11747 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too many outputs (1 required)" "F - test-index-with-too-many-outputs: error message") -11748 # check that stop(1) was called -11749 (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status") -11750 # don't restore from ebp -11751 81 0/subop/add %esp 8/imm32 -11752 # . epilogue -11753 5d/pop-to-ebp -11754 c3/return -11755 -11756 test-compute-offset-with-non-array-atom-base-type: -11757 # . prologue -11758 55/push-ebp -11759 89/<- %ebp 4/r32/esp -11760 # setup -11761 (clear-stream _test-input-stream) -11762 (clear-stream $_test-input-buffered-file->buffer) -11763 (clear-stream _test-output-stream) -11764 (clear-stream $_test-output-buffered-file->buffer) -11765 (clear-stream _test-error-stream) -11766 (clear-stream $_test-error-buffered-file->buffer) -11767 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11768 68/push 0/imm32 -11769 68/push 0/imm32 -11770 89/<- %edx 4/r32/esp -11771 (tailor-exit-descriptor %edx 0x10) -11772 # -11773 (write _test-input-stream "fn foo {\n") -11774 (write _test-input-stream " var a: int\n") -11775 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") -11776 (write _test-input-stream "}\n") -11777 # convert -11778 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11779 # registers except esp clobbered at this point -11780 # restore ed -11781 89/<- %edx 4/r32/esp -11782 (flush _test-output-buffered-file) -11783 (flush _test-error-buffered-file) -11784 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11790 # check output -11791 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-non-array-atom-base-type: output should be empty") -11792 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: var 'a' is not an array" "F - test-compute-offset-with-non-array-atom-base-type: error message") -11793 # check that stop(1) was called -11794 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status") -11795 # don't restore from ebp -11796 81 0/subop/add %esp 8/imm32 -11797 # . epilogue -11798 5d/pop-to-ebp -11799 c3/return -11800 -11801 test-compute-offset-with-non-array-compound-base-type: -11802 # . prologue -11803 55/push-ebp -11804 89/<- %ebp 4/r32/esp -11805 # setup -11806 (clear-stream _test-input-stream) -11807 (clear-stream $_test-input-buffered-file->buffer) -11808 (clear-stream _test-output-stream) -11809 (clear-stream $_test-output-buffered-file->buffer) -11810 (clear-stream _test-error-stream) -11811 (clear-stream $_test-error-buffered-file->buffer) -11812 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11813 68/push 0/imm32 -11814 68/push 0/imm32 -11815 89/<- %edx 4/r32/esp -11816 (tailor-exit-descriptor %edx 0x10) -11817 # -11818 (write _test-input-stream "fn foo {\n") -11819 (write _test-input-stream " var a: (handle int)\n") -11820 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") -11821 (write _test-input-stream "}\n") -11822 # convert -11823 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11824 # registers except esp clobbered at this point -11825 # restore ed -11826 89/<- %edx 4/r32/esp -11827 (flush _test-output-buffered-file) -11828 (flush _test-error-buffered-file) -11829 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11835 # check output -11836 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-non-array-compound-base-type: output should be empty") -11837 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: var 'a' is not an array" "F - test-compute-offset-with-non-array-compound-base-type: error message") -11838 # check that stop(1) was called -11839 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status") -11840 # don't restore from ebp -11841 81 0/subop/add %esp 8/imm32 -11842 # . epilogue -11843 5d/pop-to-ebp -11844 c3/return -11845 -11846 test-compute-offset-with-non-array-compound-base-type-2: -11847 # . prologue -11848 55/push-ebp -11849 89/<- %ebp 4/r32/esp -11850 # setup -11851 (clear-stream _test-input-stream) -11852 (clear-stream $_test-input-buffered-file->buffer) -11853 (clear-stream _test-output-stream) -11854 (clear-stream $_test-output-buffered-file->buffer) -11855 (clear-stream _test-error-stream) -11856 (clear-stream $_test-error-buffered-file->buffer) -11857 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11858 68/push 0/imm32 -11859 68/push 0/imm32 -11860 89/<- %edx 4/r32/esp -11861 (tailor-exit-descriptor %edx 0x10) -11862 # -11863 (write _test-input-stream "fn foo {\n") -11864 (write _test-input-stream " var a: (addr int)\n") -11865 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") -11866 (write _test-input-stream "}\n") -11867 # convert -11868 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11869 # registers except esp clobbered at this point -11870 # restore ed -11871 89/<- %edx 4/r32/esp -11872 (flush _test-output-buffered-file) -11873 (flush _test-error-buffered-file) -11874 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11880 # check output -11881 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty") -11882 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: var 'a' is not an array" "F - test-compute-offset-with-non-array-compound-base-type-2: error message") -11883 # check that stop(1) was called -11884 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status") -11885 # don't restore from ebp -11886 81 0/subop/add %esp 8/imm32 -11887 # . epilogue -11888 5d/pop-to-ebp -11889 c3/return -11890 -11891 test-compute-offset-with-array-atom-base-type: -11892 # . prologue -11893 55/push-ebp -11894 89/<- %ebp 4/r32/esp -11895 # setup -11896 (clear-stream _test-input-stream) -11897 (clear-stream $_test-input-buffered-file->buffer) -11898 (clear-stream _test-output-stream) -11899 (clear-stream $_test-output-buffered-file->buffer) -11900 (clear-stream _test-error-stream) -11901 (clear-stream $_test-error-buffered-file->buffer) -11902 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11903 68/push 0/imm32 -11904 68/push 0/imm32 -11905 89/<- %edx 4/r32/esp -11906 (tailor-exit-descriptor %edx 0x10) -11907 # -11908 (write _test-input-stream "fn foo {\n") -11909 (write _test-input-stream " var a: array\n") -11910 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") -11911 (write _test-input-stream "}\n") -11912 # convert -11913 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11914 # registers except esp clobbered at this point -11915 # restore ed -11916 89/<- %edx 4/r32/esp -11917 (flush _test-output-buffered-file) -11918 (flush _test-error-buffered-file) -11919 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11925 # check output -11926 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-array-atom-base-type: output should be empty") -11927 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: array 'a' must specify the type of its elements" "F - test-compute-offset-with-array-atom-base-type: error message") -11928 # check that stop(1) was called -11929 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status") -11930 # don't restore from ebp -11931 81 0/subop/add %esp 8/imm32 -11932 # . epilogue -11933 5d/pop-to-ebp -11934 c3/return -11935 -11936 test-compute-offset-with-wrong-index-type: -11937 # . prologue -11938 55/push-ebp -11939 89/<- %ebp 4/r32/esp -11940 # setup -11941 (clear-stream _test-input-stream) -11942 (clear-stream $_test-input-buffered-file->buffer) -11943 (clear-stream _test-output-stream) -11944 (clear-stream $_test-output-buffered-file->buffer) -11945 (clear-stream _test-error-stream) -11946 (clear-stream $_test-error-buffered-file->buffer) -11947 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11948 68/push 0/imm32 -11949 68/push 0/imm32 -11950 89/<- %edx 4/r32/esp -11951 (tailor-exit-descriptor %edx 0x10) -11952 # -11953 (write _test-input-stream "fn foo {\n") -11954 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") -11955 (write _test-input-stream " var b: boolean\n") -11956 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, b\n") -11957 (write _test-input-stream "}\n") -11958 # convert -11959 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -11960 # registers except esp clobbered at this point -11961 # restore ed -11962 89/<- %edx 4/r32/esp -11963 (flush _test-output-buffered-file) -11964 (flush _test-error-buffered-file) -11965 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -11971 # check output -11972 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-wrong-index-type: output should be empty") -11973 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: second argument 'b' must be an int" "F - test-compute-offset-with-wrong-index-type: error message") -11974 # check that stop(1) was called -11975 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status") -11976 # don't restore from ebp -11977 81 0/subop/add %esp 8/imm32 -11978 # . epilogue -11979 5d/pop-to-ebp -11980 c3/return -11981 -11982 test-compute-offset-with-output-not-offset: -11983 # . prologue -11984 55/push-ebp -11985 89/<- %ebp 4/r32/esp -11986 # setup -11987 (clear-stream _test-input-stream) -11988 (clear-stream $_test-input-buffered-file->buffer) -11989 (clear-stream _test-output-stream) -11990 (clear-stream $_test-output-buffered-file->buffer) -11991 (clear-stream _test-error-stream) -11992 (clear-stream $_test-error-buffered-file->buffer) -11993 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -11994 68/push 0/imm32 -11995 68/push 0/imm32 -11996 89/<- %edx 4/r32/esp -11997 (tailor-exit-descriptor %edx 0x10) -11998 # -11999 (write _test-input-stream "fn foo {\n") -12000 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -12001 (write _test-input-stream " var o/edi: int <- compute-offset a, 0\n") -12002 (write _test-input-stream "}\n") -12003 # convert -12004 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12005 # registers except esp clobbered at this point -12006 # restore ed -12007 89/<- %edx 4/r32/esp -12008 (flush _test-output-buffered-file) -12009 (flush _test-error-buffered-file) -12010 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12016 # check output -12017 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-output-not-offset: output should be empty") -12018 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' must be an offset" "F - test-compute-offset-with-output-not-offset: error message") -12019 # check that stop(1) was called -12020 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status") -12021 # don't restore from ebp -12022 81 0/subop/add %esp 8/imm32 -12023 # . epilogue -12024 5d/pop-to-ebp -12025 c3/return -12026 -12027 test-compute-offset-with-output-not-address-2: -12028 # . prologue -12029 55/push-ebp -12030 89/<- %ebp 4/r32/esp -12031 # setup -12032 (clear-stream _test-input-stream) -12033 (clear-stream $_test-input-buffered-file->buffer) -12034 (clear-stream _test-output-stream) -12035 (clear-stream $_test-output-buffered-file->buffer) -12036 (clear-stream _test-error-stream) -12037 (clear-stream $_test-error-buffered-file->buffer) -12038 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12039 68/push 0/imm32 -12040 68/push 0/imm32 -12041 89/<- %edx 4/r32/esp -12042 (tailor-exit-descriptor %edx 0x10) -12043 # -12044 (write _test-input-stream "fn foo {\n") -12045 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -12046 (write _test-input-stream " var o/edi: (int) <- compute-offset a, 0\n") -12047 (write _test-input-stream "}\n") -12048 # convert -12049 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12050 # registers except esp clobbered at this point -12051 # restore ed -12052 89/<- %edx 4/r32/esp -12053 (flush _test-output-buffered-file) -12054 (flush _test-error-buffered-file) -12055 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12061 # check output -12062 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-output-not-address-2: output should be empty") -12063 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' must be an offset" "F - test-compute-offset-with-output-not-address-2: error message") -12064 # check that stop(1) was called -12065 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status") -12066 # don't restore from ebp -12067 81 0/subop/add %esp 8/imm32 -12068 # . epilogue -12069 5d/pop-to-ebp -12070 c3/return -12071 -12072 test-compute-offset-with-wrong-output-type: -12073 # . prologue -12074 55/push-ebp -12075 89/<- %ebp 4/r32/esp -12076 # setup -12077 (clear-stream _test-input-stream) -12078 (clear-stream $_test-input-buffered-file->buffer) -12079 (clear-stream _test-output-stream) -12080 (clear-stream $_test-output-buffered-file->buffer) -12081 (clear-stream _test-error-stream) -12082 (clear-stream $_test-error-buffered-file->buffer) -12083 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12084 68/push 0/imm32 -12085 68/push 0/imm32 -12086 89/<- %edx 4/r32/esp -12087 (tailor-exit-descriptor %edx 0x10) -12088 # -12089 (write _test-input-stream "fn foo {\n") -12090 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -12091 (write _test-input-stream " var o/edi: (offset int) <- compute-offset a, 0\n") -12092 (write _test-input-stream "}\n") -12093 # convert -12094 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12095 # registers except esp clobbered at this point -12096 # restore ed -12097 89/<- %edx 4/r32/esp -12098 (flush _test-output-buffered-file) -12099 (flush _test-error-buffered-file) -12100 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12106 # check output -12107 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-wrong-output-type: output should be empty") -12108 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' does not have the right type" "F - test-compute-offset-with-wrong-output-type: error message") -12109 # check that stop(1) was called -12110 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status") -12111 # don't restore from ebp -12112 81 0/subop/add %esp 8/imm32 -12113 # . epilogue -12114 5d/pop-to-ebp -12115 c3/return -12116 -12117 test-compute-offset-with-wrong-output-compound-type: -12118 # . prologue -12119 55/push-ebp -12120 89/<- %ebp 4/r32/esp -12121 # setup -12122 (clear-stream _test-input-stream) -12123 (clear-stream $_test-input-buffered-file->buffer) -12124 (clear-stream _test-output-stream) -12125 (clear-stream $_test-output-buffered-file->buffer) -12126 (clear-stream _test-error-stream) -12127 (clear-stream $_test-error-buffered-file->buffer) -12128 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12129 68/push 0/imm32 -12130 68/push 0/imm32 -12131 89/<- %edx 4/r32/esp -12132 (tailor-exit-descriptor %edx 0x10) -12133 # -12134 (write _test-input-stream "fn foo {\n") -12135 (write _test-input-stream " var a/ebx: (addr array handle boolean) <- copy 0\n") -12136 (write _test-input-stream " var o/edi: (offset handle int) <- compute-offset a, 0\n") -12137 (write _test-input-stream "}\n") -12138 # convert -12139 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12140 # registers except esp clobbered at this point -12141 # restore ed -12142 89/<- %edx 4/r32/esp -12143 (flush _test-output-buffered-file) -12144 (flush _test-error-buffered-file) -12145 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12151 # check output -12152 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-wrong-output-compound-type: output should be empty") -12153 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' does not have the right type" "F - test-compute-offset-with-wrong-output-compound-type: error message") -12154 # check that stop(1) was called -12155 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status") -12156 # don't restore from ebp -12157 81 0/subop/add %esp 8/imm32 -12158 # . epilogue -12159 5d/pop-to-ebp -12160 c3/return -12161 -12162 test-compute-offset-with-no-inouts: -12163 # . prologue -12164 55/push-ebp -12165 89/<- %ebp 4/r32/esp -12166 # setup -12167 (clear-stream _test-input-stream) -12168 (clear-stream $_test-input-buffered-file->buffer) -12169 (clear-stream _test-output-stream) -12170 (clear-stream $_test-output-buffered-file->buffer) -12171 (clear-stream _test-error-stream) -12172 (clear-stream $_test-error-buffered-file->buffer) -12173 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12174 68/push 0/imm32 -12175 68/push 0/imm32 -12176 89/<- %edx 4/r32/esp -12177 (tailor-exit-descriptor %edx 0x10) -12178 # -12179 (write _test-input-stream "fn foo {\n") -12180 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset\n") -12181 (write _test-input-stream "}\n") -12182 # convert -12183 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12184 # registers except esp clobbered at this point -12185 # restore ed -12186 89/<- %edx 4/r32/esp -12187 (flush _test-output-buffered-file) -12188 (flush _test-error-buffered-file) -12189 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12195 # check output -12196 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-no-inouts: output should be empty") -12197 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too few inouts (2 required)" "F - test-compute-offset-with-no-inouts: error message") -12198 # check that stop(1) was called -12199 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status") -12200 # don't restore from ebp -12201 81 0/subop/add %esp 8/imm32 -12202 # . epilogue -12203 5d/pop-to-ebp -12204 c3/return -12205 -12206 test-compute-offset-with-too-few-inouts: -12207 # . prologue -12208 55/push-ebp -12209 89/<- %ebp 4/r32/esp -12210 # setup -12211 (clear-stream _test-input-stream) -12212 (clear-stream $_test-input-buffered-file->buffer) -12213 (clear-stream _test-output-stream) -12214 (clear-stream $_test-output-buffered-file->buffer) -12215 (clear-stream _test-error-stream) -12216 (clear-stream $_test-error-buffered-file->buffer) -12217 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12218 68/push 0/imm32 -12219 68/push 0/imm32 -12220 89/<- %edx 4/r32/esp -12221 (tailor-exit-descriptor %edx 0x10) -12222 # -12223 (write _test-input-stream "fn foo {\n") -12224 (write _test-input-stream " var a: (array int 3)\n") -12225 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a\n") -12226 (write _test-input-stream "}\n") -12227 # convert -12228 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12229 # registers except esp clobbered at this point -12230 # restore ed -12231 89/<- %edx 4/r32/esp -12232 (flush _test-output-buffered-file) -12233 (flush _test-error-buffered-file) -12234 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12240 # check output -12241 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-too-few-inouts: output should be empty") -12242 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too few inouts (2 required)" "F - test-compute-offset-with-too-few-inouts: error message") -12243 # check that stop(1) was called -12244 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status") -12245 # don't restore from ebp -12246 81 0/subop/add %esp 8/imm32 -12247 # . epilogue -12248 5d/pop-to-ebp -12249 c3/return -12250 -12251 test-compute-offset-with-too-many-inouts: -12252 # . prologue -12253 55/push-ebp -12254 89/<- %ebp 4/r32/esp -12255 # setup -12256 (clear-stream _test-input-stream) -12257 (clear-stream $_test-input-buffered-file->buffer) -12258 (clear-stream _test-output-stream) -12259 (clear-stream $_test-output-buffered-file->buffer) -12260 (clear-stream _test-error-stream) -12261 (clear-stream $_test-error-buffered-file->buffer) -12262 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12263 68/push 0/imm32 -12264 68/push 0/imm32 -12265 89/<- %edx 4/r32/esp -12266 (tailor-exit-descriptor %edx 0x10) -12267 # -12268 (write _test-input-stream "fn foo {\n") -12269 (write _test-input-stream " var a: (array int 3)\n") -12270 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0, 0\n") -12271 (write _test-input-stream "}\n") -12272 # convert -12273 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12274 # registers except esp clobbered at this point -12275 # restore ed -12276 89/<- %edx 4/r32/esp -12277 (flush _test-output-buffered-file) -12278 (flush _test-error-buffered-file) -12279 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12285 # check output -12286 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-too-many-inouts: output should be empty") -12287 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too many inouts (2 required)" "F - test-compute-offset-with-too-many-inouts: error message") -12288 # check that stop(1) was called -12289 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status") -12290 # don't restore from ebp -12291 81 0/subop/add %esp 8/imm32 -12292 # . epilogue -12293 5d/pop-to-ebp -12294 c3/return -12295 -12296 test-compute-offset-with-no-output: -12297 # . prologue -12298 55/push-ebp -12299 89/<- %ebp 4/r32/esp -12300 # setup -12301 (clear-stream _test-input-stream) -12302 (clear-stream $_test-input-buffered-file->buffer) -12303 (clear-stream _test-output-stream) -12304 (clear-stream $_test-output-buffered-file->buffer) -12305 (clear-stream _test-error-stream) -12306 (clear-stream $_test-error-buffered-file->buffer) -12307 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12308 68/push 0/imm32 -12309 68/push 0/imm32 -12310 89/<- %edx 4/r32/esp -12311 (tailor-exit-descriptor %edx 0x10) -12312 # -12313 (write _test-input-stream "fn foo {\n") -12314 (write _test-input-stream " var a: (array int 3)\n") -12315 (write _test-input-stream " compute-offset a, 0\n") -12316 (write _test-input-stream "}\n") -12317 # convert -12318 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12319 # registers except esp clobbered at this point -12320 # restore ed -12321 89/<- %edx 4/r32/esp -12322 (flush _test-output-buffered-file) -12323 (flush _test-error-buffered-file) -12324 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12330 # check output -12331 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-no-output: output should be empty") -12332 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: must have an output" "F - test-compute-offset-with-no-output: error message") -12333 # check that stop(1) was called -12334 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status") -12335 # don't restore from ebp -12336 81 0/subop/add %esp 8/imm32 -12337 # . epilogue -12338 5d/pop-to-ebp -12339 c3/return -12340 -12341 test-compute-offset-with-too-many-outputs: -12342 # . prologue -12343 55/push-ebp -12344 89/<- %ebp 4/r32/esp -12345 # setup -12346 (clear-stream _test-input-stream) -12347 (clear-stream $_test-input-buffered-file->buffer) -12348 (clear-stream _test-output-stream) -12349 (clear-stream $_test-output-buffered-file->buffer) -12350 (clear-stream _test-error-stream) -12351 (clear-stream $_test-error-buffered-file->buffer) -12352 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12353 68/push 0/imm32 -12354 68/push 0/imm32 -12355 89/<- %edx 4/r32/esp -12356 (tailor-exit-descriptor %edx 0x10) -12357 # -12358 (write _test-input-stream "fn foo {\n") -12359 (write _test-input-stream " var a: (array int 3)\n") -12360 (write _test-input-stream " var b/eax: (offset int) <- compute-offset a, 0\n") -12361 (write _test-input-stream " var c/ecx: (addr int) <- copy 0\n") -12362 (write _test-input-stream " b, c <- compute-offset a, 0\n") -12363 (write _test-input-stream "}\n") -12364 # convert -12365 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12366 # registers except esp clobbered at this point -12367 # restore ed -12368 89/<- %edx 4/r32/esp -12369 (flush _test-output-buffered-file) -12370 (flush _test-error-buffered-file) -12371 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12377 # check output -12378 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-too-many-outputs: output should be empty") -12379 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too many outputs (1 required)" "F - test-compute-offset-with-too-many-outputs: error message") -12380 # check that stop(1) was called -12381 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status") -12382 # don't restore from ebp -12383 81 0/subop/add %esp 8/imm32 -12384 # . epilogue -12385 5d/pop-to-ebp -12386 c3/return -12387 -12388 test-convert-read-from-stream: -12389 # . prologue -12390 55/push-ebp -12391 89/<- %ebp 4/r32/esp -12392 # setup -12393 (clear-stream _test-input-stream) -12394 (clear-stream $_test-input-buffered-file->buffer) -12395 (clear-stream _test-output-stream) -12396 (clear-stream $_test-output-buffered-file->buffer) -12397 # -12398 (write _test-input-stream "fn foo {\n") -12399 (write _test-input-stream " var s/esi: (addr stream int) <- copy 0\n") -12400 (write _test-input-stream " var o/ecx: (addr int) <- copy 0\n") -12401 (write _test-input-stream " read-from-stream s, o\n") -12402 (write _test-input-stream "}\n") -12403 # convert -12404 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -12405 # registers except esp clobbered at this point -12406 # restore ed -12407 89/<- %edx 4/r32/esp -12408 (flush _test-output-buffered-file) -12409 (flush _test-error-buffered-file) -12410 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -12416 # check output -12417 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-read-from-stream/0") -12418 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-read-from-stream/1") -12419 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-read-from-stream/2") -12420 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-read-from-stream/3") -12421 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-read-from-stream/4") -12422 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-read-from-stream/5") -12423 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-read-from-stream/6") -12424 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-read-from-stream/7") -12425 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-read-from-stream/8") -12426 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-read-from-stream/9") -12427 (check-next-stream-line-equal _test-output-stream " (read-from-stream %esi %ecx 0x00000004)" "F - test-convert-read-from-stream/10") -12428 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-read-from-stream/11") -12429 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-read-from-stream/12") -12430 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-read-from-stream/13") -12431 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-read-from-stream/14") -12432 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-read-from-stream/15") -12433 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-read-from-stream/16") -12434 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-read-from-stream/17") -12435 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-read-from-stream/18") -12436 # . epilogue -12437 89/<- %esp 5/r32/ebp -12438 5d/pop-to-ebp -12439 c3/return -12440 -12441 test-convert-read-from-stream-with-correct-payload-size: -12442 # . prologue -12443 55/push-ebp -12444 89/<- %ebp 4/r32/esp -12445 # setup -12446 (clear-stream _test-input-stream) -12447 (clear-stream $_test-input-buffered-file->buffer) -12448 (clear-stream _test-output-stream) -12449 (clear-stream $_test-output-buffered-file->buffer) -12450 # -12451 (write _test-input-stream "fn foo {\n") -12452 (write _test-input-stream " var s/esi: (addr stream handle int) <- copy 0\n") -12453 (write _test-input-stream " var o/ecx: (addr handle int) <- copy 0\n") -12454 (write _test-input-stream " read-from-stream s, o\n") -12455 (write _test-input-stream "}\n") -12456 # convert -12457 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -12458 # registers except esp clobbered at this point -12459 # restore ed -12460 89/<- %edx 4/r32/esp -12461 (flush _test-output-buffered-file) -12462 (flush _test-error-buffered-file) -12463 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -12469 # check output -12470 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-read-from-stream-with-correct-payload-size/0") -12471 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-read-from-stream-with-correct-payload-size/1") -12472 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-read-from-stream-with-correct-payload-size/2") -12473 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-read-from-stream-with-correct-payload-size/3") -12474 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-read-from-stream-with-correct-payload-size/4") -12475 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-read-from-stream-with-correct-payload-size/5") -12476 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-read-from-stream-with-correct-payload-size/6") -12477 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-read-from-stream-with-correct-payload-size/7") -12478 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-read-from-stream-with-correct-payload-size/8") -12479 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-read-from-stream-with-correct-payload-size/9") -12480 (check-next-stream-line-equal _test-output-stream " (read-from-stream %esi %ecx 0x00000008)" "F - test-convert-read-from-stream-with-correct-payload-size/10") -12481 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-read-from-stream-with-correct-payload-size/11") -12482 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-read-from-stream-with-correct-payload-size/12") -12483 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-read-from-stream-with-correct-payload-size/13") -12484 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-read-from-stream-with-correct-payload-size/14") -12485 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-read-from-stream-with-correct-payload-size/15") -12486 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-read-from-stream-with-correct-payload-size/16") -12487 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-read-from-stream-with-correct-payload-size/17") -12488 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-read-from-stream-with-correct-payload-size/18") -12489 # . epilogue -12490 89/<- %esp 5/r32/ebp -12491 5d/pop-to-ebp -12492 c3/return -12493 -12494 test-read-from-stream-with-non-stream-atom-base-type: -12495 # . prologue -12496 55/push-ebp -12497 89/<- %ebp 4/r32/esp -12498 # setup -12499 (clear-stream _test-input-stream) -12500 (clear-stream $_test-input-buffered-file->buffer) -12501 (clear-stream _test-output-stream) -12502 (clear-stream $_test-output-buffered-file->buffer) -12503 (clear-stream _test-error-stream) -12504 (clear-stream $_test-error-buffered-file->buffer) -12505 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12506 68/push 0/imm32 -12507 68/push 0/imm32 -12508 89/<- %edx 4/r32/esp -12509 (tailor-exit-descriptor %edx 0x10) -12510 # -12511 (write _test-input-stream "fn foo {\n") -12512 (write _test-input-stream " var a: int\n") -12513 (write _test-input-stream " read-from-stream a, 0\n") -12514 (write _test-input-stream "}\n") -12515 # convert -12516 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12517 # registers except esp clobbered at this point -12518 # restore ed -12519 89/<- %edx 4/r32/esp -12520 (flush _test-output-buffered-file) -12521 (flush _test-error-buffered-file) -12522 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12528 # check output -12529 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty") -12530 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-non-stream-atom-base-type: error message") -12531 # check that stop(1) was called -12532 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status") -12533 # don't restore from ebp -12534 81 0/subop/add %esp 8/imm32 -12535 # . epilogue -12536 5d/pop-to-ebp -12537 c3/return -12538 -12539 test-read-from-stream-with-non-stream-compound-base-type: -12540 # . prologue -12541 55/push-ebp -12542 89/<- %ebp 4/r32/esp -12543 # setup -12544 (clear-stream _test-input-stream) -12545 (clear-stream $_test-input-buffered-file->buffer) -12546 (clear-stream _test-output-stream) -12547 (clear-stream $_test-output-buffered-file->buffer) -12548 (clear-stream _test-error-stream) -12549 (clear-stream $_test-error-buffered-file->buffer) -12550 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12551 68/push 0/imm32 -12552 68/push 0/imm32 -12553 89/<- %edx 4/r32/esp -12554 (tailor-exit-descriptor %edx 0x10) -12555 # -12556 (write _test-input-stream "fn foo {\n") -12557 (write _test-input-stream " var a: (handle int)\n") -12558 (write _test-input-stream " read-from-stream a, 0\n") -12559 (write _test-input-stream "}\n") -12560 # convert -12561 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12562 # registers except esp clobbered at this point -12563 # restore ed -12564 89/<- %edx 4/r32/esp -12565 (flush _test-output-buffered-file) -12566 (flush _test-error-buffered-file) -12567 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12573 # check output -12574 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty") -12575 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-non-stream-compound-base-type: error message") -12576 # check that stop(1) was called -12577 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status") -12578 # don't restore from ebp -12579 81 0/subop/add %esp 8/imm32 -12580 # . epilogue -12581 5d/pop-to-ebp -12582 c3/return -12583 -12584 test-read-from-stream-with-non-stream-compound-base-type-2: -12585 # . prologue -12586 55/push-ebp -12587 89/<- %ebp 4/r32/esp -12588 # setup -12589 (clear-stream _test-input-stream) -12590 (clear-stream $_test-input-buffered-file->buffer) -12591 (clear-stream _test-output-stream) -12592 (clear-stream $_test-output-buffered-file->buffer) -12593 (clear-stream _test-error-stream) -12594 (clear-stream $_test-error-buffered-file->buffer) -12595 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12596 68/push 0/imm32 -12597 68/push 0/imm32 -12598 89/<- %edx 4/r32/esp -12599 (tailor-exit-descriptor %edx 0x10) -12600 # -12601 (write _test-input-stream "fn foo {\n") -12602 (write _test-input-stream " var a: (addr int)\n") -12603 (write _test-input-stream " read-from-stream a, 0\n") -12604 (write _test-input-stream "}\n") -12605 # convert -12606 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12607 # registers except esp clobbered at this point -12608 # restore ed -12609 89/<- %edx 4/r32/esp -12610 (flush _test-output-buffered-file) -12611 (flush _test-error-buffered-file) -12612 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12618 # check output -12619 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty") -12620 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message") -12621 # check that stop(1) was called -12622 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status") -12623 # don't restore from ebp -12624 81 0/subop/add %esp 8/imm32 -12625 # . epilogue -12626 5d/pop-to-ebp -12627 c3/return -12628 -12629 test-read-from-stream-with-stream-atom-base-type: -12630 # . prologue -12631 55/push-ebp -12632 89/<- %ebp 4/r32/esp -12633 # setup -12634 (clear-stream _test-input-stream) -12635 (clear-stream $_test-input-buffered-file->buffer) -12636 (clear-stream _test-output-stream) -12637 (clear-stream $_test-output-buffered-file->buffer) -12638 (clear-stream _test-error-stream) -12639 (clear-stream $_test-error-buffered-file->buffer) -12640 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12641 68/push 0/imm32 -12642 68/push 0/imm32 -12643 89/<- %edx 4/r32/esp -12644 (tailor-exit-descriptor %edx 0x10) -12645 # -12646 (write _test-input-stream "fn foo {\n") -12647 (write _test-input-stream " var a: stream\n") -12648 (write _test-input-stream " read-from-stream a, 0\n") -12649 (write _test-input-stream "}\n") -12650 # convert -12651 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12652 # registers except esp clobbered at this point -12653 # restore ed -12654 89/<- %edx 4/r32/esp -12655 (flush _test-output-buffered-file) -12656 (flush _test-error-buffered-file) -12657 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12663 # check output -12664 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-stream-atom-base-type: output should be empty") -12665 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-stream-atom-base-type: error message") -12666 # check that stop(1) was called -12667 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status") -12668 # don't restore from ebp -12669 81 0/subop/add %esp 8/imm32 -12670 # . epilogue -12671 5d/pop-to-ebp -12672 c3/return -12673 -12674 test-read-from-stream-with-wrong-index-type: -12675 # . prologue -12676 55/push-ebp -12677 89/<- %ebp 4/r32/esp -12678 # setup -12679 (clear-stream _test-input-stream) -12680 (clear-stream $_test-input-buffered-file->buffer) -12681 (clear-stream _test-output-stream) -12682 (clear-stream $_test-output-buffered-file->buffer) -12683 (clear-stream _test-error-stream) -12684 (clear-stream $_test-error-buffered-file->buffer) -12685 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12686 68/push 0/imm32 -12687 68/push 0/imm32 -12688 89/<- %edx 4/r32/esp -12689 (tailor-exit-descriptor %edx 0x10) -12690 # -12691 (write _test-input-stream "fn foo {\n") -12692 (write _test-input-stream " var a/eax: (addr stream int) <- copy 0\n") -12693 (write _test-input-stream " var b: boolean\n") -12694 (write _test-input-stream " read-from-stream a, b\n") -12695 (write _test-input-stream "}\n") -12696 # convert -12697 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12698 # registers except esp clobbered at this point -12699 # restore ed -12700 89/<- %edx 4/r32/esp -12701 (flush _test-output-buffered-file) -12702 (flush _test-error-buffered-file) -12703 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12709 # check output -12710 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-wrong-index-type: output should be empty") -12711 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: target 'b' must be an addr" "F - test-read-from-stream-with-wrong-index-type: error message") -12712 # check that stop(1) was called -12713 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status") -12714 # don't restore from ebp -12715 81 0/subop/add %esp 8/imm32 -12716 # . epilogue -12717 5d/pop-to-ebp -12718 c3/return -12719 -12720 test-read-from-stream-with-no-inouts: -12721 # . prologue -12722 55/push-ebp -12723 89/<- %ebp 4/r32/esp -12724 # setup -12725 (clear-stream _test-input-stream) -12726 (clear-stream $_test-input-buffered-file->buffer) -12727 (clear-stream _test-output-stream) -12728 (clear-stream $_test-output-buffered-file->buffer) -12729 (clear-stream _test-error-stream) -12730 (clear-stream $_test-error-buffered-file->buffer) -12731 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12732 68/push 0/imm32 -12733 68/push 0/imm32 -12734 89/<- %edx 4/r32/esp -12735 (tailor-exit-descriptor %edx 0x10) -12736 # -12737 (write _test-input-stream "fn foo {\n") -12738 (write _test-input-stream " read-from-stream\n") -12739 (write _test-input-stream "}\n") -12740 # convert -12741 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12742 # registers except esp clobbered at this point -12743 # restore ed -12744 89/<- %edx 4/r32/esp -12745 (flush _test-output-buffered-file) -12746 (flush _test-error-buffered-file) -12747 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12753 # check output -12754 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-no-inouts: output should be empty") -12755 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: too few inouts (2 required)" "F - test-read-from-stream-with-no-inouts: error message") -12756 # check that stop(1) was called -12757 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status") -12758 # don't restore from ebp -12759 81 0/subop/add %esp 8/imm32 -12760 # . epilogue -12761 5d/pop-to-ebp -12762 c3/return -12763 -12764 test-read-from-stream-with-too-few-inouts: -12765 # . prologue -12766 55/push-ebp -12767 89/<- %ebp 4/r32/esp -12768 # setup -12769 (clear-stream _test-input-stream) -12770 (clear-stream $_test-input-buffered-file->buffer) -12771 (clear-stream _test-output-stream) -12772 (clear-stream $_test-output-buffered-file->buffer) -12773 (clear-stream _test-error-stream) -12774 (clear-stream $_test-error-buffered-file->buffer) -12775 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12776 68/push 0/imm32 -12777 68/push 0/imm32 -12778 89/<- %edx 4/r32/esp -12779 (tailor-exit-descriptor %edx 0x10) -12780 # -12781 (write _test-input-stream "fn foo {\n") -12782 (write _test-input-stream " var a: (addr stream int)\n") -12783 (write _test-input-stream " read-from-stream a\n") -12784 (write _test-input-stream "}\n") -12785 # convert -12786 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12787 # registers except esp clobbered at this point -12788 # restore ed -12789 89/<- %edx 4/r32/esp -12790 (flush _test-output-buffered-file) -12791 (flush _test-error-buffered-file) -12792 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12798 # check output -12799 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-too-few-inouts: output should be empty") -12800 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: too few inouts (2 required)" "F - test-read-from-stream-with-too-few-inouts: error message") -12801 # check that stop(1) was called -12802 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status") -12803 # don't restore from ebp -12804 81 0/subop/add %esp 8/imm32 -12805 # . epilogue -12806 5d/pop-to-ebp -12807 c3/return -12808 -12809 test-read-from-stream-with-too-many-inouts: -12810 # . prologue -12811 55/push-ebp -12812 89/<- %ebp 4/r32/esp -12813 # setup -12814 (clear-stream _test-input-stream) -12815 (clear-stream $_test-input-buffered-file->buffer) -12816 (clear-stream _test-output-stream) -12817 (clear-stream $_test-output-buffered-file->buffer) -12818 (clear-stream _test-error-stream) -12819 (clear-stream $_test-error-buffered-file->buffer) -12820 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12821 68/push 0/imm32 -12822 68/push 0/imm32 -12823 89/<- %edx 4/r32/esp -12824 (tailor-exit-descriptor %edx 0x10) -12825 # -12826 (write _test-input-stream "fn foo {\n") -12827 (write _test-input-stream " var a: (addr stream int)\n") -12828 (write _test-input-stream " var b: (addr int)\n") -12829 (write _test-input-stream " read-from-stream a, b, 0\n") -12830 (write _test-input-stream "}\n") -12831 # convert -12832 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12833 # registers except esp clobbered at this point -12834 # restore ed -12835 89/<- %edx 4/r32/esp -12836 (flush _test-output-buffered-file) -12837 (flush _test-error-buffered-file) -12838 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12844 # check output -12845 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-too-many-inouts: output should be empty") -12846 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: too many inouts (2 required)" "F - test-read-from-stream-with-too-many-inouts: error message") -12847 # check that stop(1) was called -12848 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status") -12849 # don't restore from ebp -12850 81 0/subop/add %esp 8/imm32 -12851 # . epilogue -12852 5d/pop-to-ebp -12853 c3/return -12854 -12855 test-read-from-stream-with-output: -12856 # . prologue -12857 55/push-ebp -12858 89/<- %ebp 4/r32/esp -12859 # setup -12860 (clear-stream _test-input-stream) -12861 (clear-stream $_test-input-buffered-file->buffer) -12862 (clear-stream _test-output-stream) -12863 (clear-stream $_test-output-buffered-file->buffer) -12864 (clear-stream _test-error-stream) -12865 (clear-stream $_test-error-buffered-file->buffer) -12866 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -12867 68/push 0/imm32 -12868 68/push 0/imm32 -12869 89/<- %edx 4/r32/esp -12870 (tailor-exit-descriptor %edx 0x10) -12871 # -12872 (write _test-input-stream "fn foo {\n") -12873 (write _test-input-stream " var a: (addr stream int)\n") -12874 (write _test-input-stream " var b/eax: (addr int) <- copy 0\n") -12875 (write _test-input-stream " b <- read-from-stream a, b\n") -12876 (write _test-input-stream "}\n") -12877 # convert -12878 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -12879 # registers except esp clobbered at this point -12880 # restore ed -12881 89/<- %edx 4/r32/esp -12882 (flush _test-output-buffered-file) -12883 (flush _test-error-buffered-file) -12884 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -12890 # check output -12891 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-output: output should be empty") -12892 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: unexpected output" "F - test-read-from-stream-with-output: error message") -12893 # check that stop(1) was called -12894 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status") -12895 # don't restore from ebp -12896 81 0/subop/add %esp 8/imm32 -12897 # . epilogue -12898 5d/pop-to-ebp -12899 c3/return -12900 -12901 test-convert-write-to-stream: -12902 # . prologue -12903 55/push-ebp -12904 89/<- %ebp 4/r32/esp -12905 # setup -12906 (clear-stream _test-input-stream) -12907 (clear-stream $_test-input-buffered-file->buffer) -12908 (clear-stream _test-output-stream) -12909 (clear-stream $_test-output-buffered-file->buffer) -12910 # -12911 (write _test-input-stream "fn foo {\n") -12912 (write _test-input-stream " var s/esi: (addr stream int) <- copy 0\n") -12913 (write _test-input-stream " var o/ecx: (addr int) <- copy 0\n") -12914 (write _test-input-stream " write-to-stream s, o\n") -12915 (write _test-input-stream "}\n") -12916 # convert -12917 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -12918 # registers except esp clobbered at this point -12919 # restore ed -12920 89/<- %edx 4/r32/esp -12921 (flush _test-output-buffered-file) -12922 (flush _test-error-buffered-file) -12923 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -12929 # check output -12930 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-write-to-stream/0") -12931 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-write-to-stream/1") -12932 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-write-to-stream/2") -12933 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-write-to-stream/3") -12934 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-write-to-stream/4") -12935 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-write-to-stream/5") -12936 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-write-to-stream/6") -12937 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-write-to-stream/7") -12938 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-write-to-stream/8") -12939 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-write-to-stream/9") -12940 (check-next-stream-line-equal _test-output-stream " (write-to-stream %esi %ecx 0x00000004)" "F - test-convert-write-to-stream/10") -12941 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-write-to-stream/11") -12942 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-write-to-stream/12") -12943 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-write-to-stream/13") -12944 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-write-to-stream/14") -12945 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-write-to-stream/15") -12946 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-write-to-stream/16") -12947 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-write-to-stream/17") -12948 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-write-to-stream/18") -12949 # . epilogue -12950 89/<- %esp 5/r32/ebp -12951 5d/pop-to-ebp -12952 c3/return -12953 -12954 test-convert-write-to-stream-with-correct-payload-size: -12955 # . prologue -12956 55/push-ebp -12957 89/<- %ebp 4/r32/esp -12958 # setup -12959 (clear-stream _test-input-stream) -12960 (clear-stream $_test-input-buffered-file->buffer) -12961 (clear-stream _test-output-stream) -12962 (clear-stream $_test-output-buffered-file->buffer) -12963 # -12964 (write _test-input-stream "fn foo {\n") -12965 (write _test-input-stream " var s/esi: (addr stream handle int) <- copy 0\n") -12966 (write _test-input-stream " var o/ecx: (addr handle int) <- copy 0\n") -12967 (write _test-input-stream " write-to-stream s, o\n") -12968 (write _test-input-stream "}\n") -12969 # convert -12970 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -12971 # registers except esp clobbered at this point -12972 # restore ed -12973 89/<- %edx 4/r32/esp -12974 (flush _test-output-buffered-file) -12975 (flush _test-error-buffered-file) -12976 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -12982 # check output -12983 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-write-to-stream-with-correct-payload-size/0") -12984 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-write-to-stream-with-correct-payload-size/1") -12985 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-write-to-stream-with-correct-payload-size/2") -12986 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-write-to-stream-with-correct-payload-size/3") -12987 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-write-to-stream-with-correct-payload-size/4") -12988 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-write-to-stream-with-correct-payload-size/5") -12989 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-write-to-stream-with-correct-payload-size/6") -12990 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-write-to-stream-with-correct-payload-size/7") -12991 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-write-to-stream-with-correct-payload-size/8") -12992 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-write-to-stream-with-correct-payload-size/9") -12993 (check-next-stream-line-equal _test-output-stream " (write-to-stream %esi %ecx 0x00000008)" "F - test-convert-write-to-stream-with-correct-payload-size/10") -12994 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-write-to-stream-with-correct-payload-size/11") -12995 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-write-to-stream-with-correct-payload-size/12") -12996 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-write-to-stream-with-correct-payload-size/13") -12997 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-write-to-stream-with-correct-payload-size/14") -12998 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-write-to-stream-with-correct-payload-size/15") -12999 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-write-to-stream-with-correct-payload-size/16") -13000 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-write-to-stream-with-correct-payload-size/17") -13001 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-write-to-stream-with-correct-payload-size/18") -13002 # . epilogue -13003 89/<- %esp 5/r32/ebp -13004 5d/pop-to-ebp -13005 c3/return -13006 -13007 test-write-to-stream-with-non-stream-atom-base-type: -13008 # . prologue -13009 55/push-ebp -13010 89/<- %ebp 4/r32/esp -13011 # setup -13012 (clear-stream _test-input-stream) -13013 (clear-stream $_test-input-buffered-file->buffer) -13014 (clear-stream _test-output-stream) -13015 (clear-stream $_test-output-buffered-file->buffer) -13016 (clear-stream _test-error-stream) -13017 (clear-stream $_test-error-buffered-file->buffer) -13018 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13019 68/push 0/imm32 -13020 68/push 0/imm32 -13021 89/<- %edx 4/r32/esp -13022 (tailor-exit-descriptor %edx 0x10) -13023 # -13024 (write _test-input-stream "fn foo {\n") -13025 (write _test-input-stream " var a: int\n") -13026 (write _test-input-stream " write-to-stream a, 0\n") -13027 (write _test-input-stream "}\n") -13028 # convert -13029 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13030 # registers except esp clobbered at this point -13031 # restore ed -13032 89/<- %edx 4/r32/esp -13033 (flush _test-output-buffered-file) -13034 (flush _test-error-buffered-file) -13035 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13041 # check output -13042 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty") -13043 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-non-stream-atom-base-type: error message") -13044 # check that stop(1) was called -13045 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status") -13046 # don't restore from ebp -13047 81 0/subop/add %esp 8/imm32 -13048 # . epilogue -13049 5d/pop-to-ebp -13050 c3/return -13051 -13052 test-write-to-stream-with-non-stream-compound-base-type: -13053 # . prologue -13054 55/push-ebp -13055 89/<- %ebp 4/r32/esp -13056 # setup -13057 (clear-stream _test-input-stream) -13058 (clear-stream $_test-input-buffered-file->buffer) -13059 (clear-stream _test-output-stream) -13060 (clear-stream $_test-output-buffered-file->buffer) -13061 (clear-stream _test-error-stream) -13062 (clear-stream $_test-error-buffered-file->buffer) -13063 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13064 68/push 0/imm32 -13065 68/push 0/imm32 -13066 89/<- %edx 4/r32/esp -13067 (tailor-exit-descriptor %edx 0x10) -13068 # -13069 (write _test-input-stream "fn foo {\n") -13070 (write _test-input-stream " var a: (handle int)\n") -13071 (write _test-input-stream " write-to-stream a, 0\n") -13072 (write _test-input-stream "}\n") -13073 # convert -13074 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13075 # registers except esp clobbered at this point -13076 # restore ed -13077 89/<- %edx 4/r32/esp -13078 (flush _test-output-buffered-file) -13079 (flush _test-error-buffered-file) -13080 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13086 # check output -13087 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty") -13088 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-non-stream-compound-base-type: error message") -13089 # check that stop(1) was called -13090 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status") -13091 # don't restore from ebp -13092 81 0/subop/add %esp 8/imm32 -13093 # . epilogue -13094 5d/pop-to-ebp -13095 c3/return -13096 -13097 test-write-to-stream-with-non-stream-compound-base-type-2: -13098 # . prologue -13099 55/push-ebp -13100 89/<- %ebp 4/r32/esp -13101 # setup -13102 (clear-stream _test-input-stream) -13103 (clear-stream $_test-input-buffered-file->buffer) -13104 (clear-stream _test-output-stream) -13105 (clear-stream $_test-output-buffered-file->buffer) -13106 (clear-stream _test-error-stream) -13107 (clear-stream $_test-error-buffered-file->buffer) -13108 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13109 68/push 0/imm32 -13110 68/push 0/imm32 -13111 89/<- %edx 4/r32/esp -13112 (tailor-exit-descriptor %edx 0x10) -13113 # -13114 (write _test-input-stream "fn foo {\n") -13115 (write _test-input-stream " var a: (addr int)\n") -13116 (write _test-input-stream " write-to-stream a, 0\n") -13117 (write _test-input-stream "}\n") -13118 # convert -13119 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13120 # registers except esp clobbered at this point -13121 # restore ed -13122 89/<- %edx 4/r32/esp -13123 (flush _test-output-buffered-file) -13124 (flush _test-error-buffered-file) -13125 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13131 # check output -13132 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty") -13133 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message") -13134 # check that stop(1) was called -13135 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status") -13136 # don't restore from ebp -13137 81 0/subop/add %esp 8/imm32 -13138 # . epilogue -13139 5d/pop-to-ebp -13140 c3/return -13141 -13142 test-write-to-stream-with-stream-atom-base-type: -13143 # . prologue -13144 55/push-ebp -13145 89/<- %ebp 4/r32/esp -13146 # setup -13147 (clear-stream _test-input-stream) -13148 (clear-stream $_test-input-buffered-file->buffer) -13149 (clear-stream _test-output-stream) -13150 (clear-stream $_test-output-buffered-file->buffer) -13151 (clear-stream _test-error-stream) -13152 (clear-stream $_test-error-buffered-file->buffer) -13153 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13154 68/push 0/imm32 -13155 68/push 0/imm32 -13156 89/<- %edx 4/r32/esp -13157 (tailor-exit-descriptor %edx 0x10) -13158 # -13159 (write _test-input-stream "fn foo {\n") -13160 (write _test-input-stream " var a: stream\n") -13161 (write _test-input-stream " write-to-stream a, 0\n") -13162 (write _test-input-stream "}\n") -13163 # convert -13164 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13165 # registers except esp clobbered at this point -13166 # restore ed -13167 89/<- %edx 4/r32/esp -13168 (flush _test-output-buffered-file) -13169 (flush _test-error-buffered-file) -13170 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13176 # check output -13177 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-stream-atom-base-type: output should be empty") -13178 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-stream-atom-base-type: error message") -13179 # check that stop(1) was called -13180 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status") -13181 # don't restore from ebp -13182 81 0/subop/add %esp 8/imm32 -13183 # . epilogue -13184 5d/pop-to-ebp -13185 c3/return -13186 -13187 test-write-to-stream-with-wrong-index-type: -13188 # . prologue -13189 55/push-ebp -13190 89/<- %ebp 4/r32/esp -13191 # setup -13192 (clear-stream _test-input-stream) -13193 (clear-stream $_test-input-buffered-file->buffer) -13194 (clear-stream _test-output-stream) -13195 (clear-stream $_test-output-buffered-file->buffer) -13196 (clear-stream _test-error-stream) -13197 (clear-stream $_test-error-buffered-file->buffer) -13198 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13199 68/push 0/imm32 -13200 68/push 0/imm32 -13201 89/<- %edx 4/r32/esp -13202 (tailor-exit-descriptor %edx 0x10) -13203 # -13204 (write _test-input-stream "fn foo {\n") -13205 (write _test-input-stream " var a/eax: (addr stream int) <- copy 0\n") -13206 (write _test-input-stream " var b: boolean\n") -13207 (write _test-input-stream " write-to-stream a, b\n") -13208 (write _test-input-stream "}\n") -13209 # convert -13210 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13211 # registers except esp clobbered at this point -13212 # restore ed -13213 89/<- %edx 4/r32/esp -13214 (flush _test-output-buffered-file) -13215 (flush _test-error-buffered-file) -13216 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13222 # check output -13223 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-wrong-index-type: output should be empty") -13224 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: target 'b' must be an addr" "F - test-write-to-stream-with-wrong-index-type: error message") -13225 # check that stop(1) was called -13226 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status") -13227 # don't restore from ebp -13228 81 0/subop/add %esp 8/imm32 -13229 # . epilogue -13230 5d/pop-to-ebp -13231 c3/return -13232 -13233 test-write-to-stream-with-no-inouts: -13234 # . prologue -13235 55/push-ebp -13236 89/<- %ebp 4/r32/esp -13237 # setup -13238 (clear-stream _test-input-stream) -13239 (clear-stream $_test-input-buffered-file->buffer) -13240 (clear-stream _test-output-stream) -13241 (clear-stream $_test-output-buffered-file->buffer) -13242 (clear-stream _test-error-stream) -13243 (clear-stream $_test-error-buffered-file->buffer) -13244 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13245 68/push 0/imm32 -13246 68/push 0/imm32 -13247 89/<- %edx 4/r32/esp -13248 (tailor-exit-descriptor %edx 0x10) -13249 # -13250 (write _test-input-stream "fn foo {\n") -13251 (write _test-input-stream " write-to-stream\n") -13252 (write _test-input-stream "}\n") -13253 # convert -13254 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13255 # registers except esp clobbered at this point -13256 # restore ed -13257 89/<- %edx 4/r32/esp -13258 (flush _test-output-buffered-file) -13259 (flush _test-error-buffered-file) -13260 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13266 # check output -13267 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-no-inouts: output should be empty") -13268 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: too few inouts (2 required)" "F - test-write-to-stream-with-no-inouts: error message") -13269 # check that stop(1) was called -13270 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status") -13271 # don't restore from ebp -13272 81 0/subop/add %esp 8/imm32 -13273 # . epilogue -13274 5d/pop-to-ebp -13275 c3/return -13276 -13277 test-write-to-stream-with-too-few-inouts: -13278 # . prologue -13279 55/push-ebp -13280 89/<- %ebp 4/r32/esp -13281 # setup -13282 (clear-stream _test-input-stream) -13283 (clear-stream $_test-input-buffered-file->buffer) -13284 (clear-stream _test-output-stream) -13285 (clear-stream $_test-output-buffered-file->buffer) -13286 (clear-stream _test-error-stream) -13287 (clear-stream $_test-error-buffered-file->buffer) -13288 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13289 68/push 0/imm32 -13290 68/push 0/imm32 -13291 89/<- %edx 4/r32/esp -13292 (tailor-exit-descriptor %edx 0x10) -13293 # -13294 (write _test-input-stream "fn foo {\n") -13295 (write _test-input-stream " var a: (addr stream int)\n") -13296 (write _test-input-stream " write-to-stream a\n") -13297 (write _test-input-stream "}\n") -13298 # convert -13299 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13300 # registers except esp clobbered at this point -13301 # restore ed -13302 89/<- %edx 4/r32/esp -13303 (flush _test-output-buffered-file) -13304 (flush _test-error-buffered-file) -13305 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13311 # check output -13312 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-too-few-inouts: output should be empty") -13313 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: too few inouts (2 required)" "F - test-write-to-stream-with-too-few-inouts: error message") -13314 # check that stop(1) was called -13315 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status") -13316 # don't restore from ebp -13317 81 0/subop/add %esp 8/imm32 -13318 # . epilogue -13319 5d/pop-to-ebp -13320 c3/return -13321 -13322 test-write-to-stream-with-too-many-inouts: -13323 # . prologue -13324 55/push-ebp -13325 89/<- %ebp 4/r32/esp -13326 # setup -13327 (clear-stream _test-input-stream) -13328 (clear-stream $_test-input-buffered-file->buffer) -13329 (clear-stream _test-output-stream) -13330 (clear-stream $_test-output-buffered-file->buffer) -13331 (clear-stream _test-error-stream) -13332 (clear-stream $_test-error-buffered-file->buffer) -13333 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13334 68/push 0/imm32 -13335 68/push 0/imm32 -13336 89/<- %edx 4/r32/esp -13337 (tailor-exit-descriptor %edx 0x10) -13338 # -13339 (write _test-input-stream "fn foo {\n") -13340 (write _test-input-stream " var a: (addr stream int)\n") -13341 (write _test-input-stream " var b: (addr int)\n") -13342 (write _test-input-stream " write-to-stream a, b, 0\n") -13343 (write _test-input-stream "}\n") -13344 # convert -13345 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13346 # registers except esp clobbered at this point -13347 # restore ed -13348 89/<- %edx 4/r32/esp -13349 (flush _test-output-buffered-file) -13350 (flush _test-error-buffered-file) -13351 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13357 # check output -13358 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-too-many-inouts: output should be empty") -13359 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: too many inouts (2 required)" "F - test-write-to-stream-with-too-many-inouts: error message") -13360 # check that stop(1) was called -13361 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status") -13362 # don't restore from ebp -13363 81 0/subop/add %esp 8/imm32 -13364 # . epilogue -13365 5d/pop-to-ebp -13366 c3/return -13367 -13368 test-write-to-stream-with-output: -13369 # . prologue -13370 55/push-ebp -13371 89/<- %ebp 4/r32/esp -13372 # setup -13373 (clear-stream _test-input-stream) -13374 (clear-stream $_test-input-buffered-file->buffer) -13375 (clear-stream _test-output-stream) -13376 (clear-stream $_test-output-buffered-file->buffer) -13377 (clear-stream _test-error-stream) -13378 (clear-stream $_test-error-buffered-file->buffer) -13379 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13380 68/push 0/imm32 -13381 68/push 0/imm32 -13382 89/<- %edx 4/r32/esp -13383 (tailor-exit-descriptor %edx 0x10) -13384 # -13385 (write _test-input-stream "fn foo {\n") -13386 (write _test-input-stream " var a: (addr stream int)\n") -13387 (write _test-input-stream " var b/eax: (addr int) <- copy 0\n") -13388 (write _test-input-stream " b <- write-to-stream a, b\n") -13389 (write _test-input-stream "}\n") -13390 # convert -13391 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13392 # registers except esp clobbered at this point -13393 # restore ed -13394 89/<- %edx 4/r32/esp -13395 (flush _test-output-buffered-file) -13396 (flush _test-error-buffered-file) -13397 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13403 # check output -13404 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-output: output should be empty") -13405 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: unexpected output" "F - test-write-to-stream-with-output: error message") -13406 # check that stop(1) was called -13407 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status") -13408 # don't restore from ebp -13409 81 0/subop/add %esp 8/imm32 -13410 # . epilogue -13411 5d/pop-to-ebp -13412 c3/return -13413 -13414 test-length-with-non-array-atom-base-type: -13415 # . prologue -13416 55/push-ebp -13417 89/<- %ebp 4/r32/esp -13418 # setup -13419 (clear-stream _test-input-stream) -13420 (clear-stream $_test-input-buffered-file->buffer) -13421 (clear-stream _test-output-stream) -13422 (clear-stream $_test-output-buffered-file->buffer) -13423 (clear-stream _test-error-stream) -13424 (clear-stream $_test-error-buffered-file->buffer) -13425 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13426 68/push 0/imm32 -13427 68/push 0/imm32 -13428 89/<- %edx 4/r32/esp -13429 (tailor-exit-descriptor %edx 0x10) -13430 # -13431 (write _test-input-stream "fn foo {\n") -13432 (write _test-input-stream " var a: int\n") -13433 (write _test-input-stream " var c/ecx: int <- length a\n") -13434 (write _test-input-stream "}\n") -13435 # convert -13436 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13437 # registers except esp clobbered at this point -13438 # restore ed -13439 89/<- %edx 4/r32/esp -13440 (flush _test-output-buffered-file) -13441 (flush _test-error-buffered-file) -13442 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13448 # check output -13449 (check-stream-equal _test-output-stream "" "F - test-length-with-non-array-atom-base-type: output should be empty") -13450 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is not an array" "F - test-length-with-non-array-atom-base-type: error message") -13451 # check that stop(1) was called -13452 (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status") -13453 # don't restore from ebp -13454 81 0/subop/add %esp 8/imm32 -13455 # . epilogue -13456 5d/pop-to-ebp -13457 c3/return -13458 -13459 test-length-with-non-array-compound-base-type: -13460 # . prologue -13461 55/push-ebp -13462 89/<- %ebp 4/r32/esp -13463 # setup -13464 (clear-stream _test-input-stream) -13465 (clear-stream $_test-input-buffered-file->buffer) -13466 (clear-stream _test-output-stream) -13467 (clear-stream $_test-output-buffered-file->buffer) -13468 (clear-stream _test-error-stream) -13469 (clear-stream $_test-error-buffered-file->buffer) -13470 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13471 68/push 0/imm32 -13472 68/push 0/imm32 -13473 89/<- %edx 4/r32/esp -13474 (tailor-exit-descriptor %edx 0x10) -13475 # -13476 (write _test-input-stream "fn foo {\n") -13477 (write _test-input-stream " var a: (handle int)\n") -13478 (write _test-input-stream " var c/ecx: (addr int) <- length a, 0\n") -13479 (write _test-input-stream "}\n") -13480 # convert -13481 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13482 # registers except esp clobbered at this point -13483 # restore ed -13484 89/<- %edx 4/r32/esp -13485 (flush _test-output-buffered-file) -13486 (flush _test-error-buffered-file) -13487 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13493 # check output -13494 (check-stream-equal _test-output-stream "" "F - test-length-with-non-array-compound-base-type: output should be empty") -13495 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is not an array" "F - test-length-with-non-array-compound-base-type: error message") -13496 # check that stop(1) was called -13497 (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status") -13498 # don't restore from ebp -13499 81 0/subop/add %esp 8/imm32 -13500 # . epilogue -13501 5d/pop-to-ebp -13502 c3/return -13503 -13504 test-length-with-non-array-compound-base-type-2: -13505 # . prologue -13506 55/push-ebp -13507 89/<- %ebp 4/r32/esp -13508 # setup -13509 (clear-stream _test-input-stream) -13510 (clear-stream $_test-input-buffered-file->buffer) -13511 (clear-stream _test-output-stream) -13512 (clear-stream $_test-output-buffered-file->buffer) -13513 (clear-stream _test-error-stream) -13514 (clear-stream $_test-error-buffered-file->buffer) -13515 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13516 68/push 0/imm32 -13517 68/push 0/imm32 -13518 89/<- %edx 4/r32/esp -13519 (tailor-exit-descriptor %edx 0x10) -13520 # -13521 (write _test-input-stream "fn foo {\n") -13522 (write _test-input-stream " var a: (addr int)\n") -13523 (write _test-input-stream " var c/ecx: (addr int) <- length a, 0\n") -13524 (write _test-input-stream "}\n") -13525 # convert -13526 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13527 # registers except esp clobbered at this point -13528 # restore ed -13529 89/<- %edx 4/r32/esp -13530 (flush _test-output-buffered-file) -13531 (flush _test-error-buffered-file) -13532 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13538 # check output -13539 (check-stream-equal _test-output-stream "" "F - test-length-with-non-array-compound-base-type-2: output should be empty") -13540 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is not an array" "F - test-length-with-non-array-compound-base-type-2: error message") -13541 # check that stop(1) was called -13542 (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status") -13543 # don't restore from ebp -13544 81 0/subop/add %esp 8/imm32 -13545 # . epilogue -13546 5d/pop-to-ebp -13547 c3/return -13548 -13549 test-length-with-array-atom-base-type: -13550 # . prologue -13551 55/push-ebp -13552 89/<- %ebp 4/r32/esp -13553 # setup -13554 (clear-stream _test-input-stream) -13555 (clear-stream $_test-input-buffered-file->buffer) -13556 (clear-stream _test-output-stream) -13557 (clear-stream $_test-output-buffered-file->buffer) -13558 (clear-stream _test-error-stream) -13559 (clear-stream $_test-error-buffered-file->buffer) -13560 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13561 68/push 0/imm32 -13562 68/push 0/imm32 -13563 89/<- %edx 4/r32/esp -13564 (tailor-exit-descriptor %edx 0x10) -13565 # -13566 (write _test-input-stream "fn foo {\n") -13567 (write _test-input-stream " var a: array\n") -13568 (write _test-input-stream " var c/ecx: (addr int) <- length a\n") -13569 (write _test-input-stream "}\n") -13570 # convert -13571 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13572 # registers except esp clobbered at this point -13573 # restore ed -13574 89/<- %edx 4/r32/esp -13575 (flush _test-output-buffered-file) -13576 (flush _test-error-buffered-file) -13577 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13583 # check output -13584 (check-stream-equal _test-output-stream "" "F - test-length-with-array-atom-base-type: output should be empty") -13585 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: array 'a' must specify the type of its elements" "F - test-length-with-array-atom-base-type: error message") -13586 # check that stop(1) was called -13587 (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status") -13588 # don't restore from ebp -13589 81 0/subop/add %esp 8/imm32 -13590 # . epilogue -13591 5d/pop-to-ebp -13592 c3/return -13593 -13594 test-length-with-addr-base-on-stack: -13595 # . prologue -13596 55/push-ebp -13597 89/<- %ebp 4/r32/esp -13598 # setup -13599 (clear-stream _test-input-stream) -13600 (clear-stream $_test-input-buffered-file->buffer) -13601 (clear-stream _test-output-stream) -13602 (clear-stream $_test-output-buffered-file->buffer) -13603 (clear-stream _test-error-stream) -13604 (clear-stream $_test-error-buffered-file->buffer) -13605 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13606 68/push 0/imm32 -13607 68/push 0/imm32 -13608 89/<- %edx 4/r32/esp -13609 (tailor-exit-descriptor %edx 0x10) -13610 # -13611 (write _test-input-stream "fn foo {\n") -13612 (write _test-input-stream " var a: (addr array int)\n") -13613 (write _test-input-stream " var c/ecx: (addr int) <- length a\n") -13614 (write _test-input-stream "}\n") -13615 # convert -13616 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13617 # registers except esp clobbered at this point -13618 # restore ed -13619 89/<- %edx 4/r32/esp -13620 (flush _test-output-buffered-file) -13621 (flush _test-error-buffered-file) -13622 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13628 # check output -13629 (check-stream-equal _test-output-stream "" "F - test-length-with-addr-base-on-stack: output should be empty") -13630 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is an addr to an array, and so must live in a register" "F - test-length-with-addr-base-on-stack: error message") -13631 # check that stop(1) was called -13632 (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status") -13633 # don't restore from ebp -13634 81 0/subop/add %esp 8/imm32 -13635 # . epilogue -13636 5d/pop-to-ebp -13637 c3/return -13638 -13639 test-length-with-wrong-output-type: -13640 # . prologue -13641 55/push-ebp -13642 89/<- %ebp 4/r32/esp -13643 # setup -13644 (clear-stream _test-input-stream) -13645 (clear-stream $_test-input-buffered-file->buffer) -13646 (clear-stream _test-output-stream) -13647 (clear-stream $_test-output-buffered-file->buffer) -13648 (clear-stream _test-error-stream) -13649 (clear-stream $_test-error-buffered-file->buffer) -13650 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13651 68/push 0/imm32 -13652 68/push 0/imm32 -13653 89/<- %edx 4/r32/esp -13654 (tailor-exit-descriptor %edx 0x10) -13655 # -13656 (write _test-input-stream "fn foo {\n") -13657 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") -13658 (write _test-input-stream " var o/edi: (addr int) <- length a\n") -13659 (write _test-input-stream "}\n") -13660 # convert -13661 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13662 # registers except esp clobbered at this point -13663 # restore ed -13664 89/<- %edx 4/r32/esp -13665 (flush _test-output-buffered-file) -13666 (flush _test-error-buffered-file) -13667 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13673 # check output -13674 (check-stream-equal _test-output-stream "" "F - test-length-with-wrong-output-type: output should be empty") -13675 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: output 'o' does not have the right type" "F - test-length-with-wrong-output-type: error message") -13676 # check that stop(1) was called -13677 (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status") -13678 # don't restore from ebp -13679 81 0/subop/add %esp 8/imm32 -13680 # . epilogue -13681 5d/pop-to-ebp -13682 c3/return -13683 -13684 test-length-with-wrong-output-compound-type: -13685 # . prologue -13686 55/push-ebp -13687 89/<- %ebp 4/r32/esp -13688 # setup -13689 (clear-stream _test-input-stream) -13690 (clear-stream $_test-input-buffered-file->buffer) -13691 (clear-stream _test-output-stream) -13692 (clear-stream $_test-output-buffered-file->buffer) -13693 (clear-stream _test-error-stream) -13694 (clear-stream $_test-error-buffered-file->buffer) -13695 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13696 68/push 0/imm32 -13697 68/push 0/imm32 -13698 89/<- %edx 4/r32/esp -13699 (tailor-exit-descriptor %edx 0x10) -13700 # -13701 (write _test-input-stream "fn foo {\n") -13702 (write _test-input-stream " var a/ebx: (addr array handle boolean) <- copy 0\n") -13703 (write _test-input-stream " var o/edi: (addr handle int) <- length a\n") -13704 (write _test-input-stream "}\n") -13705 # convert -13706 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13707 # registers except esp clobbered at this point -13708 # restore ed -13709 89/<- %edx 4/r32/esp -13710 (flush _test-output-buffered-file) -13711 (flush _test-error-buffered-file) -13712 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13718 # check output -13719 (check-stream-equal _test-output-stream "" "F - test-length-with-wrong-output-compound-type: output should be empty") -13720 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: output 'o' does not have the right type" "F - test-length-with-wrong-output-compound-type: error message") -13721 # check that stop(1) was called -13722 (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status") -13723 # don't restore from ebp -13724 81 0/subop/add %esp 8/imm32 -13725 # . epilogue -13726 5d/pop-to-ebp -13727 c3/return -13728 -13729 test-length-with-no-inouts: -13730 # . prologue -13731 55/push-ebp -13732 89/<- %ebp 4/r32/esp -13733 # setup -13734 (clear-stream _test-input-stream) -13735 (clear-stream $_test-input-buffered-file->buffer) -13736 (clear-stream _test-output-stream) -13737 (clear-stream $_test-output-buffered-file->buffer) -13738 (clear-stream _test-error-stream) -13739 (clear-stream $_test-error-buffered-file->buffer) -13740 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13741 68/push 0/imm32 -13742 68/push 0/imm32 -13743 89/<- %edx 4/r32/esp -13744 (tailor-exit-descriptor %edx 0x10) -13745 # -13746 (write _test-input-stream "fn foo {\n") -13747 (write _test-input-stream " var c/ecx: int <- length\n") -13748 (write _test-input-stream "}\n") -13749 # convert -13750 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13751 # registers except esp clobbered at this point -13752 # restore ed -13753 89/<- %edx 4/r32/esp -13754 (flush _test-output-buffered-file) -13755 (flush _test-error-buffered-file) -13756 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13762 # check output -13763 (check-stream-equal _test-output-stream "" "F - test-length-with-no-inouts: output should be empty") -13764 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: too few inouts (1 required)" "F - test-length-with-no-inouts: error message") -13765 # check that stop(1) was called -13766 (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status") -13767 # don't restore from ebp -13768 81 0/subop/add %esp 8/imm32 -13769 # . epilogue -13770 5d/pop-to-ebp -13771 c3/return -13772 -13773 test-length-with-too-many-inouts: -13774 # . prologue -13775 55/push-ebp -13776 89/<- %ebp 4/r32/esp -13777 # setup -13778 (clear-stream _test-input-stream) -13779 (clear-stream $_test-input-buffered-file->buffer) -13780 (clear-stream _test-output-stream) -13781 (clear-stream $_test-output-buffered-file->buffer) -13782 (clear-stream _test-error-stream) -13783 (clear-stream $_test-error-buffered-file->buffer) -13784 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13785 68/push 0/imm32 -13786 68/push 0/imm32 -13787 89/<- %edx 4/r32/esp -13788 (tailor-exit-descriptor %edx 0x10) -13789 # -13790 (write _test-input-stream "fn foo {\n") -13791 (write _test-input-stream " var a: (array int 3)\n") -13792 (write _test-input-stream " var c/ecx: int <- length a, 0, 0\n") -13793 (write _test-input-stream "}\n") -13794 # convert -13795 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13796 # registers except esp clobbered at this point -13797 # restore ed -13798 89/<- %edx 4/r32/esp -13799 (flush _test-output-buffered-file) -13800 (flush _test-error-buffered-file) -13801 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13807 # check output -13808 (check-stream-equal _test-output-stream "" "F - test-length-with-too-many-inouts: output should be empty") -13809 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: too many inouts (1 required)" "F - test-length-with-too-many-inouts: error message") -13810 # check that stop(1) was called -13811 (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status") -13812 # don't restore from ebp -13813 81 0/subop/add %esp 8/imm32 -13814 # . epilogue -13815 5d/pop-to-ebp -13816 c3/return -13817 -13818 test-length-with-no-output: -13819 # . prologue -13820 55/push-ebp -13821 89/<- %ebp 4/r32/esp -13822 # setup -13823 (clear-stream _test-input-stream) -13824 (clear-stream $_test-input-buffered-file->buffer) -13825 (clear-stream _test-output-stream) -13826 (clear-stream $_test-output-buffered-file->buffer) -13827 (clear-stream _test-error-stream) -13828 (clear-stream $_test-error-buffered-file->buffer) -13829 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13830 68/push 0/imm32 -13831 68/push 0/imm32 -13832 89/<- %edx 4/r32/esp -13833 (tailor-exit-descriptor %edx 0x10) -13834 # -13835 (write _test-input-stream "fn foo {\n") -13836 (write _test-input-stream " var a: (array int 3)\n") -13837 (write _test-input-stream " length a\n") -13838 (write _test-input-stream "}\n") -13839 # convert -13840 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13841 # registers except esp clobbered at this point -13842 # restore ed -13843 89/<- %edx 4/r32/esp -13844 (flush _test-output-buffered-file) -13845 (flush _test-error-buffered-file) -13846 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13852 # check output -13853 (check-stream-equal _test-output-stream "" "F - test-length-with-no-output: output should be empty") -13854 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: must have an output" "F - test-length-with-no-output: error message") -13855 # check that stop(1) was called -13856 (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status") -13857 # don't restore from ebp -13858 81 0/subop/add %esp 8/imm32 -13859 # . epilogue -13860 5d/pop-to-ebp -13861 c3/return -13862 -13863 test-length-with-too-many-outputs: -13864 # . prologue -13865 55/push-ebp -13866 89/<- %ebp 4/r32/esp -13867 # setup -13868 (clear-stream _test-input-stream) -13869 (clear-stream $_test-input-buffered-file->buffer) -13870 (clear-stream _test-output-stream) -13871 (clear-stream $_test-output-buffered-file->buffer) -13872 (clear-stream _test-error-stream) -13873 (clear-stream $_test-error-buffered-file->buffer) -13874 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -13875 68/push 0/imm32 -13876 68/push 0/imm32 -13877 89/<- %edx 4/r32/esp -13878 (tailor-exit-descriptor %edx 0x10) -13879 # -13880 (write _test-input-stream "fn foo {\n") -13881 (write _test-input-stream " var a: (array int 3)\n") -13882 (write _test-input-stream " var b/eax: int <- copy 0\n") -13883 (write _test-input-stream " var c/ecx: int <- copy 0\n") -13884 (write _test-input-stream " b, c <- length a\n") -13885 (write _test-input-stream "}\n") -13886 # convert -13887 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -13888 # registers except esp clobbered at this point -13889 # restore ed -13890 89/<- %edx 4/r32/esp -13891 (flush _test-output-buffered-file) -13892 (flush _test-error-buffered-file) -13893 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -13899 # check output -13900 (check-stream-equal _test-output-stream "" "F - test-length-with-too-many-outputs: output should be empty") -13901 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: too many outputs (1 required)" "F - test-length-with-too-many-outputs: error message") -13902 # check that stop(1) was called -13903 (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status") -13904 # don't restore from ebp -13905 81 0/subop/add %esp 8/imm32 -13906 # . epilogue -13907 5d/pop-to-ebp -13908 c3/return -13909 -13910 test-convert-function-with-return-register-and-local: -13911 # . prologue -13912 55/push-ebp -13913 89/<- %ebp 4/r32/esp -13914 # setup -13915 (clear-stream _test-input-stream) -13916 (clear-stream $_test-input-buffered-file->buffer) -13917 (clear-stream _test-output-stream) -13918 (clear-stream $_test-output-buffered-file->buffer) -13919 # -13920 (write _test-input-stream "fn foo -> _/eax: int {\n") -13921 (write _test-input-stream " var y/eax: int <- copy 3\n") -13922 (write _test-input-stream " var z/ecx: int <- copy 4\n") -13923 (write _test-input-stream " return y\n") -13924 (write _test-input-stream "}\n") -13925 # convert -13926 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -13927 (flush _test-output-buffered-file) -13928 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -13934 # check output -13935 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-register-and-local/0") -13936 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-register-and-local/1") -13937 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-register-and-local/2") -13938 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-register-and-local/3") -13939 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-register-and-local/4") -13940 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-register-and-local/5") -13941 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-return-register-and-local/6") -13942 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 3/imm32" "F - test-convert-function-with-return-register-and-local/7") -13943 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-return-register-and-local/8") -13944 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-convert-function-with-return-register-and-local/9") -13945 (check-next-stream-line-equal _test-output-stream " 8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10") -13946 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-return-register-and-local/11") -13947 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-function-with-return-register-and-local/12") -13948 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-register-and-local/13") -13949 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-register-and-local/14") -13950 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-register-and-local/15") -13951 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-register-and-local/16") -13952 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-register-and-local/17") -13953 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-register-and-local/18") -13954 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-register-and-local/19") -13955 # . epilogue -13956 89/<- %esp 5/r32/ebp -13957 5d/pop-to-ebp -13958 c3/return -13959 -13960 test-convert-function-with-return-register-and-local-2: -13961 # . prologue -13962 55/push-ebp -13963 89/<- %ebp 4/r32/esp -13964 # setup -13965 (clear-stream _test-input-stream) -13966 (clear-stream $_test-input-buffered-file->buffer) -13967 (clear-stream _test-output-stream) -13968 (clear-stream $_test-output-buffered-file->buffer) -13969 # -13970 (write _test-input-stream "fn foo -> _/eax: int {\n") -13971 (write _test-input-stream " var y/eax: int <- copy 3\n") -13972 (write _test-input-stream " var z/ecx: int <- copy 4\n") -13973 (write _test-input-stream " return z\n") -13974 (write _test-input-stream "}\n") -13975 # convert -13976 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -13977 (flush _test-output-buffered-file) -13978 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -13984 # check output -13985 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-register-and-local-2/0") -13986 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-register-and-local-2/1") -13987 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-register-and-local-2/2") -13988 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-register-and-local-2/3") -13989 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-register-and-local-2/4") -13990 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-register-and-local-2/5") -13991 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-return-register-and-local-2/6") -13992 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 3/imm32" "F - test-convert-function-with-return-register-and-local-2/7") -13993 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-return-register-and-local-2/8") -13994 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-convert-function-with-return-register-and-local-2/9") -13995 (check-next-stream-line-equal _test-output-stream " 8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10") -13996 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-return-register-and-local-2/11") -13997 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-function-with-return-register-and-local-2/12") -13998 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-register-and-local-2/13") -13999 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-register-and-local-2/14") -14000 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-register-and-local-2/15") -14001 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-register-and-local-2/16") -14002 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-register-and-local-2/17") -14003 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-register-and-local-2/18") -14004 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-register-and-local-2/19") -14005 # . epilogue -14006 89/<- %esp 5/r32/ebp -14007 5d/pop-to-ebp -14008 c3/return -14009 -14010 test-convert-function-with-return-float-register-and-local: -14011 # . prologue -14012 55/push-ebp -14013 89/<- %ebp 4/r32/esp -14014 # setup -14015 (clear-stream _test-input-stream) -14016 (clear-stream $_test-input-buffered-file->buffer) -14017 (clear-stream _test-output-stream) -14018 (clear-stream $_test-output-buffered-file->buffer) -14019 # -14020 (write _test-input-stream "fn foo -> _/xmm1: float {\n") -14021 (write _test-input-stream " var y/eax: int <- copy 3\n") -14022 (write _test-input-stream " var g/xmm0: float <- convert y\n") -14023 (write _test-input-stream " var h/xmm1: float <- convert y\n") -14024 (write _test-input-stream " return g\n") -14025 (write _test-input-stream "}\n") -14026 # convert -14027 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -14028 (flush _test-output-buffered-file) -14029 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -14035 # check output -14036 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-float-register-and-local/0") -14037 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-float-register-and-local/1") -14038 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-float-register-and-local/2") -14039 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-float-register-and-local/3") -14040 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-float-register-and-local/4") -14041 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-float-register-and-local/5") -14042 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-return-float-register-and-local/6") # var y -14043 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 3/imm32" "F - test-convert-function-with-return-float-register-and-local/7") -14044 (check-next-stream-line-equal _test-output-stream " 81 5/subop/subtract %esp 4/imm32" "F - test-convert-function-with-return-float-register-and-local/8") # var g -14045 (check-next-stream-line-equal _test-output-stream " f3 0f 11/<- *esp 0/x32" "F - test-convert-function-with-return-float-register-and-local/9") -14046 (check-next-stream-line-equal _test-output-stream " f3 0f 2a/convert-to-float %eax 0x00000000/x32" "F - test-convert-function-with-return-float-register-and-local/10") -14047 (check-next-stream-line-equal _test-output-stream " 81 5/subop/subtract %esp 4/imm32" "F - test-convert-function-with-return-float-register-and-local/11") # var h -14048 (check-next-stream-line-equal _test-output-stream " f3 0f 11/<- *esp 1/x32" "F - test-convert-function-with-return-float-register-and-local/12") -14049 (check-next-stream-line-equal _test-output-stream " f3 0f 2a/convert-to-float %eax 0x00000001/x32" "F - test-convert-function-with-return-float-register-and-local/13") -14050 (check-next-stream-line-equal _test-output-stream " f3 0f 10/-> %xmm0 0x00000001/x32" "F - test-convert-function-with-return-float-register-and-local/14") # return g -14051 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-floating-point-dereferenced/15") # reclaim h -14052 (check-next-stream-line-equal _test-output-stream " f3 0f 10/-> *esp 0/x32" "F - test-convert-floating-point-dereferenced/16") # reclaim g -14053 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-floating-point-dereferenced/17") -14054 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-return-float-register-and-local/18") # reclaim y -14055 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-float-register-and-local/19") -14056 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-float-register-and-local/20") -14057 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-float-register-and-local/21") -14058 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-float-register-and-local/22") -14059 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-float-register-and-local/23") -14060 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-float-register-and-local/24") -14061 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-float-register-and-local/25") -14062 # . epilogue -14063 89/<- %esp 5/r32/ebp -14064 5d/pop-to-ebp -14065 c3/return -14066 -14067 test-convert-function-with-return-and-local-vars: -14068 # . prologue -14069 55/push-ebp -14070 89/<- %ebp 4/r32/esp -14071 # setup -14072 (clear-stream _test-input-stream) -14073 (clear-stream $_test-input-buffered-file->buffer) -14074 (clear-stream _test-output-stream) -14075 (clear-stream $_test-output-buffered-file->buffer) -14076 # -14077 (write _test-input-stream "fn foo -> _/eax: int {\n") -14078 (write _test-input-stream " {\n") -14079 (write _test-input-stream " var x: int\n") -14080 (write _test-input-stream " {\n") -14081 (write _test-input-stream " var y: int\n") -14082 (write _test-input-stream " return y\n") -14083 (write _test-input-stream " increment x\n") -14084 (write _test-input-stream " }\n") -14085 (write _test-input-stream " }\n") -14086 (write _test-input-stream " return 0\n") -14087 (write _test-input-stream "}\n") -14088 # convert -14089 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -14090 (flush _test-output-buffered-file) -14091 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -14097 # check output -14098 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-and-local-vars/0") -14099 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-and-local-vars/1") -14100 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-and-local-vars/2") -14101 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-and-local-vars/3") -14102 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-and-local-vars/4") -14103 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-and-local-vars/5") -14104 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-and-local-vars/6") -14105 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-return-and-local-vars/7") -14106 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/8") # var x -14107 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-and-local-vars/9") -14108 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-return-and-local-vars/10") -14109 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11") # var y -14110 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12") -14111 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-return-and-local-vars/13") -14112 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-return-and-local-vars/14") -14113 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-and-local-vars/15") -14114 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-and-local-vars/16") -14115 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-return-and-local-vars/17") -14116 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-return-and-local-vars/18") -14117 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-and-local-vars/19") -14118 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-return-and-local-vars/20") -14119 (check-next-stream-line-equal _test-output-stream " c7 0/subop/copy %eax 0/imm32" "F - test-convert-function-with-return-and-local-vars/21") -14120 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-and-local-vars/21") -14121 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-and-local-vars/21") -14122 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-and-local-vars/22") -14123 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-and-local-vars/23") -14124 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-and-local-vars/24") -14125 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-and-local-vars/25") -14126 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-and-local-vars/26") -14127 # . epilogue -14128 89/<- %esp 5/r32/ebp -14129 5d/pop-to-ebp -14130 c3/return -14131 -14132 test-copy-object-with-no-inout: -14133 # . prologue -14134 55/push-ebp -14135 89/<- %ebp 4/r32/esp -14136 # setup -14137 (clear-stream _test-input-stream) -14138 (clear-stream $_test-input-buffered-file->buffer) -14139 (clear-stream _test-output-stream) -14140 (clear-stream $_test-output-buffered-file->buffer) -14141 (clear-stream _test-error-stream) -14142 (clear-stream $_test-error-buffered-file->buffer) -14143 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14144 68/push 0/imm32 -14145 68/push 0/imm32 -14146 89/<- %edx 4/r32/esp -14147 (tailor-exit-descriptor %edx 0x10) -14148 # -14149 (write _test-input-stream "fn foo {\n") -14150 (write _test-input-stream " copy-object\n") -14151 (write _test-input-stream "}\n") -14152 # convert -14153 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14154 # registers except esp clobbered at this point -14155 # restore ed -14156 89/<- %edx 4/r32/esp -14157 (flush _test-output-buffered-file) -14158 (flush _test-error-buffered-file) -14159 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14165 # check output -14166 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-no-inout: output should be empty") -14167 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must have two inouts" "F - test-copy-object-with-no-inout: error message") -14168 # check that stop(1) was called -14169 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status") -14170 # don't restore from ebp -14171 81 0/subop/add %esp 8/imm32 -14172 # . epilogue -14173 5d/pop-to-ebp -14174 c3/return -14175 -14176 test-copy-object-with-no-source: -14177 # . prologue -14178 55/push-ebp -14179 89/<- %ebp 4/r32/esp -14180 # setup -14181 (clear-stream _test-input-stream) -14182 (clear-stream $_test-input-buffered-file->buffer) -14183 (clear-stream _test-output-stream) -14184 (clear-stream $_test-output-buffered-file->buffer) -14185 (clear-stream _test-error-stream) -14186 (clear-stream $_test-error-buffered-file->buffer) -14187 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14188 68/push 0/imm32 -14189 68/push 0/imm32 -14190 89/<- %edx 4/r32/esp -14191 (tailor-exit-descriptor %edx 0x10) -14192 # -14193 (write _test-input-stream "fn foo {\n") -14194 (write _test-input-stream " var x: (addr int)\n") -14195 (write _test-input-stream " copy-object x\n") -14196 (write _test-input-stream "}\n") -14197 # convert -14198 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14199 # registers except esp clobbered at this point -14200 # restore ed -14201 89/<- %edx 4/r32/esp -14202 (flush _test-output-buffered-file) -14203 (flush _test-error-buffered-file) -14204 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14210 # check output -14211 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-no-source: output should be empty") -14212 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must have two inouts" "F - test-copy-object-with-no-source: error message") -14213 # check that stop(1) was called -14214 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status") -14215 # don't restore from ebp -14216 81 0/subop/add %esp 8/imm32 -14217 # . epilogue -14218 5d/pop-to-ebp -14219 c3/return -14220 -14221 test-copy-object-with-too-many-inouts: -14222 # . prologue -14223 55/push-ebp -14224 89/<- %ebp 4/r32/esp -14225 # setup -14226 (clear-stream _test-input-stream) -14227 (clear-stream $_test-input-buffered-file->buffer) -14228 (clear-stream _test-output-stream) -14229 (clear-stream $_test-output-buffered-file->buffer) -14230 (clear-stream _test-error-stream) -14231 (clear-stream $_test-error-buffered-file->buffer) -14232 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14233 68/push 0/imm32 -14234 68/push 0/imm32 -14235 89/<- %edx 4/r32/esp -14236 (tailor-exit-descriptor %edx 0x10) -14237 # -14238 (write _test-input-stream "fn foo {\n") -14239 (write _test-input-stream " var x: (addr boolean)\n") -14240 (write _test-input-stream " copy-object x, x, x\n") -14241 (write _test-input-stream "}\n") -14242 # convert -14243 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14244 # registers except esp clobbered at this point -14245 # restore ed -14246 89/<- %edx 4/r32/esp -14247 (flush _test-output-buffered-file) -14248 (flush _test-error-buffered-file) -14249 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14255 # check output -14256 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-too-many-inouts: output should be empty") -14257 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must have two inouts" "F - test-copy-object-with-too-many-inouts: error message") -14258 # check that stop(1) was called -14259 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status") -14260 # don't restore from ebp -14261 81 0/subop/add %esp 8/imm32 -14262 # . epilogue -14263 5d/pop-to-ebp -14264 c3/return -14265 -14266 test-copy-object-with-output: -14267 # . prologue -14268 55/push-ebp -14269 89/<- %ebp 4/r32/esp -14270 # setup -14271 (clear-stream _test-input-stream) -14272 (clear-stream $_test-input-buffered-file->buffer) -14273 (clear-stream _test-output-stream) -14274 (clear-stream $_test-output-buffered-file->buffer) -14275 (clear-stream _test-error-stream) -14276 (clear-stream $_test-error-buffered-file->buffer) -14277 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14278 68/push 0/imm32 -14279 68/push 0/imm32 -14280 89/<- %edx 4/r32/esp -14281 (tailor-exit-descriptor %edx 0x10) -14282 # -14283 (write _test-input-stream "fn foo {\n") -14284 (write _test-input-stream " var x/eax: (addr boolean) <- copy 0\n") -14285 (write _test-input-stream " var y/ecx: (addr boolean) <- copy 0\n") -14286 (write _test-input-stream " x <- copy-object x, y\n") -14287 (write _test-input-stream "}\n") -14288 # convert -14289 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14290 # registers except esp clobbered at this point -14291 # restore ed -14292 89/<- %edx 4/r32/esp -14293 (flush _test-output-buffered-file) -14294 (flush _test-error-buffered-file) -14295 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14301 # check output -14302 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-output: output should be empty") -14303 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must not have any outputs" "F - test-copy-object-with-output: error message") -14304 # check that stop(1) was called -14305 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status") -14306 # don't restore from ebp -14307 81 0/subop/add %esp 8/imm32 -14308 # . epilogue -14309 5d/pop-to-ebp -14310 c3/return -14311 -14312 test-copy-object-deref-address: -14313 # . prologue -14314 55/push-ebp -14315 89/<- %ebp 4/r32/esp -14316 # setup -14317 (clear-stream _test-input-stream) -14318 (clear-stream $_test-input-buffered-file->buffer) -14319 (clear-stream _test-output-stream) -14320 (clear-stream $_test-output-buffered-file->buffer) -14321 # -14322 (write _test-input-stream "fn foo {\n") -14323 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") -14324 (write _test-input-stream " var y/ecx: (addr addr int) <- copy 0\n") -14325 (write _test-input-stream " copy-object *y, x\n") -14326 (write _test-input-stream "}\n") -14327 # convert -14328 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -14329 (flush _test-output-buffered-file) -14330 # no errors -14331 # . epilogue -14332 5d/pop-to-ebp -14333 c3/return -14334 -14335 test-copy-object-non-addr: -14336 # . prologue -14337 55/push-ebp -14338 89/<- %ebp 4/r32/esp -14339 # setup -14340 (clear-stream _test-input-stream) -14341 (clear-stream $_test-input-buffered-file->buffer) -14342 (clear-stream _test-output-stream) -14343 (clear-stream $_test-output-buffered-file->buffer) -14344 (clear-stream _test-error-stream) -14345 (clear-stream $_test-error-buffered-file->buffer) -14346 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14347 68/push 0/imm32 -14348 68/push 0/imm32 -14349 89/<- %edx 4/r32/esp -14350 (tailor-exit-descriptor %edx 0x10) -14351 # -14352 (write _test-input-stream "fn foo {\n") -14353 (write _test-input-stream " var x: int\n") -14354 (write _test-input-stream " var y: int\n") -14355 (write _test-input-stream " copy-object y, x\n") -14356 (write _test-input-stream "}\n") -14357 # convert -14358 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14359 # registers except esp clobbered at this point -14360 # restore ed -14361 89/<- %edx 4/r32/esp -14362 (flush _test-output-buffered-file) -14363 (flush _test-error-buffered-file) -14364 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14370 # check output -14371 (check-stream-equal _test-output-stream "" "F - test-copy-object-non-addr: output should be empty") -14372 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-object: two inouts with identical addr types expected" "F - test-copy-object-non-addr: error message") -14373 # check that stop(1) was called -14374 (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status") -14375 # don't restore from ebp -14376 81 0/subop/add %esp 8/imm32 -14377 # . epilogue -14378 5d/pop-to-ebp -14379 c3/return -14380 -14381 test-copy-object-non-equal: -14382 # . prologue -14383 55/push-ebp -14384 89/<- %ebp 4/r32/esp -14385 # setup -14386 (clear-stream _test-input-stream) -14387 (clear-stream $_test-input-buffered-file->buffer) -14388 (clear-stream _test-output-stream) -14389 (clear-stream $_test-output-buffered-file->buffer) -14390 (clear-stream _test-error-stream) -14391 (clear-stream $_test-error-buffered-file->buffer) -14392 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14393 68/push 0/imm32 -14394 68/push 0/imm32 -14395 89/<- %edx 4/r32/esp -14396 (tailor-exit-descriptor %edx 0x10) -14397 # -14398 (write _test-input-stream "fn foo {\n") -14399 (write _test-input-stream " var x: (addr int)\n") -14400 (write _test-input-stream " var y: (addr boolean)\n") -14401 (write _test-input-stream " copy-object y, x\n") -14402 (write _test-input-stream "}\n") -14403 # convert -14404 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14405 # registers except esp clobbered at this point -14406 # restore ed -14407 89/<- %edx 4/r32/esp -14408 (flush _test-output-buffered-file) -14409 (flush _test-error-buffered-file) -14410 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14416 # check output -14417 (check-stream-equal _test-output-stream "" "F - test-copy-object-non-equal: output should be empty") -14418 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-object: two inouts with identical addr types expected" "F - test-copy-object-non-equal: error message") -14419 # check that stop(1) was called -14420 (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status") -14421 # don't restore from ebp -14422 81 0/subop/add %esp 8/imm32 -14423 # . epilogue -14424 5d/pop-to-ebp -14425 c3/return -14426 -14427 test-allocate-with-no-inout: -14428 # . prologue -14429 55/push-ebp -14430 89/<- %ebp 4/r32/esp -14431 # setup -14432 (clear-stream _test-input-stream) -14433 (clear-stream $_test-input-buffered-file->buffer) -14434 (clear-stream _test-output-stream) -14435 (clear-stream $_test-output-buffered-file->buffer) -14436 (clear-stream _test-error-stream) -14437 (clear-stream $_test-error-buffered-file->buffer) -14438 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14439 68/push 0/imm32 -14440 68/push 0/imm32 -14441 89/<- %edx 4/r32/esp -14442 (tailor-exit-descriptor %edx 0x10) -14443 # -14444 (write _test-input-stream "fn foo {\n") -14445 (write _test-input-stream " allocate\n") -14446 (write _test-input-stream "}\n") -14447 # convert -14448 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14449 # registers except esp clobbered at this point -14450 # restore ed -14451 89/<- %edx 4/r32/esp -14452 (flush _test-output-buffered-file) -14453 (flush _test-error-buffered-file) -14454 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14460 # check output -14461 (check-stream-equal _test-output-stream "" "F - test-allocate-with-no-inout: output should be empty") -14462 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'allocate' must have a single inout" "F - test-allocate-with-no-inout: error message") -14463 # check that stop(1) was called -14464 (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status") -14465 # don't restore from ebp -14466 81 0/subop/add %esp 8/imm32 -14467 # . epilogue -14468 5d/pop-to-ebp -14469 c3/return -14470 -14471 test-allocate-with-too-many-inouts: -14472 # . prologue -14473 55/push-ebp -14474 89/<- %ebp 4/r32/esp -14475 # setup -14476 (clear-stream _test-input-stream) -14477 (clear-stream $_test-input-buffered-file->buffer) -14478 (clear-stream _test-output-stream) -14479 (clear-stream $_test-output-buffered-file->buffer) -14480 (clear-stream _test-error-stream) -14481 (clear-stream $_test-error-buffered-file->buffer) -14482 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14483 68/push 0/imm32 -14484 68/push 0/imm32 -14485 89/<- %edx 4/r32/esp -14486 (tailor-exit-descriptor %edx 0x10) -14487 # -14488 (write _test-input-stream "fn foo {\n") -14489 (write _test-input-stream " var x: (addr handle int)\n") -14490 (write _test-input-stream " allocate x, 0\n") -14491 (write _test-input-stream "}\n") -14492 # convert -14493 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14494 # registers except esp clobbered at this point -14495 # restore ed -14496 89/<- %edx 4/r32/esp -14497 (flush _test-output-buffered-file) -14498 (flush _test-error-buffered-file) -14499 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14505 # check output -14506 (check-stream-equal _test-output-stream "" "F - test-allocate-with-too-many-inouts: output should be empty") -14507 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'allocate' must have a single inout" "F - test-allocate-with-too-many-inouts: error message") -14508 # check that stop(1) was called -14509 (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status") -14510 # don't restore from ebp -14511 81 0/subop/add %esp 8/imm32 -14512 # . epilogue -14513 5d/pop-to-ebp -14514 c3/return -14515 -14516 test-allocate-with-output: -14517 # . prologue -14518 55/push-ebp -14519 89/<- %ebp 4/r32/esp -14520 # setup -14521 (clear-stream _test-input-stream) -14522 (clear-stream $_test-input-buffered-file->buffer) -14523 (clear-stream _test-output-stream) -14524 (clear-stream $_test-output-buffered-file->buffer) -14525 (clear-stream _test-error-stream) -14526 (clear-stream $_test-error-buffered-file->buffer) -14527 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14528 68/push 0/imm32 -14529 68/push 0/imm32 -14530 89/<- %edx 4/r32/esp -14531 (tailor-exit-descriptor %edx 0x10) -14532 # -14533 (write _test-input-stream "fn foo {\n") -14534 (write _test-input-stream " var x/eax: boolean <- copy 0\n") -14535 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") -14536 (write _test-input-stream " x <- allocate y\n") -14537 (write _test-input-stream "}\n") -14538 # convert -14539 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14540 # registers except esp clobbered at this point -14541 # restore ed -14542 89/<- %edx 4/r32/esp -14543 (flush _test-output-buffered-file) -14544 (flush _test-error-buffered-file) -14545 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14551 # check output -14552 (check-stream-equal _test-output-stream "" "F - test-allocate-with-output: output should be empty") -14553 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'allocate' must not have any outputs" "F - test-allocate-with-output: error message") -14554 # check that stop(1) was called -14555 (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status") -14556 # don't restore from ebp -14557 81 0/subop/add %esp 8/imm32 -14558 # . epilogue -14559 5d/pop-to-ebp -14560 c3/return -14561 -14562 test-allocate-non-addr: -14563 # . prologue -14564 55/push-ebp -14565 89/<- %ebp 4/r32/esp -14566 # setup -14567 (clear-stream _test-input-stream) -14568 (clear-stream $_test-input-buffered-file->buffer) -14569 (clear-stream _test-output-stream) -14570 (clear-stream $_test-output-buffered-file->buffer) -14571 (clear-stream _test-error-stream) -14572 (clear-stream $_test-error-buffered-file->buffer) -14573 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14574 68/push 0/imm32 -14575 68/push 0/imm32 -14576 89/<- %edx 4/r32/esp -14577 (tailor-exit-descriptor %edx 0x10) -14578 # -14579 (write _test-input-stream "fn foo {\n") -14580 (write _test-input-stream " var y: (handle int)\n") -14581 (write _test-input-stream " allocate y\n") -14582 (write _test-input-stream "}\n") -14583 # convert -14584 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14585 # registers except esp clobbered at this point -14586 # restore ed -14587 89/<- %edx 4/r32/esp -14588 (flush _test-output-buffered-file) -14589 (flush _test-error-buffered-file) -14590 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14596 # check output -14597 (check-stream-equal _test-output-stream "" "F - test-allocate-non-addr: output must be empty") -14598 (check-next-stream-line-equal _test-error-stream "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)" "F - test-allocate-non-addr: error message") -14599 # check that stop(1) was called -14600 (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status") -14601 # don't restore from ebp -14602 81 0/subop/add %esp 8/imm32 -14603 # . epilogue -14604 5d/pop-to-ebp -14605 c3/return -14606 -14607 test-allocate-non-addr-handle: -14608 # . prologue -14609 55/push-ebp -14610 89/<- %ebp 4/r32/esp -14611 # setup -14612 (clear-stream _test-input-stream) -14613 (clear-stream $_test-input-buffered-file->buffer) -14614 (clear-stream _test-output-stream) -14615 (clear-stream $_test-output-buffered-file->buffer) -14616 (clear-stream _test-error-stream) -14617 (clear-stream $_test-error-buffered-file->buffer) -14618 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14619 68/push 0/imm32 -14620 68/push 0/imm32 -14621 89/<- %edx 4/r32/esp -14622 (tailor-exit-descriptor %edx 0x10) -14623 # -14624 (write _test-input-stream "fn foo {\n") -14625 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") -14626 (write _test-input-stream " allocate y\n") -14627 (write _test-input-stream "}\n") -14628 # convert -14629 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14630 # registers except esp clobbered at this point -14631 # restore ed -14632 89/<- %edx 4/r32/esp -14633 (flush _test-output-buffered-file) -14634 (flush _test-error-buffered-file) -14635 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14641 # check output -14642 (check-stream-equal _test-output-stream "" "F - test-allocate-non-addr-handle: output should be empty") -14643 (check-next-stream-line-equal _test-error-stream "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)" "F - test-allocate-non-addr-handle: error message") -14644 # check that stop(1) was called -14645 (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status") -14646 # don't restore from ebp -14647 81 0/subop/add %esp 8/imm32 -14648 # . epilogue -14649 5d/pop-to-ebp -14650 c3/return -14651 -14652 test-allocate-deref-address: -14653 # . prologue -14654 55/push-ebp -14655 89/<- %ebp 4/r32/esp -14656 # setup -14657 (clear-stream _test-input-stream) -14658 (clear-stream $_test-input-buffered-file->buffer) -14659 (clear-stream _test-output-stream) -14660 (clear-stream $_test-output-buffered-file->buffer) -14661 # -14662 (write _test-input-stream "fn foo {\n") -14663 (write _test-input-stream " var y/ecx: (addr addr handle int) <- copy 0\n") -14664 (write _test-input-stream " allocate *y\n") -14665 (write _test-input-stream "}\n") -14666 # convert -14667 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -14668 (flush _test-output-buffered-file) -14669 # no errors + 6312 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array/11") + 6313 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array/12") + 6314 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/13") + 6315 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/14") + 6316 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/15") + 6317 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/16") + 6318 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/17") + 6319 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/18") + 6320 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/19") + 6321 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/20") + 6322 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/21") + 6323 # . epilogue + 6324 89/<- %esp 5/r32/ebp + 6325 5d/pop-to-ebp + 6326 c3/return + 6327 + 6328 test-convert-index-into-array-of-bytes: + 6329 # . prologue + 6330 55/push-ebp + 6331 89/<- %ebp 4/r32/esp + 6332 # setup + 6333 (clear-stream _test-input-stream) + 6334 (clear-stream $_test-input-buffered-file->buffer) + 6335 (clear-stream _test-output-stream) + 6336 (clear-stream $_test-output-buffered-file->buffer) + 6337 # + 6338 (write _test-input-stream "fn foo {\n") + 6339 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") + 6340 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 6341 (write _test-input-stream " var x/eax: (addr byte) <- index arr, idx\n") + 6342 (write _test-input-stream "}\n") + 6343 # convert + 6344 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6345 (flush _test-output-buffered-file) + 6346 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6352 # check output + 6353 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes/0") + 6354 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes/1") + 6355 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes/2") + 6356 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes/3") + 6357 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes/4") + 6358 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes/5") + 6359 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes/6") + 6360 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes/7") + 6361 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes/8") + 6362 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-of-bytes/9") + 6363 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes/10") + 6364 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-of-bytes/11") + 6365 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-of-bytes/12") + 6366 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes/13") + 6367 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes/14") + 6368 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes/15") + 6369 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes/16") + 6370 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes/17") + 6371 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes/18") + 6372 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes/19") + 6373 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes/20") + 6374 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes/21") + 6375 # . epilogue + 6376 89/<- %esp 5/r32/ebp + 6377 5d/pop-to-ebp + 6378 c3/return + 6379 + 6380 test-convert-index-into-array-with-literal: + 6381 # . prologue + 6382 55/push-ebp + 6383 89/<- %ebp 4/r32/esp + 6384 # setup + 6385 (clear-stream _test-input-stream) + 6386 (clear-stream $_test-input-buffered-file->buffer) + 6387 (clear-stream _test-output-stream) + 6388 (clear-stream $_test-output-buffered-file->buffer) + 6389 # + 6390 (write _test-input-stream "fn foo {\n") + 6391 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 6392 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") + 6393 (write _test-input-stream "}\n") + 6394 # convert + 6395 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6396 (flush _test-output-buffered-file) + 6397 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6403 # check output + 6404 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-with-literal/0") + 6405 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-with-literal/1") + 6406 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-with-literal/2") + 6407 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-with-literal/3") + 6408 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-with-literal/4") + 6409 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5") + 6410 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6") + 6411 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7") + 6412 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-with-literal/8") + 6413 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-with-literal/9") + 6414 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-with-literal/10") + 6415 # 2 * 4 bytes/elem + 4 bytes for size = offset 12 + 6416 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/11") + 6417 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/12") + 6418 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/13") + 6419 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/14") + 6420 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/15") + 6421 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/16") + 6422 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/17") + 6423 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/18") + 6424 # . epilogue + 6425 89/<- %esp 5/r32/ebp + 6426 5d/pop-to-ebp + 6427 c3/return + 6428 + 6429 test-convert-index-into-array-of-bytes-with-literal: + 6430 # . prologue + 6431 55/push-ebp + 6432 89/<- %ebp 4/r32/esp + 6433 # setup + 6434 (clear-stream _test-input-stream) + 6435 (clear-stream $_test-input-buffered-file->buffer) + 6436 (clear-stream _test-output-stream) + 6437 (clear-stream $_test-output-buffered-file->buffer) + 6438 # + 6439 (write _test-input-stream "fn foo {\n") + 6440 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") + 6441 (write _test-input-stream " var x/eax: (addr byte) <- index arr, 2\n") + 6442 (write _test-input-stream "}\n") + 6443 # convert + 6444 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6445 (flush _test-output-buffered-file) + 6446 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6452 # check output + 6453 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-with-literal/0") + 6454 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-with-literal/1") + 6455 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-with-literal/2") + 6456 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-with-literal/3") + 6457 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-with-literal/4") + 6458 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-with-literal/5") + 6459 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-with-literal/6") + 6460 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-with-literal/7") + 6461 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-with-literal/8") + 6462 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-of-bytes-with-literal/9") + 6463 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-of-bytes-with-literal/10") + 6464 # 2 * 1 byte/elem + 4 bytes for size = offset 6 + 6465 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000006) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-with-literal/11") + 6466 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-with-literal/12") + 6467 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-with-literal/13") + 6468 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-with-literal/14") + 6469 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-with-literal/15") + 6470 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-with-literal/16") + 6471 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-with-literal/17") + 6472 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-with-literal/18") + 6473 # . epilogue + 6474 89/<- %esp 5/r32/ebp + 6475 5d/pop-to-ebp + 6476 c3/return + 6477 + 6478 test-convert-index-into-array-on-stack: + 6479 # . prologue + 6480 55/push-ebp + 6481 89/<- %ebp 4/r32/esp + 6482 # setup + 6483 (clear-stream _test-input-stream) + 6484 (clear-stream $_test-input-buffered-file->buffer) + 6485 (clear-stream _test-output-stream) + 6486 (clear-stream $_test-output-buffered-file->buffer) + 6487 # + 6488 (write _test-input-stream "fn foo {\n") + 6489 (write _test-input-stream " var arr: (array int 3)\n") + 6490 (write _test-input-stream " var idx/eax: int <- copy 2\n") + 6491 (write _test-input-stream " var x/eax: (addr int) <- index arr, idx\n") + 6492 (write _test-input-stream "}\n") + 6493 # convert + 6494 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6495 (flush _test-output-buffered-file) + 6496 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6502 # check output + 6503 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack/0") + 6504 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack/1") + 6505 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack/2") + 6506 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack/3") + 6507 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack/4") + 6508 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack/5") + 6509 # var arr + 6510 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack/6") + 6511 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack/7") + 6512 # var idx + 6513 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8") + 6514 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9") + 6515 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")" "F - test-convert-index-into-array-on-stack/10") + 6516 # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc + 6517 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/11") + 6518 # reclaim idx + 6519 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/12") + 6520 # reclaim arr + 6521 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/13") + 6522 # + 6523 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/14") + 6524 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/15") + 6525 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/16") + 6526 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/17") + 6527 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/18") + 6528 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/19") + 6529 # . epilogue + 6530 89/<- %esp 5/r32/ebp + 6531 5d/pop-to-ebp + 6532 c3/return + 6533 + 6534 test-convert-index-into-array-on-stack-with-literal: + 6535 # . prologue + 6536 55/push-ebp + 6537 89/<- %ebp 4/r32/esp + 6538 # setup + 6539 (clear-stream _test-input-stream) + 6540 (clear-stream $_test-input-buffered-file->buffer) + 6541 (clear-stream _test-output-stream) + 6542 (clear-stream $_test-output-buffered-file->buffer) + 6543 # + 6544 (write _test-input-stream "fn foo {\n") + 6545 (write _test-input-stream " var arr: (array int 3)\n") + 6546 (write _test-input-stream " var x/eax: (addr int) <- index arr, 2\n") + 6547 (write _test-input-stream "}\n") + 6548 # convert + 6549 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6550 (flush _test-output-buffered-file) + 6551 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6557 # check output + 6558 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-on-stack-with-literal/0") + 6559 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-on-stack-with-literal/1") + 6560 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-on-stack-with-literal/2") + 6561 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-on-stack-with-literal/3") + 6562 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-on-stack-with-literal/4") + 6563 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-on-stack-with-literal/5") + 6564 # var arr + 6565 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x0000000c)" "F - test-convert-index-into-array-on-stack-with-literal/6") + 6566 (check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7") + 6567 # var x + 6568 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8") + 6569 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")" "F - test-convert-index-into-array-on-stack-with-literal/9") + 6570 # x is at (ebp-0x10) + 4 + 2*4 = ebp-4 + 6571 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/10") + 6572 # reclaim x + 6573 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/11") + 6574 # reclaim arr + 6575 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/12") + 6576 # + 6577 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/13") + 6578 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/14") + 6579 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/15") + 6580 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/16") + 6581 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/17") + 6582 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/18") + 6583 # . epilogue + 6584 89/<- %esp 5/r32/ebp + 6585 5d/pop-to-ebp + 6586 c3/return + 6587 + 6588 test-convert-index-into-array-of-bytes-on-stack-with-literal: + 6589 # . prologue + 6590 55/push-ebp + 6591 89/<- %ebp 4/r32/esp + 6592 # setup + 6593 (clear-stream _test-input-stream) + 6594 (clear-stream $_test-input-buffered-file->buffer) + 6595 (clear-stream _test-output-stream) + 6596 (clear-stream $_test-output-buffered-file->buffer) + 6597 # + 6598 (write _test-input-stream "fn foo {\n") + 6599 (write _test-input-stream " var arr: (array byte 3)\n") + 6600 (write _test-input-stream " var x/eax: (addr byte) <- index arr, 2\n") + 6601 (write _test-input-stream "}\n") + 6602 # convert + 6603 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6604 (flush _test-output-buffered-file) + 6605 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6611 # check output + 6612 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0") + 6613 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1") + 6614 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2") + 6615 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/3") + 6616 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4") + 6617 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5") + 6618 # var arr + 6619 (check-next-stream-line-equal _test-output-stream " (push-n-zero-bytes 0x00000003)" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/6") + 6620 (check-next-stream-line-equal _test-output-stream " 68/push 0x00000003/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/7") + 6621 # var x + 6622 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/8") + 6623 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9") + 6624 # x is at (ebp-7) + 4 + 2 = ebp-1 + 6625 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10") + 6626 # reclaim x + 6627 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11") + 6628 # reclaim arr + 6629 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000007/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12") + 6630 # + 6631 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13") + 6632 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14") + 6633 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15") + 6634 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16") + 6635 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17") + 6636 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18") + 6637 # . epilogue + 6638 89/<- %esp 5/r32/ebp + 6639 5d/pop-to-ebp + 6640 c3/return + 6641 + 6642 test-convert-index-into-array-using-offset: + 6643 # . prologue + 6644 55/push-ebp + 6645 89/<- %ebp 4/r32/esp + 6646 # setup + 6647 (clear-stream _test-input-stream) + 6648 (clear-stream $_test-input-buffered-file->buffer) + 6649 (clear-stream _test-output-stream) + 6650 (clear-stream $_test-output-buffered-file->buffer) + 6651 # + 6652 (write _test-input-stream "fn foo {\n") + 6653 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 6654 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 6655 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") + 6656 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") + 6657 (write _test-input-stream "}\n") + 6658 # convert + 6659 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6660 (flush _test-output-buffered-file) + 6661 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6667 # check output + 6668 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset/0") + 6669 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset/1") + 6670 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset/2") + 6671 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset/3") + 6672 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset/4") + 6673 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset/5") + 6674 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset/6") + 6675 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset/7") + 6676 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8") + 6677 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9") + 6678 (check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10") + 6679 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-using-offset/11") + 6680 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-using-offset/12") + 6681 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-using-offset/13") + 6682 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/15") + 6683 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/16") + 6684 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/17") + 6685 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/18") + 6686 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/19") + 6687 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/20") + 6688 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/21") + 6689 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/22") + 6690 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/23") + 6691 # . epilogue + 6692 89/<- %esp 5/r32/ebp + 6693 5d/pop-to-ebp + 6694 c3/return + 6695 + 6696 test-convert-index-into-array-of-bytes-using-offset: + 6697 # . prologue + 6698 55/push-ebp + 6699 89/<- %ebp 4/r32/esp + 6700 # setup + 6701 (clear-stream _test-input-stream) + 6702 (clear-stream $_test-input-buffered-file->buffer) + 6703 (clear-stream _test-output-stream) + 6704 (clear-stream $_test-output-buffered-file->buffer) + 6705 # + 6706 (write _test-input-stream "fn foo {\n") + 6707 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") + 6708 (write _test-input-stream " var idx/ecx: int <- copy 3\n") + 6709 (write _test-input-stream " var off/ecx: (offset byte) <- compute-offset arr, idx\n") + 6710 (write _test-input-stream " var x/eax: (addr byte) <- index arr, off\n") + 6711 (write _test-input-stream "}\n") + 6712 # convert + 6713 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6714 (flush _test-output-buffered-file) + 6715 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6721 # check output + 6722 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-using-offset/0") + 6723 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-using-offset/1") + 6724 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-using-offset/2") + 6725 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-using-offset/3") + 6726 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-using-offset/4") + 6727 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-using-offset/5") + 6728 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-using-offset/6") + 6729 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset/7") + 6730 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/8") + 6731 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-of-bytes-using-offset/9") + 6732 (check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000001/imm32 0x00000001/r32" "F - test-convert-index-into-array-of-bytes-using-offset/10") + 6733 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-using-offset/11") + 6734 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset/12") + 6735 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-of-bytes-using-offset/13") + 6736 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset/14") + 6737 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/15") + 6738 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset/16") + 6739 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset/17") + 6740 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset/18") + 6741 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset/19") + 6742 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset/20") + 6743 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset/21") + 6744 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset/22") + 6745 # . epilogue + 6746 89/<- %esp 5/r32/ebp + 6747 5d/pop-to-ebp + 6748 c3/return + 6749 + 6750 test-convert-index-into-array-using-offset-on-stack: + 6751 # . prologue + 6752 55/push-ebp + 6753 89/<- %ebp 4/r32/esp + 6754 # setup + 6755 (clear-stream _test-input-stream) + 6756 (clear-stream $_test-input-buffered-file->buffer) + 6757 (clear-stream _test-output-stream) + 6758 (clear-stream $_test-output-buffered-file->buffer) + 6759 # + 6760 (write _test-input-stream "fn foo {\n") + 6761 (write _test-input-stream " var arr/eax: (addr array int) <- copy 0\n") + 6762 (write _test-input-stream " var idx: int\n") + 6763 (write _test-input-stream " var off/ecx: (offset int) <- compute-offset arr, idx\n") + 6764 (write _test-input-stream " var x/eax: (addr int) <- index arr, off\n") + 6765 (write _test-input-stream "}\n") + 6766 # convert + 6767 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6768 (flush _test-output-buffered-file) + 6769 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6775 # check output + 6776 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-using-offset-on-stack/0") + 6777 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-using-offset-on-stack/1") + 6778 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-using-offset-on-stack/2") + 6779 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-using-offset-on-stack/3") + 6780 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-using-offset-on-stack/4") + 6781 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-using-offset-on-stack/5") + 6782 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-using-offset-on-stack/6") + 6783 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/7") + 6784 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8") + 6785 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9") + 6786 (check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10") + 6787 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-using-offset-on-stack/11") + 6788 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/12") + 6789 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-using-offset-on-stack/13") + 6790 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/14") + 6791 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/15") + 6792 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/16") + 6793 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/17") + 6794 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/18") + 6795 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/19") + 6796 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/20") + 6797 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/21") + 6798 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/22") + 6799 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/23") + 6800 # . epilogue + 6801 89/<- %esp 5/r32/ebp + 6802 5d/pop-to-ebp + 6803 c3/return + 6804 + 6805 test-convert-index-into-array-of-bytes-using-offset-on-stack: + 6806 # . prologue + 6807 55/push-ebp + 6808 89/<- %ebp 4/r32/esp + 6809 # setup + 6810 (clear-stream _test-input-stream) + 6811 (clear-stream $_test-input-buffered-file->buffer) + 6812 (clear-stream _test-output-stream) + 6813 (clear-stream $_test-output-buffered-file->buffer) + 6814 # + 6815 (write _test-input-stream "fn foo {\n") + 6816 (write _test-input-stream " var arr/eax: (addr array byte) <- copy 0\n") + 6817 (write _test-input-stream " var idx: int\n") + 6818 (write _test-input-stream " var off/ecx: (offset byte) <- compute-offset arr, idx\n") + 6819 (write _test-input-stream " var x/eax: (addr byte) <- index arr, off\n") + 6820 (write _test-input-stream "}\n") + 6821 # convert + 6822 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6823 (flush _test-output-buffered-file) + 6824 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6830 # check output + 6831 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0") + 6832 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1") + 6833 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2") + 6834 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/3") + 6835 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4") + 6836 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5") + 6837 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/6") + 6838 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/7") + 6839 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/8") + 6840 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9") + 6841 (check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10") + 6842 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11") + 6843 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12") + 6844 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13") + 6845 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14") + 6846 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15") + 6847 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16") + 6848 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17") + 6849 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18") + 6850 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19") + 6851 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20") + 6852 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21") + 6853 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/22") + 6854 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/23") + 6855 # . epilogue + 6856 89/<- %esp 5/r32/ebp + 6857 5d/pop-to-ebp + 6858 c3/return + 6859 + 6860 test-convert-function-and-type-definition: + 6861 # . prologue + 6862 55/push-ebp + 6863 89/<- %ebp 4/r32/esp + 6864 # setup + 6865 (clear-stream _test-input-stream) + 6866 (clear-stream $_test-input-buffered-file->buffer) + 6867 (clear-stream _test-output-stream) + 6868 (clear-stream $_test-output-buffered-file->buffer) + 6869 # + 6870 (write _test-input-stream "fn foo a: (addr t) {\n") + 6871 (write _test-input-stream " var _a/eax: (addr t) <- copy a\n") + 6872 (write _test-input-stream " var b/ecx: (addr int) <- get _a, x\n") + 6873 (write _test-input-stream " var c/ecx: (addr int) <- get _a, y\n") + 6874 (write _test-input-stream "}\n") + 6875 (write _test-input-stream "type t {\n") + 6876 (write _test-input-stream " x: int\n") + 6877 (write _test-input-stream " y: int\n") + 6878 (write _test-input-stream "}\n") + 6879 # convert + 6880 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 6881 (flush _test-output-buffered-file) + 6882 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 6888 # check output + 6889 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-and-type-definition/0") + 6890 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-and-type-definition/1") + 6891 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-and-type-definition/2") + 6892 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-and-type-definition/3") + 6893 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-and-type-definition/4") + 6894 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-and-type-definition/5") + 6895 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-and-type-definition/6") + 6896 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-and-type-definition/7") + 6897 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-and-type-definition/8") + 6898 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-function-and-type-definition/9") + 6899 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-get-base-address/disp32" "F - test-convert-function-and-type-definition/10") + 6900 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000000) 0x00000001/r32" "F - test-convert-function-and-type-definition/11") + 6901 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-function-and-type-definition/12") + 6902 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-get-base-address/disp32" "F - test-convert-function-and-type-definition/13") + 6903 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000004) 0x00000001/r32" "F - test-convert-function-and-type-definition/14") + 6904 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/15") + 6905 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/16") + 6906 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-and-type-definition/17") + 6907 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-and-type-definition/18") + 6908 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-and-type-definition/19") + 6909 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-and-type-definition/20") + 6910 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-and-type-definition/21") + 6911 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-and-type-definition/22") + 6912 # . epilogue + 6913 89/<- %esp 5/r32/ebp + 6914 5d/pop-to-ebp + 6915 c3/return + 6916 + 6917 test-type-definition-with-array: + 6918 # . prologue + 6919 55/push-ebp + 6920 89/<- %ebp 4/r32/esp + 6921 # setup + 6922 (clear-stream _test-input-stream) + 6923 (clear-stream $_test-input-buffered-file->buffer) + 6924 (clear-stream _test-output-stream) + 6925 (clear-stream $_test-output-buffered-file->buffer) + 6926 (clear-stream _test-error-stream) + 6927 (clear-stream $_test-error-buffered-file->buffer) + 6928 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 6929 68/push 0/imm32 + 6930 68/push 0/imm32 + 6931 89/<- %edx 4/r32/esp + 6932 (tailor-exit-descriptor %edx 0x10) + 6933 # + 6934 (write _test-input-stream "type t {\n") + 6935 (write _test-input-stream " a: (array int 3)\n") + 6936 (write _test-input-stream "}\n") + 6937 # convert + 6938 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 6939 # registers except esp clobbered at this point + 6940 # restore ed + 6941 89/<- %edx 4/r32/esp + 6942 (flush _test-output-buffered-file) + 6943 (flush _test-error-buffered-file) + 6944 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 6950 # check output + 6951 (check-stream-equal _test-output-stream "" "F - test-type-definition-with-array: output should be empty") + 6952 (check-next-stream-line-equal _test-error-stream "type t: 'array' elements not allowed for now" "F - test-type-definition-with-array: error message") + 6953 # check that stop(1) was called + 6954 (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status") + 6955 # don't restore from ebp + 6956 81 0/subop/add %esp 8/imm32 + 6957 # . epilogue + 6958 5d/pop-to-ebp + 6959 c3/return + 6960 + 6961 test-type-definition-with-addr: + 6962 # . prologue + 6963 55/push-ebp + 6964 89/<- %ebp 4/r32/esp + 6965 # setup + 6966 (clear-stream _test-input-stream) + 6967 (clear-stream $_test-input-buffered-file->buffer) + 6968 (clear-stream _test-output-stream) + 6969 (clear-stream $_test-output-buffered-file->buffer) + 6970 (clear-stream _test-error-stream) + 6971 (clear-stream $_test-error-buffered-file->buffer) + 6972 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 6973 68/push 0/imm32 + 6974 68/push 0/imm32 + 6975 89/<- %edx 4/r32/esp + 6976 (tailor-exit-descriptor %edx 0x10) + 6977 # + 6978 (write _test-input-stream "type t {\n") + 6979 (write _test-input-stream " a: (addr int)\n") + 6980 (write _test-input-stream "}\n") + 6981 # convert + 6982 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 6983 # registers except esp clobbered at this point + 6984 # restore ed + 6985 89/<- %edx 4/r32/esp + 6986 (flush _test-output-buffered-file) + 6987 (flush _test-error-buffered-file) + 6988 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 6994 # check output + 6995 (check-stream-equal _test-output-stream "" "F - test-type-definition-with-addr: output should be empty") + 6996 (check-next-stream-line-equal _test-error-stream "type t: 'addr' elements not allowed" "F - test-type-definition-with-addr: error message") + 6997 # check that stop(1) was called + 6998 (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status") + 6999 # don't restore from ebp + 7000 81 0/subop/add %esp 8/imm32 + 7001 # . epilogue + 7002 5d/pop-to-ebp + 7003 c3/return + 7004 + 7005 test-convert-function-with-local-var-with-user-defined-type: + 7006 # . prologue + 7007 55/push-ebp + 7008 89/<- %ebp 4/r32/esp + 7009 # setup + 7010 (clear-stream _test-input-stream) + 7011 (clear-stream $_test-input-buffered-file->buffer) + 7012 (clear-stream _test-output-stream) + 7013 (clear-stream $_test-output-buffered-file->buffer) + 7014 # + 7015 (write _test-input-stream "fn foo {\n") + 7016 (write _test-input-stream " var a: t\n") + 7017 (write _test-input-stream "}\n") + 7018 (write _test-input-stream "type t {\n") + 7019 (write _test-input-stream " x: int\n") + 7020 (write _test-input-stream " y: int\n") + 7021 (write _test-input-stream "}\n") + 7022 # convert + 7023 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7024 (flush _test-output-buffered-file) + 7025 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7031 # check output + 7032 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type/0") + 7033 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type/1") + 7034 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/2") + 7035 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type/3") + 7036 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type/4") + 7037 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type/5") + 7038 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/6") + 7039 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/7") + 7040 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-with-local-var-with-user-defined-type/8") + 7041 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type/9") + 7042 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type/10") + 7043 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type/11") + 7044 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type/12") + 7045 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type/13") + 7046 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type/14") + 7047 # . epilogue + 7048 89/<- %esp 5/r32/ebp + 7049 5d/pop-to-ebp + 7050 c3/return + 7051 + 7052 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type: + 7053 # . prologue + 7054 55/push-ebp + 7055 89/<- %ebp 4/r32/esp + 7056 # setup + 7057 (clear-stream _test-input-stream) + 7058 (clear-stream $_test-input-buffered-file->buffer) + 7059 (clear-stream _test-output-stream) + 7060 (clear-stream $_test-output-buffered-file->buffer) + 7061 # + 7062 (write _test-input-stream "fn foo {\n") + 7063 (write _test-input-stream " var a: t\n") + 7064 (write _test-input-stream "}\n") + 7065 (write _test-input-stream "type t {\n") + 7066 (write _test-input-stream " x: s\n") + 7067 (write _test-input-stream "}\n") + 7068 (write _test-input-stream "type s {\n") + 7069 (write _test-input-stream " z: int\n") + 7070 (write _test-input-stream "}\n") + 7071 # convert + 7072 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7073 (flush _test-output-buffered-file) + 7074 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7080 # check output + 7081 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/0") + 7082 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/1") + 7083 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/2") + 7084 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/3") + 7085 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4") + 7086 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/5") + 7087 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/7") + 7088 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/8") + 7089 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9") + 7090 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/10") + 7091 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/11") + 7092 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/12") + 7093 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/13") + 7094 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/14") + 7095 # . epilogue + 7096 89/<- %esp 5/r32/ebp + 7097 5d/pop-to-ebp + 7098 c3/return + 7099 + 7100 test-convert-function-call-with-arg-of-user-defined-type: + 7101 # . prologue + 7102 55/push-ebp + 7103 89/<- %ebp 4/r32/esp + 7104 # setup + 7105 (clear-stream _test-input-stream) + 7106 (clear-stream $_test-input-buffered-file->buffer) + 7107 (clear-stream _test-output-stream) + 7108 (clear-stream $_test-output-buffered-file->buffer) + 7109 # + 7110 (write _test-input-stream "fn f {\n") + 7111 (write _test-input-stream " var a: t\n") + 7112 (write _test-input-stream " foo a\n") + 7113 (write _test-input-stream "}\n") + 7114 (write _test-input-stream "fn foo x: t {\n") + 7115 (write _test-input-stream "}\n") + 7116 (write _test-input-stream "type t {\n") + 7117 (write _test-input-stream " x: int\n") + 7118 (write _test-input-stream " y: int\n") + 7119 (write _test-input-stream "}\n") + 7120 # convert + 7121 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7122 (flush _test-output-buffered-file) + 7123 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7129 # check output + 7130 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type/0") + 7131 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/1") + 7132 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/2") + 7133 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/3") + 7134 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type/4") + 7135 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type/5") + 7136 # var a: t + 7137 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/6") + 7138 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/7") + 7139 # foo a + 7140 (check-next-stream-line-equal _test-output-stream " (foo *(ebp+0xfffffff8) *(ebp+0xfffffffc))" "F - test-convert-function-call-with-arg-of-user-defined-type/8") + 7141 # + 7142 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/9") + 7143 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type/10") + 7144 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type/11") + 7145 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/12") + 7146 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/13") + 7147 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/14") + 7148 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/15") + 7149 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type/16") + 7150 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/17") + 7151 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/18") + 7152 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/19") + 7153 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/20") + 7154 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/21") + 7155 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/22") + 7156 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/23") + 7157 # . epilogue + 7158 89/<- %esp 5/r32/ebp + 7159 5d/pop-to-ebp + 7160 c3/return + 7161 + 7162 test-convert-function-call-with-arg-of-user-defined-type-register-indirect: + 7163 # . prologue + 7164 55/push-ebp + 7165 89/<- %ebp 4/r32/esp + 7166 # setup + 7167 (clear-stream _test-input-stream) + 7168 (clear-stream $_test-input-buffered-file->buffer) + 7169 (clear-stream _test-output-stream) + 7170 (clear-stream $_test-output-buffered-file->buffer) + 7171 # + 7172 (write _test-input-stream "fn f {\n") + 7173 (write _test-input-stream " var a/eax: (addr t) <- copy 0\n") + 7174 (write _test-input-stream " foo *a\n") + 7175 (write _test-input-stream "}\n") + 7176 (write _test-input-stream "fn foo x: t {\n") + 7177 (write _test-input-stream "}\n") + 7178 (write _test-input-stream "type t {\n") + 7179 (write _test-input-stream " x: int\n") + 7180 (write _test-input-stream " y: int\n") + 7181 (write _test-input-stream "}\n") + 7182 # convert + 7183 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7184 (flush _test-output-buffered-file) + 7185 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7191 # check output + 7192 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type/0") + 7193 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/1") + 7194 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/2") + 7195 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/3") + 7196 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type/4") + 7197 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type/5") + 7198 # var a + 7199 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/6") + 7200 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type/7") + 7201 # foo a + 7202 (check-next-stream-line-equal _test-output-stream " (foo *(eax+0x00000000) *(eax+0x00000004))" "F - test-convert-function-call-with-arg-of-user-defined-type/8") + 7203 # + 7204 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/9") + 7205 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type/10") + 7206 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type/11") + 7207 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/12") + 7208 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/13") + 7209 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/14") + 7210 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/15") + 7211 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type/16") + 7212 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type/17") + 7213 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/18") + 7214 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type/19") + 7215 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type/20") + 7216 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/21") + 7217 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type/22") + 7218 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type/23") + 7219 # . epilogue + 7220 89/<- %esp 5/r32/ebp + 7221 5d/pop-to-ebp + 7222 c3/return + 7223 + 7224 # we don't have special support for call-by-reference; just explicitly create + 7225 # a new variable with the address of the arg + 7226 test-convert-function-call-with-arg-of-user-defined-type-by-reference: + 7227 # . prologue + 7228 55/push-ebp + 7229 89/<- %ebp 4/r32/esp + 7230 # setup + 7231 (clear-stream _test-input-stream) + 7232 (clear-stream $_test-input-buffered-file->buffer) + 7233 (clear-stream _test-output-stream) + 7234 (clear-stream $_test-output-buffered-file->buffer) + 7235 # + 7236 (write _test-input-stream "fn f {\n") + 7237 (write _test-input-stream " var a: t\n") + 7238 (write _test-input-stream " var b/eax: (addr t) <- address a\n") + 7239 (write _test-input-stream " foo b\n") + 7240 (write _test-input-stream "}\n") + 7241 (write _test-input-stream "fn foo x: (addr t) {\n") + 7242 (write _test-input-stream " var x/ecx: (addr t) <- copy x\n") + 7243 (write _test-input-stream "}\n") + 7244 (write _test-input-stream "type t {\n") + 7245 (write _test-input-stream " x: int\n") + 7246 (write _test-input-stream " y: int\n") + 7247 (write _test-input-stream "}\n") + 7248 # convert + 7249 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7250 (flush _test-output-buffered-file) + 7251 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7257 # check output + 7258 (check-next-stream-line-equal _test-output-stream "f:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0") + 7259 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1") + 7260 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/2") + 7261 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/3") + 7262 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4") + 7263 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/5") + 7264 # var a: t + 7265 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/6") + 7266 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/7") + 7267 # var b/eax: (addr t) + 7268 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/8") + 7269 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/9") + 7270 # foo a + 7271 (check-next-stream-line-equal _test-output-stream " (foo %eax)" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10") + 7272 # + 7273 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/11") + 7274 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/12") + 7275 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13") + 7276 (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/14") + 7277 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15") + 7278 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/16") + 7279 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/17") + 7280 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18") + 7281 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19") + 7282 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20") + 7283 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/21") + 7284 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/22") + 7285 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23") + 7286 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/24") + 7287 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/25") + 7288 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000001/r32" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/26") + 7289 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27") + 7290 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28") + 7291 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29") + 7292 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30") + 7293 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31") + 7294 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32") + 7295 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33") + 7296 # . epilogue + 7297 89/<- %esp 5/r32/ebp + 7298 5d/pop-to-ebp + 7299 c3/return + 7300 + 7301 test-convert-get-on-local-variable: + 7302 # . prologue + 7303 55/push-ebp + 7304 89/<- %ebp 4/r32/esp + 7305 # setup + 7306 (clear-stream _test-input-stream) + 7307 (clear-stream $_test-input-buffered-file->buffer) + 7308 (clear-stream _test-output-stream) + 7309 (clear-stream $_test-output-buffered-file->buffer) + 7310 # + 7311 (write _test-input-stream "fn foo {\n") + 7312 (write _test-input-stream " var a: t\n") + 7313 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") + 7314 (write _test-input-stream "}\n") + 7315 (write _test-input-stream "type t {\n") + 7316 (write _test-input-stream " x: int\n") + 7317 (write _test-input-stream " y: int\n") + 7318 (write _test-input-stream "}\n") + 7319 # convert + 7320 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7321 (flush _test-output-buffered-file) + 7322 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7328 # check output + 7329 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-on-local-variable/0") + 7330 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-on-local-variable/1") + 7331 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-on-local-variable/2") + 7332 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-on-local-variable/3") + 7333 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-on-local-variable/4") + 7334 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-on-local-variable/5") + 7335 # var a + 7336 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-on-local-variable/6") + 7337 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-get-on-local-variable/7") + 7338 # var c + 7339 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-on-local-variable/8") + 7340 # get + 7341 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32" "F - test-convert-get-on-local-variable/9") + 7342 # reclaim c + 7343 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10") + 7344 # reclaim a + 7345 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000008/imm32" "F - test-convert-get-on-local-variable/11") + 7346 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-on-local-variable/12") + 7347 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-on-local-variable/13") + 7348 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-on-local-variable/14") + 7349 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-on-local-variable/15") + 7350 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-on-local-variable/16") + 7351 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-on-local-variable/17") + 7352 # . epilogue + 7353 89/<- %esp 5/r32/ebp + 7354 5d/pop-to-ebp + 7355 c3/return + 7356 + 7357 test-convert-get-on-function-argument: + 7358 # . prologue + 7359 55/push-ebp + 7360 89/<- %ebp 4/r32/esp + 7361 # setup + 7362 (clear-stream _test-input-stream) + 7363 (clear-stream $_test-input-buffered-file->buffer) + 7364 (clear-stream _test-output-stream) + 7365 (clear-stream $_test-output-buffered-file->buffer) + 7366 # + 7367 (write _test-input-stream "fn foo a: t {\n") + 7368 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") + 7369 (write _test-input-stream "}\n") + 7370 (write _test-input-stream "type t {\n") + 7371 (write _test-input-stream " x: int\n") + 7372 (write _test-input-stream " y: int\n") + 7373 (write _test-input-stream "}\n") + 7374 # convert + 7375 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7376 (flush _test-output-buffered-file) + 7377 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7383 # check output + 7384 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-on-function-argument/0") + 7385 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-on-function-argument/1") + 7386 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-on-function-argument/2") + 7387 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-on-function-argument/3") + 7388 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-on-function-argument/4") + 7389 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-on-function-argument/5") + 7390 # var c + 7391 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-on-function-argument/6") + 7392 # get + 7393 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0x0000000c) 0x00000001/r32" "F - test-convert-get-on-function-argument/7") + 7394 # reclaim c + 7395 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8") + 7396 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-on-function-argument/9") + 7397 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-on-function-argument/10") + 7398 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-on-function-argument/11") + 7399 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-on-function-argument/12") + 7400 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-on-function-argument/13") + 7401 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-on-function-argument/14") + 7402 # . epilogue + 7403 89/<- %esp 5/r32/ebp + 7404 5d/pop-to-ebp + 7405 c3/return + 7406 + 7407 test-convert-get-on-function-argument-with-known-type: + 7408 # . prologue + 7409 55/push-ebp + 7410 89/<- %ebp 4/r32/esp + 7411 # setup + 7412 (clear-stream _test-input-stream) + 7413 (clear-stream $_test-input-buffered-file->buffer) + 7414 (clear-stream _test-output-stream) + 7415 (clear-stream $_test-output-buffered-file->buffer) + 7416 # + 7417 (write _test-input-stream "type t {\n") + 7418 (write _test-input-stream " x: int\n") + 7419 (write _test-input-stream " y: int\n") + 7420 (write _test-input-stream "}\n") + 7421 (write _test-input-stream "fn foo a: t {\n") + 7422 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") + 7423 (write _test-input-stream "}\n") + 7424 # convert + 7425 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7426 (flush _test-output-buffered-file) + 7427 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 7433 # check output + 7434 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-get-on-function-argument-with-known-type/0") + 7435 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-get-on-function-argument-with-known-type/1") + 7436 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-get-on-function-argument-with-known-type/2") + 7437 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-get-on-function-argument-with-known-type/3") + 7438 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-get-on-function-argument-with-known-type/4") + 7439 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-get-on-function-argument-with-known-type/5") + 7440 # var c + 7441 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-get-on-function-argument-with-known-type/6") + 7442 # get + 7443 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp+0x0000000c) 0x00000001/r32" "F - test-convert-get-on-function-argument-with-known-type/7") + 7444 # reclaim c + 7445 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8") + 7446 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-get-on-function-argument-with-known-type/9") + 7447 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-get-on-function-argument-with-known-type/10") + 7448 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-get-on-function-argument-with-known-type/11") + 7449 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-get-on-function-argument-with-known-type/12") + 7450 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-get-on-function-argument-with-known-type/13") + 7451 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-get-on-function-argument-with-known-type/14") + 7452 # . epilogue + 7453 89/<- %esp 5/r32/ebp + 7454 5d/pop-to-ebp + 7455 c3/return + 7456 + 7457 test-add-with-too-many-inouts: + 7458 # . prologue + 7459 55/push-ebp + 7460 89/<- %ebp 4/r32/esp + 7461 # setup + 7462 (clear-stream _test-input-stream) + 7463 (clear-stream $_test-input-buffered-file->buffer) + 7464 (clear-stream _test-output-stream) + 7465 (clear-stream $_test-output-buffered-file->buffer) + 7466 (clear-stream _test-error-stream) + 7467 (clear-stream $_test-error-buffered-file->buffer) + 7468 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7469 68/push 0/imm32 + 7470 68/push 0/imm32 + 7471 89/<- %edx 4/r32/esp + 7472 (tailor-exit-descriptor %edx 0x10) + 7473 # + 7474 (write _test-input-stream "fn foo {\n") + 7475 (write _test-input-stream " var a: int\n") + 7476 (write _test-input-stream " var b/ecx: int <- add a, 0\n") + 7477 (write _test-input-stream "}\n") + 7478 # convert + 7479 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7480 # registers except esp clobbered at this point + 7481 # restore ed + 7482 89/<- %edx 4/r32/esp + 7483 (flush _test-output-buffered-file) + 7484 (flush _test-error-buffered-file) + 7485 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7491 # check output + 7492 (check-stream-equal _test-output-stream "" "F - test-add-with-too-many-inouts: output should be empty") + 7493 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: too many inouts; most primitives support at most two arguments, across inouts and outputs" "F - test-add-with-too-many-inouts: error message") + 7494 # check that stop(1) was called + 7495 (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status") + 7496 # don't restore from ebp + 7497 81 0/subop/add %esp 8/imm32 + 7498 # . epilogue + 7499 5d/pop-to-ebp + 7500 c3/return + 7501 + 7502 test-add-with-too-many-inouts-2: + 7503 # . prologue + 7504 55/push-ebp + 7505 89/<- %ebp 4/r32/esp + 7506 # setup + 7507 (clear-stream _test-input-stream) + 7508 (clear-stream $_test-input-buffered-file->buffer) + 7509 (clear-stream _test-output-stream) + 7510 (clear-stream $_test-output-buffered-file->buffer) + 7511 (clear-stream _test-error-stream) + 7512 (clear-stream $_test-error-buffered-file->buffer) + 7513 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7514 68/push 0/imm32 + 7515 68/push 0/imm32 + 7516 89/<- %edx 4/r32/esp + 7517 (tailor-exit-descriptor %edx 0x10) + 7518 # + 7519 (write _test-input-stream "fn foo {\n") + 7520 (write _test-input-stream " var a: int\n") + 7521 (write _test-input-stream " add-to a, 0, 1\n") + 7522 (write _test-input-stream "}\n") + 7523 # convert + 7524 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7525 # registers except esp clobbered at this point + 7526 # restore ed + 7527 89/<- %edx 4/r32/esp + 7528 (flush _test-output-buffered-file) + 7529 (flush _test-error-buffered-file) + 7530 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7536 # check output + 7537 (check-stream-equal _test-output-stream "" "F - test-add-with-too-many-inouts-2: output should be empty") + 7538 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add-to: too many inouts; most primitives support at most two arguments, across inouts and outputs" "F - test-add-with-too-many-inouts-2: error message") + 7539 # check that stop(1) was called + 7540 (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status") + 7541 # don't restore from ebp + 7542 81 0/subop/add %esp 8/imm32 + 7543 # . epilogue + 7544 5d/pop-to-ebp + 7545 c3/return + 7546 + 7547 test-add-with-too-many-outputs: + 7548 # . prologue + 7549 55/push-ebp + 7550 89/<- %ebp 4/r32/esp + 7551 # setup + 7552 (clear-stream _test-input-stream) + 7553 (clear-stream $_test-input-buffered-file->buffer) + 7554 (clear-stream _test-output-stream) + 7555 (clear-stream $_test-output-buffered-file->buffer) + 7556 (clear-stream _test-error-stream) + 7557 (clear-stream $_test-error-buffered-file->buffer) + 7558 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7559 68/push 0/imm32 + 7560 68/push 0/imm32 + 7561 89/<- %edx 4/r32/esp + 7562 (tailor-exit-descriptor %edx 0x10) + 7563 # + 7564 (write _test-input-stream "fn foo {\n") + 7565 (write _test-input-stream " var a/eax: int <- copy 0\n") + 7566 (write _test-input-stream " var b/ebx: int <- copy 0\n") + 7567 (write _test-input-stream " var c/ecx: int <- copy 0\n") + 7568 (write _test-input-stream " c, b <- add a\n") + 7569 (write _test-input-stream "}\n") + 7570 # convert + 7571 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7572 # registers except esp clobbered at this point + 7573 # restore ed + 7574 89/<- %edx 4/r32/esp + 7575 (flush _test-output-buffered-file) + 7576 (flush _test-error-buffered-file) + 7577 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7583 # check output + 7584 (check-stream-equal _test-output-stream "" "F - test-add-with-too-many-outputs: output should be empty") + 7585 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: too many outputs; most primitives support at most one output" "F - test-add-with-too-many-outputs: error message") + 7586 # check that stop(1) was called + 7587 (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status") + 7588 # don't restore from ebp + 7589 81 0/subop/add %esp 8/imm32 + 7590 # . epilogue + 7591 5d/pop-to-ebp + 7592 c3/return + 7593 + 7594 test-add-with-non-number: + 7595 # . prologue + 7596 55/push-ebp + 7597 89/<- %ebp 4/r32/esp + 7598 # setup + 7599 (clear-stream _test-input-stream) + 7600 (clear-stream $_test-input-buffered-file->buffer) + 7601 (clear-stream _test-output-stream) + 7602 (clear-stream $_test-output-buffered-file->buffer) + 7603 (clear-stream _test-error-stream) + 7604 (clear-stream $_test-error-buffered-file->buffer) + 7605 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7606 68/push 0/imm32 + 7607 68/push 0/imm32 + 7608 89/<- %edx 4/r32/esp + 7609 (tailor-exit-descriptor %edx 0x10) + 7610 # + 7611 (write _test-input-stream "fn foo {\n") + 7612 (write _test-input-stream " var a: int\n") + 7613 (write _test-input-stream " var b/ecx: (addr int) <- add a\n") + 7614 (write _test-input-stream "}\n") + 7615 # convert + 7616 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7617 # registers except esp clobbered at this point + 7618 # restore ed + 7619 89/<- %edx 4/r32/esp + 7620 (flush _test-output-buffered-file) + 7621 (flush _test-error-buffered-file) + 7622 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7628 # check output + 7629 (check-stream-equal _test-output-stream "" "F - test-add-with-non-number: output should be empty") + 7630 (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: 'b' must be a non-addr non-offset scalar" "F - test-add-with-non-number: error message") + 7631 # check that stop(1) was called + 7632 (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status") + 7633 # don't restore from ebp + 7634 81 0/subop/add %esp 8/imm32 + 7635 # . epilogue + 7636 5d/pop-to-ebp + 7637 c3/return + 7638 + 7639 test-add-with-addr-dereferenced: + 7640 # . prologue + 7641 55/push-ebp + 7642 89/<- %ebp 4/r32/esp + 7643 # setup + 7644 (clear-stream _test-input-stream) + 7645 (clear-stream $_test-input-buffered-file->buffer) + 7646 (clear-stream _test-output-stream) + 7647 (clear-stream $_test-output-buffered-file->buffer) + 7648 # + 7649 (write _test-input-stream "fn foo {\n") + 7650 (write _test-input-stream " var a/eax: (addr int) <- copy 0\n") + 7651 (write _test-input-stream " add-to *a, 1\n") + 7652 (write _test-input-stream "}\n") + 7653 # convert + 7654 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7655 (flush _test-output-buffered-file) + 7656 # no error + 7657 # . epilogue + 7658 89/<- %esp 5/r32/ebp + 7659 5d/pop-to-ebp + 7660 c3/return + 7661 + 7662 test-copy-with-no-inout: + 7663 # . prologue + 7664 55/push-ebp + 7665 89/<- %ebp 4/r32/esp + 7666 # setup + 7667 (clear-stream _test-input-stream) + 7668 (clear-stream $_test-input-buffered-file->buffer) + 7669 (clear-stream _test-output-stream) + 7670 (clear-stream $_test-output-buffered-file->buffer) + 7671 (clear-stream _test-error-stream) + 7672 (clear-stream $_test-error-buffered-file->buffer) + 7673 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7674 68/push 0/imm32 + 7675 68/push 0/imm32 + 7676 89/<- %edx 4/r32/esp + 7677 (tailor-exit-descriptor %edx 0x10) + 7678 # + 7679 (write _test-input-stream "fn foo {\n") + 7680 (write _test-input-stream " var x/eax: boolean <- copy\n") + 7681 (write _test-input-stream "}\n") + 7682 # convert + 7683 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7684 # registers except esp clobbered at this point + 7685 # restore ed + 7686 89/<- %edx 4/r32/esp + 7687 (flush _test-output-buffered-file) + 7688 (flush _test-error-buffered-file) + 7689 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7695 # check output + 7696 (check-stream-equal _test-output-stream "" "F - test-copy-with-no-inout: output should be empty") + 7697 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' expects an inout" "F - test-copy-with-no-inout: error message") + 7698 # check that stop(1) was called + 7699 (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status") + 7700 # don't restore from ebp + 7701 81 0/subop/add %esp 8/imm32 + 7702 # . epilogue + 7703 5d/pop-to-ebp + 7704 c3/return + 7705 + 7706 test-copy-with-multiple-inouts: + 7707 # . prologue + 7708 55/push-ebp + 7709 89/<- %ebp 4/r32/esp + 7710 # setup + 7711 (clear-stream _test-input-stream) + 7712 (clear-stream $_test-input-buffered-file->buffer) + 7713 (clear-stream _test-output-stream) + 7714 (clear-stream $_test-output-buffered-file->buffer) + 7715 (clear-stream _test-error-stream) + 7716 (clear-stream $_test-error-buffered-file->buffer) + 7717 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7718 68/push 0/imm32 + 7719 68/push 0/imm32 + 7720 89/<- %edx 4/r32/esp + 7721 (tailor-exit-descriptor %edx 0x10) + 7722 # + 7723 (write _test-input-stream "fn foo {\n") + 7724 (write _test-input-stream " var x/eax: boolean <- copy 0, 0\n") + 7725 (write _test-input-stream "}\n") + 7726 # convert + 7727 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7728 # registers except esp clobbered at this point + 7729 # restore ed + 7730 89/<- %edx 4/r32/esp + 7731 (flush _test-output-buffered-file) + 7732 (flush _test-error-buffered-file) + 7733 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7739 # check output + 7740 (check-stream-equal _test-output-stream "" "F - test-copy-with-multiple-inouts: output should be empty") + 7741 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' must have just one inout" "F - test-copy-with-multiple-inouts: error message") + 7742 # check that stop(1) was called + 7743 (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status") + 7744 # don't restore from ebp + 7745 81 0/subop/add %esp 8/imm32 + 7746 # . epilogue + 7747 5d/pop-to-ebp + 7748 c3/return + 7749 + 7750 test-copy-with-no-output: + 7751 # . prologue + 7752 55/push-ebp + 7753 89/<- %ebp 4/r32/esp + 7754 # setup + 7755 (clear-stream _test-input-stream) + 7756 (clear-stream $_test-input-buffered-file->buffer) + 7757 (clear-stream _test-output-stream) + 7758 (clear-stream $_test-output-buffered-file->buffer) + 7759 (clear-stream _test-error-stream) + 7760 (clear-stream $_test-error-buffered-file->buffer) + 7761 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7762 68/push 0/imm32 + 7763 68/push 0/imm32 + 7764 89/<- %edx 4/r32/esp + 7765 (tailor-exit-descriptor %edx 0x10) + 7766 # + 7767 (write _test-input-stream "fn foo {\n") + 7768 (write _test-input-stream " copy 0\n") + 7769 (write _test-input-stream "}\n") + 7770 # convert + 7771 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7772 # registers except esp clobbered at this point + 7773 # restore ed + 7774 89/<- %edx 4/r32/esp + 7775 (flush _test-output-buffered-file) + 7776 (flush _test-error-buffered-file) + 7777 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7783 # check output + 7784 (check-stream-equal _test-output-stream "" "F - test-copy-with-no-output: output should be empty") + 7785 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' expects an output" "F - test-copy-with-no-output: error message") + 7786 # check that stop(1) was called + 7787 (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status") + 7788 # don't restore from ebp + 7789 81 0/subop/add %esp 8/imm32 + 7790 # . epilogue + 7791 5d/pop-to-ebp + 7792 c3/return + 7793 + 7794 test-copy-with-multiple-outputs: + 7795 # . prologue + 7796 55/push-ebp + 7797 89/<- %ebp 4/r32/esp + 7798 # setup + 7799 (clear-stream _test-input-stream) + 7800 (clear-stream $_test-input-buffered-file->buffer) + 7801 (clear-stream _test-output-stream) + 7802 (clear-stream $_test-output-buffered-file->buffer) + 7803 (clear-stream _test-error-stream) + 7804 (clear-stream $_test-error-buffered-file->buffer) + 7805 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7806 68/push 0/imm32 + 7807 68/push 0/imm32 + 7808 89/<- %edx 4/r32/esp + 7809 (tailor-exit-descriptor %edx 0x10) + 7810 # + 7811 (write _test-input-stream "fn foo {\n") + 7812 (write _test-input-stream " var x/eax: boolean <- copy 0\n") + 7813 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") + 7814 (write _test-input-stream " x, y <- copy 0\n") + 7815 (write _test-input-stream "}\n") + 7816 # convert + 7817 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7818 # registers except esp clobbered at this point + 7819 # restore ed + 7820 89/<- %edx 4/r32/esp + 7821 (flush _test-output-buffered-file) + 7822 (flush _test-error-buffered-file) + 7823 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7829 # check output + 7830 (check-stream-equal _test-output-stream "" "F - test-copy-with-multiple-outputs: output should be empty") + 7831 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy' must have just one output" "F - test-copy-with-multiple-outputs: error message") + 7832 # check that stop(1) was called + 7833 (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status") + 7834 # don't restore from ebp + 7835 81 0/subop/add %esp 8/imm32 + 7836 # . epilogue + 7837 5d/pop-to-ebp + 7838 c3/return + 7839 + 7840 test-copy-invalid-value-to-address: + 7841 # . prologue + 7842 55/push-ebp + 7843 89/<- %ebp 4/r32/esp + 7844 # setup + 7845 (clear-stream _test-input-stream) + 7846 (clear-stream $_test-input-buffered-file->buffer) + 7847 (clear-stream _test-output-stream) + 7848 (clear-stream $_test-output-buffered-file->buffer) + 7849 (clear-stream _test-error-stream) + 7850 (clear-stream $_test-error-buffered-file->buffer) + 7851 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7852 68/push 0/imm32 + 7853 68/push 0/imm32 + 7854 89/<- %edx 4/r32/esp + 7855 (tailor-exit-descriptor %edx 0x10) + 7856 # + 7857 (write _test-input-stream "fn foo {\n") + 7858 (write _test-input-stream " var x/eax: int <- copy 0\n") + 7859 (write _test-input-stream " var y/ecx: (addr int) <- copy x\n") + 7860 (write _test-input-stream "}\n") + 7861 # convert + 7862 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7863 # registers except esp clobbered at this point + 7864 # restore ed + 7865 89/<- %edx 4/r32/esp + 7866 (flush _test-output-buffered-file) + 7867 (flush _test-error-buffered-file) + 7868 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7874 # check output + 7875 (check-stream-equal _test-output-stream "" "F - test-copy-invalid-value-to-address: output should be empty") + 7876 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar" "F - test-copy-invalid-value-to-address: error message") + 7877 # check that stop(1) was called + 7878 (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status") + 7879 # don't restore from ebp + 7880 81 0/subop/add %esp 8/imm32 + 7881 # . epilogue + 7882 5d/pop-to-ebp + 7883 c3/return + 7884 + 7885 test-copy-null-value-to-address: + 7886 # . prologue + 7887 55/push-ebp + 7888 89/<- %ebp 4/r32/esp + 7889 # setup + 7890 (clear-stream _test-input-stream) + 7891 (clear-stream $_test-input-buffered-file->buffer) + 7892 (clear-stream _test-output-stream) + 7893 (clear-stream $_test-output-buffered-file->buffer) + 7894 # + 7895 (write _test-input-stream "fn foo {\n") + 7896 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") + 7897 (write _test-input-stream "}\n") + 7898 # convert + 7899 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7900 (flush _test-output-buffered-file) + 7901 # no errors + 7902 # . epilogue + 7903 89/<- %esp 5/r32/ebp + 7904 5d/pop-to-ebp + 7905 c3/return + 7906 + 7907 test-copy-invalid-value-to-offset: + 7908 # . prologue + 7909 55/push-ebp + 7910 89/<- %ebp 4/r32/esp + 7911 # setup + 7912 (clear-stream _test-input-stream) + 7913 (clear-stream $_test-input-buffered-file->buffer) + 7914 (clear-stream _test-output-stream) + 7915 (clear-stream $_test-output-buffered-file->buffer) + 7916 (clear-stream _test-error-stream) + 7917 (clear-stream $_test-error-buffered-file->buffer) + 7918 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7919 68/push 0/imm32 + 7920 68/push 0/imm32 + 7921 89/<- %edx 4/r32/esp + 7922 (tailor-exit-descriptor %edx 0x10) + 7923 # + 7924 (write _test-input-stream "fn foo {\n") + 7925 (write _test-input-stream " var x/eax: int <- copy 0\n") + 7926 (write _test-input-stream " var y/ecx: (offset int) <- copy x\n") + 7927 (write _test-input-stream "}\n") + 7928 # convert + 7929 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 7930 # registers except esp clobbered at this point + 7931 # restore ed + 7932 89/<- %edx 4/r32/esp + 7933 (flush _test-output-buffered-file) + 7934 (flush _test-error-buffered-file) + 7935 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7941 # check output + 7942 (check-stream-equal _test-output-stream "" "F - test-copy-invalid-value-to-address: output should be empty") + 7943 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar" "F - test-copy-invalid-value-to-address: error message") + 7944 # check that stop(1) was called + 7945 (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status") + 7946 # don't restore from ebp + 7947 81 0/subop/add %esp 8/imm32 + 7948 # . epilogue + 7949 5d/pop-to-ebp + 7950 c3/return + 7951 + 7952 test-copy-null-value-to-offset: + 7953 # . prologue + 7954 55/push-ebp + 7955 89/<- %ebp 4/r32/esp + 7956 # setup + 7957 (clear-stream _test-input-stream) + 7958 (clear-stream $_test-input-buffered-file->buffer) + 7959 (clear-stream _test-output-stream) + 7960 (clear-stream $_test-output-buffered-file->buffer) + 7961 # + 7962 (write _test-input-stream "fn foo {\n") + 7963 (write _test-input-stream " var y/ecx: (offset int) <- copy 0\n") + 7964 (write _test-input-stream "}\n") + 7965 # convert + 7966 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 7967 (flush _test-output-buffered-file) + 7968 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 7974 # no errors + 7975 # . epilogue + 7976 89/<- %esp 5/r32/ebp + 7977 5d/pop-to-ebp + 7978 c3/return + 7979 + 7980 test-copy-non-literal-to-byte: + 7981 # . prologue + 7982 55/push-ebp + 7983 89/<- %ebp 4/r32/esp + 7984 # setup + 7985 (clear-stream _test-input-stream) + 7986 (clear-stream $_test-input-buffered-file->buffer) + 7987 (clear-stream _test-output-stream) + 7988 (clear-stream $_test-output-buffered-file->buffer) + 7989 (clear-stream _test-error-stream) + 7990 (clear-stream $_test-error-buffered-file->buffer) + 7991 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 7992 68/push 0/imm32 + 7993 68/push 0/imm32 + 7994 89/<- %edx 4/r32/esp + 7995 (tailor-exit-descriptor %edx 0x10) + 7996 # + 7997 (write _test-input-stream "fn foo {\n") + 7998 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 7999 (write _test-input-stream " var y/ecx: byte <- copy x\n") + 8000 (write _test-input-stream "}\n") + 8001 # convert + 8002 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8003 # registers except esp clobbered at this point + 8004 # restore ed + 8005 89/<- %edx 4/r32/esp + 8006 (flush _test-output-buffered-file) + 8007 (flush _test-error-buffered-file) + 8008 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8014 # check output + 8015 (check-stream-equal _test-output-stream "" "F - test-copy-non-literal-to-byte: output should be empty") + 8016 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte" "F - test-copy-non-literal-to-byte: error message") + 8017 # check that stop(1) was called + 8018 (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status") + 8019 # don't restore from ebp + 8020 81 0/subop/add %esp 8/imm32 + 8021 # . epilogue + 8022 5d/pop-to-ebp + 8023 c3/return + 8024 + 8025 test-copy-deref-address: + 8026 # . prologue + 8027 55/push-ebp + 8028 89/<- %ebp 4/r32/esp + 8029 # setup + 8030 (clear-stream _test-input-stream) + 8031 (clear-stream $_test-input-buffered-file->buffer) + 8032 (clear-stream _test-output-stream) + 8033 (clear-stream $_test-output-buffered-file->buffer) + 8034 # + 8035 (write _test-input-stream "fn foo {\n") + 8036 (write _test-input-stream " var x/eax: (addr addr int) <- copy 0\n") + 8037 (write _test-input-stream " var y/ecx: (addr int) <- copy *x\n") + 8038 (write _test-input-stream "}\n") + 8039 # convert + 8040 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 8041 (flush _test-output-buffered-file) + 8042 # no errors + 8043 # . epilogue + 8044 5d/pop-to-ebp + 8045 c3/return + 8046 + 8047 test-copy-to-non-register: + 8048 # . prologue + 8049 55/push-ebp + 8050 89/<- %ebp 4/r32/esp + 8051 # setup + 8052 (clear-stream _test-input-stream) + 8053 (clear-stream $_test-input-buffered-file->buffer) + 8054 (clear-stream _test-output-stream) + 8055 (clear-stream $_test-output-buffered-file->buffer) + 8056 (clear-stream _test-error-stream) + 8057 (clear-stream $_test-error-buffered-file->buffer) + 8058 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8059 68/push 0/imm32 + 8060 68/push 0/imm32 + 8061 89/<- %edx 4/r32/esp + 8062 (tailor-exit-descriptor %edx 0x10) + 8063 # + 8064 (write _test-input-stream "fn foo {\n") + 8065 (write _test-input-stream " var x: int\n") + 8066 (write _test-input-stream " x <- copy 0\n") + 8067 (write _test-input-stream "}\n") + 8068 # convert + 8069 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8070 # registers except esp clobbered at this point + 8071 # restore ed + 8072 89/<- %edx 4/r32/esp + 8073 (flush _test-output-buffered-file) + 8074 (flush _test-error-buffered-file) + 8075 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8081 # check output + 8082 (check-stream-equal _test-output-stream "" "F - test-copy-to-non-register: output should be empty") + 8083 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: output 'x' not in a register" "F - test-copy-to-non-register: error message") + 8084 # check that stop(1) was called + 8085 (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status") + 8086 # don't restore from ebp + 8087 81 0/subop/add %esp 8/imm32 + 8088 # . epilogue + 8089 5d/pop-to-ebp + 8090 c3/return + 8091 + 8092 test-copy-from-non-scalar-inout: + 8093 # . prologue + 8094 55/push-ebp + 8095 89/<- %ebp 4/r32/esp + 8096 # setup + 8097 (clear-stream _test-input-stream) + 8098 (clear-stream $_test-input-buffered-file->buffer) + 8099 (clear-stream _test-output-stream) + 8100 (clear-stream $_test-output-buffered-file->buffer) + 8101 (clear-stream _test-error-stream) + 8102 (clear-stream $_test-error-buffered-file->buffer) + 8103 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8104 68/push 0/imm32 + 8105 68/push 0/imm32 + 8106 89/<- %edx 4/r32/esp + 8107 (tailor-exit-descriptor %edx 0x10) + 8108 # + 8109 (write _test-input-stream "fn foo {\n") + 8110 (write _test-input-stream " var x: (handle int)\n") + 8111 (write _test-input-stream " var y/eax: int <- copy x\n") + 8112 (write _test-input-stream "}\n") + 8113 # convert + 8114 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8115 # registers except esp clobbered at this point + 8116 # restore ed + 8117 89/<- %edx 4/r32/esp + 8118 (flush _test-output-buffered-file) + 8119 (flush _test-error-buffered-file) + 8120 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8126 # check output + 8127 (check-stream-equal _test-output-stream "" "F - test-copy-from-non-scalar-inout: output should be empty") + 8128 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy: 'x' is too large to fit in a register" "F - test-copy-from-non-scalar-inout: error message") + 8129 # check that stop(1) was called + 8130 (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status") + 8131 # don't restore from ebp + 8132 81 0/subop/add %esp 8/imm32 + 8133 # . epilogue + 8134 5d/pop-to-ebp + 8135 c3/return + 8136 + 8137 test-copy-to-with-no-inout: + 8138 # . prologue + 8139 55/push-ebp + 8140 89/<- %ebp 4/r32/esp + 8141 # setup + 8142 (clear-stream _test-input-stream) + 8143 (clear-stream $_test-input-buffered-file->buffer) + 8144 (clear-stream _test-output-stream) + 8145 (clear-stream $_test-output-buffered-file->buffer) + 8146 (clear-stream _test-error-stream) + 8147 (clear-stream $_test-error-buffered-file->buffer) + 8148 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8149 68/push 0/imm32 + 8150 68/push 0/imm32 + 8151 89/<- %edx 4/r32/esp + 8152 (tailor-exit-descriptor %edx 0x10) + 8153 # + 8154 (write _test-input-stream "fn foo {\n") + 8155 (write _test-input-stream " copy-to\n") + 8156 (write _test-input-stream "}\n") + 8157 # convert + 8158 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8159 # registers except esp clobbered at this point + 8160 # restore ed + 8161 89/<- %edx 4/r32/esp + 8162 (flush _test-output-buffered-file) + 8163 (flush _test-error-buffered-file) + 8164 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8170 # check output + 8171 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-no-inout: output should be empty") + 8172 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must have two inouts" "F - test-copy-to-with-no-inout: error message") + 8173 # check that stop(1) was called + 8174 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status") + 8175 # don't restore from ebp + 8176 81 0/subop/add %esp 8/imm32 + 8177 # . epilogue + 8178 5d/pop-to-ebp + 8179 c3/return + 8180 + 8181 test-copy-to-with-no-source: + 8182 # . prologue + 8183 55/push-ebp + 8184 89/<- %ebp 4/r32/esp + 8185 # setup + 8186 (clear-stream _test-input-stream) + 8187 (clear-stream $_test-input-buffered-file->buffer) + 8188 (clear-stream _test-output-stream) + 8189 (clear-stream $_test-output-buffered-file->buffer) + 8190 (clear-stream _test-error-stream) + 8191 (clear-stream $_test-error-buffered-file->buffer) + 8192 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8193 68/push 0/imm32 + 8194 68/push 0/imm32 + 8195 89/<- %edx 4/r32/esp + 8196 (tailor-exit-descriptor %edx 0x10) + 8197 # + 8198 (write _test-input-stream "fn foo {\n") + 8199 (write _test-input-stream " var x: boolean\n") + 8200 (write _test-input-stream " copy-to x\n") + 8201 (write _test-input-stream "}\n") + 8202 # convert + 8203 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8204 # registers except esp clobbered at this point + 8205 # restore ed + 8206 89/<- %edx 4/r32/esp + 8207 (flush _test-output-buffered-file) + 8208 (flush _test-error-buffered-file) + 8209 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8215 # check output + 8216 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-no-source: output should be empty") + 8217 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must have two inouts" "F - test-copy-to-with-no-source: error message") + 8218 # check that stop(1) was called + 8219 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status") + 8220 # don't restore from ebp + 8221 81 0/subop/add %esp 8/imm32 + 8222 # . epilogue + 8223 5d/pop-to-ebp + 8224 c3/return + 8225 + 8226 test-copy-to-with-no-register: + 8227 # . prologue + 8228 55/push-ebp + 8229 89/<- %ebp 4/r32/esp + 8230 # setup + 8231 (clear-stream _test-input-stream) + 8232 (clear-stream $_test-input-buffered-file->buffer) + 8233 (clear-stream _test-output-stream) + 8234 (clear-stream $_test-output-buffered-file->buffer) + 8235 (clear-stream _test-error-stream) + 8236 (clear-stream $_test-error-buffered-file->buffer) + 8237 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8238 68/push 0/imm32 + 8239 68/push 0/imm32 + 8240 89/<- %edx 4/r32/esp + 8241 (tailor-exit-descriptor %edx 0x10) + 8242 # + 8243 (write _test-input-stream "fn foo {\n") + 8244 (write _test-input-stream " var x: boolean\n") + 8245 (write _test-input-stream " copy-to x, x\n") + 8246 (write _test-input-stream "}\n") + 8247 # convert + 8248 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8249 # registers except esp clobbered at this point + 8250 # restore ed + 8251 89/<- %edx 4/r32/esp + 8252 (flush _test-output-buffered-file) + 8253 (flush _test-error-buffered-file) + 8254 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8260 # check output + 8261 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-no-register: output should be empty") + 8262 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: source (second inout) is in memory" "F - test-copy-to-with-no-register: error message") + 8263 # check that stop(1) was called + 8264 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status") + 8265 # don't restore from ebp + 8266 81 0/subop/add %esp 8/imm32 + 8267 # . epilogue + 8268 5d/pop-to-ebp + 8269 c3/return + 8270 + 8271 test-copy-to-with-too-many-inouts: + 8272 # . prologue + 8273 55/push-ebp + 8274 89/<- %ebp 4/r32/esp + 8275 # setup + 8276 (clear-stream _test-input-stream) + 8277 (clear-stream $_test-input-buffered-file->buffer) + 8278 (clear-stream _test-output-stream) + 8279 (clear-stream $_test-output-buffered-file->buffer) + 8280 (clear-stream _test-error-stream) + 8281 (clear-stream $_test-error-buffered-file->buffer) + 8282 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8283 68/push 0/imm32 + 8284 68/push 0/imm32 + 8285 89/<- %edx 4/r32/esp + 8286 (tailor-exit-descriptor %edx 0x10) + 8287 # + 8288 (write _test-input-stream "fn foo {\n") + 8289 (write _test-input-stream " var x: boolean\n") + 8290 (write _test-input-stream " copy-to x, 0, 0\n") + 8291 (write _test-input-stream "}\n") + 8292 # convert + 8293 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8294 # registers except esp clobbered at this point + 8295 # restore ed + 8296 89/<- %edx 4/r32/esp + 8297 (flush _test-output-buffered-file) + 8298 (flush _test-error-buffered-file) + 8299 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8305 # check output + 8306 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-too-many-inouts: output should be empty") + 8307 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must have two inouts" "F - test-copy-to-with-too-many-inouts: error message") + 8308 # check that stop(1) was called + 8309 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status") + 8310 # don't restore from ebp + 8311 81 0/subop/add %esp 8/imm32 + 8312 # . epilogue + 8313 5d/pop-to-ebp + 8314 c3/return + 8315 + 8316 test-copy-to-with-output: + 8317 # . prologue + 8318 55/push-ebp + 8319 89/<- %ebp 4/r32/esp + 8320 # setup + 8321 (clear-stream _test-input-stream) + 8322 (clear-stream $_test-input-buffered-file->buffer) + 8323 (clear-stream _test-output-stream) + 8324 (clear-stream $_test-output-buffered-file->buffer) + 8325 (clear-stream _test-error-stream) + 8326 (clear-stream $_test-error-buffered-file->buffer) + 8327 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8328 68/push 0/imm32 + 8329 68/push 0/imm32 + 8330 89/<- %edx 4/r32/esp + 8331 (tailor-exit-descriptor %edx 0x10) + 8332 # + 8333 (write _test-input-stream "fn foo {\n") + 8334 (write _test-input-stream " var x/eax: boolean <- copy 0\n") + 8335 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") + 8336 (write _test-input-stream " x <- copy-to y, 0\n") + 8337 (write _test-input-stream "}\n") + 8338 # convert + 8339 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8340 # registers except esp clobbered at this point + 8341 # restore ed + 8342 89/<- %edx 4/r32/esp + 8343 (flush _test-output-buffered-file) + 8344 (flush _test-error-buffered-file) + 8345 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8351 # check output + 8352 (check-stream-equal _test-output-stream "" "F - test-copy-to-with-output: output should be empty") + 8353 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-to' must not have any outputs" "F - test-copy-to-with-output: error message") + 8354 # check that stop(1) was called + 8355 (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status") + 8356 # don't restore from ebp + 8357 81 0/subop/add %esp 8/imm32 + 8358 # . epilogue + 8359 5d/pop-to-ebp + 8360 c3/return + 8361 + 8362 test-copy-to-invalid-value-to-address: + 8363 # . prologue + 8364 55/push-ebp + 8365 89/<- %ebp 4/r32/esp + 8366 # setup + 8367 (clear-stream _test-input-stream) + 8368 (clear-stream $_test-input-buffered-file->buffer) + 8369 (clear-stream _test-output-stream) + 8370 (clear-stream $_test-output-buffered-file->buffer) + 8371 (clear-stream _test-error-stream) + 8372 (clear-stream $_test-error-buffered-file->buffer) + 8373 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8374 68/push 0/imm32 + 8375 68/push 0/imm32 + 8376 89/<- %edx 4/r32/esp + 8377 (tailor-exit-descriptor %edx 0x10) + 8378 # + 8379 (write _test-input-stream "fn foo {\n") + 8380 (write _test-input-stream " var x/eax: int <- copy 0\n") + 8381 (write _test-input-stream " var y: (addr int)\n") + 8382 (write _test-input-stream " copy-to y, x\n") + 8383 (write _test-input-stream "}\n") + 8384 # convert + 8385 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8386 # registers except esp clobbered at this point + 8387 # restore ed + 8388 89/<- %edx 4/r32/esp + 8389 (flush _test-output-buffered-file) + 8390 (flush _test-error-buffered-file) + 8391 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8397 # check output + 8398 (check-stream-equal _test-output-stream "" "F - test-copy-to-invalid-value-to-address: output should be empty") + 8399 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar" "F - test-copy-to-invalid-value-to-address: error message") + 8400 # check that stop(1) was called + 8401 (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status") + 8402 # don't restore from ebp + 8403 81 0/subop/add %esp 8/imm32 + 8404 # . epilogue + 8405 5d/pop-to-ebp + 8406 c3/return + 8407 + 8408 test-copy-to-null-value-to-address: + 8409 # . prologue + 8410 55/push-ebp + 8411 89/<- %ebp 4/r32/esp + 8412 # setup + 8413 (clear-stream _test-input-stream) + 8414 (clear-stream $_test-input-buffered-file->buffer) + 8415 (clear-stream _test-output-stream) + 8416 (clear-stream $_test-output-buffered-file->buffer) + 8417 # + 8418 (write _test-input-stream "fn foo {\n") + 8419 (write _test-input-stream " var y: (addr int)\n") + 8420 (write _test-input-stream " copy-to y, 0\n") + 8421 (write _test-input-stream "}\n") + 8422 # convert + 8423 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 8424 (flush _test-output-buffered-file) + 8425 # no errors + 8426 # . epilogue + 8427 89/<- %esp 5/r32/ebp + 8428 5d/pop-to-ebp + 8429 c3/return + 8430 + 8431 test-copy-to-invalid-value-to-offset: + 8432 # . prologue + 8433 55/push-ebp + 8434 89/<- %ebp 4/r32/esp + 8435 # setup + 8436 (clear-stream _test-input-stream) + 8437 (clear-stream $_test-input-buffered-file->buffer) + 8438 (clear-stream _test-output-stream) + 8439 (clear-stream $_test-output-buffered-file->buffer) + 8440 (clear-stream _test-error-stream) + 8441 (clear-stream $_test-error-buffered-file->buffer) + 8442 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8443 68/push 0/imm32 + 8444 68/push 0/imm32 + 8445 89/<- %edx 4/r32/esp + 8446 (tailor-exit-descriptor %edx 0x10) + 8447 # + 8448 (write _test-input-stream "fn foo {\n") + 8449 (write _test-input-stream " var x/eax: int <- copy 0\n") + 8450 (write _test-input-stream " var y: (offset int)\n") + 8451 (write _test-input-stream " copy-to y, x\n") + 8452 (write _test-input-stream "}\n") + 8453 # convert + 8454 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8455 # registers except esp clobbered at this point + 8456 # restore ed + 8457 89/<- %edx 4/r32/esp + 8458 (flush _test-output-buffered-file) + 8459 (flush _test-error-buffered-file) + 8460 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8466 # check output + 8467 (check-stream-equal _test-output-stream "" "F - test-copy-to-invalid-value-to-offset: output should be empty") + 8468 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar" "F - test-copy-to-invalid-value-to-offset: error message") + 8469 # check that stop(1) was called + 8470 (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status") + 8471 # don't restore from ebp + 8472 81 0/subop/add %esp 8/imm32 + 8473 # . epilogue + 8474 5d/pop-to-ebp + 8475 c3/return + 8476 + 8477 test-copy-to-null-value-to-offset: + 8478 # . prologue + 8479 55/push-ebp + 8480 89/<- %ebp 4/r32/esp + 8481 # setup + 8482 (clear-stream _test-input-stream) + 8483 (clear-stream $_test-input-buffered-file->buffer) + 8484 (clear-stream _test-output-stream) + 8485 (clear-stream $_test-output-buffered-file->buffer) + 8486 # + 8487 (write _test-input-stream "fn foo {\n") + 8488 (write _test-input-stream " var y: (offset int)\n") + 8489 (write _test-input-stream " copy-to y, 0\n") + 8490 (write _test-input-stream "}\n") + 8491 # convert + 8492 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 8493 (flush _test-output-buffered-file) + 8494 # no errors + 8495 # . epilogue + 8496 89/<- %esp 5/r32/ebp + 8497 5d/pop-to-ebp + 8498 c3/return + 8499 + 8500 test-copy-to-non-literal-to-byte: + 8501 # . prologue + 8502 55/push-ebp + 8503 89/<- %ebp 4/r32/esp + 8504 # setup + 8505 (clear-stream _test-input-stream) + 8506 (clear-stream $_test-input-buffered-file->buffer) + 8507 (clear-stream _test-output-stream) + 8508 (clear-stream $_test-output-buffered-file->buffer) + 8509 (clear-stream _test-error-stream) + 8510 (clear-stream $_test-error-buffered-file->buffer) + 8511 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8512 68/push 0/imm32 + 8513 68/push 0/imm32 + 8514 89/<- %edx 4/r32/esp + 8515 (tailor-exit-descriptor %edx 0x10) + 8516 # + 8517 (write _test-input-stream "fn foo {\n") + 8518 (write _test-input-stream " var x/ecx: byte <- copy 3\n") + 8519 (write _test-input-stream " var y/eax: (addr byte) <- copy 0\n") + 8520 (write _test-input-stream " copy-to *y, x\n") + 8521 (write _test-input-stream "}\n") + 8522 # convert + 8523 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8524 # registers except esp clobbered at this point + 8525 # restore ed + 8526 89/<- %edx 4/r32/esp + 8527 (flush _test-output-buffered-file) + 8528 (flush _test-error-buffered-file) + 8529 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8535 # check output + 8536 (check-stream-equal _test-output-stream "" "F - test-copy-to-non-literal-to-byte: output should be empty") + 8537 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to" "F - test-copy-to-non-literal-to-byte: error message") + 8538 # check that stop(1) was called + 8539 (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status") + 8540 # don't restore from ebp + 8541 81 0/subop/add %esp 8/imm32 + 8542 # . epilogue + 8543 5d/pop-to-ebp + 8544 c3/return + 8545 + 8546 test-copy-to-deref-address: + 8547 # . prologue + 8548 55/push-ebp + 8549 89/<- %ebp 4/r32/esp + 8550 # setup + 8551 (clear-stream _test-input-stream) + 8552 (clear-stream $_test-input-buffered-file->buffer) + 8553 (clear-stream _test-output-stream) + 8554 (clear-stream $_test-output-buffered-file->buffer) + 8555 # + 8556 (write _test-input-stream "fn foo {\n") + 8557 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") + 8558 (write _test-input-stream " var y/ecx: (addr addr int) <- copy 0\n") + 8559 (write _test-input-stream " copy-to *y, x\n") + 8560 (write _test-input-stream "}\n") + 8561 # convert + 8562 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 8563 (flush _test-output-buffered-file) + 8564 # no errors + 8565 # . epilogue + 8566 5d/pop-to-ebp + 8567 c3/return + 8568 + 8569 test-copy-to-from-non-scalar-inout: + 8570 # . prologue + 8571 55/push-ebp + 8572 89/<- %ebp 4/r32/esp + 8573 # setup + 8574 (clear-stream _test-input-stream) + 8575 (clear-stream $_test-input-buffered-file->buffer) + 8576 (clear-stream _test-output-stream) + 8577 (clear-stream $_test-output-buffered-file->buffer) + 8578 (clear-stream _test-error-stream) + 8579 (clear-stream $_test-error-buffered-file->buffer) + 8580 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8581 68/push 0/imm32 + 8582 68/push 0/imm32 + 8583 89/<- %edx 4/r32/esp + 8584 (tailor-exit-descriptor %edx 0x10) + 8585 # + 8586 (write _test-input-stream "fn foo {\n") + 8587 (write _test-input-stream " var x: (handle int)\n") + 8588 (write _test-input-stream " var y: int\n") + 8589 (write _test-input-stream " copy-to y, x\n") + 8590 (write _test-input-stream "}\n") + 8591 # convert + 8592 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8593 # registers except esp clobbered at this point + 8594 # restore ed + 8595 89/<- %edx 4/r32/esp + 8596 (flush _test-output-buffered-file) + 8597 (flush _test-error-buffered-file) + 8598 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8604 # check output + 8605 (check-stream-equal _test-output-stream "" "F - test-copy-to-from-non-scalar-inout: output should be empty") + 8606 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-to: 'x' is too large to copy" "F - test-copy-to-from-non-scalar-inout: error message") + 8607 # check that stop(1) was called + 8608 (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status") + 8609 # don't restore from ebp + 8610 81 0/subop/add %esp 8/imm32 + 8611 # . epilogue + 8612 5d/pop-to-ebp + 8613 c3/return + 8614 + 8615 test-copy-byte-with-no-inout: + 8616 # . prologue + 8617 55/push-ebp + 8618 89/<- %ebp 4/r32/esp + 8619 # setup + 8620 (clear-stream _test-input-stream) + 8621 (clear-stream $_test-input-buffered-file->buffer) + 8622 (clear-stream _test-output-stream) + 8623 (clear-stream $_test-output-buffered-file->buffer) + 8624 (clear-stream _test-error-stream) + 8625 (clear-stream $_test-error-buffered-file->buffer) + 8626 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8627 68/push 0/imm32 + 8628 68/push 0/imm32 + 8629 89/<- %edx 4/r32/esp + 8630 (tailor-exit-descriptor %edx 0x10) + 8631 # + 8632 (write _test-input-stream "fn foo {\n") + 8633 (write _test-input-stream " var x/eax: byte <- copy-byte\n") + 8634 (write _test-input-stream "}\n") + 8635 # convert + 8636 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8637 # registers except esp clobbered at this point + 8638 # restore ed + 8639 89/<- %edx 4/r32/esp + 8640 (flush _test-output-buffered-file) + 8641 (flush _test-error-buffered-file) + 8642 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8648 # check output + 8649 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-no-inout: output should be empty") + 8650 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' expects an inout" "F - test-copy-byte-with-no-inout: error message") + 8651 # check that stop(1) was called + 8652 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status") + 8653 # don't restore from ebp + 8654 81 0/subop/add %esp 8/imm32 + 8655 # . epilogue + 8656 5d/pop-to-ebp + 8657 c3/return + 8658 + 8659 test-copy-byte-with-multiple-inouts: + 8660 # . prologue + 8661 55/push-ebp + 8662 89/<- %ebp 4/r32/esp + 8663 # setup + 8664 (clear-stream _test-input-stream) + 8665 (clear-stream $_test-input-buffered-file->buffer) + 8666 (clear-stream _test-output-stream) + 8667 (clear-stream $_test-output-buffered-file->buffer) + 8668 (clear-stream _test-error-stream) + 8669 (clear-stream $_test-error-buffered-file->buffer) + 8670 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8671 68/push 0/imm32 + 8672 68/push 0/imm32 + 8673 89/<- %edx 4/r32/esp + 8674 (tailor-exit-descriptor %edx 0x10) + 8675 # + 8676 (write _test-input-stream "fn foo {\n") + 8677 (write _test-input-stream " var x/eax: byte <- copy-byte 0, 0\n") + 8678 (write _test-input-stream "}\n") + 8679 # convert + 8680 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8681 # registers except esp clobbered at this point + 8682 # restore ed + 8683 89/<- %edx 4/r32/esp + 8684 (flush _test-output-buffered-file) + 8685 (flush _test-error-buffered-file) + 8686 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8692 # check output + 8693 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-multiple-inouts: output should be empty") + 8694 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' must have just one inout" "F - test-copy-byte-with-multiple-inouts: error message") + 8695 # check that stop(1) was called + 8696 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status") + 8697 # don't restore from ebp + 8698 81 0/subop/add %esp 8/imm32 + 8699 # . epilogue + 8700 5d/pop-to-ebp + 8701 c3/return + 8702 + 8703 test-copy-byte-with-no-output: + 8704 # . prologue + 8705 55/push-ebp + 8706 89/<- %ebp 4/r32/esp + 8707 # setup + 8708 (clear-stream _test-input-stream) + 8709 (clear-stream $_test-input-buffered-file->buffer) + 8710 (clear-stream _test-output-stream) + 8711 (clear-stream $_test-output-buffered-file->buffer) + 8712 (clear-stream _test-error-stream) + 8713 (clear-stream $_test-error-buffered-file->buffer) + 8714 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8715 68/push 0/imm32 + 8716 68/push 0/imm32 + 8717 89/<- %edx 4/r32/esp + 8718 (tailor-exit-descriptor %edx 0x10) + 8719 # + 8720 (write _test-input-stream "fn foo {\n") + 8721 (write _test-input-stream " copy-byte 0\n") + 8722 (write _test-input-stream "}\n") + 8723 # convert + 8724 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8725 # registers except esp clobbered at this point + 8726 # restore ed + 8727 89/<- %edx 4/r32/esp + 8728 (flush _test-output-buffered-file) + 8729 (flush _test-error-buffered-file) + 8730 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8736 # check output + 8737 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-no-output: output should be empty") + 8738 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' expects an output" "F - test-copy-byte-with-no-output: error message") + 8739 # check that stop(1) was called + 8740 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status") + 8741 # don't restore from ebp + 8742 81 0/subop/add %esp 8/imm32 + 8743 # . epilogue + 8744 5d/pop-to-ebp + 8745 c3/return + 8746 + 8747 test-copy-byte-with-multiple-outputs: + 8748 # . prologue + 8749 55/push-ebp + 8750 89/<- %ebp 4/r32/esp + 8751 # setup + 8752 (clear-stream _test-input-stream) + 8753 (clear-stream $_test-input-buffered-file->buffer) + 8754 (clear-stream _test-output-stream) + 8755 (clear-stream $_test-output-buffered-file->buffer) + 8756 (clear-stream _test-error-stream) + 8757 (clear-stream $_test-error-buffered-file->buffer) + 8758 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8759 68/push 0/imm32 + 8760 68/push 0/imm32 + 8761 89/<- %edx 4/r32/esp + 8762 (tailor-exit-descriptor %edx 0x10) + 8763 # + 8764 (write _test-input-stream "fn foo {\n") + 8765 (write _test-input-stream " var x/eax: byte <- copy 0\n") + 8766 (write _test-input-stream " var y/ecx: byte <- copy 0\n") + 8767 (write _test-input-stream " x, y <- copy-byte 0\n") + 8768 (write _test-input-stream "}\n") + 8769 # convert + 8770 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8771 # registers except esp clobbered at this point + 8772 # restore ed + 8773 89/<- %edx 4/r32/esp + 8774 (flush _test-output-buffered-file) + 8775 (flush _test-error-buffered-file) + 8776 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8782 # check output + 8783 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-multiple-outputs: output should be empty") + 8784 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' must have just one output" "F - test-copy-byte-with-multiple-outputs: error message") + 8785 # check that stop(1) was called + 8786 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status") + 8787 # don't restore from ebp + 8788 81 0/subop/add %esp 8/imm32 + 8789 # . epilogue + 8790 5d/pop-to-ebp + 8791 c3/return + 8792 + 8793 test-copy-byte-deref-address: + 8794 # . prologue + 8795 55/push-ebp + 8796 89/<- %ebp 4/r32/esp + 8797 # setup + 8798 (clear-stream _test-input-stream) + 8799 (clear-stream $_test-input-buffered-file->buffer) + 8800 (clear-stream _test-output-stream) + 8801 (clear-stream $_test-output-buffered-file->buffer) + 8802 # + 8803 (write _test-input-stream "fn foo {\n") + 8804 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") + 8805 (write _test-input-stream " var y/ecx: byte <- copy-byte *x\n") + 8806 (write _test-input-stream "}\n") + 8807 # convert + 8808 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 8809 (flush _test-output-buffered-file) + 8810 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8816 # not bothering checking output + 8817 (check-next-stream-line-equal _test-error-stream "" "F - test-copy-byte-deref-address: error message") + 8818 # . epilogue + 8819 5d/pop-to-ebp + 8820 c3/return + 8821 + 8822 test-copy-byte-with-invalid-output-type: + 8823 # . prologue + 8824 55/push-ebp + 8825 89/<- %ebp 4/r32/esp + 8826 # setup + 8827 (clear-stream _test-input-stream) + 8828 (clear-stream $_test-input-buffered-file->buffer) + 8829 (clear-stream _test-output-stream) + 8830 (clear-stream $_test-output-buffered-file->buffer) + 8831 (clear-stream _test-error-stream) + 8832 (clear-stream $_test-error-buffered-file->buffer) + 8833 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8834 68/push 0/imm32 + 8835 68/push 0/imm32 + 8836 89/<- %edx 4/r32/esp + 8837 (tailor-exit-descriptor %edx 0x10) + 8838 # + 8839 (write _test-input-stream "fn foo {\n") + 8840 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") + 8841 (write _test-input-stream " var y/eax: int <- copy-byte *x\n") + 8842 (write _test-input-stream "}\n") + 8843 # convert + 8844 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8845 # registers except esp clobbered at this point + 8846 # restore ed + 8847 89/<- %edx 4/r32/esp + 8848 (flush _test-output-buffered-file) + 8849 (flush _test-error-buffered-file) + 8850 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8856 # check output + 8857 (check-stream-equal _test-output-stream "" "F - test-copy-byte-with-invalid-output-type: output should be empty") + 8858 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte' must write to output of type byte" "F - test-copy-byte-with-invalid-output-type: error message") + 8859 # check that stop(1) was called + 8860 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status") + 8861 # don't restore from ebp + 8862 81 0/subop/add %esp 8/imm32 + 8863 # . epilogue + 8864 5d/pop-to-ebp + 8865 c3/return + 8866 + 8867 test-copy-byte-from-non-scalar-inout: + 8868 # . prologue + 8869 55/push-ebp + 8870 89/<- %ebp 4/r32/esp + 8871 # setup + 8872 (clear-stream _test-input-stream) + 8873 (clear-stream $_test-input-buffered-file->buffer) + 8874 (clear-stream _test-output-stream) + 8875 (clear-stream $_test-output-buffered-file->buffer) + 8876 (clear-stream _test-error-stream) + 8877 (clear-stream $_test-error-buffered-file->buffer) + 8878 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8879 68/push 0/imm32 + 8880 68/push 0/imm32 + 8881 89/<- %edx 4/r32/esp + 8882 (tailor-exit-descriptor %edx 0x10) + 8883 # + 8884 (write _test-input-stream "fn foo {\n") + 8885 (write _test-input-stream " var x: (handle int)\n") + 8886 (write _test-input-stream " var y/eax: byte <- copy-byte x\n") + 8887 (write _test-input-stream "}\n") + 8888 # convert + 8889 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8890 # registers except esp clobbered at this point + 8891 # restore ed + 8892 89/<- %edx 4/r32/esp + 8893 (flush _test-output-buffered-file) + 8894 (flush _test-error-buffered-file) + 8895 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8901 # check output + 8902 (check-stream-equal _test-output-stream "" "F - test-copy-byte-from-non-scalar-inout: output should be empty") + 8903 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte: 'x' is too large to fit in a register" "F - test-copy-byte-from-non-scalar-inout: error message") + 8904 # check that stop(1) was called + 8905 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status") + 8906 # don't restore from ebp + 8907 81 0/subop/add %esp 8/imm32 + 8908 # . epilogue + 8909 5d/pop-to-ebp + 8910 c3/return + 8911 + 8912 test-copy-byte-to-with-no-inout: + 8913 # . prologue + 8914 55/push-ebp + 8915 89/<- %ebp 4/r32/esp + 8916 # setup + 8917 (clear-stream _test-input-stream) + 8918 (clear-stream $_test-input-buffered-file->buffer) + 8919 (clear-stream _test-output-stream) + 8920 (clear-stream $_test-output-buffered-file->buffer) + 8921 (clear-stream _test-error-stream) + 8922 (clear-stream $_test-error-buffered-file->buffer) + 8923 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8924 68/push 0/imm32 + 8925 68/push 0/imm32 + 8926 89/<- %edx 4/r32/esp + 8927 (tailor-exit-descriptor %edx 0x10) + 8928 # + 8929 (write _test-input-stream "fn foo {\n") + 8930 (write _test-input-stream " copy-byte-to\n") + 8931 (write _test-input-stream "}\n") + 8932 # convert + 8933 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8934 # registers except esp clobbered at this point + 8935 # restore ed + 8936 89/<- %edx 4/r32/esp + 8937 (flush _test-output-buffered-file) + 8938 (flush _test-error-buffered-file) + 8939 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8945 # check output + 8946 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-no-inout: output should be empty") + 8947 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must have two inouts" "F - test-copy-byte-to-with-no-inout: error message") + 8948 # check that stop(1) was called + 8949 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status") + 8950 # don't restore from ebp + 8951 81 0/subop/add %esp 8/imm32 + 8952 # . epilogue + 8953 5d/pop-to-ebp + 8954 c3/return + 8955 + 8956 test-copy-byte-to-with-no-source: + 8957 # . prologue + 8958 55/push-ebp + 8959 89/<- %ebp 4/r32/esp + 8960 # setup + 8961 (clear-stream _test-input-stream) + 8962 (clear-stream $_test-input-buffered-file->buffer) + 8963 (clear-stream _test-output-stream) + 8964 (clear-stream $_test-output-buffered-file->buffer) + 8965 (clear-stream _test-error-stream) + 8966 (clear-stream $_test-error-buffered-file->buffer) + 8967 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 8968 68/push 0/imm32 + 8969 68/push 0/imm32 + 8970 89/<- %edx 4/r32/esp + 8971 (tailor-exit-descriptor %edx 0x10) + 8972 # + 8973 (write _test-input-stream "fn foo {\n") + 8974 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") + 8975 (write _test-input-stream " copy-byte-to *x\n") + 8976 (write _test-input-stream "}\n") + 8977 # convert + 8978 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 8979 # registers except esp clobbered at this point + 8980 # restore ed + 8981 89/<- %edx 4/r32/esp + 8982 (flush _test-output-buffered-file) + 8983 (flush _test-error-buffered-file) + 8984 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 8990 # check output + 8991 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-no-source: output should be empty") + 8992 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must have two inouts" "F - test-copy-byte-to-with-no-source: error message") + 8993 # check that stop(1) was called + 8994 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status") + 8995 # don't restore from ebp + 8996 81 0/subop/add %esp 8/imm32 + 8997 # . epilogue + 8998 5d/pop-to-ebp + 8999 c3/return + 9000 + 9001 test-copy-byte-to-with-too-many-inouts: + 9002 # . prologue + 9003 55/push-ebp + 9004 89/<- %ebp 4/r32/esp + 9005 # setup + 9006 (clear-stream _test-input-stream) + 9007 (clear-stream $_test-input-buffered-file->buffer) + 9008 (clear-stream _test-output-stream) + 9009 (clear-stream $_test-output-buffered-file->buffer) + 9010 (clear-stream _test-error-stream) + 9011 (clear-stream $_test-error-buffered-file->buffer) + 9012 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9013 68/push 0/imm32 + 9014 68/push 0/imm32 + 9015 89/<- %edx 4/r32/esp + 9016 (tailor-exit-descriptor %edx 0x10) + 9017 # + 9018 (write _test-input-stream "fn foo {\n") + 9019 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") + 9020 (write _test-input-stream " copy-byte-to *x, 0, 0\n") + 9021 (write _test-input-stream "}\n") + 9022 # convert + 9023 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9024 # registers except esp clobbered at this point + 9025 # restore ed + 9026 89/<- %edx 4/r32/esp + 9027 (flush _test-output-buffered-file) + 9028 (flush _test-error-buffered-file) + 9029 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9035 # check output + 9036 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-too-many-inouts: output should be empty") + 9037 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must have two inouts" "F - test-copy-byte-to-with-too-many-inouts: error message") + 9038 # check that stop(1) was called + 9039 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status") + 9040 # don't restore from ebp + 9041 81 0/subop/add %esp 8/imm32 + 9042 # . epilogue + 9043 5d/pop-to-ebp + 9044 c3/return + 9045 + 9046 test-copy-byte-to-with-output: + 9047 # . prologue + 9048 55/push-ebp + 9049 89/<- %ebp 4/r32/esp + 9050 # setup + 9051 (clear-stream _test-input-stream) + 9052 (clear-stream $_test-input-buffered-file->buffer) + 9053 (clear-stream _test-output-stream) + 9054 (clear-stream $_test-output-buffered-file->buffer) + 9055 (clear-stream _test-error-stream) + 9056 (clear-stream $_test-error-buffered-file->buffer) + 9057 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9058 68/push 0/imm32 + 9059 68/push 0/imm32 + 9060 89/<- %edx 4/r32/esp + 9061 (tailor-exit-descriptor %edx 0x10) + 9062 # + 9063 (write _test-input-stream "fn foo {\n") + 9064 (write _test-input-stream " var x/eax: byte <- copy 0\n") + 9065 (write _test-input-stream " var y/ecx: (addr byte) <- copy 0\n") + 9066 (write _test-input-stream " x <- copy-byte-to *y, 0\n") + 9067 (write _test-input-stream "}\n") + 9068 # convert + 9069 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9070 # registers except esp clobbered at this point + 9071 # restore ed + 9072 89/<- %edx 4/r32/esp + 9073 (flush _test-output-buffered-file) + 9074 (flush _test-error-buffered-file) + 9075 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9081 # check output + 9082 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-output: output should be empty") + 9083 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-byte-to' must not have any outputs" "F - test-copy-byte-to-with-output: error message") + 9084 # check that stop(1) was called + 9085 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status") + 9086 # don't restore from ebp + 9087 81 0/subop/add %esp 8/imm32 + 9088 # . epilogue + 9089 5d/pop-to-ebp + 9090 c3/return + 9091 + 9092 test-copy-byte-to-with-invalid-output-type: + 9093 # . prologue + 9094 55/push-ebp + 9095 89/<- %ebp 4/r32/esp + 9096 # setup + 9097 (clear-stream _test-input-stream) + 9098 (clear-stream $_test-input-buffered-file->buffer) + 9099 (clear-stream _test-output-stream) + 9100 (clear-stream $_test-output-buffered-file->buffer) + 9101 (clear-stream _test-error-stream) + 9102 (clear-stream $_test-error-buffered-file->buffer) + 9103 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9104 68/push 0/imm32 + 9105 68/push 0/imm32 + 9106 89/<- %edx 4/r32/esp + 9107 (tailor-exit-descriptor %edx 0x10) + 9108 # + 9109 (write _test-input-stream "fn foo {\n") + 9110 (write _test-input-stream " var x/eax: byte <- copy 0\n") + 9111 (write _test-input-stream " var y: int\n") + 9112 (write _test-input-stream " copy-byte-to y, x\n") + 9113 (write _test-input-stream "}\n") + 9114 # convert + 9115 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9116 # registers except esp clobbered at this point + 9117 # restore ed + 9118 89/<- %edx 4/r32/esp + 9119 (flush _test-output-buffered-file) + 9120 (flush _test-error-buffered-file) + 9121 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9127 # check output + 9128 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-invalid-output-type: output should be empty") + 9129 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte-to: 'y' must be a byte" "F - test-copy-byte-to-with-invalid-output-type: error message") + 9130 # check that stop(1) was called + 9131 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status") + 9132 # don't restore from ebp + 9133 81 0/subop/add %esp 8/imm32 + 9134 # . epilogue + 9135 5d/pop-to-ebp + 9136 c3/return + 9137 + 9138 test-copy-byte-to-with-literal-inout: + 9139 # . prologue + 9140 55/push-ebp + 9141 89/<- %ebp 4/r32/esp + 9142 # setup + 9143 (clear-stream _test-input-stream) + 9144 (clear-stream $_test-input-buffered-file->buffer) + 9145 (clear-stream _test-output-stream) + 9146 (clear-stream $_test-output-buffered-file->buffer) + 9147 (clear-stream _test-error-stream) + 9148 (clear-stream $_test-error-buffered-file->buffer) + 9149 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9150 68/push 0/imm32 + 9151 68/push 0/imm32 + 9152 89/<- %edx 4/r32/esp + 9153 (tailor-exit-descriptor %edx 0x10) + 9154 # + 9155 (write _test-input-stream "fn foo {\n") + 9156 (write _test-input-stream " var x/eax: (addr byte) <- copy 0\n") + 9157 (write _test-input-stream " copy-byte-to *x, 0\n") + 9158 (write _test-input-stream "}\n") + 9159 # convert + 9160 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9161 # registers except esp clobbered at this point + 9162 # restore ed + 9163 89/<- %edx 4/r32/esp + 9164 (flush _test-output-buffered-file) + 9165 (flush _test-error-buffered-file) + 9166 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9172 # check output + 9173 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-with-literal-inout: output should be empty") + 9174 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte-to: source (second inout) must be in a register" "F - test-copy-byte-to-with-literal-inout: error message") + 9175 # check that stop(1) was called + 9176 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status") + 9177 # don't restore from ebp + 9178 81 0/subop/add %esp 8/imm32 + 9179 # . epilogue + 9180 5d/pop-to-ebp + 9181 c3/return + 9182 + 9183 test-copy-byte-to-deref-address: + 9184 # . prologue + 9185 55/push-ebp + 9186 89/<- %ebp 4/r32/esp + 9187 # setup + 9188 (clear-stream _test-input-stream) + 9189 (clear-stream $_test-input-buffered-file->buffer) + 9190 (clear-stream _test-output-stream) + 9191 (clear-stream $_test-output-buffered-file->buffer) + 9192 # + 9193 (write _test-input-stream "fn foo {\n") + 9194 (write _test-input-stream " var x/eax: byte <- copy 0\n") + 9195 (write _test-input-stream " var y/ecx: (addr byte) <- copy 0\n") + 9196 (write _test-input-stream " copy-byte-to *y, x\n") + 9197 (write _test-input-stream "}\n") + 9198 # convert + 9199 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 9200 (flush _test-output-buffered-file) + 9201 # no errors + 9202 # . epilogue + 9203 5d/pop-to-ebp + 9204 c3/return + 9205 + 9206 test-copy-byte-to-from-non-scalar-inout: + 9207 # . prologue + 9208 55/push-ebp + 9209 89/<- %ebp 4/r32/esp + 9210 # setup + 9211 (clear-stream _test-input-stream) + 9212 (clear-stream $_test-input-buffered-file->buffer) + 9213 (clear-stream _test-output-stream) + 9214 (clear-stream $_test-output-buffered-file->buffer) + 9215 (clear-stream _test-error-stream) + 9216 (clear-stream $_test-error-buffered-file->buffer) + 9217 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9218 68/push 0/imm32 + 9219 68/push 0/imm32 + 9220 89/<- %edx 4/r32/esp + 9221 (tailor-exit-descriptor %edx 0x10) + 9222 # + 9223 (write _test-input-stream "fn foo {\n") + 9224 (write _test-input-stream " var x: (handle int)\n") + 9225 (write _test-input-stream " var y/eax: (addr byte) <- copy 0\n") + 9226 (write _test-input-stream " copy-byte-to *y, x\n") + 9227 (write _test-input-stream "}\n") + 9228 # convert + 9229 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9230 # registers except esp clobbered at this point + 9231 # restore ed + 9232 89/<- %edx 4/r32/esp + 9233 (flush _test-output-buffered-file) + 9234 (flush _test-error-buffered-file) + 9235 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9241 # check output + 9242 (check-stream-equal _test-output-stream "" "F - test-copy-byte-to-from-non-scalar-inout: output should be empty") + 9243 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-byte-to: 'x' is too large to copy" "F - test-copy-byte-to-from-non-scalar-inout: error message") + 9244 # check that stop(1) was called + 9245 (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status") + 9246 # don't restore from ebp + 9247 81 0/subop/add %esp 8/imm32 + 9248 # . epilogue + 9249 5d/pop-to-ebp + 9250 c3/return + 9251 + 9252 test-compare-with-no-inout: + 9253 # . prologue + 9254 55/push-ebp + 9255 89/<- %ebp 4/r32/esp + 9256 # setup + 9257 (clear-stream _test-input-stream) + 9258 (clear-stream $_test-input-buffered-file->buffer) + 9259 (clear-stream _test-output-stream) + 9260 (clear-stream $_test-output-buffered-file->buffer) + 9261 (clear-stream _test-error-stream) + 9262 (clear-stream $_test-error-buffered-file->buffer) + 9263 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9264 68/push 0/imm32 + 9265 68/push 0/imm32 + 9266 89/<- %edx 4/r32/esp + 9267 (tailor-exit-descriptor %edx 0x10) + 9268 # + 9269 (write _test-input-stream "fn foo {\n") + 9270 (write _test-input-stream " var x: boolean\n") + 9271 (write _test-input-stream " compare\n") + 9272 (write _test-input-stream "}\n") + 9273 # convert + 9274 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9275 # registers except esp clobbered at this point + 9276 # restore ed + 9277 89/<- %edx 4/r32/esp + 9278 (flush _test-output-buffered-file) + 9279 (flush _test-error-buffered-file) + 9280 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9286 # check output + 9287 (check-stream-equal _test-output-stream "" "F - test-compare-with-no-inout: output should be empty") + 9288 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must have two inouts" "F - test-compare-with-no-inout: error message") + 9289 # check that stop(1) was called + 9290 (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status") + 9291 # don't restore from ebp + 9292 81 0/subop/add %esp 8/imm32 + 9293 # . epilogue + 9294 5d/pop-to-ebp + 9295 c3/return + 9296 + 9297 test-compare-with-just-one-inout: + 9298 # . prologue + 9299 55/push-ebp + 9300 89/<- %ebp 4/r32/esp + 9301 # setup + 9302 (clear-stream _test-input-stream) + 9303 (clear-stream $_test-input-buffered-file->buffer) + 9304 (clear-stream _test-output-stream) + 9305 (clear-stream $_test-output-buffered-file->buffer) + 9306 (clear-stream _test-error-stream) + 9307 (clear-stream $_test-error-buffered-file->buffer) + 9308 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9309 68/push 0/imm32 + 9310 68/push 0/imm32 + 9311 89/<- %edx 4/r32/esp + 9312 (tailor-exit-descriptor %edx 0x10) + 9313 # + 9314 (write _test-input-stream "fn foo {\n") + 9315 (write _test-input-stream " var x: boolean\n") + 9316 (write _test-input-stream " compare x\n") + 9317 (write _test-input-stream "}\n") + 9318 # convert + 9319 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9320 # registers except esp clobbered at this point + 9321 # restore ed + 9322 89/<- %edx 4/r32/esp + 9323 (flush _test-output-buffered-file) + 9324 (flush _test-error-buffered-file) + 9325 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9331 # check output + 9332 (check-stream-equal _test-output-stream "" "F - test-compare-with-just-one-inout: output should be empty") + 9333 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must have two inouts" "F - test-compare-with-just-one-inout: error message") + 9334 # check that stop(1) was called + 9335 (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status") + 9336 # don't restore from ebp + 9337 81 0/subop/add %esp 8/imm32 + 9338 # . epilogue + 9339 5d/pop-to-ebp + 9340 c3/return + 9341 + 9342 test-compare-with-too-many-inouts: + 9343 # . prologue + 9344 55/push-ebp + 9345 89/<- %ebp 4/r32/esp + 9346 # setup + 9347 (clear-stream _test-input-stream) + 9348 (clear-stream $_test-input-buffered-file->buffer) + 9349 (clear-stream _test-output-stream) + 9350 (clear-stream $_test-output-buffered-file->buffer) + 9351 (clear-stream _test-error-stream) + 9352 (clear-stream $_test-error-buffered-file->buffer) + 9353 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9354 68/push 0/imm32 + 9355 68/push 0/imm32 + 9356 89/<- %edx 4/r32/esp + 9357 (tailor-exit-descriptor %edx 0x10) + 9358 # + 9359 (write _test-input-stream "fn foo {\n") + 9360 (write _test-input-stream " var x: boolean\n") + 9361 (write _test-input-stream " compare x, 0, 0\n") + 9362 (write _test-input-stream "}\n") + 9363 # convert + 9364 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9365 # registers except esp clobbered at this point + 9366 # restore ed + 9367 89/<- %edx 4/r32/esp + 9368 (flush _test-output-buffered-file) + 9369 (flush _test-error-buffered-file) + 9370 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9376 # check output + 9377 (check-stream-equal _test-output-stream "" "F - test-compare-with-too-many-inouts: output should be empty") + 9378 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must have two inouts" "F - test-compare-with-too-many-inouts: error message") + 9379 # check that stop(1) was called + 9380 (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status") + 9381 # don't restore from ebp + 9382 81 0/subop/add %esp 8/imm32 + 9383 # . epilogue + 9384 5d/pop-to-ebp + 9385 c3/return + 9386 + 9387 test-compare-with-output: + 9388 # . prologue + 9389 55/push-ebp + 9390 89/<- %ebp 4/r32/esp + 9391 # setup + 9392 (clear-stream _test-input-stream) + 9393 (clear-stream $_test-input-buffered-file->buffer) + 9394 (clear-stream _test-output-stream) + 9395 (clear-stream $_test-output-buffered-file->buffer) + 9396 (clear-stream _test-error-stream) + 9397 (clear-stream $_test-error-buffered-file->buffer) + 9398 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9399 68/push 0/imm32 + 9400 68/push 0/imm32 + 9401 89/<- %edx 4/r32/esp + 9402 (tailor-exit-descriptor %edx 0x10) + 9403 # + 9404 (write _test-input-stream "fn foo {\n") + 9405 (write _test-input-stream " var x/eax: boolean <- copy 0\n") + 9406 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") + 9407 (write _test-input-stream " x <- compare y, 0\n") + 9408 (write _test-input-stream "}\n") + 9409 # convert + 9410 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9411 # registers except esp clobbered at this point + 9412 # restore ed + 9413 89/<- %edx 4/r32/esp + 9414 (flush _test-output-buffered-file) + 9415 (flush _test-error-buffered-file) + 9416 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9422 # check output + 9423 (check-stream-equal _test-output-stream "" "F - test-compare-with-output: output should be empty") + 9424 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'compare' must not have any outputs" "F - test-compare-with-output: error message") + 9425 # check that stop(1) was called + 9426 (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status") + 9427 # don't restore from ebp + 9428 81 0/subop/add %esp 8/imm32 + 9429 # . epilogue + 9430 5d/pop-to-ebp + 9431 c3/return + 9432 + 9433 test-compare-invalid-value-to-address: + 9434 # . prologue + 9435 55/push-ebp + 9436 89/<- %ebp 4/r32/esp + 9437 # setup + 9438 (clear-stream _test-input-stream) + 9439 (clear-stream $_test-input-buffered-file->buffer) + 9440 (clear-stream _test-output-stream) + 9441 (clear-stream $_test-output-buffered-file->buffer) + 9442 (clear-stream _test-error-stream) + 9443 (clear-stream $_test-error-buffered-file->buffer) + 9444 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9445 68/push 0/imm32 + 9446 68/push 0/imm32 + 9447 89/<- %edx 4/r32/esp + 9448 (tailor-exit-descriptor %edx 0x10) + 9449 # + 9450 (write _test-input-stream "fn foo {\n") + 9451 (write _test-input-stream " var x/eax: int <- copy 0\n") + 9452 (write _test-input-stream " var y: (addr int)\n") + 9453 (write _test-input-stream " compare y, x\n") + 9454 (write _test-input-stream "}\n") + 9455 # convert + 9456 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9457 # registers except esp clobbered at this point + 9458 # restore ed + 9459 89/<- %edx 4/r32/esp + 9460 (flush _test-output-buffered-file) + 9461 (flush _test-error-buffered-file) + 9462 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9468 # check output + 9469 (check-stream-equal _test-output-stream "" "F - test-compare-invalid-value-to-address: output should be empty") + 9470 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar" "F - test-compare-invalid-value-to-address: error message") + 9471 # check that stop(1) was called + 9472 (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status") + 9473 # don't restore from ebp + 9474 81 0/subop/add %esp 8/imm32 + 9475 # . epilogue + 9476 5d/pop-to-ebp + 9477 c3/return + 9478 + 9479 test-compare-address: + 9480 # . prologue + 9481 55/push-ebp + 9482 89/<- %ebp 4/r32/esp + 9483 # setup + 9484 (clear-stream _test-input-stream) + 9485 (clear-stream $_test-input-buffered-file->buffer) + 9486 (clear-stream _test-output-stream) + 9487 (clear-stream $_test-output-buffered-file->buffer) + 9488 # + 9489 (write _test-input-stream "fn foo {\n") + 9490 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") + 9491 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") + 9492 (write _test-input-stream " compare y, x\n") + 9493 (write _test-input-stream "}\n") + 9494 # convert + 9495 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 9496 (flush _test-output-buffered-file) + 9497 # no errors + 9498 # . epilogue + 9499 5d/pop-to-ebp + 9500 c3/return + 9501 + 9502 test-compare-deref-address: + 9503 # . prologue + 9504 55/push-ebp + 9505 89/<- %ebp 4/r32/esp + 9506 # setup + 9507 (clear-stream _test-input-stream) + 9508 (clear-stream $_test-input-buffered-file->buffer) + 9509 (clear-stream _test-output-stream) + 9510 (clear-stream $_test-output-buffered-file->buffer) + 9511 # + 9512 (write _test-input-stream "fn foo {\n") + 9513 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") + 9514 (write _test-input-stream " var y/ecx: (addr addr int) <- copy 0\n") + 9515 (write _test-input-stream " compare *y, x\n") + 9516 (write _test-input-stream "}\n") + 9517 # convert + 9518 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 9519 (flush _test-output-buffered-file) + 9520 # no errors + 9521 # . epilogue + 9522 5d/pop-to-ebp + 9523 c3/return + 9524 + 9525 test-compare-two-vars-in-memory: + 9526 # . prologue + 9527 55/push-ebp + 9528 89/<- %ebp 4/r32/esp + 9529 # setup + 9530 (clear-stream _test-input-stream) + 9531 (clear-stream $_test-input-buffered-file->buffer) + 9532 (clear-stream _test-output-stream) + 9533 (clear-stream $_test-output-buffered-file->buffer) + 9534 (clear-stream _test-error-stream) + 9535 (clear-stream $_test-error-buffered-file->buffer) + 9536 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9537 68/push 0/imm32 + 9538 68/push 0/imm32 + 9539 89/<- %edx 4/r32/esp + 9540 (tailor-exit-descriptor %edx 0x10) + 9541 # + 9542 (write _test-input-stream "fn foo {\n") + 9543 (write _test-input-stream " var x: boolean\n") + 9544 (write _test-input-stream " compare x, x\n") + 9545 (write _test-input-stream "}\n") + 9546 # convert + 9547 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9548 # registers except esp clobbered at this point + 9549 # restore ed + 9550 89/<- %edx 4/r32/esp + 9551 (flush _test-output-buffered-file) + 9552 (flush _test-error-buffered-file) + 9553 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9559 # check output + 9560 (check-stream-equal _test-output-stream "" "F - test-compare-two-vars-in-memory: output should be empty") + 9561 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: both inouts are in memory" "F - test-compare-two-vars-in-memory: error message") + 9562 # check that stop(1) was called + 9563 (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status") + 9564 # don't restore from ebp + 9565 81 0/subop/add %esp 8/imm32 + 9566 # . epilogue + 9567 5d/pop-to-ebp + 9568 c3/return + 9569 + 9570 test-compare-non-scalar: + 9571 # . prologue + 9572 55/push-ebp + 9573 89/<- %ebp 4/r32/esp + 9574 # setup + 9575 (clear-stream _test-input-stream) + 9576 (clear-stream $_test-input-buffered-file->buffer) + 9577 (clear-stream _test-output-stream) + 9578 (clear-stream $_test-output-buffered-file->buffer) + 9579 (clear-stream _test-error-stream) + 9580 (clear-stream $_test-error-buffered-file->buffer) + 9581 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9582 68/push 0/imm32 + 9583 68/push 0/imm32 + 9584 89/<- %edx 4/r32/esp + 9585 (tailor-exit-descriptor %edx 0x10) + 9586 # + 9587 (write _test-input-stream "fn foo {\n") + 9588 (write _test-input-stream " var x: (handle int)\n") + 9589 (write _test-input-stream " var y: int\n") + 9590 (write _test-input-stream " compare y, x\n") + 9591 (write _test-input-stream "}\n") + 9592 # convert + 9593 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9594 # registers except esp clobbered at this point + 9595 # restore ed + 9596 89/<- %edx 4/r32/esp + 9597 (flush _test-output-buffered-file) + 9598 (flush _test-error-buffered-file) + 9599 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9605 # check output + 9606 (check-stream-equal _test-output-stream "" "F - test-compare-non-scalar: output should be empty") + 9607 #? (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: 'x' is too large to compare" "F - test-compare-non-scalar: error message") + 9608 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: both inouts are in memory" "F - test-compare-non-scalar: error message") + 9609 # check that stop(1) was called + 9610 (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status") + 9611 # don't restore from ebp + 9612 81 0/subop/add %esp 8/imm32 + 9613 # . epilogue + 9614 5d/pop-to-ebp + 9615 c3/return + 9616 + 9617 test-compare-with-string-literal: + 9618 # . prologue + 9619 55/push-ebp + 9620 89/<- %ebp 4/r32/esp + 9621 # setup + 9622 (clear-stream _test-input-stream) + 9623 (clear-stream $_test-input-buffered-file->buffer) + 9624 (clear-stream _test-output-stream) + 9625 (clear-stream $_test-output-buffered-file->buffer) + 9626 (clear-stream _test-error-stream) + 9627 (clear-stream $_test-error-buffered-file->buffer) + 9628 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9629 68/push 0/imm32 + 9630 68/push 0/imm32 + 9631 89/<- %edx 4/r32/esp + 9632 (tailor-exit-descriptor %edx 0x10) + 9633 # + 9634 (write _test-input-stream "fn foo {\n") + 9635 (write _test-input-stream " var x/eax: (addr array byte) <- copy 0\n") + 9636 (write _test-input-stream " compare x, \"abc\"\n") + 9637 (write _test-input-stream "}\n") + 9638 # convert + 9639 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9640 # registers except esp clobbered at this point + 9641 # restore ed + 9642 89/<- %edx 4/r32/esp + 9643 (flush _test-output-buffered-file) + 9644 (flush _test-error-buffered-file) + 9645 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9651 # check output + 9652 (check-stream-equal _test-output-stream "" "F - test-compare-with-string-literal: output should be empty") + 9653 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compare: string literal \"abc\" is not supported; use the string-equal? function" "F - test-compare-with-string-literal: error message") + 9654 # check that stop(1) was called + 9655 (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status") + 9656 # don't restore from ebp + 9657 81 0/subop/add %esp 8/imm32 + 9658 # . epilogue + 9659 5d/pop-to-ebp + 9660 c3/return + 9661 + 9662 test-address-with-no-inout: + 9663 # . prologue + 9664 55/push-ebp + 9665 89/<- %ebp 4/r32/esp + 9666 # setup + 9667 (clear-stream _test-input-stream) + 9668 (clear-stream $_test-input-buffered-file->buffer) + 9669 (clear-stream _test-output-stream) + 9670 (clear-stream $_test-output-buffered-file->buffer) + 9671 (clear-stream _test-error-stream) + 9672 (clear-stream $_test-error-buffered-file->buffer) + 9673 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9674 68/push 0/imm32 + 9675 68/push 0/imm32 + 9676 89/<- %edx 4/r32/esp + 9677 (tailor-exit-descriptor %edx 0x10) + 9678 # + 9679 (write _test-input-stream "fn foo {\n") + 9680 (write _test-input-stream " var x/eax: boolean <- address\n") + 9681 (write _test-input-stream "}\n") + 9682 # convert + 9683 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9684 # registers except esp clobbered at this point + 9685 # restore ed + 9686 89/<- %edx 4/r32/esp + 9687 (flush _test-output-buffered-file) + 9688 (flush _test-error-buffered-file) + 9689 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9695 # check output + 9696 (check-stream-equal _test-output-stream "" "F - test-address-with-no-inout: output should be empty") + 9697 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' expects an inout" "F - test-address-with-no-inout: error message") + 9698 # check that stop(1) was called + 9699 (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status") + 9700 # don't restore from ebp + 9701 81 0/subop/add %esp 8/imm32 + 9702 # . epilogue + 9703 5d/pop-to-ebp + 9704 c3/return + 9705 + 9706 test-address-with-multiple-inouts: + 9707 # . prologue + 9708 55/push-ebp + 9709 89/<- %ebp 4/r32/esp + 9710 # setup + 9711 (clear-stream _test-input-stream) + 9712 (clear-stream $_test-input-buffered-file->buffer) + 9713 (clear-stream _test-output-stream) + 9714 (clear-stream $_test-output-buffered-file->buffer) + 9715 (clear-stream _test-error-stream) + 9716 (clear-stream $_test-error-buffered-file->buffer) + 9717 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9718 68/push 0/imm32 + 9719 68/push 0/imm32 + 9720 89/<- %edx 4/r32/esp + 9721 (tailor-exit-descriptor %edx 0x10) + 9722 # + 9723 (write _test-input-stream "fn foo {\n") + 9724 (write _test-input-stream " var x/eax: boolean <- address 0, 0\n") + 9725 (write _test-input-stream "}\n") + 9726 # convert + 9727 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9728 # registers except esp clobbered at this point + 9729 # restore ed + 9730 89/<- %edx 4/r32/esp + 9731 (flush _test-output-buffered-file) + 9732 (flush _test-error-buffered-file) + 9733 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9739 # check output + 9740 (check-stream-equal _test-output-stream "" "F - test-address-with-multiple-inouts: output should be empty") + 9741 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' must have just one inout" "F - test-address-with-multiple-inouts: error message") + 9742 # check that stop(1) was called + 9743 (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status") + 9744 # don't restore from ebp + 9745 81 0/subop/add %esp 8/imm32 + 9746 # . epilogue + 9747 5d/pop-to-ebp + 9748 c3/return + 9749 + 9750 test-address-with-no-output: + 9751 # . prologue + 9752 55/push-ebp + 9753 89/<- %ebp 4/r32/esp + 9754 # setup + 9755 (clear-stream _test-input-stream) + 9756 (clear-stream $_test-input-buffered-file->buffer) + 9757 (clear-stream _test-output-stream) + 9758 (clear-stream $_test-output-buffered-file->buffer) + 9759 (clear-stream _test-error-stream) + 9760 (clear-stream $_test-error-buffered-file->buffer) + 9761 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9762 68/push 0/imm32 + 9763 68/push 0/imm32 + 9764 89/<- %edx 4/r32/esp + 9765 (tailor-exit-descriptor %edx 0x10) + 9766 # + 9767 (write _test-input-stream "fn foo {\n") + 9768 (write _test-input-stream " address 0\n") + 9769 (write _test-input-stream "}\n") + 9770 # convert + 9771 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9772 # registers except esp clobbered at this point + 9773 # restore ed + 9774 89/<- %edx 4/r32/esp + 9775 (flush _test-output-buffered-file) + 9776 (flush _test-error-buffered-file) + 9777 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9783 # check output + 9784 (check-stream-equal _test-output-stream "" "F - test-address-with-no-output: output should be empty") + 9785 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' expects an output" "F - test-address-with-no-output: error message") + 9786 # check that stop(1) was called + 9787 (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status") + 9788 # don't restore from ebp + 9789 81 0/subop/add %esp 8/imm32 + 9790 # . epilogue + 9791 5d/pop-to-ebp + 9792 c3/return + 9793 + 9794 test-address-with-multiple-outputs: + 9795 # . prologue + 9796 55/push-ebp + 9797 89/<- %ebp 4/r32/esp + 9798 # setup + 9799 (clear-stream _test-input-stream) + 9800 (clear-stream $_test-input-buffered-file->buffer) + 9801 (clear-stream _test-output-stream) + 9802 (clear-stream $_test-output-buffered-file->buffer) + 9803 (clear-stream _test-error-stream) + 9804 (clear-stream $_test-error-buffered-file->buffer) + 9805 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9806 68/push 0/imm32 + 9807 68/push 0/imm32 + 9808 89/<- %edx 4/r32/esp + 9809 (tailor-exit-descriptor %edx 0x10) + 9810 # + 9811 (write _test-input-stream "fn foo {\n") + 9812 (write _test-input-stream " var x/eax: boolean <- copy 0\n") + 9813 (write _test-input-stream " var y/ecx: boolean <- copy 0\n") + 9814 (write _test-input-stream " x, y <- address 0\n") + 9815 (write _test-input-stream "}\n") + 9816 # convert + 9817 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9818 # registers except esp clobbered at this point + 9819 # restore ed + 9820 89/<- %edx 4/r32/esp + 9821 (flush _test-output-buffered-file) + 9822 (flush _test-error-buffered-file) + 9823 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9829 # check output + 9830 (check-stream-equal _test-output-stream "" "F - test-address-with-multiple-outputs: output should be empty") + 9831 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'address' must have just one output" "F - test-address-with-multiple-outputs: error message") + 9832 # check that stop(1) was called + 9833 (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status") + 9834 # don't restore from ebp + 9835 81 0/subop/add %esp 8/imm32 + 9836 # . epilogue + 9837 5d/pop-to-ebp + 9838 c3/return + 9839 + 9840 # silly but it works + 9841 test-address-of-deref: + 9842 # . prologue + 9843 55/push-ebp + 9844 89/<- %ebp 4/r32/esp + 9845 # setup + 9846 (clear-stream _test-input-stream) + 9847 (clear-stream $_test-input-buffered-file->buffer) + 9848 (clear-stream _test-output-stream) + 9849 (clear-stream $_test-output-buffered-file->buffer) + 9850 # + 9851 (write _test-input-stream "fn foo {\n") + 9852 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") + 9853 (write _test-input-stream " var y/ecx: (addr int) <- address *x\n") + 9854 (write _test-input-stream "}\n") + 9855 # convert + 9856 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 9857 (flush _test-output-buffered-file) + 9858 # no errors + 9859 # . epilogue + 9860 5d/pop-to-ebp + 9861 c3/return + 9862 + 9863 test-address-to-non-register: + 9864 # . prologue + 9865 55/push-ebp + 9866 89/<- %ebp 4/r32/esp + 9867 # setup + 9868 (clear-stream _test-input-stream) + 9869 (clear-stream $_test-input-buffered-file->buffer) + 9870 (clear-stream _test-output-stream) + 9871 (clear-stream $_test-output-buffered-file->buffer) + 9872 (clear-stream _test-error-stream) + 9873 (clear-stream $_test-error-buffered-file->buffer) + 9874 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9875 68/push 0/imm32 + 9876 68/push 0/imm32 + 9877 89/<- %edx 4/r32/esp + 9878 (tailor-exit-descriptor %edx 0x10) + 9879 # + 9880 (write _test-input-stream "fn foo {\n") + 9881 (write _test-input-stream " var x: (addr int)\n") + 9882 (write _test-input-stream " x <- address 0\n") + 9883 (write _test-input-stream "}\n") + 9884 # convert + 9885 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9886 # registers except esp clobbered at this point + 9887 # restore ed + 9888 89/<- %edx 4/r32/esp + 9889 (flush _test-output-buffered-file) + 9890 (flush _test-error-buffered-file) + 9891 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9897 # check output + 9898 (check-stream-equal _test-output-stream "" "F - test-address-to-non-register: output should be empty") + 9899 (check-next-stream-line-equal _test-error-stream "fn foo: stmt address: output 'x' not in a register" "F - test-address-to-non-register: error message") + 9900 # check that stop(1) was called + 9901 (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status") + 9902 # don't restore from ebp + 9903 81 0/subop/add %esp 8/imm32 + 9904 # . epilogue + 9905 5d/pop-to-ebp + 9906 c3/return + 9907 + 9908 test-address-with-wrong-type: + 9909 # . prologue + 9910 55/push-ebp + 9911 89/<- %ebp 4/r32/esp + 9912 # setup + 9913 (clear-stream _test-input-stream) + 9914 (clear-stream $_test-input-buffered-file->buffer) + 9915 (clear-stream _test-output-stream) + 9916 (clear-stream $_test-output-buffered-file->buffer) + 9917 (clear-stream _test-error-stream) + 9918 (clear-stream $_test-error-buffered-file->buffer) + 9919 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 9920 68/push 0/imm32 + 9921 68/push 0/imm32 + 9922 89/<- %edx 4/r32/esp + 9923 (tailor-exit-descriptor %edx 0x10) + 9924 # + 9925 (write _test-input-stream "fn foo {\n") + 9926 (write _test-input-stream " var x: int\n") + 9927 (write _test-input-stream " var y/eax: (addr boolean) <- address x\n") + 9928 (write _test-input-stream "}\n") + 9929 # convert + 9930 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + 9931 # registers except esp clobbered at this point + 9932 # restore ed + 9933 89/<- %edx 4/r32/esp + 9934 (flush _test-output-buffered-file) + 9935 (flush _test-error-buffered-file) + 9936 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ + 9942 # check output + 9943 (check-stream-equal _test-output-stream "" "F - test-address-with-wrong-type: output should be empty") + 9944 (check-next-stream-line-equal _test-error-stream "fn foo: stmt address: output 'y' cannot hold address of 'x'" "F - test-address-with-wrong-type: error message") + 9945 # check that stop(1) was called + 9946 (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status") + 9947 # don't restore from ebp + 9948 81 0/subop/add %esp 8/imm32 + 9949 # . epilogue + 9950 5d/pop-to-ebp + 9951 c3/return + 9952 + 9953 test-address-with-right-type-for-array: + 9954 # . prologue + 9955 55/push-ebp + 9956 89/<- %ebp 4/r32/esp + 9957 # setup + 9958 (clear-stream _test-input-stream) + 9959 (clear-stream $_test-input-buffered-file->buffer) + 9960 (clear-stream _test-output-stream) + 9961 (clear-stream $_test-output-buffered-file->buffer) + 9962 # + 9963 (write _test-input-stream "fn foo {\n") + 9964 (write _test-input-stream " var x: (array int 3)\n") + 9965 (write _test-input-stream " var y/eax: (addr array int) <- address x\n") + 9966 (write _test-input-stream "}\n") + 9967 # convert + 9968 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 9969 (flush _test-output-buffered-file) + 9970 # no errors + 9971 # . epilogue + 9972 89/<- %esp 5/r32/ebp + 9973 5d/pop-to-ebp + 9974 c3/return + 9975 + 9976 test-address-with-right-type-for-stream: + 9977 # . prologue + 9978 55/push-ebp + 9979 89/<- %ebp 4/r32/esp + 9980 # setup + 9981 (clear-stream _test-input-stream) + 9982 (clear-stream $_test-input-buffered-file->buffer) + 9983 (clear-stream _test-output-stream) + 9984 (clear-stream $_test-output-buffered-file->buffer) + 9985 # + 9986 (write _test-input-stream "fn foo {\n") + 9987 (write _test-input-stream " var x: (stream int 3)\n") + 9988 (write _test-input-stream " var y/eax: (addr stream int) <- address x\n") + 9989 (write _test-input-stream "}\n") + 9990 # convert + 9991 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + 9992 (flush _test-output-buffered-file) + 9993 # no errors + 9994 # . epilogue + 9995 89/<- %esp 5/r32/ebp + 9996 5d/pop-to-ebp + 9997 c3/return + 9998 + 9999 test-get-with-wrong-field: +10000 # . prologue +10001 55/push-ebp +10002 89/<- %ebp 4/r32/esp +10003 # setup +10004 (clear-stream _test-input-stream) +10005 (clear-stream $_test-input-buffered-file->buffer) +10006 (clear-stream _test-output-stream) +10007 (clear-stream $_test-output-buffered-file->buffer) +10008 (clear-stream _test-error-stream) +10009 (clear-stream $_test-error-buffered-file->buffer) +10010 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10011 68/push 0/imm32 +10012 68/push 0/imm32 +10013 89/<- %edx 4/r32/esp +10014 (tailor-exit-descriptor %edx 0x10) +10015 # +10016 (write _test-input-stream "fn foo {\n") +10017 (write _test-input-stream " var a: t\n") +10018 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") +10019 (write _test-input-stream "}\n") +10020 (write _test-input-stream "type t {\n") +10021 (write _test-input-stream " x: int\n") +10022 (write _test-input-stream "}\n") +10023 # convert +10024 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10025 # registers except esp clobbered at this point +10026 # restore ed +10027 89/<- %edx 4/r32/esp +10028 (flush _test-output-buffered-file) +10029 (flush _test-error-buffered-file) +10030 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10036 # check output +10037 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-field: output should be empty") +10038 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: type 't' has no member called 'y'" "F - test-get-with-wrong-field: error message") +10039 # check that stop(1) was called +10040 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status") +10041 # don't restore from ebp +10042 81 0/subop/add %esp 8/imm32 +10043 # . epilogue +10044 5d/pop-to-ebp +10045 c3/return +10046 +10047 test-get-with-wrong-base-type: +10048 # . prologue +10049 55/push-ebp +10050 89/<- %ebp 4/r32/esp +10051 # setup +10052 (clear-stream _test-input-stream) +10053 (clear-stream $_test-input-buffered-file->buffer) +10054 (clear-stream _test-output-stream) +10055 (clear-stream $_test-output-buffered-file->buffer) +10056 (clear-stream _test-error-stream) +10057 (clear-stream $_test-error-buffered-file->buffer) +10058 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10059 68/push 0/imm32 +10060 68/push 0/imm32 +10061 89/<- %edx 4/r32/esp +10062 (tailor-exit-descriptor %edx 0x10) +10063 # +10064 (write _test-input-stream "fn foo {\n") +10065 (write _test-input-stream " var a: int\n") +10066 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") +10067 (write _test-input-stream "}\n") +10068 # convert +10069 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10070 # registers except esp clobbered at this point +10071 # restore ed +10072 89/<- %edx 4/r32/esp +10073 (flush _test-output-buffered-file) +10074 (flush _test-error-buffered-file) +10075 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10081 # check output +10082 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-base-type: output should be empty") +10083 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' must have a 'type' definition" "F - test-get-with-wrong-base-type: error message") +10084 # check that stop(1) was called +10085 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status") +10086 # don't restore from ebp +10087 81 0/subop/add %esp 8/imm32 +10088 # . epilogue +10089 5d/pop-to-ebp +10090 c3/return +10091 +10092 test-get-with-wrong-base-type-2: +10093 # . prologue +10094 55/push-ebp +10095 89/<- %ebp 4/r32/esp +10096 # setup +10097 (clear-stream _test-input-stream) +10098 (clear-stream $_test-input-buffered-file->buffer) +10099 (clear-stream _test-output-stream) +10100 (clear-stream $_test-output-buffered-file->buffer) +10101 (clear-stream _test-error-stream) +10102 (clear-stream $_test-error-buffered-file->buffer) +10103 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10104 68/push 0/imm32 +10105 68/push 0/imm32 +10106 89/<- %edx 4/r32/esp +10107 (tailor-exit-descriptor %edx 0x10) +10108 # +10109 (write _test-input-stream "fn foo {\n") +10110 (write _test-input-stream " var a: (addr t)\n") +10111 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") +10112 (write _test-input-stream "}\n") +10113 (write _test-input-stream "type t {\n") +10114 (write _test-input-stream " x: int\n") +10115 (write _test-input-stream "}\n") +10116 # convert +10117 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10118 # registers except esp clobbered at this point +10119 # restore ed +10120 89/<- %edx 4/r32/esp +10121 (flush _test-output-buffered-file) +10122 (flush _test-error-buffered-file) +10123 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10129 # check output +10130 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-base-type-2: output should be empty") +10131 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' is an 'addr' type, and so must live in a register" "F - test-get-with-wrong-base-type-2: error message") +10132 # check that stop(1) was called +10133 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status") +10134 # don't restore from ebp +10135 81 0/subop/add %esp 8/imm32 +10136 # . epilogue +10137 5d/pop-to-ebp +10138 c3/return +10139 +10140 test-get-with-wrong-base-type-3: +10141 # . prologue +10142 55/push-ebp +10143 89/<- %ebp 4/r32/esp +10144 # setup +10145 (clear-stream _test-input-stream) +10146 (clear-stream $_test-input-buffered-file->buffer) +10147 (clear-stream _test-output-stream) +10148 (clear-stream $_test-output-buffered-file->buffer) +10149 (clear-stream _test-error-stream) +10150 (clear-stream $_test-error-buffered-file->buffer) +10151 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10152 68/push 0/imm32 +10153 68/push 0/imm32 +10154 89/<- %edx 4/r32/esp +10155 (tailor-exit-descriptor %edx 0x10) +10156 # +10157 (write _test-input-stream "fn foo {\n") +10158 (write _test-input-stream " var a: (handle int)\n") +10159 (write _test-input-stream " var c/ecx: (addr int) <- get a, y\n") +10160 (write _test-input-stream "}\n") +10161 # convert +10162 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10163 # registers except esp clobbered at this point +10164 # restore ed +10165 89/<- %edx 4/r32/esp +10166 (flush _test-output-buffered-file) +10167 (flush _test-error-buffered-file) +10168 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10174 # check output +10175 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-base-type-3: output should be empty") +10176 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' must have a 'type' definition" "F - test-get-with-wrong-base-type-3: error message") +10177 # check that stop(1) was called +10178 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status") +10179 # don't restore from ebp +10180 81 0/subop/add %esp 8/imm32 +10181 # . epilogue +10182 5d/pop-to-ebp +10183 c3/return +10184 +10185 test-get-with-wrong-offset-type: +10186 # . prologue +10187 55/push-ebp +10188 89/<- %ebp 4/r32/esp +10189 # setup +10190 (clear-stream _test-input-stream) +10191 (clear-stream $_test-input-buffered-file->buffer) +10192 (clear-stream _test-output-stream) +10193 (clear-stream $_test-output-buffered-file->buffer) +10194 (clear-stream _test-error-stream) +10195 (clear-stream $_test-error-buffered-file->buffer) +10196 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10197 68/push 0/imm32 +10198 68/push 0/imm32 +10199 89/<- %edx 4/r32/esp +10200 (tailor-exit-descriptor %edx 0x10) +10201 # +10202 (write _test-input-stream "fn foo {\n") +10203 (write _test-input-stream " var a: t\n") +10204 (write _test-input-stream " var b: int\n") +10205 (write _test-input-stream " var c/ecx: (addr int) <- get a, b\n") +10206 (write _test-input-stream "}\n") +10207 (write _test-input-stream "type t {\n") +10208 (write _test-input-stream " x: int\n") +10209 (write _test-input-stream "}\n") +10210 # convert +10211 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10212 # registers except esp clobbered at this point +10213 # restore ed +10214 89/<- %edx 4/r32/esp +10215 (flush _test-output-buffered-file) +10216 (flush _test-error-buffered-file) +10217 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10223 # check output +10224 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-offset-type: output should be empty") +10225 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: type 't' has no member called 'b'" "F - test-get-with-wrong-offset-type: error message") +10226 # check that stop(1) was called +10227 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status") +10228 # don't restore from ebp +10229 81 0/subop/add %esp 8/imm32 +10230 # . epilogue +10231 5d/pop-to-ebp +10232 c3/return +10233 +10234 test-get-with-wrong-output-type: +10235 # . prologue +10236 55/push-ebp +10237 89/<- %ebp 4/r32/esp +10238 # setup +10239 (clear-stream _test-input-stream) +10240 (clear-stream $_test-input-buffered-file->buffer) +10241 (clear-stream _test-output-stream) +10242 (clear-stream $_test-output-buffered-file->buffer) +10243 (clear-stream _test-error-stream) +10244 (clear-stream $_test-error-buffered-file->buffer) +10245 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10246 68/push 0/imm32 +10247 68/push 0/imm32 +10248 89/<- %edx 4/r32/esp +10249 (tailor-exit-descriptor %edx 0x10) +10250 # +10251 (write _test-input-stream "fn foo {\n") +10252 (write _test-input-stream " var a: t\n") +10253 (write _test-input-stream " var c: (addr int)\n") +10254 (write _test-input-stream " c <- get a, x\n") +10255 (write _test-input-stream "}\n") +10256 (write _test-input-stream "type t {\n") +10257 (write _test-input-stream " x: int\n") +10258 (write _test-input-stream "}\n") +10259 # convert +10260 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10261 # registers except esp clobbered at this point +10262 # restore ed +10263 89/<- %edx 4/r32/esp +10264 (flush _test-output-buffered-file) +10265 (flush _test-error-buffered-file) +10266 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10272 # check output +10273 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type: output should be empty") +10274 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: output 'c' is not in a register" "F - test-get-with-wrong-output-type: error message") +10275 # check that stop(1) was called +10276 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status") +10277 # don't restore from ebp +10278 81 0/subop/add %esp 8/imm32 +10279 # . epilogue +10280 5d/pop-to-ebp +10281 c3/return +10282 +10283 test-get-with-wrong-output-type-2: +10284 # . prologue +10285 55/push-ebp +10286 89/<- %ebp 4/r32/esp +10287 # setup +10288 (clear-stream _test-input-stream) +10289 (clear-stream $_test-input-buffered-file->buffer) +10290 (clear-stream _test-output-stream) +10291 (clear-stream $_test-output-buffered-file->buffer) +10292 (clear-stream _test-error-stream) +10293 (clear-stream $_test-error-buffered-file->buffer) +10294 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10295 68/push 0/imm32 +10296 68/push 0/imm32 +10297 89/<- %edx 4/r32/esp +10298 (tailor-exit-descriptor %edx 0x10) +10299 # +10300 (write _test-input-stream "fn foo {\n") +10301 (write _test-input-stream " var a: t\n") +10302 (write _test-input-stream " var c/ecx: int <- get a, x\n") +10303 (write _test-input-stream "}\n") +10304 (write _test-input-stream "type t {\n") +10305 (write _test-input-stream " x: int\n") +10306 (write _test-input-stream "}\n") +10307 # convert +10308 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10309 # registers except esp clobbered at this point +10310 # restore ed +10311 89/<- %edx 4/r32/esp +10312 (flush _test-output-buffered-file) +10313 (flush _test-error-buffered-file) +10314 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10320 # check output +10321 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type-2: output should be empty") +10322 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: output must be an addr" "F - test-get-with-wrong-output-type-2: error message") +10323 # check that stop(1) was called +10324 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status") +10325 # don't restore from ebp +10326 81 0/subop/add %esp 8/imm32 +10327 # . epilogue +10328 5d/pop-to-ebp +10329 c3/return +10330 +10331 test-get-with-wrong-output-type-3: +10332 # . prologue +10333 55/push-ebp +10334 89/<- %ebp 4/r32/esp +10335 # setup +10336 (clear-stream _test-input-stream) +10337 (clear-stream $_test-input-buffered-file->buffer) +10338 (clear-stream _test-output-stream) +10339 (clear-stream $_test-output-buffered-file->buffer) +10340 (clear-stream _test-error-stream) +10341 (clear-stream $_test-error-buffered-file->buffer) +10342 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10343 68/push 0/imm32 +10344 68/push 0/imm32 +10345 89/<- %edx 4/r32/esp +10346 (tailor-exit-descriptor %edx 0x10) +10347 # +10348 (write _test-input-stream "fn foo {\n") +10349 (write _test-input-stream " var a: t\n") +10350 (write _test-input-stream " var c/ecx: (array int) <- get a, x\n") +10351 (write _test-input-stream "}\n") +10352 (write _test-input-stream "type t {\n") +10353 (write _test-input-stream " x: int\n") +10354 (write _test-input-stream "}\n") +10355 # convert +10356 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10357 # registers except esp clobbered at this point +10358 # restore ed +10359 89/<- %edx 4/r32/esp +10360 (flush _test-output-buffered-file) +10361 (flush _test-error-buffered-file) +10362 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10368 # check output +10369 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type-3: output should be empty") +10370 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: output must be an addr" "F - test-get-with-wrong-output-type-3: error message") +10371 # check that stop(1) was called +10372 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status") +10373 # don't restore from ebp +10374 81 0/subop/add %esp 8/imm32 +10375 # . epilogue +10376 5d/pop-to-ebp +10377 c3/return +10378 +10379 test-get-with-wrong-output-type-4: +10380 # . prologue +10381 55/push-ebp +10382 89/<- %ebp 4/r32/esp +10383 # setup +10384 (clear-stream _test-input-stream) +10385 (clear-stream $_test-input-buffered-file->buffer) +10386 (clear-stream _test-output-stream) +10387 (clear-stream $_test-output-buffered-file->buffer) +10388 (clear-stream _test-error-stream) +10389 (clear-stream $_test-error-buffered-file->buffer) +10390 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10391 68/push 0/imm32 +10392 68/push 0/imm32 +10393 89/<- %edx 4/r32/esp +10394 (tailor-exit-descriptor %edx 0x10) +10395 # +10396 (write _test-input-stream "fn foo {\n") +10397 (write _test-input-stream " var a: t\n") +10398 (write _test-input-stream " var c/ecx: (addr boolean) <- get a, x\n") +10399 (write _test-input-stream "}\n") +10400 (write _test-input-stream "type t {\n") +10401 (write _test-input-stream " x: int\n") +10402 (write _test-input-stream "}\n") +10403 # convert +10404 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10405 # registers except esp clobbered at this point +10406 # restore ed +10407 89/<- %edx 4/r32/esp +10408 (flush _test-output-buffered-file) +10409 (flush _test-error-buffered-file) +10410 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10416 # check output +10417 (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-output-type-4: output should be empty") +10418 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: wrong output type for member 'x' of type 't'" "F - test-get-with-wrong-output-type-4: error message") +10419 # check that stop(1) was called +10420 (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status") +10421 # don't restore from ebp +10422 81 0/subop/add %esp 8/imm32 +10423 # . epilogue +10424 5d/pop-to-ebp +10425 c3/return +10426 +10427 test-get-with-wrong-output-type-5: +10428 # . prologue +10429 55/push-ebp +10430 89/<- %ebp 4/r32/esp +10431 # setup +10432 (clear-stream _test-input-stream) +10433 (clear-stream $_test-input-buffered-file->buffer) +10434 (clear-stream _test-output-stream) +10435 (clear-stream $_test-output-buffered-file->buffer) +10436 # +10437 (write _test-input-stream "fn foo {\n") +10438 (write _test-input-stream " var a: t\n") +10439 (write _test-input-stream " var c/ecx: (addr handle int) <- get a, x\n") +10440 (write _test-input-stream "}\n") +10441 (write _test-input-stream "type t {\n") +10442 (write _test-input-stream " x: (handle int)\n") +10443 (write _test-input-stream "}\n") +10444 # convert +10445 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +10446 (flush _test-output-buffered-file) +10447 # no errors +10448 # . epilogue +10449 89/<- %esp 5/r32/ebp +10450 5d/pop-to-ebp +10451 c3/return +10452 +10453 test-get-with-too-few-inouts: +10454 # . prologue +10455 55/push-ebp +10456 89/<- %ebp 4/r32/esp +10457 # setup +10458 (clear-stream _test-input-stream) +10459 (clear-stream $_test-input-buffered-file->buffer) +10460 (clear-stream _test-output-stream) +10461 (clear-stream $_test-output-buffered-file->buffer) +10462 (clear-stream _test-error-stream) +10463 (clear-stream $_test-error-buffered-file->buffer) +10464 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10465 68/push 0/imm32 +10466 68/push 0/imm32 +10467 89/<- %edx 4/r32/esp +10468 (tailor-exit-descriptor %edx 0x10) +10469 # +10470 (write _test-input-stream "fn foo {\n") +10471 (write _test-input-stream " var a: t\n") +10472 (write _test-input-stream " var c/ecx: (addr int) <- get a\n") +10473 (write _test-input-stream "}\n") +10474 (write _test-input-stream "type t {\n") +10475 (write _test-input-stream " x: int\n") +10476 (write _test-input-stream "}\n") +10477 # convert +10478 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10479 # registers except esp clobbered at this point +10480 # restore ed +10481 89/<- %edx 4/r32/esp +10482 (flush _test-output-buffered-file) +10483 (flush _test-error-buffered-file) +10484 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10490 # check output +10491 (check-stream-equal _test-output-stream "" "F - test-get-with-too-few-inouts: output should be empty") +10492 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: too few inouts (2 required)" "F - test-get-with-too-few-inouts: error message") +10493 # check that stop(1) was called +10494 (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status") +10495 # don't restore from ebp +10496 81 0/subop/add %esp 8/imm32 +10497 # . epilogue +10498 5d/pop-to-ebp +10499 c3/return +10500 +10501 test-get-with-too-many-inouts: +10502 # . prologue +10503 55/push-ebp +10504 89/<- %ebp 4/r32/esp +10505 # setup +10506 (clear-stream _test-input-stream) +10507 (clear-stream $_test-input-buffered-file->buffer) +10508 (clear-stream _test-output-stream) +10509 (clear-stream $_test-output-buffered-file->buffer) +10510 (clear-stream _test-error-stream) +10511 (clear-stream $_test-error-buffered-file->buffer) +10512 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10513 68/push 0/imm32 +10514 68/push 0/imm32 +10515 89/<- %edx 4/r32/esp +10516 (tailor-exit-descriptor %edx 0x10) +10517 # +10518 (write _test-input-stream "fn foo {\n") +10519 (write _test-input-stream " var a: t\n") +10520 (write _test-input-stream " var c/ecx: (addr int) <- get a, x, 0\n") +10521 (write _test-input-stream "}\n") +10522 (write _test-input-stream "type t {\n") +10523 (write _test-input-stream " x: int\n") +10524 (write _test-input-stream "}\n") +10525 # convert +10526 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10527 # registers except esp clobbered at this point +10528 # restore ed +10529 89/<- %edx 4/r32/esp +10530 (flush _test-output-buffered-file) +10531 (flush _test-error-buffered-file) +10532 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10538 # check output +10539 (check-stream-equal _test-output-stream "" "F - test-get-with-too-many-inouts: output should be empty") +10540 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: too many inouts (2 required)" "F - test-get-with-too-many-inouts: error message") +10541 # check that stop(1) was called +10542 (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status") +10543 # don't restore from ebp +10544 81 0/subop/add %esp 8/imm32 +10545 # . epilogue +10546 5d/pop-to-ebp +10547 c3/return +10548 +10549 test-get-with-no-output: +10550 # . prologue +10551 55/push-ebp +10552 89/<- %ebp 4/r32/esp +10553 # setup +10554 (clear-stream _test-input-stream) +10555 (clear-stream $_test-input-buffered-file->buffer) +10556 (clear-stream _test-output-stream) +10557 (clear-stream $_test-output-buffered-file->buffer) +10558 (clear-stream _test-error-stream) +10559 (clear-stream $_test-error-buffered-file->buffer) +10560 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10561 68/push 0/imm32 +10562 68/push 0/imm32 +10563 89/<- %edx 4/r32/esp +10564 (tailor-exit-descriptor %edx 0x10) +10565 # +10566 (write _test-input-stream "fn foo {\n") +10567 (write _test-input-stream " var a: t\n") +10568 (write _test-input-stream " get a, x\n") +10569 (write _test-input-stream "}\n") +10570 (write _test-input-stream "type t {\n") +10571 (write _test-input-stream " x: int\n") +10572 (write _test-input-stream "}\n") +10573 # convert +10574 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10575 # registers except esp clobbered at this point +10576 # restore ed +10577 89/<- %edx 4/r32/esp +10578 (flush _test-output-buffered-file) +10579 (flush _test-error-buffered-file) +10580 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10586 # check output +10587 (check-stream-equal _test-output-stream "" "F - test-get-with-no-output: output should be empty") +10588 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: must have an output" "F - test-get-with-no-output: error message") +10589 # check that stop(1) was called +10590 (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status") +10591 # don't restore from ebp +10592 81 0/subop/add %esp 8/imm32 +10593 # . epilogue +10594 5d/pop-to-ebp +10595 c3/return +10596 +10597 test-get-with-too-many-outputs: +10598 # . prologue +10599 55/push-ebp +10600 89/<- %ebp 4/r32/esp +10601 # setup +10602 (clear-stream _test-input-stream) +10603 (clear-stream $_test-input-buffered-file->buffer) +10604 (clear-stream _test-output-stream) +10605 (clear-stream $_test-output-buffered-file->buffer) +10606 (clear-stream _test-error-stream) +10607 (clear-stream $_test-error-buffered-file->buffer) +10608 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10609 68/push 0/imm32 +10610 68/push 0/imm32 +10611 89/<- %edx 4/r32/esp +10612 (tailor-exit-descriptor %edx 0x10) +10613 # +10614 (write _test-input-stream "fn foo {\n") +10615 (write _test-input-stream " var a: t\n") +10616 (write _test-input-stream " var b: int\n") +10617 (write _test-input-stream " var c/eax: (addr int) <- copy 0\n") +10618 (write _test-input-stream " c, b <- get a, x\n") +10619 (write _test-input-stream "}\n") +10620 (write _test-input-stream "type t {\n") +10621 (write _test-input-stream " x: int\n") +10622 (write _test-input-stream "}\n") +10623 # convert +10624 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10625 # registers except esp clobbered at this point +10626 # restore ed +10627 89/<- %edx 4/r32/esp +10628 (flush _test-output-buffered-file) +10629 (flush _test-error-buffered-file) +10630 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10636 # check output +10637 (check-stream-equal _test-output-stream "" "F - test-get-with-too-many-outputs: output should be empty") +10638 (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: too many outputs (1 required)" "F - test-get-with-too-many-outputs: error message") +10639 # check that stop(1) was called +10640 (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status") +10641 # don't restore from ebp +10642 81 0/subop/add %esp 8/imm32 +10643 # . epilogue +10644 5d/pop-to-ebp +10645 c3/return +10646 +10647 test-convert-array-of-user-defined-types: +10648 # . prologue +10649 55/push-ebp +10650 89/<- %ebp 4/r32/esp +10651 # setup +10652 (clear-stream _test-input-stream) +10653 (clear-stream $_test-input-buffered-file->buffer) +10654 (clear-stream _test-output-stream) +10655 (clear-stream $_test-output-buffered-file->buffer) +10656 # +10657 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 +10658 (write _test-input-stream " x: int\n") +10659 (write _test-input-stream " y: int\n") +10660 (write _test-input-stream "}\n") +10661 (write _test-input-stream "fn foo {\n") +10662 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") +10663 (write _test-input-stream " var idx/ecx: int <- copy 3\n") +10664 (write _test-input-stream " var x/eax: (addr t) <- index arr, idx\n") +10665 (write _test-input-stream "}\n") +10666 # convert +10667 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +10668 (flush _test-output-buffered-file) +10669 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10675 # check output +10676 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-array-of-user-defined-types/0") +10677 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-array-of-user-defined-types/1") +10678 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-array-of-user-defined-types/2") +10679 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-array-of-user-defined-types/3") +10680 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-array-of-user-defined-types/4") +10681 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-array-of-user-defined-types/5") +10682 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-array-of-user-defined-types/6") +10683 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7") +10684 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8") +10685 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9") +10686 (check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")" "F - test-convert-array-of-user-defined-types/10") +10687 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %eax 0/imm32" "F - test-convert-array-of-user-defined-types/12") +10688 (check-next-stream-line-equal _test-output-stream " 0f 84/jump-if-= __mu-abort-null-index-base-address/disp32" "F - test-convert-array-of-user-defined-types/13") +10689 (check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/14") +10690 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/15") +10691 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/16") +10692 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/17") +10693 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/18") +10694 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/19") +10695 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/20") +10696 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/21") +10697 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/22") +10698 # . epilogue +10699 89/<- %esp 5/r32/ebp +10700 5d/pop-to-ebp +10701 c3/return +10702 +10703 test-convert-length-of-array-of-user-defined-types-to-eax: +10704 # . prologue +10705 55/push-ebp +10706 89/<- %ebp 4/r32/esp +10707 # setup +10708 (clear-stream _test-input-stream) +10709 (clear-stream $_test-input-buffered-file->buffer) +10710 (clear-stream _test-output-stream) +10711 (clear-stream $_test-output-buffered-file->buffer) +10712 # +10713 (write _test-input-stream "type t {\n") # size = 12, which is not a power of 2 +10714 (write _test-input-stream " x: int\n") +10715 (write _test-input-stream " y: int\n") +10716 (write _test-input-stream " z: int\n") +10717 (write _test-input-stream "}\n") +10718 (write _test-input-stream "fn foo {\n") +10719 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") +10720 (write _test-input-stream " var x/eax: int <- length arr\n") +10721 (write _test-input-stream "}\n") +10722 # convert +10723 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +10724 (flush _test-output-buffered-file) +10725 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10731 # check output +10732 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types-to-eax/0") +10733 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types-to-eax/1") +10734 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/2") +10735 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/3") +10736 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types-to-eax/4") +10737 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types-to-eax/5") +10738 # var arr +10739 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types-to-eax/6") +10740 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-eax/7") +10741 # length instruction +10742 (check-next-stream-line-equal _test-output-stream " 51/push-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/8") +10743 (check-next-stream-line-equal _test-output-stream " 52/push-edx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/9") +10744 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types-to-eax/10") +10745 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/11") +10746 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-eax/12") +10747 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/13") +10748 (check-next-stream-line-equal _test-output-stream " 5a/pop-to-edx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/14") +10749 (check-next-stream-line-equal _test-output-stream " 59/pop-to-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-eax/15") +10750 # reclaim arr +10751 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types-to-eax/16") +10752 # +10753 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types-to-eax/17") +10754 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types-to-eax/18") +10755 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types-to-eax/19") +10756 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/20") +10757 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-eax/21") +10758 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types-to-eax/22") +10759 # . epilogue +10760 89/<- %esp 5/r32/ebp +10761 5d/pop-to-ebp +10762 c3/return +10763 +10764 test-convert-length-of-array-of-user-defined-types-to-ecx: +10765 # . prologue +10766 55/push-ebp +10767 89/<- %ebp 4/r32/esp +10768 # setup +10769 (clear-stream _test-input-stream) +10770 (clear-stream $_test-input-buffered-file->buffer) +10771 (clear-stream _test-output-stream) +10772 (clear-stream $_test-output-buffered-file->buffer) +10773 # +10774 (write _test-input-stream "type t {\n") # size = 12, which is not a power of 2 +10775 (write _test-input-stream " x: int\n") +10776 (write _test-input-stream " y: int\n") +10777 (write _test-input-stream " z: int\n") +10778 (write _test-input-stream "}\n") +10779 (write _test-input-stream "fn foo {\n") +10780 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") +10781 (write _test-input-stream " var x/ecx: int <- length arr\n") +10782 (write _test-input-stream "}\n") +10783 # convert +10784 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +10785 (flush _test-output-buffered-file) +10786 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10792 # check output +10793 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0") +10794 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1") +10795 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2") +10796 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/3") +10797 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4") +10798 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5") +10799 # var a +10800 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/6") +10801 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/7") +10802 # var x +10803 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/8") +10804 # length instruction +10805 (check-next-stream-line-equal _test-output-stream " 50/push-eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9") +10806 (check-next-stream-line-equal _test-output-stream " 52/push-edx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10") +10807 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/11") +10808 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/12") +10809 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/13") +10810 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/14") +10811 (check-next-stream-line-equal _test-output-stream " 89/<- %ecx 0/r32/eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/15") +10812 (check-next-stream-line-equal _test-output-stream " 5a/pop-to-edx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/16") +10813 (check-next-stream-line-equal _test-output-stream " 58/pop-to-eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/17") +10814 # reclaim x +10815 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/18") +10816 # reclaim a +10817 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/19") +10818 # +10819 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20") +10820 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21") +10821 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22") +10822 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/23") +10823 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/24") +10824 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25") +10825 # . epilogue +10826 89/<- %esp 5/r32/ebp +10827 5d/pop-to-ebp +10828 c3/return +10829 +10830 test-convert-length-of-array-of-user-defined-types-to-edx: +10831 # . prologue +10832 55/push-ebp +10833 89/<- %ebp 4/r32/esp +10834 # setup +10835 (clear-stream _test-input-stream) +10836 (clear-stream $_test-input-buffered-file->buffer) +10837 (clear-stream _test-output-stream) +10838 (clear-stream $_test-output-buffered-file->buffer) +10839 # +10840 (write _test-input-stream "type t {\n") # size = 12, which is not a power of 2 +10841 (write _test-input-stream " x: int\n") +10842 (write _test-input-stream " y: int\n") +10843 (write _test-input-stream " z: int\n") +10844 (write _test-input-stream "}\n") +10845 (write _test-input-stream "fn foo {\n") +10846 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") +10847 (write _test-input-stream " var x/edx: int <- length arr\n") +10848 (write _test-input-stream "}\n") +10849 # convert +10850 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +10851 (flush _test-output-buffered-file) +10852 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10858 # check output +10859 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types-to-edx/0") +10860 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types-to-edx/1") +10861 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/2") +10862 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/3") +10863 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types-to-edx/4") +10864 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types-to-edx/5") +10865 # var a +10866 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/6") +10867 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-edx/7") +10868 # var x +10869 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %edx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/8") +10870 # length instruction +10871 (check-next-stream-line-equal _test-output-stream " 50/push-eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/9") +10872 (check-next-stream-line-equal _test-output-stream " 51/push-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/10") +10873 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types-to-edx/11") +10874 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/12") +10875 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types-to-edx/13") +10876 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/14") +10877 (check-next-stream-line-equal _test-output-stream " 89/<- %edx 0/r32/eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/15") +10878 (check-next-stream-line-equal _test-output-stream " 59/pop-to-ecx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/16") +10879 (check-next-stream-line-equal _test-output-stream " 58/pop-to-eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/17") +10880 # reclaim x +10881 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %edx" "F - test-convert-length-of-array-of-user-defined-types-to-edx/18") +10882 # reclaim a +10883 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types-to-edx/19") +10884 # +10885 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types-to-edx/20") +10886 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types-to-edx/21") +10887 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types-to-edx/22") +10888 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/23") +10889 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types-to-edx/24") +10890 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types-to-edx/25") +10891 # . epilogue +10892 89/<- %esp 5/r32/ebp +10893 5d/pop-to-ebp +10894 c3/return +10895 +10896 test-convert-length-of-array-of-user-defined-types: +10897 # . prologue +10898 55/push-ebp +10899 89/<- %ebp 4/r32/esp +10900 # setup +10901 (clear-stream _test-input-stream) +10902 (clear-stream $_test-input-buffered-file->buffer) +10903 (clear-stream _test-output-stream) +10904 (clear-stream $_test-output-buffered-file->buffer) +10905 # +10906 (write _test-input-stream "type t {\n") # each t is 8 bytes, which is a power of 2 +10907 (write _test-input-stream " x: int\n") +10908 (write _test-input-stream " y: int\n") +10909 (write _test-input-stream " z: int\n") +10910 (write _test-input-stream "}\n") +10911 (write _test-input-stream "fn foo {\n") +10912 (write _test-input-stream " var arr/eax: (addr array t) <- copy 0\n") +10913 (write _test-input-stream " var x/ebx: int <- length arr\n") +10914 (write _test-input-stream "}\n") +10915 # convert +10916 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +10917 (flush _test-output-buffered-file) +10918 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +10924 # check output +10925 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array-of-user-defined-types/0") +10926 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array-of-user-defined-types/1") +10927 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array-of-user-defined-types/2") +10928 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array-of-user-defined-types/3") +10929 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array-of-user-defined-types/4") +10930 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array-of-user-defined-types/5") +10931 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-of-user-defined-types/6") +10932 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-length-of-array-of-user-defined-types/7") +10933 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ebx" "F - test-convert-length-of-array-of-user-defined-types/8") +10934 (check-next-stream-line-equal _test-output-stream " 50/push-eax" "F - test-convert-length-of-array-of-user-defined-types/9") +10935 (check-next-stream-line-equal _test-output-stream " 51/push-ecx" "F - test-convert-length-of-array-of-user-defined-types/10") +10936 (check-next-stream-line-equal _test-output-stream " 52/push-edx" "F - test-convert-length-of-array-of-user-defined-types/11") +10937 (check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array-of-user-defined-types/12") +10938 (check-next-stream-line-equal _test-output-stream " 31/xor %edx 2/r32/edx" "F - test-convert-length-of-array-of-user-defined-types/13") +10939 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0x0000000c/imm32" "F - test-convert-length-of-array-of-user-defined-types/14") +10940 (check-next-stream-line-equal _test-output-stream " f7 7/subop/idiv-eax-edx-by %ecx" "F - test-convert-length-of-array-of-user-defined-types/15") +10941 (check-next-stream-line-equal _test-output-stream " 89/<- %ebx 0/r32/eax" "F - test-convert-length-of-array-of-user-defined-types/16") +10942 (check-next-stream-line-equal _test-output-stream " 5a/pop-to-edx" "F - test-convert-length-of-array-of-user-defined-types/17") +10943 (check-next-stream-line-equal _test-output-stream " 59/pop-to-ecx" "F - test-convert-length-of-array-of-user-defined-types/18") +10944 (check-next-stream-line-equal _test-output-stream " 58/pop-to-eax" "F - test-convert-length-of-array-of-user-defined-types/19") +10945 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ebx" "F - test-convert-length-of-array-of-user-defined-types/20") +10946 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-of-user-defined-types/21") +10947 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-of-user-defined-types/22") +10948 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-of-user-defined-types/23") +10949 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-of-user-defined-types/24") +10950 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-of-user-defined-types/25") +10951 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-of-user-defined-types/26") +10952 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-of-user-defined-types/27") +10953 # . epilogue +10954 89/<- %esp 5/r32/ebp +10955 5d/pop-to-ebp +10956 c3/return +10957 +10958 test-index-with-non-array-atom-base-type: +10959 # . prologue +10960 55/push-ebp +10961 89/<- %ebp 4/r32/esp +10962 # setup +10963 (clear-stream _test-input-stream) +10964 (clear-stream $_test-input-buffered-file->buffer) +10965 (clear-stream _test-output-stream) +10966 (clear-stream $_test-output-buffered-file->buffer) +10967 (clear-stream _test-error-stream) +10968 (clear-stream $_test-error-buffered-file->buffer) +10969 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +10970 68/push 0/imm32 +10971 68/push 0/imm32 +10972 89/<- %edx 4/r32/esp +10973 (tailor-exit-descriptor %edx 0x10) +10974 # +10975 (write _test-input-stream "fn foo {\n") +10976 (write _test-input-stream " var a: int\n") +10977 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") +10978 (write _test-input-stream "}\n") +10979 # convert +10980 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +10981 # registers except esp clobbered at this point +10982 # restore ed +10983 89/<- %edx 4/r32/esp +10984 (flush _test-output-buffered-file) +10985 (flush _test-error-buffered-file) +10986 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +10992 # check output +10993 (check-stream-equal _test-output-stream "" "F - test-index-with-non-array-atom-base-type: output should be empty") +10994 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is not an array" "F - test-index-with-non-array-atom-base-type: error message") +10995 # check that stop(1) was called +10996 (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status") +10997 # don't restore from ebp +10998 81 0/subop/add %esp 8/imm32 +10999 # . epilogue +11000 5d/pop-to-ebp +11001 c3/return +11002 +11003 test-index-with-non-array-compound-base-type: +11004 # . prologue +11005 55/push-ebp +11006 89/<- %ebp 4/r32/esp +11007 # setup +11008 (clear-stream _test-input-stream) +11009 (clear-stream $_test-input-buffered-file->buffer) +11010 (clear-stream _test-output-stream) +11011 (clear-stream $_test-output-buffered-file->buffer) +11012 (clear-stream _test-error-stream) +11013 (clear-stream $_test-error-buffered-file->buffer) +11014 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11015 68/push 0/imm32 +11016 68/push 0/imm32 +11017 89/<- %edx 4/r32/esp +11018 (tailor-exit-descriptor %edx 0x10) +11019 # +11020 (write _test-input-stream "fn foo {\n") +11021 (write _test-input-stream " var a: (handle int)\n") +11022 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") +11023 (write _test-input-stream "}\n") +11024 # convert +11025 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11026 # registers except esp clobbered at this point +11027 # restore ed +11028 89/<- %edx 4/r32/esp +11029 (flush _test-output-buffered-file) +11030 (flush _test-error-buffered-file) +11031 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11037 # check output +11038 (check-stream-equal _test-output-stream "" "F - test-index-with-non-array-compound-base-type: output should be empty") +11039 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is not an array" "F - test-index-with-non-array-compound-base-type: error message") +11040 # check that stop(1) was called +11041 (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status") +11042 # don't restore from ebp +11043 81 0/subop/add %esp 8/imm32 +11044 # . epilogue +11045 5d/pop-to-ebp +11046 c3/return +11047 +11048 test-index-with-non-array-compound-base-type-2: +11049 # . prologue +11050 55/push-ebp +11051 89/<- %ebp 4/r32/esp +11052 # setup +11053 (clear-stream _test-input-stream) +11054 (clear-stream $_test-input-buffered-file->buffer) +11055 (clear-stream _test-output-stream) +11056 (clear-stream $_test-output-buffered-file->buffer) +11057 (clear-stream _test-error-stream) +11058 (clear-stream $_test-error-buffered-file->buffer) +11059 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11060 68/push 0/imm32 +11061 68/push 0/imm32 +11062 89/<- %edx 4/r32/esp +11063 (tailor-exit-descriptor %edx 0x10) +11064 # +11065 (write _test-input-stream "fn foo {\n") +11066 (write _test-input-stream " var a: (addr int)\n") +11067 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") +11068 (write _test-input-stream "}\n") +11069 # convert +11070 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11071 # registers except esp clobbered at this point +11072 # restore ed +11073 89/<- %edx 4/r32/esp +11074 (flush _test-output-buffered-file) +11075 (flush _test-error-buffered-file) +11076 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11082 # check output +11083 (check-stream-equal _test-output-stream "" "F - test-index-with-non-array-compound-base-type-2: output should be empty") +11084 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is not an array" "F - test-index-with-non-array-compound-base-type-2: error message") +11085 # check that stop(1) was called +11086 (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status") +11087 # don't restore from ebp +11088 81 0/subop/add %esp 8/imm32 +11089 # . epilogue +11090 5d/pop-to-ebp +11091 c3/return +11092 +11093 test-index-with-array-atom-base-type: +11094 # . prologue +11095 55/push-ebp +11096 89/<- %ebp 4/r32/esp +11097 # setup +11098 (clear-stream _test-input-stream) +11099 (clear-stream $_test-input-buffered-file->buffer) +11100 (clear-stream _test-output-stream) +11101 (clear-stream $_test-output-buffered-file->buffer) +11102 (clear-stream _test-error-stream) +11103 (clear-stream $_test-error-buffered-file->buffer) +11104 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11105 68/push 0/imm32 +11106 68/push 0/imm32 +11107 89/<- %edx 4/r32/esp +11108 (tailor-exit-descriptor %edx 0x10) +11109 # +11110 (write _test-input-stream "fn foo {\n") +11111 (write _test-input-stream " var a: array\n") +11112 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") +11113 (write _test-input-stream "}\n") +11114 # convert +11115 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11116 # registers except esp clobbered at this point +11117 # restore ed +11118 89/<- %edx 4/r32/esp +11119 (flush _test-output-buffered-file) +11120 (flush _test-error-buffered-file) +11121 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11127 # check output +11128 (check-stream-equal _test-output-stream "" "F - test-index-with-array-atom-base-type: output should be empty") +11129 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: array 'a' must specify the type of its elements" "F - test-index-with-array-atom-base-type: error message") +11130 # check that stop(1) was called +11131 (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status") +11132 # don't restore from ebp +11133 81 0/subop/add %esp 8/imm32 +11134 # . epilogue +11135 5d/pop-to-ebp +11136 c3/return +11137 +11138 test-index-with-addr-base-on-stack: +11139 # . prologue +11140 55/push-ebp +11141 89/<- %ebp 4/r32/esp +11142 # setup +11143 (clear-stream _test-input-stream) +11144 (clear-stream $_test-input-buffered-file->buffer) +11145 (clear-stream _test-output-stream) +11146 (clear-stream $_test-output-buffered-file->buffer) +11147 (clear-stream _test-error-stream) +11148 (clear-stream $_test-error-buffered-file->buffer) +11149 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11150 68/push 0/imm32 +11151 68/push 0/imm32 +11152 89/<- %edx 4/r32/esp +11153 (tailor-exit-descriptor %edx 0x10) +11154 # +11155 (write _test-input-stream "fn foo {\n") +11156 (write _test-input-stream " var a: (addr array int)\n") +11157 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0\n") +11158 (write _test-input-stream "}\n") +11159 # convert +11160 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11161 # registers except esp clobbered at this point +11162 # restore ed +11163 89/<- %edx 4/r32/esp +11164 (flush _test-output-buffered-file) +11165 (flush _test-error-buffered-file) +11166 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11172 # check output +11173 (check-stream-equal _test-output-stream "" "F - test-index-with-addr-base-on-stack: output should be empty") +11174 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: var 'a' is an addr to an array, and so must live in a register" "F - test-index-with-addr-base-on-stack: error message") +11175 # check that stop(1) was called +11176 (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status") +11177 # don't restore from ebp +11178 81 0/subop/add %esp 8/imm32 +11179 # . epilogue +11180 5d/pop-to-ebp +11181 c3/return +11182 +11183 test-index-with-wrong-index-type: +11184 # . prologue +11185 55/push-ebp +11186 89/<- %ebp 4/r32/esp +11187 # setup +11188 (clear-stream _test-input-stream) +11189 (clear-stream $_test-input-buffered-file->buffer) +11190 (clear-stream _test-output-stream) +11191 (clear-stream $_test-output-buffered-file->buffer) +11192 (clear-stream _test-error-stream) +11193 (clear-stream $_test-error-buffered-file->buffer) +11194 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11195 68/push 0/imm32 +11196 68/push 0/imm32 +11197 89/<- %edx 4/r32/esp +11198 (tailor-exit-descriptor %edx 0x10) +11199 # +11200 (write _test-input-stream "fn foo {\n") +11201 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") +11202 (write _test-input-stream " var b: boolean\n") +11203 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") +11204 (write _test-input-stream "}\n") +11205 # convert +11206 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11207 # registers except esp clobbered at this point +11208 # restore ed +11209 89/<- %edx 4/r32/esp +11210 (flush _test-output-buffered-file) +11211 (flush _test-error-buffered-file) +11212 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11218 # check output +11219 (check-stream-equal _test-output-stream "" "F - test-index-with-wrong-index-type: output should be empty") +11220 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: second argument 'b' must be an int or offset" "F - test-index-with-wrong-index-type: error message") +11221 # check that stop(1) was called +11222 (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status") +11223 # don't restore from ebp +11224 81 0/subop/add %esp 8/imm32 +11225 # . epilogue +11226 5d/pop-to-ebp +11227 c3/return +11228 +11229 test-index-with-offset-atom-index-type: +11230 # . prologue +11231 55/push-ebp +11232 89/<- %ebp 4/r32/esp +11233 # setup +11234 (clear-stream _test-input-stream) +11235 (clear-stream $_test-input-buffered-file->buffer) +11236 (clear-stream _test-output-stream) +11237 (clear-stream $_test-output-buffered-file->buffer) +11238 (clear-stream _test-error-stream) +11239 (clear-stream $_test-error-buffered-file->buffer) +11240 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11241 68/push 0/imm32 +11242 68/push 0/imm32 +11243 89/<- %edx 4/r32/esp +11244 (tailor-exit-descriptor %edx 0x10) +11245 # +11246 (write _test-input-stream "fn foo {\n") +11247 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") +11248 (write _test-input-stream " var b: offset\n") +11249 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") +11250 (write _test-input-stream "}\n") +11251 # convert +11252 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11253 # registers except esp clobbered at this point +11254 # restore ed +11255 89/<- %edx 4/r32/esp +11256 (flush _test-output-buffered-file) +11257 (flush _test-error-buffered-file) +11258 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11264 # check output +11265 (check-stream-equal _test-output-stream "" "F - test-index-with-offset-atom-index-type: output should be empty") +11266 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: offset 'b' must specify the type of array elements" "F - test-index-with-offset-atom-index-type: error message") +11267 # check that stop(1) was called +11268 (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status") +11269 # don't restore from ebp +11270 81 0/subop/add %esp 8/imm32 +11271 # . epilogue +11272 5d/pop-to-ebp +11273 c3/return +11274 +11275 test-index-with-offset-on-stack: +11276 # . prologue +11277 55/push-ebp +11278 89/<- %ebp 4/r32/esp +11279 # setup +11280 (clear-stream _test-input-stream) +11281 (clear-stream $_test-input-buffered-file->buffer) +11282 (clear-stream _test-output-stream) +11283 (clear-stream $_test-output-buffered-file->buffer) +11284 (clear-stream _test-error-stream) +11285 (clear-stream $_test-error-buffered-file->buffer) +11286 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11287 68/push 0/imm32 +11288 68/push 0/imm32 +11289 89/<- %edx 4/r32/esp +11290 (tailor-exit-descriptor %edx 0x10) +11291 # +11292 (write _test-input-stream "fn foo {\n") +11293 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") +11294 (write _test-input-stream " var b: int\n") +11295 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") +11296 (write _test-input-stream "}\n") +11297 # convert +11298 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11299 # registers except esp clobbered at this point +11300 # restore ed +11301 89/<- %edx 4/r32/esp +11302 (flush _test-output-buffered-file) +11303 (flush _test-error-buffered-file) +11304 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11310 # check output +11311 (check-stream-equal _test-output-stream "" "F - test-index-with-offset-on-stack: output should be empty") +11312 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: second argument 'b' must be in a register" "F - test-index-with-offset-on-stack: error message") +11313 # check that stop(1) was called +11314 (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status") +11315 # don't restore from ebp +11316 81 0/subop/add %esp 8/imm32 +11317 # . epilogue +11318 5d/pop-to-ebp +11319 c3/return +11320 +11321 test-index-needs-offset-type: +11322 # . prologue +11323 55/push-ebp +11324 89/<- %ebp 4/r32/esp +11325 # setup +11326 (clear-stream _test-input-stream) +11327 (clear-stream $_test-input-buffered-file->buffer) +11328 (clear-stream _test-output-stream) +11329 (clear-stream $_test-output-buffered-file->buffer) +11330 (clear-stream _test-error-stream) +11331 (clear-stream $_test-error-buffered-file->buffer) +11332 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11333 68/push 0/imm32 +11334 68/push 0/imm32 +11335 89/<- %edx 4/r32/esp +11336 (tailor-exit-descriptor %edx 0x10) +11337 # +11338 (write _test-input-stream "fn foo {\n") +11339 (write _test-input-stream " var a/eax: (addr array t) <- copy 0\n") +11340 (write _test-input-stream " var b/ebx: int <- copy 0\n") +11341 (write _test-input-stream " var c/ecx: (addr int) <- index a, b\n") +11342 (write _test-input-stream "}\n") +11343 (write _test-input-stream "type t {\n") # size 12 is not a power of two +11344 (write _test-input-stream " x: int\n") +11345 (write _test-input-stream " y: int\n") +11346 (write _test-input-stream " z: int\n") +11347 (write _test-input-stream "}\n") +11348 # convert +11349 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11350 # registers except esp clobbered at this point +11351 # restore ed +11352 89/<- %edx 4/r32/esp +11353 (flush _test-output-buffered-file) +11354 (flush _test-error-buffered-file) +11355 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11361 # check output +11362 (check-stream-equal _test-output-stream "" "F - test-index-needs-offset-type: output should be empty") +11363 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: cannot take an int for array 'a'; create an offset instead. See mu.md for details." "F - test-index-needs-offset-type: error message") +11364 # check that stop(1) was called +11365 (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status") +11366 # don't restore from ebp +11367 81 0/subop/add %esp 8/imm32 +11368 # . epilogue +11369 5d/pop-to-ebp +11370 c3/return +11371 +11372 test-index-with-output-not-address: +11373 # . prologue +11374 55/push-ebp +11375 89/<- %ebp 4/r32/esp +11376 # setup +11377 (clear-stream _test-input-stream) +11378 (clear-stream $_test-input-buffered-file->buffer) +11379 (clear-stream _test-output-stream) +11380 (clear-stream $_test-output-buffered-file->buffer) +11381 (clear-stream _test-error-stream) +11382 (clear-stream $_test-error-buffered-file->buffer) +11383 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11384 68/push 0/imm32 +11385 68/push 0/imm32 +11386 89/<- %edx 4/r32/esp +11387 (tailor-exit-descriptor %edx 0x10) +11388 # +11389 (write _test-input-stream "fn foo {\n") +11390 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +11391 (write _test-input-stream " var o/edi: int <- index a, 0\n") +11392 (write _test-input-stream "}\n") +11393 # convert +11394 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11395 # registers except esp clobbered at this point +11396 # restore ed +11397 89/<- %edx 4/r32/esp +11398 (flush _test-output-buffered-file) +11399 (flush _test-error-buffered-file) +11400 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11406 # check output +11407 (check-stream-equal _test-output-stream "" "F - test-index-with-output-not-address: output should be empty") +11408 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' must be an addr" "F - test-index-with-output-not-address: error message") +11409 # check that stop(1) was called +11410 (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status") +11411 # don't restore from ebp +11412 81 0/subop/add %esp 8/imm32 +11413 # . epilogue +11414 5d/pop-to-ebp +11415 c3/return +11416 +11417 test-index-with-output-not-address-2: +11418 # . prologue +11419 55/push-ebp +11420 89/<- %ebp 4/r32/esp +11421 # setup +11422 (clear-stream _test-input-stream) +11423 (clear-stream $_test-input-buffered-file->buffer) +11424 (clear-stream _test-output-stream) +11425 (clear-stream $_test-output-buffered-file->buffer) +11426 (clear-stream _test-error-stream) +11427 (clear-stream $_test-error-buffered-file->buffer) +11428 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11429 68/push 0/imm32 +11430 68/push 0/imm32 +11431 89/<- %edx 4/r32/esp +11432 (tailor-exit-descriptor %edx 0x10) +11433 # +11434 (write _test-input-stream "fn foo {\n") +11435 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +11436 (write _test-input-stream " var o/edi: (int) <- index a, 0\n") +11437 (write _test-input-stream "}\n") +11438 # convert +11439 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11440 # registers except esp clobbered at this point +11441 # restore ed +11442 89/<- %edx 4/r32/esp +11443 (flush _test-output-buffered-file) +11444 (flush _test-error-buffered-file) +11445 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11451 # check output +11452 (check-stream-equal _test-output-stream "" "F - test-index-with-output-not-address-2: output should be empty") +11453 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' must be an addr" "F - test-index-with-output-not-address-2: error message") +11454 # check that stop(1) was called +11455 (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status") +11456 # don't restore from ebp +11457 81 0/subop/add %esp 8/imm32 +11458 # . epilogue +11459 5d/pop-to-ebp +11460 c3/return +11461 +11462 test-index-with-wrong-output-type: +11463 # . prologue +11464 55/push-ebp +11465 89/<- %ebp 4/r32/esp +11466 # setup +11467 (clear-stream _test-input-stream) +11468 (clear-stream $_test-input-buffered-file->buffer) +11469 (clear-stream _test-output-stream) +11470 (clear-stream $_test-output-buffered-file->buffer) +11471 (clear-stream _test-error-stream) +11472 (clear-stream $_test-error-buffered-file->buffer) +11473 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11474 68/push 0/imm32 +11475 68/push 0/imm32 +11476 89/<- %edx 4/r32/esp +11477 (tailor-exit-descriptor %edx 0x10) +11478 # +11479 (write _test-input-stream "fn foo {\n") +11480 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +11481 (write _test-input-stream " var o/edi: (addr int) <- index a, 0\n") +11482 (write _test-input-stream "}\n") +11483 # convert +11484 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11485 # registers except esp clobbered at this point +11486 # restore ed +11487 89/<- %edx 4/r32/esp +11488 (flush _test-output-buffered-file) +11489 (flush _test-error-buffered-file) +11490 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11496 # check output +11497 (check-stream-equal _test-output-stream "" "F - test-index-with-wrong-output-type: output should be empty") +11498 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' does not have the right type" "F - test-index-with-wrong-output-type: error message") +11499 # check that stop(1) was called +11500 (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status") +11501 # don't restore from ebp +11502 81 0/subop/add %esp 8/imm32 +11503 # . epilogue +11504 5d/pop-to-ebp +11505 c3/return +11506 +11507 test-index-with-wrong-output-compound-type: +11508 # . prologue +11509 55/push-ebp +11510 89/<- %ebp 4/r32/esp +11511 # setup +11512 (clear-stream _test-input-stream) +11513 (clear-stream $_test-input-buffered-file->buffer) +11514 (clear-stream _test-output-stream) +11515 (clear-stream $_test-output-buffered-file->buffer) +11516 (clear-stream _test-error-stream) +11517 (clear-stream $_test-error-buffered-file->buffer) +11518 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11519 68/push 0/imm32 +11520 68/push 0/imm32 +11521 89/<- %edx 4/r32/esp +11522 (tailor-exit-descriptor %edx 0x10) +11523 # +11524 (write _test-input-stream "fn foo {\n") +11525 (write _test-input-stream " var a/ebx: (addr array handle boolean) <- copy 0\n") +11526 (write _test-input-stream " var o/edi: (addr handle int) <- index a, 0\n") +11527 (write _test-input-stream "}\n") +11528 # convert +11529 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11530 # registers except esp clobbered at this point +11531 # restore ed +11532 89/<- %edx 4/r32/esp +11533 (flush _test-output-buffered-file) +11534 (flush _test-error-buffered-file) +11535 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11541 # check output +11542 (check-stream-equal _test-output-stream "" "F - test-index-with-wrong-output-compound-type: output should be empty") +11543 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: output 'o' does not have the right type" "F - test-index-with-wrong-output-compound-type: error message") +11544 # check that stop(1) was called +11545 (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status") +11546 # don't restore from ebp +11547 81 0/subop/add %esp 8/imm32 +11548 # . epilogue +11549 5d/pop-to-ebp +11550 c3/return +11551 +11552 test-index-with-no-inouts: +11553 # . prologue +11554 55/push-ebp +11555 89/<- %ebp 4/r32/esp +11556 # setup +11557 (clear-stream _test-input-stream) +11558 (clear-stream $_test-input-buffered-file->buffer) +11559 (clear-stream _test-output-stream) +11560 (clear-stream $_test-output-buffered-file->buffer) +11561 (clear-stream _test-error-stream) +11562 (clear-stream $_test-error-buffered-file->buffer) +11563 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11564 68/push 0/imm32 +11565 68/push 0/imm32 +11566 89/<- %edx 4/r32/esp +11567 (tailor-exit-descriptor %edx 0x10) +11568 # +11569 (write _test-input-stream "fn foo {\n") +11570 (write _test-input-stream " var c/ecx: (addr int) <- index\n") +11571 (write _test-input-stream "}\n") +11572 # convert +11573 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11574 # registers except esp clobbered at this point +11575 # restore ed +11576 89/<- %edx 4/r32/esp +11577 (flush _test-output-buffered-file) +11578 (flush _test-error-buffered-file) +11579 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11585 # check output +11586 (check-stream-equal _test-output-stream "" "F - test-index-with-no-inouts: output should be empty") +11587 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too few inouts (2 required)" "F - test-index-with-no-inouts: error message") +11588 # check that stop(1) was called +11589 (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status") +11590 # don't restore from ebp +11591 81 0/subop/add %esp 8/imm32 +11592 # . epilogue +11593 5d/pop-to-ebp +11594 c3/return +11595 +11596 test-index-with-too-few-inouts: +11597 # . prologue +11598 55/push-ebp +11599 89/<- %ebp 4/r32/esp +11600 # setup +11601 (clear-stream _test-input-stream) +11602 (clear-stream $_test-input-buffered-file->buffer) +11603 (clear-stream _test-output-stream) +11604 (clear-stream $_test-output-buffered-file->buffer) +11605 (clear-stream _test-error-stream) +11606 (clear-stream $_test-error-buffered-file->buffer) +11607 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11608 68/push 0/imm32 +11609 68/push 0/imm32 +11610 89/<- %edx 4/r32/esp +11611 (tailor-exit-descriptor %edx 0x10) +11612 # +11613 (write _test-input-stream "fn foo {\n") +11614 (write _test-input-stream " var a: (array int 3)\n") +11615 (write _test-input-stream " var c/ecx: (addr int) <- index a\n") +11616 (write _test-input-stream "}\n") +11617 # convert +11618 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11619 # registers except esp clobbered at this point +11620 # restore ed +11621 89/<- %edx 4/r32/esp +11622 (flush _test-output-buffered-file) +11623 (flush _test-error-buffered-file) +11624 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11630 # check output +11631 (check-stream-equal _test-output-stream "" "F - test-index-with-too-few-inouts: output should be empty") +11632 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too few inouts (2 required)" "F - test-index-with-too-few-inouts: error message") +11633 # check that stop(1) was called +11634 (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status") +11635 # don't restore from ebp +11636 81 0/subop/add %esp 8/imm32 +11637 # . epilogue +11638 5d/pop-to-ebp +11639 c3/return +11640 +11641 test-index-with-too-many-inouts: +11642 # . prologue +11643 55/push-ebp +11644 89/<- %ebp 4/r32/esp +11645 # setup +11646 (clear-stream _test-input-stream) +11647 (clear-stream $_test-input-buffered-file->buffer) +11648 (clear-stream _test-output-stream) +11649 (clear-stream $_test-output-buffered-file->buffer) +11650 (clear-stream _test-error-stream) +11651 (clear-stream $_test-error-buffered-file->buffer) +11652 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11653 68/push 0/imm32 +11654 68/push 0/imm32 +11655 89/<- %edx 4/r32/esp +11656 (tailor-exit-descriptor %edx 0x10) +11657 # +11658 (write _test-input-stream "fn foo {\n") +11659 (write _test-input-stream " var a: (array int 3)\n") +11660 (write _test-input-stream " var c/ecx: (addr int) <- index a, 0, 0\n") +11661 (write _test-input-stream "}\n") +11662 # convert +11663 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11664 # registers except esp clobbered at this point +11665 # restore ed +11666 89/<- %edx 4/r32/esp +11667 (flush _test-output-buffered-file) +11668 (flush _test-error-buffered-file) +11669 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11675 # check output +11676 (check-stream-equal _test-output-stream "" "F - test-index-with-too-many-inouts: output should be empty") +11677 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too many inouts (2 required)" "F - test-index-with-too-many-inouts: error message") +11678 # check that stop(1) was called +11679 (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status") +11680 # don't restore from ebp +11681 81 0/subop/add %esp 8/imm32 +11682 # . epilogue +11683 5d/pop-to-ebp +11684 c3/return +11685 +11686 test-index-with-no-output: +11687 # . prologue +11688 55/push-ebp +11689 89/<- %ebp 4/r32/esp +11690 # setup +11691 (clear-stream _test-input-stream) +11692 (clear-stream $_test-input-buffered-file->buffer) +11693 (clear-stream _test-output-stream) +11694 (clear-stream $_test-output-buffered-file->buffer) +11695 (clear-stream _test-error-stream) +11696 (clear-stream $_test-error-buffered-file->buffer) +11697 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11698 68/push 0/imm32 +11699 68/push 0/imm32 +11700 89/<- %edx 4/r32/esp +11701 (tailor-exit-descriptor %edx 0x10) +11702 # +11703 (write _test-input-stream "fn foo {\n") +11704 (write _test-input-stream " var a: (array int 3)\n") +11705 (write _test-input-stream " index a, 0\n") +11706 (write _test-input-stream "}\n") +11707 # convert +11708 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11709 # registers except esp clobbered at this point +11710 # restore ed +11711 89/<- %edx 4/r32/esp +11712 (flush _test-output-buffered-file) +11713 (flush _test-error-buffered-file) +11714 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11720 # check output +11721 (check-stream-equal _test-output-stream "" "F - test-index-with-no-output: output should be empty") +11722 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: must have an output" "F - test-index-with-no-output: error message") +11723 # check that stop(1) was called +11724 (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status") +11725 # don't restore from ebp +11726 81 0/subop/add %esp 8/imm32 +11727 # . epilogue +11728 5d/pop-to-ebp +11729 c3/return +11730 +11731 test-index-with-too-many-outputs: +11732 # . prologue +11733 55/push-ebp +11734 89/<- %ebp 4/r32/esp +11735 # setup +11736 (clear-stream _test-input-stream) +11737 (clear-stream $_test-input-buffered-file->buffer) +11738 (clear-stream _test-output-stream) +11739 (clear-stream $_test-output-buffered-file->buffer) +11740 (clear-stream _test-error-stream) +11741 (clear-stream $_test-error-buffered-file->buffer) +11742 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11743 68/push 0/imm32 +11744 68/push 0/imm32 +11745 89/<- %edx 4/r32/esp +11746 (tailor-exit-descriptor %edx 0x10) +11747 # +11748 (write _test-input-stream "fn foo {\n") +11749 (write _test-input-stream " var a: (array int 3)\n") +11750 (write _test-input-stream " var b/eax: (addr int) <- copy 0\n") +11751 (write _test-input-stream " var c/ecx: (addr int) <- copy 0\n") +11752 (write _test-input-stream " b, c <- index a, 0\n") +11753 (write _test-input-stream "}\n") +11754 # convert +11755 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11756 # registers except esp clobbered at this point +11757 # restore ed +11758 89/<- %edx 4/r32/esp +11759 (flush _test-output-buffered-file) +11760 (flush _test-error-buffered-file) +11761 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11767 # check output +11768 (check-stream-equal _test-output-stream "" "F - test-index-with-too-many-outputs: output should be empty") +11769 (check-next-stream-line-equal _test-error-stream "fn foo: stmt index: too many outputs (1 required)" "F - test-index-with-too-many-outputs: error message") +11770 # check that stop(1) was called +11771 (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status") +11772 # don't restore from ebp +11773 81 0/subop/add %esp 8/imm32 +11774 # . epilogue +11775 5d/pop-to-ebp +11776 c3/return +11777 +11778 test-compute-offset-with-non-array-atom-base-type: +11779 # . prologue +11780 55/push-ebp +11781 89/<- %ebp 4/r32/esp +11782 # setup +11783 (clear-stream _test-input-stream) +11784 (clear-stream $_test-input-buffered-file->buffer) +11785 (clear-stream _test-output-stream) +11786 (clear-stream $_test-output-buffered-file->buffer) +11787 (clear-stream _test-error-stream) +11788 (clear-stream $_test-error-buffered-file->buffer) +11789 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11790 68/push 0/imm32 +11791 68/push 0/imm32 +11792 89/<- %edx 4/r32/esp +11793 (tailor-exit-descriptor %edx 0x10) +11794 # +11795 (write _test-input-stream "fn foo {\n") +11796 (write _test-input-stream " var a: int\n") +11797 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") +11798 (write _test-input-stream "}\n") +11799 # convert +11800 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11801 # registers except esp clobbered at this point +11802 # restore ed +11803 89/<- %edx 4/r32/esp +11804 (flush _test-output-buffered-file) +11805 (flush _test-error-buffered-file) +11806 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11812 # check output +11813 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-non-array-atom-base-type: output should be empty") +11814 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: var 'a' is not an array" "F - test-compute-offset-with-non-array-atom-base-type: error message") +11815 # check that stop(1) was called +11816 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status") +11817 # don't restore from ebp +11818 81 0/subop/add %esp 8/imm32 +11819 # . epilogue +11820 5d/pop-to-ebp +11821 c3/return +11822 +11823 test-compute-offset-with-non-array-compound-base-type: +11824 # . prologue +11825 55/push-ebp +11826 89/<- %ebp 4/r32/esp +11827 # setup +11828 (clear-stream _test-input-stream) +11829 (clear-stream $_test-input-buffered-file->buffer) +11830 (clear-stream _test-output-stream) +11831 (clear-stream $_test-output-buffered-file->buffer) +11832 (clear-stream _test-error-stream) +11833 (clear-stream $_test-error-buffered-file->buffer) +11834 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11835 68/push 0/imm32 +11836 68/push 0/imm32 +11837 89/<- %edx 4/r32/esp +11838 (tailor-exit-descriptor %edx 0x10) +11839 # +11840 (write _test-input-stream "fn foo {\n") +11841 (write _test-input-stream " var a: (handle int)\n") +11842 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") +11843 (write _test-input-stream "}\n") +11844 # convert +11845 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11846 # registers except esp clobbered at this point +11847 # restore ed +11848 89/<- %edx 4/r32/esp +11849 (flush _test-output-buffered-file) +11850 (flush _test-error-buffered-file) +11851 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11857 # check output +11858 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-non-array-compound-base-type: output should be empty") +11859 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: var 'a' is not an array" "F - test-compute-offset-with-non-array-compound-base-type: error message") +11860 # check that stop(1) was called +11861 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status") +11862 # don't restore from ebp +11863 81 0/subop/add %esp 8/imm32 +11864 # . epilogue +11865 5d/pop-to-ebp +11866 c3/return +11867 +11868 test-compute-offset-with-non-array-compound-base-type-2: +11869 # . prologue +11870 55/push-ebp +11871 89/<- %ebp 4/r32/esp +11872 # setup +11873 (clear-stream _test-input-stream) +11874 (clear-stream $_test-input-buffered-file->buffer) +11875 (clear-stream _test-output-stream) +11876 (clear-stream $_test-output-buffered-file->buffer) +11877 (clear-stream _test-error-stream) +11878 (clear-stream $_test-error-buffered-file->buffer) +11879 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11880 68/push 0/imm32 +11881 68/push 0/imm32 +11882 89/<- %edx 4/r32/esp +11883 (tailor-exit-descriptor %edx 0x10) +11884 # +11885 (write _test-input-stream "fn foo {\n") +11886 (write _test-input-stream " var a: (addr int)\n") +11887 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") +11888 (write _test-input-stream "}\n") +11889 # convert +11890 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11891 # registers except esp clobbered at this point +11892 # restore ed +11893 89/<- %edx 4/r32/esp +11894 (flush _test-output-buffered-file) +11895 (flush _test-error-buffered-file) +11896 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11902 # check output +11903 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty") +11904 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: var 'a' is not an array" "F - test-compute-offset-with-non-array-compound-base-type-2: error message") +11905 # check that stop(1) was called +11906 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status") +11907 # don't restore from ebp +11908 81 0/subop/add %esp 8/imm32 +11909 # . epilogue +11910 5d/pop-to-ebp +11911 c3/return +11912 +11913 test-compute-offset-with-array-atom-base-type: +11914 # . prologue +11915 55/push-ebp +11916 89/<- %ebp 4/r32/esp +11917 # setup +11918 (clear-stream _test-input-stream) +11919 (clear-stream $_test-input-buffered-file->buffer) +11920 (clear-stream _test-output-stream) +11921 (clear-stream $_test-output-buffered-file->buffer) +11922 (clear-stream _test-error-stream) +11923 (clear-stream $_test-error-buffered-file->buffer) +11924 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11925 68/push 0/imm32 +11926 68/push 0/imm32 +11927 89/<- %edx 4/r32/esp +11928 (tailor-exit-descriptor %edx 0x10) +11929 # +11930 (write _test-input-stream "fn foo {\n") +11931 (write _test-input-stream " var a: array\n") +11932 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0\n") +11933 (write _test-input-stream "}\n") +11934 # convert +11935 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11936 # registers except esp clobbered at this point +11937 # restore ed +11938 89/<- %edx 4/r32/esp +11939 (flush _test-output-buffered-file) +11940 (flush _test-error-buffered-file) +11941 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11947 # check output +11948 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-array-atom-base-type: output should be empty") +11949 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: array 'a' must specify the type of its elements" "F - test-compute-offset-with-array-atom-base-type: error message") +11950 # check that stop(1) was called +11951 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status") +11952 # don't restore from ebp +11953 81 0/subop/add %esp 8/imm32 +11954 # . epilogue +11955 5d/pop-to-ebp +11956 c3/return +11957 +11958 test-compute-offset-with-wrong-index-type: +11959 # . prologue +11960 55/push-ebp +11961 89/<- %ebp 4/r32/esp +11962 # setup +11963 (clear-stream _test-input-stream) +11964 (clear-stream $_test-input-buffered-file->buffer) +11965 (clear-stream _test-output-stream) +11966 (clear-stream $_test-output-buffered-file->buffer) +11967 (clear-stream _test-error-stream) +11968 (clear-stream $_test-error-buffered-file->buffer) +11969 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +11970 68/push 0/imm32 +11971 68/push 0/imm32 +11972 89/<- %edx 4/r32/esp +11973 (tailor-exit-descriptor %edx 0x10) +11974 # +11975 (write _test-input-stream "fn foo {\n") +11976 (write _test-input-stream " var a/eax: (addr array int) <- copy 0\n") +11977 (write _test-input-stream " var b: boolean\n") +11978 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, b\n") +11979 (write _test-input-stream "}\n") +11980 # convert +11981 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +11982 # registers except esp clobbered at this point +11983 # restore ed +11984 89/<- %edx 4/r32/esp +11985 (flush _test-output-buffered-file) +11986 (flush _test-error-buffered-file) +11987 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +11993 # check output +11994 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-wrong-index-type: output should be empty") +11995 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: second argument 'b' must be an int" "F - test-compute-offset-with-wrong-index-type: error message") +11996 # check that stop(1) was called +11997 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status") +11998 # don't restore from ebp +11999 81 0/subop/add %esp 8/imm32 +12000 # . epilogue +12001 5d/pop-to-ebp +12002 c3/return +12003 +12004 test-compute-offset-with-output-not-offset: +12005 # . prologue +12006 55/push-ebp +12007 89/<- %ebp 4/r32/esp +12008 # setup +12009 (clear-stream _test-input-stream) +12010 (clear-stream $_test-input-buffered-file->buffer) +12011 (clear-stream _test-output-stream) +12012 (clear-stream $_test-output-buffered-file->buffer) +12013 (clear-stream _test-error-stream) +12014 (clear-stream $_test-error-buffered-file->buffer) +12015 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12016 68/push 0/imm32 +12017 68/push 0/imm32 +12018 89/<- %edx 4/r32/esp +12019 (tailor-exit-descriptor %edx 0x10) +12020 # +12021 (write _test-input-stream "fn foo {\n") +12022 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +12023 (write _test-input-stream " var o/edi: int <- compute-offset a, 0\n") +12024 (write _test-input-stream "}\n") +12025 # convert +12026 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12027 # registers except esp clobbered at this point +12028 # restore ed +12029 89/<- %edx 4/r32/esp +12030 (flush _test-output-buffered-file) +12031 (flush _test-error-buffered-file) +12032 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12038 # check output +12039 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-output-not-offset: output should be empty") +12040 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' must be an offset" "F - test-compute-offset-with-output-not-offset: error message") +12041 # check that stop(1) was called +12042 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status") +12043 # don't restore from ebp +12044 81 0/subop/add %esp 8/imm32 +12045 # . epilogue +12046 5d/pop-to-ebp +12047 c3/return +12048 +12049 test-compute-offset-with-output-not-address-2: +12050 # . prologue +12051 55/push-ebp +12052 89/<- %ebp 4/r32/esp +12053 # setup +12054 (clear-stream _test-input-stream) +12055 (clear-stream $_test-input-buffered-file->buffer) +12056 (clear-stream _test-output-stream) +12057 (clear-stream $_test-output-buffered-file->buffer) +12058 (clear-stream _test-error-stream) +12059 (clear-stream $_test-error-buffered-file->buffer) +12060 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12061 68/push 0/imm32 +12062 68/push 0/imm32 +12063 89/<- %edx 4/r32/esp +12064 (tailor-exit-descriptor %edx 0x10) +12065 # +12066 (write _test-input-stream "fn foo {\n") +12067 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +12068 (write _test-input-stream " var o/edi: (int) <- compute-offset a, 0\n") +12069 (write _test-input-stream "}\n") +12070 # convert +12071 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12072 # registers except esp clobbered at this point +12073 # restore ed +12074 89/<- %edx 4/r32/esp +12075 (flush _test-output-buffered-file) +12076 (flush _test-error-buffered-file) +12077 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12083 # check output +12084 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-output-not-address-2: output should be empty") +12085 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' must be an offset" "F - test-compute-offset-with-output-not-address-2: error message") +12086 # check that stop(1) was called +12087 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status") +12088 # don't restore from ebp +12089 81 0/subop/add %esp 8/imm32 +12090 # . epilogue +12091 5d/pop-to-ebp +12092 c3/return +12093 +12094 test-compute-offset-with-wrong-output-type: +12095 # . prologue +12096 55/push-ebp +12097 89/<- %ebp 4/r32/esp +12098 # setup +12099 (clear-stream _test-input-stream) +12100 (clear-stream $_test-input-buffered-file->buffer) +12101 (clear-stream _test-output-stream) +12102 (clear-stream $_test-output-buffered-file->buffer) +12103 (clear-stream _test-error-stream) +12104 (clear-stream $_test-error-buffered-file->buffer) +12105 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12106 68/push 0/imm32 +12107 68/push 0/imm32 +12108 89/<- %edx 4/r32/esp +12109 (tailor-exit-descriptor %edx 0x10) +12110 # +12111 (write _test-input-stream "fn foo {\n") +12112 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +12113 (write _test-input-stream " var o/edi: (offset int) <- compute-offset a, 0\n") +12114 (write _test-input-stream "}\n") +12115 # convert +12116 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12117 # registers except esp clobbered at this point +12118 # restore ed +12119 89/<- %edx 4/r32/esp +12120 (flush _test-output-buffered-file) +12121 (flush _test-error-buffered-file) +12122 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12128 # check output +12129 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-wrong-output-type: output should be empty") +12130 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' does not have the right type" "F - test-compute-offset-with-wrong-output-type: error message") +12131 # check that stop(1) was called +12132 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status") +12133 # don't restore from ebp +12134 81 0/subop/add %esp 8/imm32 +12135 # . epilogue +12136 5d/pop-to-ebp +12137 c3/return +12138 +12139 test-compute-offset-with-wrong-output-compound-type: +12140 # . prologue +12141 55/push-ebp +12142 89/<- %ebp 4/r32/esp +12143 # setup +12144 (clear-stream _test-input-stream) +12145 (clear-stream $_test-input-buffered-file->buffer) +12146 (clear-stream _test-output-stream) +12147 (clear-stream $_test-output-buffered-file->buffer) +12148 (clear-stream _test-error-stream) +12149 (clear-stream $_test-error-buffered-file->buffer) +12150 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12151 68/push 0/imm32 +12152 68/push 0/imm32 +12153 89/<- %edx 4/r32/esp +12154 (tailor-exit-descriptor %edx 0x10) +12155 # +12156 (write _test-input-stream "fn foo {\n") +12157 (write _test-input-stream " var a/ebx: (addr array handle boolean) <- copy 0\n") +12158 (write _test-input-stream " var o/edi: (offset handle int) <- compute-offset a, 0\n") +12159 (write _test-input-stream "}\n") +12160 # convert +12161 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12162 # registers except esp clobbered at this point +12163 # restore ed +12164 89/<- %edx 4/r32/esp +12165 (flush _test-output-buffered-file) +12166 (flush _test-error-buffered-file) +12167 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12173 # check output +12174 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-wrong-output-compound-type: output should be empty") +12175 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: output 'o' does not have the right type" "F - test-compute-offset-with-wrong-output-compound-type: error message") +12176 # check that stop(1) was called +12177 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status") +12178 # don't restore from ebp +12179 81 0/subop/add %esp 8/imm32 +12180 # . epilogue +12181 5d/pop-to-ebp +12182 c3/return +12183 +12184 test-compute-offset-with-no-inouts: +12185 # . prologue +12186 55/push-ebp +12187 89/<- %ebp 4/r32/esp +12188 # setup +12189 (clear-stream _test-input-stream) +12190 (clear-stream $_test-input-buffered-file->buffer) +12191 (clear-stream _test-output-stream) +12192 (clear-stream $_test-output-buffered-file->buffer) +12193 (clear-stream _test-error-stream) +12194 (clear-stream $_test-error-buffered-file->buffer) +12195 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12196 68/push 0/imm32 +12197 68/push 0/imm32 +12198 89/<- %edx 4/r32/esp +12199 (tailor-exit-descriptor %edx 0x10) +12200 # +12201 (write _test-input-stream "fn foo {\n") +12202 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset\n") +12203 (write _test-input-stream "}\n") +12204 # convert +12205 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12206 # registers except esp clobbered at this point +12207 # restore ed +12208 89/<- %edx 4/r32/esp +12209 (flush _test-output-buffered-file) +12210 (flush _test-error-buffered-file) +12211 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12217 # check output +12218 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-no-inouts: output should be empty") +12219 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too few inouts (2 required)" "F - test-compute-offset-with-no-inouts: error message") +12220 # check that stop(1) was called +12221 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status") +12222 # don't restore from ebp +12223 81 0/subop/add %esp 8/imm32 +12224 # . epilogue +12225 5d/pop-to-ebp +12226 c3/return +12227 +12228 test-compute-offset-with-too-few-inouts: +12229 # . prologue +12230 55/push-ebp +12231 89/<- %ebp 4/r32/esp +12232 # setup +12233 (clear-stream _test-input-stream) +12234 (clear-stream $_test-input-buffered-file->buffer) +12235 (clear-stream _test-output-stream) +12236 (clear-stream $_test-output-buffered-file->buffer) +12237 (clear-stream _test-error-stream) +12238 (clear-stream $_test-error-buffered-file->buffer) +12239 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12240 68/push 0/imm32 +12241 68/push 0/imm32 +12242 89/<- %edx 4/r32/esp +12243 (tailor-exit-descriptor %edx 0x10) +12244 # +12245 (write _test-input-stream "fn foo {\n") +12246 (write _test-input-stream " var a: (array int 3)\n") +12247 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a\n") +12248 (write _test-input-stream "}\n") +12249 # convert +12250 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12251 # registers except esp clobbered at this point +12252 # restore ed +12253 89/<- %edx 4/r32/esp +12254 (flush _test-output-buffered-file) +12255 (flush _test-error-buffered-file) +12256 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12262 # check output +12263 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-too-few-inouts: output should be empty") +12264 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too few inouts (2 required)" "F - test-compute-offset-with-too-few-inouts: error message") +12265 # check that stop(1) was called +12266 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status") +12267 # don't restore from ebp +12268 81 0/subop/add %esp 8/imm32 +12269 # . epilogue +12270 5d/pop-to-ebp +12271 c3/return +12272 +12273 test-compute-offset-with-too-many-inouts: +12274 # . prologue +12275 55/push-ebp +12276 89/<- %ebp 4/r32/esp +12277 # setup +12278 (clear-stream _test-input-stream) +12279 (clear-stream $_test-input-buffered-file->buffer) +12280 (clear-stream _test-output-stream) +12281 (clear-stream $_test-output-buffered-file->buffer) +12282 (clear-stream _test-error-stream) +12283 (clear-stream $_test-error-buffered-file->buffer) +12284 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12285 68/push 0/imm32 +12286 68/push 0/imm32 +12287 89/<- %edx 4/r32/esp +12288 (tailor-exit-descriptor %edx 0x10) +12289 # +12290 (write _test-input-stream "fn foo {\n") +12291 (write _test-input-stream " var a: (array int 3)\n") +12292 (write _test-input-stream " var c/ecx: (offset int) <- compute-offset a, 0, 0\n") +12293 (write _test-input-stream "}\n") +12294 # convert +12295 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12296 # registers except esp clobbered at this point +12297 # restore ed +12298 89/<- %edx 4/r32/esp +12299 (flush _test-output-buffered-file) +12300 (flush _test-error-buffered-file) +12301 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12307 # check output +12308 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-too-many-inouts: output should be empty") +12309 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too many inouts (2 required)" "F - test-compute-offset-with-too-many-inouts: error message") +12310 # check that stop(1) was called +12311 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status") +12312 # don't restore from ebp +12313 81 0/subop/add %esp 8/imm32 +12314 # . epilogue +12315 5d/pop-to-ebp +12316 c3/return +12317 +12318 test-compute-offset-with-no-output: +12319 # . prologue +12320 55/push-ebp +12321 89/<- %ebp 4/r32/esp +12322 # setup +12323 (clear-stream _test-input-stream) +12324 (clear-stream $_test-input-buffered-file->buffer) +12325 (clear-stream _test-output-stream) +12326 (clear-stream $_test-output-buffered-file->buffer) +12327 (clear-stream _test-error-stream) +12328 (clear-stream $_test-error-buffered-file->buffer) +12329 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12330 68/push 0/imm32 +12331 68/push 0/imm32 +12332 89/<- %edx 4/r32/esp +12333 (tailor-exit-descriptor %edx 0x10) +12334 # +12335 (write _test-input-stream "fn foo {\n") +12336 (write _test-input-stream " var a: (array int 3)\n") +12337 (write _test-input-stream " compute-offset a, 0\n") +12338 (write _test-input-stream "}\n") +12339 # convert +12340 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12341 # registers except esp clobbered at this point +12342 # restore ed +12343 89/<- %edx 4/r32/esp +12344 (flush _test-output-buffered-file) +12345 (flush _test-error-buffered-file) +12346 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12352 # check output +12353 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-no-output: output should be empty") +12354 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: must have an output" "F - test-compute-offset-with-no-output: error message") +12355 # check that stop(1) was called +12356 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status") +12357 # don't restore from ebp +12358 81 0/subop/add %esp 8/imm32 +12359 # . epilogue +12360 5d/pop-to-ebp +12361 c3/return +12362 +12363 test-compute-offset-with-too-many-outputs: +12364 # . prologue +12365 55/push-ebp +12366 89/<- %ebp 4/r32/esp +12367 # setup +12368 (clear-stream _test-input-stream) +12369 (clear-stream $_test-input-buffered-file->buffer) +12370 (clear-stream _test-output-stream) +12371 (clear-stream $_test-output-buffered-file->buffer) +12372 (clear-stream _test-error-stream) +12373 (clear-stream $_test-error-buffered-file->buffer) +12374 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12375 68/push 0/imm32 +12376 68/push 0/imm32 +12377 89/<- %edx 4/r32/esp +12378 (tailor-exit-descriptor %edx 0x10) +12379 # +12380 (write _test-input-stream "fn foo {\n") +12381 (write _test-input-stream " var a: (array int 3)\n") +12382 (write _test-input-stream " var b/eax: (offset int) <- compute-offset a, 0\n") +12383 (write _test-input-stream " var c/ecx: (addr int) <- copy 0\n") +12384 (write _test-input-stream " b, c <- compute-offset a, 0\n") +12385 (write _test-input-stream "}\n") +12386 # convert +12387 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12388 # registers except esp clobbered at this point +12389 # restore ed +12390 89/<- %edx 4/r32/esp +12391 (flush _test-output-buffered-file) +12392 (flush _test-error-buffered-file) +12393 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12399 # check output +12400 (check-stream-equal _test-output-stream "" "F - test-compute-offset-with-too-many-outputs: output should be empty") +12401 (check-next-stream-line-equal _test-error-stream "fn foo: stmt compute-offset: too many outputs (1 required)" "F - test-compute-offset-with-too-many-outputs: error message") +12402 # check that stop(1) was called +12403 (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status") +12404 # don't restore from ebp +12405 81 0/subop/add %esp 8/imm32 +12406 # . epilogue +12407 5d/pop-to-ebp +12408 c3/return +12409 +12410 test-convert-read-from-stream: +12411 # . prologue +12412 55/push-ebp +12413 89/<- %ebp 4/r32/esp +12414 # setup +12415 (clear-stream _test-input-stream) +12416 (clear-stream $_test-input-buffered-file->buffer) +12417 (clear-stream _test-output-stream) +12418 (clear-stream $_test-output-buffered-file->buffer) +12419 # +12420 (write _test-input-stream "fn foo {\n") +12421 (write _test-input-stream " var s/esi: (addr stream int) <- copy 0\n") +12422 (write _test-input-stream " var o/ecx: (addr int) <- copy 0\n") +12423 (write _test-input-stream " read-from-stream s, o\n") +12424 (write _test-input-stream "}\n") +12425 # convert +12426 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +12427 # registers except esp clobbered at this point +12428 # restore ed +12429 89/<- %edx 4/r32/esp +12430 (flush _test-output-buffered-file) +12431 (flush _test-error-buffered-file) +12432 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +12438 # check output +12439 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-read-from-stream/0") +12440 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-read-from-stream/1") +12441 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-read-from-stream/2") +12442 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-read-from-stream/3") +12443 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-read-from-stream/4") +12444 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-read-from-stream/5") +12445 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-read-from-stream/6") +12446 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-read-from-stream/7") +12447 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-read-from-stream/8") +12448 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-read-from-stream/9") +12449 (check-next-stream-line-equal _test-output-stream " (read-from-stream %esi %ecx 0x00000004)" "F - test-convert-read-from-stream/10") +12450 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-read-from-stream/11") +12451 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-read-from-stream/12") +12452 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-read-from-stream/13") +12453 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-read-from-stream/14") +12454 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-read-from-stream/15") +12455 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-read-from-stream/16") +12456 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-read-from-stream/17") +12457 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-read-from-stream/18") +12458 # . epilogue +12459 89/<- %esp 5/r32/ebp +12460 5d/pop-to-ebp +12461 c3/return +12462 +12463 test-convert-read-from-stream-with-correct-payload-size: +12464 # . prologue +12465 55/push-ebp +12466 89/<- %ebp 4/r32/esp +12467 # setup +12468 (clear-stream _test-input-stream) +12469 (clear-stream $_test-input-buffered-file->buffer) +12470 (clear-stream _test-output-stream) +12471 (clear-stream $_test-output-buffered-file->buffer) +12472 # +12473 (write _test-input-stream "fn foo {\n") +12474 (write _test-input-stream " var s/esi: (addr stream handle int) <- copy 0\n") +12475 (write _test-input-stream " var o/ecx: (addr handle int) <- copy 0\n") +12476 (write _test-input-stream " read-from-stream s, o\n") +12477 (write _test-input-stream "}\n") +12478 # convert +12479 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +12480 # registers except esp clobbered at this point +12481 # restore ed +12482 89/<- %edx 4/r32/esp +12483 (flush _test-output-buffered-file) +12484 (flush _test-error-buffered-file) +12485 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +12491 # check output +12492 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-read-from-stream-with-correct-payload-size/0") +12493 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-read-from-stream-with-correct-payload-size/1") +12494 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-read-from-stream-with-correct-payload-size/2") +12495 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-read-from-stream-with-correct-payload-size/3") +12496 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-read-from-stream-with-correct-payload-size/4") +12497 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-read-from-stream-with-correct-payload-size/5") +12498 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-read-from-stream-with-correct-payload-size/6") +12499 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-read-from-stream-with-correct-payload-size/7") +12500 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-read-from-stream-with-correct-payload-size/8") +12501 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-read-from-stream-with-correct-payload-size/9") +12502 (check-next-stream-line-equal _test-output-stream " (read-from-stream %esi %ecx 0x00000008)" "F - test-convert-read-from-stream-with-correct-payload-size/10") +12503 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-read-from-stream-with-correct-payload-size/11") +12504 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-read-from-stream-with-correct-payload-size/12") +12505 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-read-from-stream-with-correct-payload-size/13") +12506 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-read-from-stream-with-correct-payload-size/14") +12507 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-read-from-stream-with-correct-payload-size/15") +12508 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-read-from-stream-with-correct-payload-size/16") +12509 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-read-from-stream-with-correct-payload-size/17") +12510 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-read-from-stream-with-correct-payload-size/18") +12511 # . epilogue +12512 89/<- %esp 5/r32/ebp +12513 5d/pop-to-ebp +12514 c3/return +12515 +12516 test-read-from-stream-with-non-stream-atom-base-type: +12517 # . prologue +12518 55/push-ebp +12519 89/<- %ebp 4/r32/esp +12520 # setup +12521 (clear-stream _test-input-stream) +12522 (clear-stream $_test-input-buffered-file->buffer) +12523 (clear-stream _test-output-stream) +12524 (clear-stream $_test-output-buffered-file->buffer) +12525 (clear-stream _test-error-stream) +12526 (clear-stream $_test-error-buffered-file->buffer) +12527 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12528 68/push 0/imm32 +12529 68/push 0/imm32 +12530 89/<- %edx 4/r32/esp +12531 (tailor-exit-descriptor %edx 0x10) +12532 # +12533 (write _test-input-stream "fn foo {\n") +12534 (write _test-input-stream " var a: int\n") +12535 (write _test-input-stream " read-from-stream a, 0\n") +12536 (write _test-input-stream "}\n") +12537 # convert +12538 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12539 # registers except esp clobbered at this point +12540 # restore ed +12541 89/<- %edx 4/r32/esp +12542 (flush _test-output-buffered-file) +12543 (flush _test-error-buffered-file) +12544 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12550 # check output +12551 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty") +12552 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-non-stream-atom-base-type: error message") +12553 # check that stop(1) was called +12554 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status") +12555 # don't restore from ebp +12556 81 0/subop/add %esp 8/imm32 +12557 # . epilogue +12558 5d/pop-to-ebp +12559 c3/return +12560 +12561 test-read-from-stream-with-non-stream-compound-base-type: +12562 # . prologue +12563 55/push-ebp +12564 89/<- %ebp 4/r32/esp +12565 # setup +12566 (clear-stream _test-input-stream) +12567 (clear-stream $_test-input-buffered-file->buffer) +12568 (clear-stream _test-output-stream) +12569 (clear-stream $_test-output-buffered-file->buffer) +12570 (clear-stream _test-error-stream) +12571 (clear-stream $_test-error-buffered-file->buffer) +12572 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12573 68/push 0/imm32 +12574 68/push 0/imm32 +12575 89/<- %edx 4/r32/esp +12576 (tailor-exit-descriptor %edx 0x10) +12577 # +12578 (write _test-input-stream "fn foo {\n") +12579 (write _test-input-stream " var a: (handle int)\n") +12580 (write _test-input-stream " read-from-stream a, 0\n") +12581 (write _test-input-stream "}\n") +12582 # convert +12583 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12584 # registers except esp clobbered at this point +12585 # restore ed +12586 89/<- %edx 4/r32/esp +12587 (flush _test-output-buffered-file) +12588 (flush _test-error-buffered-file) +12589 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12595 # check output +12596 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty") +12597 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-non-stream-compound-base-type: error message") +12598 # check that stop(1) was called +12599 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status") +12600 # don't restore from ebp +12601 81 0/subop/add %esp 8/imm32 +12602 # . epilogue +12603 5d/pop-to-ebp +12604 c3/return +12605 +12606 test-read-from-stream-with-non-stream-compound-base-type-2: +12607 # . prologue +12608 55/push-ebp +12609 89/<- %ebp 4/r32/esp +12610 # setup +12611 (clear-stream _test-input-stream) +12612 (clear-stream $_test-input-buffered-file->buffer) +12613 (clear-stream _test-output-stream) +12614 (clear-stream $_test-output-buffered-file->buffer) +12615 (clear-stream _test-error-stream) +12616 (clear-stream $_test-error-buffered-file->buffer) +12617 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12618 68/push 0/imm32 +12619 68/push 0/imm32 +12620 89/<- %edx 4/r32/esp +12621 (tailor-exit-descriptor %edx 0x10) +12622 # +12623 (write _test-input-stream "fn foo {\n") +12624 (write _test-input-stream " var a: (addr int)\n") +12625 (write _test-input-stream " read-from-stream a, 0\n") +12626 (write _test-input-stream "}\n") +12627 # convert +12628 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12629 # registers except esp clobbered at this point +12630 # restore ed +12631 89/<- %edx 4/r32/esp +12632 (flush _test-output-buffered-file) +12633 (flush _test-error-buffered-file) +12634 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12640 # check output +12641 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty") +12642 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message") +12643 # check that stop(1) was called +12644 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status") +12645 # don't restore from ebp +12646 81 0/subop/add %esp 8/imm32 +12647 # . epilogue +12648 5d/pop-to-ebp +12649 c3/return +12650 +12651 test-read-from-stream-with-stream-atom-base-type: +12652 # . prologue +12653 55/push-ebp +12654 89/<- %ebp 4/r32/esp +12655 # setup +12656 (clear-stream _test-input-stream) +12657 (clear-stream $_test-input-buffered-file->buffer) +12658 (clear-stream _test-output-stream) +12659 (clear-stream $_test-output-buffered-file->buffer) +12660 (clear-stream _test-error-stream) +12661 (clear-stream $_test-error-buffered-file->buffer) +12662 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12663 68/push 0/imm32 +12664 68/push 0/imm32 +12665 89/<- %edx 4/r32/esp +12666 (tailor-exit-descriptor %edx 0x10) +12667 # +12668 (write _test-input-stream "fn foo {\n") +12669 (write _test-input-stream " var a: stream\n") +12670 (write _test-input-stream " read-from-stream a, 0\n") +12671 (write _test-input-stream "}\n") +12672 # convert +12673 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12674 # registers except esp clobbered at this point +12675 # restore ed +12676 89/<- %edx 4/r32/esp +12677 (flush _test-output-buffered-file) +12678 (flush _test-error-buffered-file) +12679 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12685 # check output +12686 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-stream-atom-base-type: output should be empty") +12687 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream" "F - test-read-from-stream-with-stream-atom-base-type: error message") +12688 # check that stop(1) was called +12689 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status") +12690 # don't restore from ebp +12691 81 0/subop/add %esp 8/imm32 +12692 # . epilogue +12693 5d/pop-to-ebp +12694 c3/return +12695 +12696 test-read-from-stream-with-wrong-index-type: +12697 # . prologue +12698 55/push-ebp +12699 89/<- %ebp 4/r32/esp +12700 # setup +12701 (clear-stream _test-input-stream) +12702 (clear-stream $_test-input-buffered-file->buffer) +12703 (clear-stream _test-output-stream) +12704 (clear-stream $_test-output-buffered-file->buffer) +12705 (clear-stream _test-error-stream) +12706 (clear-stream $_test-error-buffered-file->buffer) +12707 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12708 68/push 0/imm32 +12709 68/push 0/imm32 +12710 89/<- %edx 4/r32/esp +12711 (tailor-exit-descriptor %edx 0x10) +12712 # +12713 (write _test-input-stream "fn foo {\n") +12714 (write _test-input-stream " var a/eax: (addr stream int) <- copy 0\n") +12715 (write _test-input-stream " var b: boolean\n") +12716 (write _test-input-stream " read-from-stream a, b\n") +12717 (write _test-input-stream "}\n") +12718 # convert +12719 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12720 # registers except esp clobbered at this point +12721 # restore ed +12722 89/<- %edx 4/r32/esp +12723 (flush _test-output-buffered-file) +12724 (flush _test-error-buffered-file) +12725 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12731 # check output +12732 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-wrong-index-type: output should be empty") +12733 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: target 'b' must be an addr" "F - test-read-from-stream-with-wrong-index-type: error message") +12734 # check that stop(1) was called +12735 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status") +12736 # don't restore from ebp +12737 81 0/subop/add %esp 8/imm32 +12738 # . epilogue +12739 5d/pop-to-ebp +12740 c3/return +12741 +12742 test-read-from-stream-with-no-inouts: +12743 # . prologue +12744 55/push-ebp +12745 89/<- %ebp 4/r32/esp +12746 # setup +12747 (clear-stream _test-input-stream) +12748 (clear-stream $_test-input-buffered-file->buffer) +12749 (clear-stream _test-output-stream) +12750 (clear-stream $_test-output-buffered-file->buffer) +12751 (clear-stream _test-error-stream) +12752 (clear-stream $_test-error-buffered-file->buffer) +12753 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12754 68/push 0/imm32 +12755 68/push 0/imm32 +12756 89/<- %edx 4/r32/esp +12757 (tailor-exit-descriptor %edx 0x10) +12758 # +12759 (write _test-input-stream "fn foo {\n") +12760 (write _test-input-stream " read-from-stream\n") +12761 (write _test-input-stream "}\n") +12762 # convert +12763 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12764 # registers except esp clobbered at this point +12765 # restore ed +12766 89/<- %edx 4/r32/esp +12767 (flush _test-output-buffered-file) +12768 (flush _test-error-buffered-file) +12769 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12775 # check output +12776 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-no-inouts: output should be empty") +12777 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: too few inouts (2 required)" "F - test-read-from-stream-with-no-inouts: error message") +12778 # check that stop(1) was called +12779 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status") +12780 # don't restore from ebp +12781 81 0/subop/add %esp 8/imm32 +12782 # . epilogue +12783 5d/pop-to-ebp +12784 c3/return +12785 +12786 test-read-from-stream-with-too-few-inouts: +12787 # . prologue +12788 55/push-ebp +12789 89/<- %ebp 4/r32/esp +12790 # setup +12791 (clear-stream _test-input-stream) +12792 (clear-stream $_test-input-buffered-file->buffer) +12793 (clear-stream _test-output-stream) +12794 (clear-stream $_test-output-buffered-file->buffer) +12795 (clear-stream _test-error-stream) +12796 (clear-stream $_test-error-buffered-file->buffer) +12797 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12798 68/push 0/imm32 +12799 68/push 0/imm32 +12800 89/<- %edx 4/r32/esp +12801 (tailor-exit-descriptor %edx 0x10) +12802 # +12803 (write _test-input-stream "fn foo {\n") +12804 (write _test-input-stream " var a: (addr stream int)\n") +12805 (write _test-input-stream " read-from-stream a\n") +12806 (write _test-input-stream "}\n") +12807 # convert +12808 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12809 # registers except esp clobbered at this point +12810 # restore ed +12811 89/<- %edx 4/r32/esp +12812 (flush _test-output-buffered-file) +12813 (flush _test-error-buffered-file) +12814 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12820 # check output +12821 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-too-few-inouts: output should be empty") +12822 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: too few inouts (2 required)" "F - test-read-from-stream-with-too-few-inouts: error message") +12823 # check that stop(1) was called +12824 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status") +12825 # don't restore from ebp +12826 81 0/subop/add %esp 8/imm32 +12827 # . epilogue +12828 5d/pop-to-ebp +12829 c3/return +12830 +12831 test-read-from-stream-with-too-many-inouts: +12832 # . prologue +12833 55/push-ebp +12834 89/<- %ebp 4/r32/esp +12835 # setup +12836 (clear-stream _test-input-stream) +12837 (clear-stream $_test-input-buffered-file->buffer) +12838 (clear-stream _test-output-stream) +12839 (clear-stream $_test-output-buffered-file->buffer) +12840 (clear-stream _test-error-stream) +12841 (clear-stream $_test-error-buffered-file->buffer) +12842 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12843 68/push 0/imm32 +12844 68/push 0/imm32 +12845 89/<- %edx 4/r32/esp +12846 (tailor-exit-descriptor %edx 0x10) +12847 # +12848 (write _test-input-stream "fn foo {\n") +12849 (write _test-input-stream " var a: (addr stream int)\n") +12850 (write _test-input-stream " var b: (addr int)\n") +12851 (write _test-input-stream " read-from-stream a, b, 0\n") +12852 (write _test-input-stream "}\n") +12853 # convert +12854 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12855 # registers except esp clobbered at this point +12856 # restore ed +12857 89/<- %edx 4/r32/esp +12858 (flush _test-output-buffered-file) +12859 (flush _test-error-buffered-file) +12860 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12866 # check output +12867 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-too-many-inouts: output should be empty") +12868 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: too many inouts (2 required)" "F - test-read-from-stream-with-too-many-inouts: error message") +12869 # check that stop(1) was called +12870 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status") +12871 # don't restore from ebp +12872 81 0/subop/add %esp 8/imm32 +12873 # . epilogue +12874 5d/pop-to-ebp +12875 c3/return +12876 +12877 test-read-from-stream-with-output: +12878 # . prologue +12879 55/push-ebp +12880 89/<- %ebp 4/r32/esp +12881 # setup +12882 (clear-stream _test-input-stream) +12883 (clear-stream $_test-input-buffered-file->buffer) +12884 (clear-stream _test-output-stream) +12885 (clear-stream $_test-output-buffered-file->buffer) +12886 (clear-stream _test-error-stream) +12887 (clear-stream $_test-error-buffered-file->buffer) +12888 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +12889 68/push 0/imm32 +12890 68/push 0/imm32 +12891 89/<- %edx 4/r32/esp +12892 (tailor-exit-descriptor %edx 0x10) +12893 # +12894 (write _test-input-stream "fn foo {\n") +12895 (write _test-input-stream " var a: (addr stream int)\n") +12896 (write _test-input-stream " var b/eax: (addr int) <- copy 0\n") +12897 (write _test-input-stream " b <- read-from-stream a, b\n") +12898 (write _test-input-stream "}\n") +12899 # convert +12900 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +12901 # registers except esp clobbered at this point +12902 # restore ed +12903 89/<- %edx 4/r32/esp +12904 (flush _test-output-buffered-file) +12905 (flush _test-error-buffered-file) +12906 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +12912 # check output +12913 (check-stream-equal _test-output-stream "" "F - test-read-from-stream-with-output: output should be empty") +12914 (check-next-stream-line-equal _test-error-stream "fn foo: stmt read-from-stream: unexpected output" "F - test-read-from-stream-with-output: error message") +12915 # check that stop(1) was called +12916 (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status") +12917 # don't restore from ebp +12918 81 0/subop/add %esp 8/imm32 +12919 # . epilogue +12920 5d/pop-to-ebp +12921 c3/return +12922 +12923 test-convert-write-to-stream: +12924 # . prologue +12925 55/push-ebp +12926 89/<- %ebp 4/r32/esp +12927 # setup +12928 (clear-stream _test-input-stream) +12929 (clear-stream $_test-input-buffered-file->buffer) +12930 (clear-stream _test-output-stream) +12931 (clear-stream $_test-output-buffered-file->buffer) +12932 # +12933 (write _test-input-stream "fn foo {\n") +12934 (write _test-input-stream " var s/esi: (addr stream int) <- copy 0\n") +12935 (write _test-input-stream " var o/ecx: (addr int) <- copy 0\n") +12936 (write _test-input-stream " write-to-stream s, o\n") +12937 (write _test-input-stream "}\n") +12938 # convert +12939 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +12940 # registers except esp clobbered at this point +12941 # restore ed +12942 89/<- %edx 4/r32/esp +12943 (flush _test-output-buffered-file) +12944 (flush _test-error-buffered-file) +12945 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +12951 # check output +12952 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-write-to-stream/0") +12953 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-write-to-stream/1") +12954 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-write-to-stream/2") +12955 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-write-to-stream/3") +12956 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-write-to-stream/4") +12957 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-write-to-stream/5") +12958 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-write-to-stream/6") +12959 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-write-to-stream/7") +12960 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-write-to-stream/8") +12961 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-write-to-stream/9") +12962 (check-next-stream-line-equal _test-output-stream " (write-to-stream %esi %ecx 0x00000004)" "F - test-convert-write-to-stream/10") +12963 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-write-to-stream/11") +12964 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-write-to-stream/12") +12965 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-write-to-stream/13") +12966 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-write-to-stream/14") +12967 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-write-to-stream/15") +12968 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-write-to-stream/16") +12969 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-write-to-stream/17") +12970 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-write-to-stream/18") +12971 # . epilogue +12972 89/<- %esp 5/r32/ebp +12973 5d/pop-to-ebp +12974 c3/return +12975 +12976 test-convert-write-to-stream-with-correct-payload-size: +12977 # . prologue +12978 55/push-ebp +12979 89/<- %ebp 4/r32/esp +12980 # setup +12981 (clear-stream _test-input-stream) +12982 (clear-stream $_test-input-buffered-file->buffer) +12983 (clear-stream _test-output-stream) +12984 (clear-stream $_test-output-buffered-file->buffer) +12985 # +12986 (write _test-input-stream "fn foo {\n") +12987 (write _test-input-stream " var s/esi: (addr stream handle int) <- copy 0\n") +12988 (write _test-input-stream " var o/ecx: (addr handle int) <- copy 0\n") +12989 (write _test-input-stream " write-to-stream s, o\n") +12990 (write _test-input-stream "}\n") +12991 # convert +12992 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +12993 # registers except esp clobbered at this point +12994 # restore ed +12995 89/<- %edx 4/r32/esp +12996 (flush _test-output-buffered-file) +12997 (flush _test-error-buffered-file) +12998 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +13004 # check output +13005 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-write-to-stream-with-correct-payload-size/0") +13006 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-write-to-stream-with-correct-payload-size/1") +13007 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-write-to-stream-with-correct-payload-size/2") +13008 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-write-to-stream-with-correct-payload-size/3") +13009 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-write-to-stream-with-correct-payload-size/4") +13010 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-write-to-stream-with-correct-payload-size/5") +13011 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %esi" "F - test-convert-write-to-stream-with-correct-payload-size/6") +13012 (check-next-stream-line-equal _test-output-stream " be/copy-to-esi 0/imm32" "F - test-convert-write-to-stream-with-correct-payload-size/7") +13013 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-write-to-stream-with-correct-payload-size/8") +13014 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-write-to-stream-with-correct-payload-size/9") +13015 (check-next-stream-line-equal _test-output-stream " (write-to-stream %esi %ecx 0x00000008)" "F - test-convert-write-to-stream-with-correct-payload-size/10") +13016 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-write-to-stream-with-correct-payload-size/11") +13017 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %esi" "F - test-convert-write-to-stream-with-correct-payload-size/12") +13018 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-write-to-stream-with-correct-payload-size/13") +13019 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-write-to-stream-with-correct-payload-size/14") +13020 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-write-to-stream-with-correct-payload-size/15") +13021 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-write-to-stream-with-correct-payload-size/16") +13022 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-write-to-stream-with-correct-payload-size/17") +13023 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-write-to-stream-with-correct-payload-size/18") +13024 # . epilogue +13025 89/<- %esp 5/r32/ebp +13026 5d/pop-to-ebp +13027 c3/return +13028 +13029 test-write-to-stream-with-non-stream-atom-base-type: +13030 # . prologue +13031 55/push-ebp +13032 89/<- %ebp 4/r32/esp +13033 # setup +13034 (clear-stream _test-input-stream) +13035 (clear-stream $_test-input-buffered-file->buffer) +13036 (clear-stream _test-output-stream) +13037 (clear-stream $_test-output-buffered-file->buffer) +13038 (clear-stream _test-error-stream) +13039 (clear-stream $_test-error-buffered-file->buffer) +13040 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13041 68/push 0/imm32 +13042 68/push 0/imm32 +13043 89/<- %edx 4/r32/esp +13044 (tailor-exit-descriptor %edx 0x10) +13045 # +13046 (write _test-input-stream "fn foo {\n") +13047 (write _test-input-stream " var a: int\n") +13048 (write _test-input-stream " write-to-stream a, 0\n") +13049 (write _test-input-stream "}\n") +13050 # convert +13051 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13052 # registers except esp clobbered at this point +13053 # restore ed +13054 89/<- %edx 4/r32/esp +13055 (flush _test-output-buffered-file) +13056 (flush _test-error-buffered-file) +13057 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13063 # check output +13064 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty") +13065 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-non-stream-atom-base-type: error message") +13066 # check that stop(1) was called +13067 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status") +13068 # don't restore from ebp +13069 81 0/subop/add %esp 8/imm32 +13070 # . epilogue +13071 5d/pop-to-ebp +13072 c3/return +13073 +13074 test-write-to-stream-with-non-stream-compound-base-type: +13075 # . prologue +13076 55/push-ebp +13077 89/<- %ebp 4/r32/esp +13078 # setup +13079 (clear-stream _test-input-stream) +13080 (clear-stream $_test-input-buffered-file->buffer) +13081 (clear-stream _test-output-stream) +13082 (clear-stream $_test-output-buffered-file->buffer) +13083 (clear-stream _test-error-stream) +13084 (clear-stream $_test-error-buffered-file->buffer) +13085 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13086 68/push 0/imm32 +13087 68/push 0/imm32 +13088 89/<- %edx 4/r32/esp +13089 (tailor-exit-descriptor %edx 0x10) +13090 # +13091 (write _test-input-stream "fn foo {\n") +13092 (write _test-input-stream " var a: (handle int)\n") +13093 (write _test-input-stream " write-to-stream a, 0\n") +13094 (write _test-input-stream "}\n") +13095 # convert +13096 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13097 # registers except esp clobbered at this point +13098 # restore ed +13099 89/<- %edx 4/r32/esp +13100 (flush _test-output-buffered-file) +13101 (flush _test-error-buffered-file) +13102 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13108 # check output +13109 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty") +13110 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-non-stream-compound-base-type: error message") +13111 # check that stop(1) was called +13112 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status") +13113 # don't restore from ebp +13114 81 0/subop/add %esp 8/imm32 +13115 # . epilogue +13116 5d/pop-to-ebp +13117 c3/return +13118 +13119 test-write-to-stream-with-non-stream-compound-base-type-2: +13120 # . prologue +13121 55/push-ebp +13122 89/<- %ebp 4/r32/esp +13123 # setup +13124 (clear-stream _test-input-stream) +13125 (clear-stream $_test-input-buffered-file->buffer) +13126 (clear-stream _test-output-stream) +13127 (clear-stream $_test-output-buffered-file->buffer) +13128 (clear-stream _test-error-stream) +13129 (clear-stream $_test-error-buffered-file->buffer) +13130 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13131 68/push 0/imm32 +13132 68/push 0/imm32 +13133 89/<- %edx 4/r32/esp +13134 (tailor-exit-descriptor %edx 0x10) +13135 # +13136 (write _test-input-stream "fn foo {\n") +13137 (write _test-input-stream " var a: (addr int)\n") +13138 (write _test-input-stream " write-to-stream a, 0\n") +13139 (write _test-input-stream "}\n") +13140 # convert +13141 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13142 # registers except esp clobbered at this point +13143 # restore ed +13144 89/<- %edx 4/r32/esp +13145 (flush _test-output-buffered-file) +13146 (flush _test-error-buffered-file) +13147 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13153 # check output +13154 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty") +13155 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message") +13156 # check that stop(1) was called +13157 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status") +13158 # don't restore from ebp +13159 81 0/subop/add %esp 8/imm32 +13160 # . epilogue +13161 5d/pop-to-ebp +13162 c3/return +13163 +13164 test-write-to-stream-with-stream-atom-base-type: +13165 # . prologue +13166 55/push-ebp +13167 89/<- %ebp 4/r32/esp +13168 # setup +13169 (clear-stream _test-input-stream) +13170 (clear-stream $_test-input-buffered-file->buffer) +13171 (clear-stream _test-output-stream) +13172 (clear-stream $_test-output-buffered-file->buffer) +13173 (clear-stream _test-error-stream) +13174 (clear-stream $_test-error-buffered-file->buffer) +13175 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13176 68/push 0/imm32 +13177 68/push 0/imm32 +13178 89/<- %edx 4/r32/esp +13179 (tailor-exit-descriptor %edx 0x10) +13180 # +13181 (write _test-input-stream "fn foo {\n") +13182 (write _test-input-stream " var a: stream\n") +13183 (write _test-input-stream " write-to-stream a, 0\n") +13184 (write _test-input-stream "}\n") +13185 # convert +13186 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13187 # registers except esp clobbered at this point +13188 # restore ed +13189 89/<- %edx 4/r32/esp +13190 (flush _test-output-buffered-file) +13191 (flush _test-error-buffered-file) +13192 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13198 # check output +13199 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-stream-atom-base-type: output should be empty") +13200 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream" "F - test-write-to-stream-with-stream-atom-base-type: error message") +13201 # check that stop(1) was called +13202 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status") +13203 # don't restore from ebp +13204 81 0/subop/add %esp 8/imm32 +13205 # . epilogue +13206 5d/pop-to-ebp +13207 c3/return +13208 +13209 test-write-to-stream-with-wrong-index-type: +13210 # . prologue +13211 55/push-ebp +13212 89/<- %ebp 4/r32/esp +13213 # setup +13214 (clear-stream _test-input-stream) +13215 (clear-stream $_test-input-buffered-file->buffer) +13216 (clear-stream _test-output-stream) +13217 (clear-stream $_test-output-buffered-file->buffer) +13218 (clear-stream _test-error-stream) +13219 (clear-stream $_test-error-buffered-file->buffer) +13220 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13221 68/push 0/imm32 +13222 68/push 0/imm32 +13223 89/<- %edx 4/r32/esp +13224 (tailor-exit-descriptor %edx 0x10) +13225 # +13226 (write _test-input-stream "fn foo {\n") +13227 (write _test-input-stream " var a/eax: (addr stream int) <- copy 0\n") +13228 (write _test-input-stream " var b: boolean\n") +13229 (write _test-input-stream " write-to-stream a, b\n") +13230 (write _test-input-stream "}\n") +13231 # convert +13232 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13233 # registers except esp clobbered at this point +13234 # restore ed +13235 89/<- %edx 4/r32/esp +13236 (flush _test-output-buffered-file) +13237 (flush _test-error-buffered-file) +13238 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13244 # check output +13245 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-wrong-index-type: output should be empty") +13246 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: target 'b' must be an addr" "F - test-write-to-stream-with-wrong-index-type: error message") +13247 # check that stop(1) was called +13248 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status") +13249 # don't restore from ebp +13250 81 0/subop/add %esp 8/imm32 +13251 # . epilogue +13252 5d/pop-to-ebp +13253 c3/return +13254 +13255 test-write-to-stream-with-no-inouts: +13256 # . prologue +13257 55/push-ebp +13258 89/<- %ebp 4/r32/esp +13259 # setup +13260 (clear-stream _test-input-stream) +13261 (clear-stream $_test-input-buffered-file->buffer) +13262 (clear-stream _test-output-stream) +13263 (clear-stream $_test-output-buffered-file->buffer) +13264 (clear-stream _test-error-stream) +13265 (clear-stream $_test-error-buffered-file->buffer) +13266 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13267 68/push 0/imm32 +13268 68/push 0/imm32 +13269 89/<- %edx 4/r32/esp +13270 (tailor-exit-descriptor %edx 0x10) +13271 # +13272 (write _test-input-stream "fn foo {\n") +13273 (write _test-input-stream " write-to-stream\n") +13274 (write _test-input-stream "}\n") +13275 # convert +13276 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13277 # registers except esp clobbered at this point +13278 # restore ed +13279 89/<- %edx 4/r32/esp +13280 (flush _test-output-buffered-file) +13281 (flush _test-error-buffered-file) +13282 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13288 # check output +13289 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-no-inouts: output should be empty") +13290 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: too few inouts (2 required)" "F - test-write-to-stream-with-no-inouts: error message") +13291 # check that stop(1) was called +13292 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status") +13293 # don't restore from ebp +13294 81 0/subop/add %esp 8/imm32 +13295 # . epilogue +13296 5d/pop-to-ebp +13297 c3/return +13298 +13299 test-write-to-stream-with-too-few-inouts: +13300 # . prologue +13301 55/push-ebp +13302 89/<- %ebp 4/r32/esp +13303 # setup +13304 (clear-stream _test-input-stream) +13305 (clear-stream $_test-input-buffered-file->buffer) +13306 (clear-stream _test-output-stream) +13307 (clear-stream $_test-output-buffered-file->buffer) +13308 (clear-stream _test-error-stream) +13309 (clear-stream $_test-error-buffered-file->buffer) +13310 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13311 68/push 0/imm32 +13312 68/push 0/imm32 +13313 89/<- %edx 4/r32/esp +13314 (tailor-exit-descriptor %edx 0x10) +13315 # +13316 (write _test-input-stream "fn foo {\n") +13317 (write _test-input-stream " var a: (addr stream int)\n") +13318 (write _test-input-stream " write-to-stream a\n") +13319 (write _test-input-stream "}\n") +13320 # convert +13321 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13322 # registers except esp clobbered at this point +13323 # restore ed +13324 89/<- %edx 4/r32/esp +13325 (flush _test-output-buffered-file) +13326 (flush _test-error-buffered-file) +13327 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13333 # check output +13334 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-too-few-inouts: output should be empty") +13335 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: too few inouts (2 required)" "F - test-write-to-stream-with-too-few-inouts: error message") +13336 # check that stop(1) was called +13337 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status") +13338 # don't restore from ebp +13339 81 0/subop/add %esp 8/imm32 +13340 # . epilogue +13341 5d/pop-to-ebp +13342 c3/return +13343 +13344 test-write-to-stream-with-too-many-inouts: +13345 # . prologue +13346 55/push-ebp +13347 89/<- %ebp 4/r32/esp +13348 # setup +13349 (clear-stream _test-input-stream) +13350 (clear-stream $_test-input-buffered-file->buffer) +13351 (clear-stream _test-output-stream) +13352 (clear-stream $_test-output-buffered-file->buffer) +13353 (clear-stream _test-error-stream) +13354 (clear-stream $_test-error-buffered-file->buffer) +13355 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13356 68/push 0/imm32 +13357 68/push 0/imm32 +13358 89/<- %edx 4/r32/esp +13359 (tailor-exit-descriptor %edx 0x10) +13360 # +13361 (write _test-input-stream "fn foo {\n") +13362 (write _test-input-stream " var a: (addr stream int)\n") +13363 (write _test-input-stream " var b: (addr int)\n") +13364 (write _test-input-stream " write-to-stream a, b, 0\n") +13365 (write _test-input-stream "}\n") +13366 # convert +13367 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13368 # registers except esp clobbered at this point +13369 # restore ed +13370 89/<- %edx 4/r32/esp +13371 (flush _test-output-buffered-file) +13372 (flush _test-error-buffered-file) +13373 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13379 # check output +13380 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-too-many-inouts: output should be empty") +13381 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: too many inouts (2 required)" "F - test-write-to-stream-with-too-many-inouts: error message") +13382 # check that stop(1) was called +13383 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status") +13384 # don't restore from ebp +13385 81 0/subop/add %esp 8/imm32 +13386 # . epilogue +13387 5d/pop-to-ebp +13388 c3/return +13389 +13390 test-write-to-stream-with-output: +13391 # . prologue +13392 55/push-ebp +13393 89/<- %ebp 4/r32/esp +13394 # setup +13395 (clear-stream _test-input-stream) +13396 (clear-stream $_test-input-buffered-file->buffer) +13397 (clear-stream _test-output-stream) +13398 (clear-stream $_test-output-buffered-file->buffer) +13399 (clear-stream _test-error-stream) +13400 (clear-stream $_test-error-buffered-file->buffer) +13401 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13402 68/push 0/imm32 +13403 68/push 0/imm32 +13404 89/<- %edx 4/r32/esp +13405 (tailor-exit-descriptor %edx 0x10) +13406 # +13407 (write _test-input-stream "fn foo {\n") +13408 (write _test-input-stream " var a: (addr stream int)\n") +13409 (write _test-input-stream " var b/eax: (addr int) <- copy 0\n") +13410 (write _test-input-stream " b <- write-to-stream a, b\n") +13411 (write _test-input-stream "}\n") +13412 # convert +13413 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13414 # registers except esp clobbered at this point +13415 # restore ed +13416 89/<- %edx 4/r32/esp +13417 (flush _test-output-buffered-file) +13418 (flush _test-error-buffered-file) +13419 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13425 # check output +13426 (check-stream-equal _test-output-stream "" "F - test-write-to-stream-with-output: output should be empty") +13427 (check-next-stream-line-equal _test-error-stream "fn foo: stmt write-to-stream: unexpected output" "F - test-write-to-stream-with-output: error message") +13428 # check that stop(1) was called +13429 (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status") +13430 # don't restore from ebp +13431 81 0/subop/add %esp 8/imm32 +13432 # . epilogue +13433 5d/pop-to-ebp +13434 c3/return +13435 +13436 test-length-with-non-array-atom-base-type: +13437 # . prologue +13438 55/push-ebp +13439 89/<- %ebp 4/r32/esp +13440 # setup +13441 (clear-stream _test-input-stream) +13442 (clear-stream $_test-input-buffered-file->buffer) +13443 (clear-stream _test-output-stream) +13444 (clear-stream $_test-output-buffered-file->buffer) +13445 (clear-stream _test-error-stream) +13446 (clear-stream $_test-error-buffered-file->buffer) +13447 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13448 68/push 0/imm32 +13449 68/push 0/imm32 +13450 89/<- %edx 4/r32/esp +13451 (tailor-exit-descriptor %edx 0x10) +13452 # +13453 (write _test-input-stream "fn foo {\n") +13454 (write _test-input-stream " var a: int\n") +13455 (write _test-input-stream " var c/ecx: int <- length a\n") +13456 (write _test-input-stream "}\n") +13457 # convert +13458 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13459 # registers except esp clobbered at this point +13460 # restore ed +13461 89/<- %edx 4/r32/esp +13462 (flush _test-output-buffered-file) +13463 (flush _test-error-buffered-file) +13464 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13470 # check output +13471 (check-stream-equal _test-output-stream "" "F - test-length-with-non-array-atom-base-type: output should be empty") +13472 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is not an array" "F - test-length-with-non-array-atom-base-type: error message") +13473 # check that stop(1) was called +13474 (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status") +13475 # don't restore from ebp +13476 81 0/subop/add %esp 8/imm32 +13477 # . epilogue +13478 5d/pop-to-ebp +13479 c3/return +13480 +13481 test-length-with-non-array-compound-base-type: +13482 # . prologue +13483 55/push-ebp +13484 89/<- %ebp 4/r32/esp +13485 # setup +13486 (clear-stream _test-input-stream) +13487 (clear-stream $_test-input-buffered-file->buffer) +13488 (clear-stream _test-output-stream) +13489 (clear-stream $_test-output-buffered-file->buffer) +13490 (clear-stream _test-error-stream) +13491 (clear-stream $_test-error-buffered-file->buffer) +13492 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13493 68/push 0/imm32 +13494 68/push 0/imm32 +13495 89/<- %edx 4/r32/esp +13496 (tailor-exit-descriptor %edx 0x10) +13497 # +13498 (write _test-input-stream "fn foo {\n") +13499 (write _test-input-stream " var a: (handle int)\n") +13500 (write _test-input-stream " var c/ecx: (addr int) <- length a, 0\n") +13501 (write _test-input-stream "}\n") +13502 # convert +13503 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13504 # registers except esp clobbered at this point +13505 # restore ed +13506 89/<- %edx 4/r32/esp +13507 (flush _test-output-buffered-file) +13508 (flush _test-error-buffered-file) +13509 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13515 # check output +13516 (check-stream-equal _test-output-stream "" "F - test-length-with-non-array-compound-base-type: output should be empty") +13517 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is not an array" "F - test-length-with-non-array-compound-base-type: error message") +13518 # check that stop(1) was called +13519 (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status") +13520 # don't restore from ebp +13521 81 0/subop/add %esp 8/imm32 +13522 # . epilogue +13523 5d/pop-to-ebp +13524 c3/return +13525 +13526 test-length-with-non-array-compound-base-type-2: +13527 # . prologue +13528 55/push-ebp +13529 89/<- %ebp 4/r32/esp +13530 # setup +13531 (clear-stream _test-input-stream) +13532 (clear-stream $_test-input-buffered-file->buffer) +13533 (clear-stream _test-output-stream) +13534 (clear-stream $_test-output-buffered-file->buffer) +13535 (clear-stream _test-error-stream) +13536 (clear-stream $_test-error-buffered-file->buffer) +13537 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13538 68/push 0/imm32 +13539 68/push 0/imm32 +13540 89/<- %edx 4/r32/esp +13541 (tailor-exit-descriptor %edx 0x10) +13542 # +13543 (write _test-input-stream "fn foo {\n") +13544 (write _test-input-stream " var a: (addr int)\n") +13545 (write _test-input-stream " var c/ecx: (addr int) <- length a, 0\n") +13546 (write _test-input-stream "}\n") +13547 # convert +13548 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13549 # registers except esp clobbered at this point +13550 # restore ed +13551 89/<- %edx 4/r32/esp +13552 (flush _test-output-buffered-file) +13553 (flush _test-error-buffered-file) +13554 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13560 # check output +13561 (check-stream-equal _test-output-stream "" "F - test-length-with-non-array-compound-base-type-2: output should be empty") +13562 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is not an array" "F - test-length-with-non-array-compound-base-type-2: error message") +13563 # check that stop(1) was called +13564 (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status") +13565 # don't restore from ebp +13566 81 0/subop/add %esp 8/imm32 +13567 # . epilogue +13568 5d/pop-to-ebp +13569 c3/return +13570 +13571 test-length-with-array-atom-base-type: +13572 # . prologue +13573 55/push-ebp +13574 89/<- %ebp 4/r32/esp +13575 # setup +13576 (clear-stream _test-input-stream) +13577 (clear-stream $_test-input-buffered-file->buffer) +13578 (clear-stream _test-output-stream) +13579 (clear-stream $_test-output-buffered-file->buffer) +13580 (clear-stream _test-error-stream) +13581 (clear-stream $_test-error-buffered-file->buffer) +13582 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13583 68/push 0/imm32 +13584 68/push 0/imm32 +13585 89/<- %edx 4/r32/esp +13586 (tailor-exit-descriptor %edx 0x10) +13587 # +13588 (write _test-input-stream "fn foo {\n") +13589 (write _test-input-stream " var a: array\n") +13590 (write _test-input-stream " var c/ecx: (addr int) <- length a\n") +13591 (write _test-input-stream "}\n") +13592 # convert +13593 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13594 # registers except esp clobbered at this point +13595 # restore ed +13596 89/<- %edx 4/r32/esp +13597 (flush _test-output-buffered-file) +13598 (flush _test-error-buffered-file) +13599 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13605 # check output +13606 (check-stream-equal _test-output-stream "" "F - test-length-with-array-atom-base-type: output should be empty") +13607 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: array 'a' must specify the type of its elements" "F - test-length-with-array-atom-base-type: error message") +13608 # check that stop(1) was called +13609 (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status") +13610 # don't restore from ebp +13611 81 0/subop/add %esp 8/imm32 +13612 # . epilogue +13613 5d/pop-to-ebp +13614 c3/return +13615 +13616 test-length-with-addr-base-on-stack: +13617 # . prologue +13618 55/push-ebp +13619 89/<- %ebp 4/r32/esp +13620 # setup +13621 (clear-stream _test-input-stream) +13622 (clear-stream $_test-input-buffered-file->buffer) +13623 (clear-stream _test-output-stream) +13624 (clear-stream $_test-output-buffered-file->buffer) +13625 (clear-stream _test-error-stream) +13626 (clear-stream $_test-error-buffered-file->buffer) +13627 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13628 68/push 0/imm32 +13629 68/push 0/imm32 +13630 89/<- %edx 4/r32/esp +13631 (tailor-exit-descriptor %edx 0x10) +13632 # +13633 (write _test-input-stream "fn foo {\n") +13634 (write _test-input-stream " var a: (addr array int)\n") +13635 (write _test-input-stream " var c/ecx: (addr int) <- length a\n") +13636 (write _test-input-stream "}\n") +13637 # convert +13638 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13639 # registers except esp clobbered at this point +13640 # restore ed +13641 89/<- %edx 4/r32/esp +13642 (flush _test-output-buffered-file) +13643 (flush _test-error-buffered-file) +13644 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13650 # check output +13651 (check-stream-equal _test-output-stream "" "F - test-length-with-addr-base-on-stack: output should be empty") +13652 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: var 'a' is an addr to an array, and so must live in a register" "F - test-length-with-addr-base-on-stack: error message") +13653 # check that stop(1) was called +13654 (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status") +13655 # don't restore from ebp +13656 81 0/subop/add %esp 8/imm32 +13657 # . epilogue +13658 5d/pop-to-ebp +13659 c3/return +13660 +13661 test-length-with-wrong-output-type: +13662 # . prologue +13663 55/push-ebp +13664 89/<- %ebp 4/r32/esp +13665 # setup +13666 (clear-stream _test-input-stream) +13667 (clear-stream $_test-input-buffered-file->buffer) +13668 (clear-stream _test-output-stream) +13669 (clear-stream $_test-output-buffered-file->buffer) +13670 (clear-stream _test-error-stream) +13671 (clear-stream $_test-error-buffered-file->buffer) +13672 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13673 68/push 0/imm32 +13674 68/push 0/imm32 +13675 89/<- %edx 4/r32/esp +13676 (tailor-exit-descriptor %edx 0x10) +13677 # +13678 (write _test-input-stream "fn foo {\n") +13679 (write _test-input-stream " var a/ebx: (addr array boolean) <- copy 0\n") +13680 (write _test-input-stream " var o/edi: (addr int) <- length a\n") +13681 (write _test-input-stream "}\n") +13682 # convert +13683 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13684 # registers except esp clobbered at this point +13685 # restore ed +13686 89/<- %edx 4/r32/esp +13687 (flush _test-output-buffered-file) +13688 (flush _test-error-buffered-file) +13689 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13695 # check output +13696 (check-stream-equal _test-output-stream "" "F - test-length-with-wrong-output-type: output should be empty") +13697 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: output 'o' does not have the right type" "F - test-length-with-wrong-output-type: error message") +13698 # check that stop(1) was called +13699 (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status") +13700 # don't restore from ebp +13701 81 0/subop/add %esp 8/imm32 +13702 # . epilogue +13703 5d/pop-to-ebp +13704 c3/return +13705 +13706 test-length-with-wrong-output-compound-type: +13707 # . prologue +13708 55/push-ebp +13709 89/<- %ebp 4/r32/esp +13710 # setup +13711 (clear-stream _test-input-stream) +13712 (clear-stream $_test-input-buffered-file->buffer) +13713 (clear-stream _test-output-stream) +13714 (clear-stream $_test-output-buffered-file->buffer) +13715 (clear-stream _test-error-stream) +13716 (clear-stream $_test-error-buffered-file->buffer) +13717 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13718 68/push 0/imm32 +13719 68/push 0/imm32 +13720 89/<- %edx 4/r32/esp +13721 (tailor-exit-descriptor %edx 0x10) +13722 # +13723 (write _test-input-stream "fn foo {\n") +13724 (write _test-input-stream " var a/ebx: (addr array handle boolean) <- copy 0\n") +13725 (write _test-input-stream " var o/edi: (addr handle int) <- length a\n") +13726 (write _test-input-stream "}\n") +13727 # convert +13728 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13729 # registers except esp clobbered at this point +13730 # restore ed +13731 89/<- %edx 4/r32/esp +13732 (flush _test-output-buffered-file) +13733 (flush _test-error-buffered-file) +13734 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13740 # check output +13741 (check-stream-equal _test-output-stream "" "F - test-length-with-wrong-output-compound-type: output should be empty") +13742 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: output 'o' does not have the right type" "F - test-length-with-wrong-output-compound-type: error message") +13743 # check that stop(1) was called +13744 (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status") +13745 # don't restore from ebp +13746 81 0/subop/add %esp 8/imm32 +13747 # . epilogue +13748 5d/pop-to-ebp +13749 c3/return +13750 +13751 test-length-with-no-inouts: +13752 # . prologue +13753 55/push-ebp +13754 89/<- %ebp 4/r32/esp +13755 # setup +13756 (clear-stream _test-input-stream) +13757 (clear-stream $_test-input-buffered-file->buffer) +13758 (clear-stream _test-output-stream) +13759 (clear-stream $_test-output-buffered-file->buffer) +13760 (clear-stream _test-error-stream) +13761 (clear-stream $_test-error-buffered-file->buffer) +13762 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13763 68/push 0/imm32 +13764 68/push 0/imm32 +13765 89/<- %edx 4/r32/esp +13766 (tailor-exit-descriptor %edx 0x10) +13767 # +13768 (write _test-input-stream "fn foo {\n") +13769 (write _test-input-stream " var c/ecx: int <- length\n") +13770 (write _test-input-stream "}\n") +13771 # convert +13772 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13773 # registers except esp clobbered at this point +13774 # restore ed +13775 89/<- %edx 4/r32/esp +13776 (flush _test-output-buffered-file) +13777 (flush _test-error-buffered-file) +13778 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13784 # check output +13785 (check-stream-equal _test-output-stream "" "F - test-length-with-no-inouts: output should be empty") +13786 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: too few inouts (1 required)" "F - test-length-with-no-inouts: error message") +13787 # check that stop(1) was called +13788 (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status") +13789 # don't restore from ebp +13790 81 0/subop/add %esp 8/imm32 +13791 # . epilogue +13792 5d/pop-to-ebp +13793 c3/return +13794 +13795 test-length-with-too-many-inouts: +13796 # . prologue +13797 55/push-ebp +13798 89/<- %ebp 4/r32/esp +13799 # setup +13800 (clear-stream _test-input-stream) +13801 (clear-stream $_test-input-buffered-file->buffer) +13802 (clear-stream _test-output-stream) +13803 (clear-stream $_test-output-buffered-file->buffer) +13804 (clear-stream _test-error-stream) +13805 (clear-stream $_test-error-buffered-file->buffer) +13806 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13807 68/push 0/imm32 +13808 68/push 0/imm32 +13809 89/<- %edx 4/r32/esp +13810 (tailor-exit-descriptor %edx 0x10) +13811 # +13812 (write _test-input-stream "fn foo {\n") +13813 (write _test-input-stream " var a: (array int 3)\n") +13814 (write _test-input-stream " var c/ecx: int <- length a, 0, 0\n") +13815 (write _test-input-stream "}\n") +13816 # convert +13817 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13818 # registers except esp clobbered at this point +13819 # restore ed +13820 89/<- %edx 4/r32/esp +13821 (flush _test-output-buffered-file) +13822 (flush _test-error-buffered-file) +13823 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13829 # check output +13830 (check-stream-equal _test-output-stream "" "F - test-length-with-too-many-inouts: output should be empty") +13831 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: too many inouts (1 required)" "F - test-length-with-too-many-inouts: error message") +13832 # check that stop(1) was called +13833 (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status") +13834 # don't restore from ebp +13835 81 0/subop/add %esp 8/imm32 +13836 # . epilogue +13837 5d/pop-to-ebp +13838 c3/return +13839 +13840 test-length-with-no-output: +13841 # . prologue +13842 55/push-ebp +13843 89/<- %ebp 4/r32/esp +13844 # setup +13845 (clear-stream _test-input-stream) +13846 (clear-stream $_test-input-buffered-file->buffer) +13847 (clear-stream _test-output-stream) +13848 (clear-stream $_test-output-buffered-file->buffer) +13849 (clear-stream _test-error-stream) +13850 (clear-stream $_test-error-buffered-file->buffer) +13851 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13852 68/push 0/imm32 +13853 68/push 0/imm32 +13854 89/<- %edx 4/r32/esp +13855 (tailor-exit-descriptor %edx 0x10) +13856 # +13857 (write _test-input-stream "fn foo {\n") +13858 (write _test-input-stream " var a: (array int 3)\n") +13859 (write _test-input-stream " length a\n") +13860 (write _test-input-stream "}\n") +13861 # convert +13862 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13863 # registers except esp clobbered at this point +13864 # restore ed +13865 89/<- %edx 4/r32/esp +13866 (flush _test-output-buffered-file) +13867 (flush _test-error-buffered-file) +13868 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13874 # check output +13875 (check-stream-equal _test-output-stream "" "F - test-length-with-no-output: output should be empty") +13876 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: must have an output" "F - test-length-with-no-output: error message") +13877 # check that stop(1) was called +13878 (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status") +13879 # don't restore from ebp +13880 81 0/subop/add %esp 8/imm32 +13881 # . epilogue +13882 5d/pop-to-ebp +13883 c3/return +13884 +13885 test-length-with-too-many-outputs: +13886 # . prologue +13887 55/push-ebp +13888 89/<- %ebp 4/r32/esp +13889 # setup +13890 (clear-stream _test-input-stream) +13891 (clear-stream $_test-input-buffered-file->buffer) +13892 (clear-stream _test-output-stream) +13893 (clear-stream $_test-output-buffered-file->buffer) +13894 (clear-stream _test-error-stream) +13895 (clear-stream $_test-error-buffered-file->buffer) +13896 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +13897 68/push 0/imm32 +13898 68/push 0/imm32 +13899 89/<- %edx 4/r32/esp +13900 (tailor-exit-descriptor %edx 0x10) +13901 # +13902 (write _test-input-stream "fn foo {\n") +13903 (write _test-input-stream " var a: (array int 3)\n") +13904 (write _test-input-stream " var b/eax: int <- copy 0\n") +13905 (write _test-input-stream " var c/ecx: int <- copy 0\n") +13906 (write _test-input-stream " b, c <- length a\n") +13907 (write _test-input-stream "}\n") +13908 # convert +13909 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +13910 # registers except esp clobbered at this point +13911 # restore ed +13912 89/<- %edx 4/r32/esp +13913 (flush _test-output-buffered-file) +13914 (flush _test-error-buffered-file) +13915 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +13921 # check output +13922 (check-stream-equal _test-output-stream "" "F - test-length-with-too-many-outputs: output should be empty") +13923 (check-next-stream-line-equal _test-error-stream "fn foo: stmt length: too many outputs (1 required)" "F - test-length-with-too-many-outputs: error message") +13924 # check that stop(1) was called +13925 (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status") +13926 # don't restore from ebp +13927 81 0/subop/add %esp 8/imm32 +13928 # . epilogue +13929 5d/pop-to-ebp +13930 c3/return +13931 +13932 test-convert-function-with-return-register-and-local: +13933 # . prologue +13934 55/push-ebp +13935 89/<- %ebp 4/r32/esp +13936 # setup +13937 (clear-stream _test-input-stream) +13938 (clear-stream $_test-input-buffered-file->buffer) +13939 (clear-stream _test-output-stream) +13940 (clear-stream $_test-output-buffered-file->buffer) +13941 # +13942 (write _test-input-stream "fn foo -> _/eax: int {\n") +13943 (write _test-input-stream " var y/eax: int <- copy 3\n") +13944 (write _test-input-stream " var z/ecx: int <- copy 4\n") +13945 (write _test-input-stream " return y\n") +13946 (write _test-input-stream "}\n") +13947 # convert +13948 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +13949 (flush _test-output-buffered-file) +13950 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +13956 # check output +13957 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-register-and-local/0") +13958 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-register-and-local/1") +13959 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-register-and-local/2") +13960 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-register-and-local/3") +13961 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-register-and-local/4") +13962 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-register-and-local/5") +13963 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-return-register-and-local/6") +13964 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 3/imm32" "F - test-convert-function-with-return-register-and-local/7") +13965 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-return-register-and-local/8") +13966 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-convert-function-with-return-register-and-local/9") +13967 (check-next-stream-line-equal _test-output-stream " 8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10") +13968 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-return-register-and-local/11") +13969 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-function-with-return-register-and-local/12") +13970 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-register-and-local/13") +13971 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-register-and-local/14") +13972 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-register-and-local/15") +13973 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-register-and-local/16") +13974 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-register-and-local/17") +13975 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-register-and-local/18") +13976 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-register-and-local/19") +13977 # . epilogue +13978 89/<- %esp 5/r32/ebp +13979 5d/pop-to-ebp +13980 c3/return +13981 +13982 test-convert-function-with-return-register-and-local-2: +13983 # . prologue +13984 55/push-ebp +13985 89/<- %ebp 4/r32/esp +13986 # setup +13987 (clear-stream _test-input-stream) +13988 (clear-stream $_test-input-buffered-file->buffer) +13989 (clear-stream _test-output-stream) +13990 (clear-stream $_test-output-buffered-file->buffer) +13991 # +13992 (write _test-input-stream "fn foo -> _/eax: int {\n") +13993 (write _test-input-stream " var y/eax: int <- copy 3\n") +13994 (write _test-input-stream " var z/ecx: int <- copy 4\n") +13995 (write _test-input-stream " return z\n") +13996 (write _test-input-stream "}\n") +13997 # convert +13998 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +13999 (flush _test-output-buffered-file) +14000 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +14006 # check output +14007 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-register-and-local-2/0") +14008 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-register-and-local-2/1") +14009 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-register-and-local-2/2") +14010 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-register-and-local-2/3") +14011 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-register-and-local-2/4") +14012 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-register-and-local-2/5") +14013 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-return-register-and-local-2/6") +14014 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 3/imm32" "F - test-convert-function-with-return-register-and-local-2/7") +14015 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-return-register-and-local-2/8") +14016 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-convert-function-with-return-register-and-local-2/9") +14017 (check-next-stream-line-equal _test-output-stream " 8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10") +14018 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-return-register-and-local-2/11") +14019 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-function-with-return-register-and-local-2/12") +14020 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-register-and-local-2/13") +14021 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-register-and-local-2/14") +14022 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-register-and-local-2/15") +14023 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-register-and-local-2/16") +14024 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-register-and-local-2/17") +14025 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-register-and-local-2/18") +14026 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-register-and-local-2/19") +14027 # . epilogue +14028 89/<- %esp 5/r32/ebp +14029 5d/pop-to-ebp +14030 c3/return +14031 +14032 test-convert-function-with-return-float-register-and-local: +14033 # . prologue +14034 55/push-ebp +14035 89/<- %ebp 4/r32/esp +14036 # setup +14037 (clear-stream _test-input-stream) +14038 (clear-stream $_test-input-buffered-file->buffer) +14039 (clear-stream _test-output-stream) +14040 (clear-stream $_test-output-buffered-file->buffer) +14041 # +14042 (write _test-input-stream "fn foo -> _/xmm1: float {\n") +14043 (write _test-input-stream " var y/eax: int <- copy 3\n") +14044 (write _test-input-stream " var g/xmm0: float <- convert y\n") +14045 (write _test-input-stream " var h/xmm1: float <- convert y\n") +14046 (write _test-input-stream " return g\n") +14047 (write _test-input-stream "}\n") +14048 # convert +14049 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +14050 (flush _test-output-buffered-file) +14051 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +14057 # check output +14058 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-float-register-and-local/0") +14059 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-float-register-and-local/1") +14060 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-float-register-and-local/2") +14061 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-float-register-and-local/3") +14062 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-float-register-and-local/4") +14063 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-float-register-and-local/5") +14064 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-return-float-register-and-local/6") # var y +14065 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 3/imm32" "F - test-convert-function-with-return-float-register-and-local/7") +14066 (check-next-stream-line-equal _test-output-stream " 81 5/subop/subtract %esp 4/imm32" "F - test-convert-function-with-return-float-register-and-local/8") # var g +14067 (check-next-stream-line-equal _test-output-stream " f3 0f 11/<- *esp 0/x32" "F - test-convert-function-with-return-float-register-and-local/9") +14068 (check-next-stream-line-equal _test-output-stream " f3 0f 2a/convert-to-float %eax 0x00000000/x32" "F - test-convert-function-with-return-float-register-and-local/10") +14069 (check-next-stream-line-equal _test-output-stream " 81 5/subop/subtract %esp 4/imm32" "F - test-convert-function-with-return-float-register-and-local/11") # var h +14070 (check-next-stream-line-equal _test-output-stream " f3 0f 11/<- *esp 1/x32" "F - test-convert-function-with-return-float-register-and-local/12") +14071 (check-next-stream-line-equal _test-output-stream " f3 0f 2a/convert-to-float %eax 0x00000001/x32" "F - test-convert-function-with-return-float-register-and-local/13") +14072 (check-next-stream-line-equal _test-output-stream " f3 0f 10/-> %xmm0 0x00000001/x32" "F - test-convert-function-with-return-float-register-and-local/14") # return g +14073 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-floating-point-dereferenced/15") # reclaim h +14074 (check-next-stream-line-equal _test-output-stream " f3 0f 10/-> *esp 0/x32" "F - test-convert-floating-point-dereferenced/16") # reclaim g +14075 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 4/imm32" "F - test-convert-floating-point-dereferenced/17") +14076 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-return-float-register-and-local/18") # reclaim y +14077 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-float-register-and-local/19") +14078 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-float-register-and-local/20") +14079 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-float-register-and-local/21") +14080 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-float-register-and-local/22") +14081 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-float-register-and-local/23") +14082 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-float-register-and-local/24") +14083 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-float-register-and-local/25") +14084 # . epilogue +14085 89/<- %esp 5/r32/ebp +14086 5d/pop-to-ebp +14087 c3/return +14088 +14089 test-convert-function-with-return-and-local-vars: +14090 # . prologue +14091 55/push-ebp +14092 89/<- %ebp 4/r32/esp +14093 # setup +14094 (clear-stream _test-input-stream) +14095 (clear-stream $_test-input-buffered-file->buffer) +14096 (clear-stream _test-output-stream) +14097 (clear-stream $_test-output-buffered-file->buffer) +14098 # +14099 (write _test-input-stream "fn foo -> _/eax: int {\n") +14100 (write _test-input-stream " {\n") +14101 (write _test-input-stream " var x: int\n") +14102 (write _test-input-stream " {\n") +14103 (write _test-input-stream " var y: int\n") +14104 (write _test-input-stream " return y\n") +14105 (write _test-input-stream " increment x\n") +14106 (write _test-input-stream " }\n") +14107 (write _test-input-stream " }\n") +14108 (write _test-input-stream " return 0\n") +14109 (write _test-input-stream "}\n") +14110 # convert +14111 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +14112 (flush _test-output-buffered-file) +14113 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +14119 # check output +14120 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-return-and-local-vars/0") +14121 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-return-and-local-vars/1") +14122 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-return-and-local-vars/2") +14123 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-return-and-local-vars/3") +14124 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-and-local-vars/4") +14125 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-return-and-local-vars/5") +14126 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-and-local-vars/6") +14127 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-return-and-local-vars/7") +14128 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/8") # var x +14129 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-return-and-local-vars/9") +14130 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-return-and-local-vars/10") +14131 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11") # var y +14132 (check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12") +14133 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-return-and-local-vars/13") +14134 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-return-and-local-vars/14") +14135 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-and-local-vars/15") +14136 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-and-local-vars/16") +14137 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-return-and-local-vars/17") +14138 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-return-and-local-vars/18") +14139 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-and-local-vars/19") +14140 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-return-and-local-vars/20") +14141 (check-next-stream-line-equal _test-output-stream " c7 0/subop/copy %eax 0/imm32" "F - test-convert-function-with-return-and-local-vars/21") +14142 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000001:break/disp32" "F - test-convert-function-with-return-and-local-vars/21") +14143 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-return-and-local-vars/21") +14144 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-return-and-local-vars/22") +14145 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-return-and-local-vars/23") +14146 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-return-and-local-vars/24") +14147 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-return-and-local-vars/25") +14148 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-return-and-local-vars/26") +14149 # . epilogue +14150 89/<- %esp 5/r32/ebp +14151 5d/pop-to-ebp +14152 c3/return +14153 +14154 test-copy-object-with-no-inout: +14155 # . prologue +14156 55/push-ebp +14157 89/<- %ebp 4/r32/esp +14158 # setup +14159 (clear-stream _test-input-stream) +14160 (clear-stream $_test-input-buffered-file->buffer) +14161 (clear-stream _test-output-stream) +14162 (clear-stream $_test-output-buffered-file->buffer) +14163 (clear-stream _test-error-stream) +14164 (clear-stream $_test-error-buffered-file->buffer) +14165 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14166 68/push 0/imm32 +14167 68/push 0/imm32 +14168 89/<- %edx 4/r32/esp +14169 (tailor-exit-descriptor %edx 0x10) +14170 # +14171 (write _test-input-stream "fn foo {\n") +14172 (write _test-input-stream " copy-object\n") +14173 (write _test-input-stream "}\n") +14174 # convert +14175 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14176 # registers except esp clobbered at this point +14177 # restore ed +14178 89/<- %edx 4/r32/esp +14179 (flush _test-output-buffered-file) +14180 (flush _test-error-buffered-file) +14181 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14187 # check output +14188 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-no-inout: output should be empty") +14189 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must have two inouts" "F - test-copy-object-with-no-inout: error message") +14190 # check that stop(1) was called +14191 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status") +14192 # don't restore from ebp +14193 81 0/subop/add %esp 8/imm32 +14194 # . epilogue +14195 5d/pop-to-ebp +14196 c3/return +14197 +14198 test-copy-object-with-no-source: +14199 # . prologue +14200 55/push-ebp +14201 89/<- %ebp 4/r32/esp +14202 # setup +14203 (clear-stream _test-input-stream) +14204 (clear-stream $_test-input-buffered-file->buffer) +14205 (clear-stream _test-output-stream) +14206 (clear-stream $_test-output-buffered-file->buffer) +14207 (clear-stream _test-error-stream) +14208 (clear-stream $_test-error-buffered-file->buffer) +14209 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14210 68/push 0/imm32 +14211 68/push 0/imm32 +14212 89/<- %edx 4/r32/esp +14213 (tailor-exit-descriptor %edx 0x10) +14214 # +14215 (write _test-input-stream "fn foo {\n") +14216 (write _test-input-stream " var x: (addr int)\n") +14217 (write _test-input-stream " copy-object x\n") +14218 (write _test-input-stream "}\n") +14219 # convert +14220 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14221 # registers except esp clobbered at this point +14222 # restore ed +14223 89/<- %edx 4/r32/esp +14224 (flush _test-output-buffered-file) +14225 (flush _test-error-buffered-file) +14226 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14232 # check output +14233 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-no-source: output should be empty") +14234 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must have two inouts" "F - test-copy-object-with-no-source: error message") +14235 # check that stop(1) was called +14236 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status") +14237 # don't restore from ebp +14238 81 0/subop/add %esp 8/imm32 +14239 # . epilogue +14240 5d/pop-to-ebp +14241 c3/return +14242 +14243 test-copy-object-with-too-many-inouts: +14244 # . prologue +14245 55/push-ebp +14246 89/<- %ebp 4/r32/esp +14247 # setup +14248 (clear-stream _test-input-stream) +14249 (clear-stream $_test-input-buffered-file->buffer) +14250 (clear-stream _test-output-stream) +14251 (clear-stream $_test-output-buffered-file->buffer) +14252 (clear-stream _test-error-stream) +14253 (clear-stream $_test-error-buffered-file->buffer) +14254 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14255 68/push 0/imm32 +14256 68/push 0/imm32 +14257 89/<- %edx 4/r32/esp +14258 (tailor-exit-descriptor %edx 0x10) +14259 # +14260 (write _test-input-stream "fn foo {\n") +14261 (write _test-input-stream " var x: (addr boolean)\n") +14262 (write _test-input-stream " copy-object x, x, x\n") +14263 (write _test-input-stream "}\n") +14264 # convert +14265 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14266 # registers except esp clobbered at this point +14267 # restore ed +14268 89/<- %edx 4/r32/esp +14269 (flush _test-output-buffered-file) +14270 (flush _test-error-buffered-file) +14271 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14277 # check output +14278 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-too-many-inouts: output should be empty") +14279 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must have two inouts" "F - test-copy-object-with-too-many-inouts: error message") +14280 # check that stop(1) was called +14281 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status") +14282 # don't restore from ebp +14283 81 0/subop/add %esp 8/imm32 +14284 # . epilogue +14285 5d/pop-to-ebp +14286 c3/return +14287 +14288 test-copy-object-with-output: +14289 # . prologue +14290 55/push-ebp +14291 89/<- %ebp 4/r32/esp +14292 # setup +14293 (clear-stream _test-input-stream) +14294 (clear-stream $_test-input-buffered-file->buffer) +14295 (clear-stream _test-output-stream) +14296 (clear-stream $_test-output-buffered-file->buffer) +14297 (clear-stream _test-error-stream) +14298 (clear-stream $_test-error-buffered-file->buffer) +14299 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14300 68/push 0/imm32 +14301 68/push 0/imm32 +14302 89/<- %edx 4/r32/esp +14303 (tailor-exit-descriptor %edx 0x10) +14304 # +14305 (write _test-input-stream "fn foo {\n") +14306 (write _test-input-stream " var x/eax: (addr boolean) <- copy 0\n") +14307 (write _test-input-stream " var y/ecx: (addr boolean) <- copy 0\n") +14308 (write _test-input-stream " x <- copy-object x, y\n") +14309 (write _test-input-stream "}\n") +14310 # convert +14311 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14312 # registers except esp clobbered at this point +14313 # restore ed +14314 89/<- %edx 4/r32/esp +14315 (flush _test-output-buffered-file) +14316 (flush _test-error-buffered-file) +14317 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14323 # check output +14324 (check-stream-equal _test-output-stream "" "F - test-copy-object-with-output: output should be empty") +14325 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'copy-object' must not have any outputs" "F - test-copy-object-with-output: error message") +14326 # check that stop(1) was called +14327 (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status") +14328 # don't restore from ebp +14329 81 0/subop/add %esp 8/imm32 +14330 # . epilogue +14331 5d/pop-to-ebp +14332 c3/return +14333 +14334 test-copy-object-deref-address: +14335 # . prologue +14336 55/push-ebp +14337 89/<- %ebp 4/r32/esp +14338 # setup +14339 (clear-stream _test-input-stream) +14340 (clear-stream $_test-input-buffered-file->buffer) +14341 (clear-stream _test-output-stream) +14342 (clear-stream $_test-output-buffered-file->buffer) +14343 # +14344 (write _test-input-stream "fn foo {\n") +14345 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") +14346 (write _test-input-stream " var y/ecx: (addr addr int) <- copy 0\n") +14347 (write _test-input-stream " copy-object *y, x\n") +14348 (write _test-input-stream "}\n") +14349 # convert +14350 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +14351 (flush _test-output-buffered-file) +14352 # no errors +14353 # . epilogue +14354 5d/pop-to-ebp +14355 c3/return +14356 +14357 test-copy-object-non-addr: +14358 # . prologue +14359 55/push-ebp +14360 89/<- %ebp 4/r32/esp +14361 # setup +14362 (clear-stream _test-input-stream) +14363 (clear-stream $_test-input-buffered-file->buffer) +14364 (clear-stream _test-output-stream) +14365 (clear-stream $_test-output-buffered-file->buffer) +14366 (clear-stream _test-error-stream) +14367 (clear-stream $_test-error-buffered-file->buffer) +14368 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14369 68/push 0/imm32 +14370 68/push 0/imm32 +14371 89/<- %edx 4/r32/esp +14372 (tailor-exit-descriptor %edx 0x10) +14373 # +14374 (write _test-input-stream "fn foo {\n") +14375 (write _test-input-stream " var x: int\n") +14376 (write _test-input-stream " var y: int\n") +14377 (write _test-input-stream " copy-object y, x\n") +14378 (write _test-input-stream "}\n") +14379 # convert +14380 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14381 # registers except esp clobbered at this point +14382 # restore ed +14383 89/<- %edx 4/r32/esp +14384 (flush _test-output-buffered-file) +14385 (flush _test-error-buffered-file) +14386 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14392 # check output +14393 (check-stream-equal _test-output-stream "" "F - test-copy-object-non-addr: output should be empty") +14394 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-object: two inouts with identical addr types expected" "F - test-copy-object-non-addr: error message") +14395 # check that stop(1) was called +14396 (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status") +14397 # don't restore from ebp +14398 81 0/subop/add %esp 8/imm32 +14399 # . epilogue +14400 5d/pop-to-ebp +14401 c3/return +14402 +14403 test-copy-object-non-equal: +14404 # . prologue +14405 55/push-ebp +14406 89/<- %ebp 4/r32/esp +14407 # setup +14408 (clear-stream _test-input-stream) +14409 (clear-stream $_test-input-buffered-file->buffer) +14410 (clear-stream _test-output-stream) +14411 (clear-stream $_test-output-buffered-file->buffer) +14412 (clear-stream _test-error-stream) +14413 (clear-stream $_test-error-buffered-file->buffer) +14414 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14415 68/push 0/imm32 +14416 68/push 0/imm32 +14417 89/<- %edx 4/r32/esp +14418 (tailor-exit-descriptor %edx 0x10) +14419 # +14420 (write _test-input-stream "fn foo {\n") +14421 (write _test-input-stream " var x: (addr int)\n") +14422 (write _test-input-stream " var y: (addr boolean)\n") +14423 (write _test-input-stream " copy-object y, x\n") +14424 (write _test-input-stream "}\n") +14425 # convert +14426 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14427 # registers except esp clobbered at this point +14428 # restore ed +14429 89/<- %edx 4/r32/esp +14430 (flush _test-output-buffered-file) +14431 (flush _test-error-buffered-file) +14432 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14438 # check output +14439 (check-stream-equal _test-output-stream "" "F - test-copy-object-non-equal: output should be empty") +14440 (check-next-stream-line-equal _test-error-stream "fn foo: stmt copy-object: two inouts with identical addr types expected" "F - test-copy-object-non-equal: error message") +14441 # check that stop(1) was called +14442 (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status") +14443 # don't restore from ebp +14444 81 0/subop/add %esp 8/imm32 +14445 # . epilogue +14446 5d/pop-to-ebp +14447 c3/return +14448 +14449 test-allocate-with-no-inout: +14450 # . prologue +14451 55/push-ebp +14452 89/<- %ebp 4/r32/esp +14453 # setup +14454 (clear-stream _test-input-stream) +14455 (clear-stream $_test-input-buffered-file->buffer) +14456 (clear-stream _test-output-stream) +14457 (clear-stream $_test-output-buffered-file->buffer) +14458 (clear-stream _test-error-stream) +14459 (clear-stream $_test-error-buffered-file->buffer) +14460 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14461 68/push 0/imm32 +14462 68/push 0/imm32 +14463 89/<- %edx 4/r32/esp +14464 (tailor-exit-descriptor %edx 0x10) +14465 # +14466 (write _test-input-stream "fn foo {\n") +14467 (write _test-input-stream " allocate\n") +14468 (write _test-input-stream "}\n") +14469 # convert +14470 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14471 # registers except esp clobbered at this point +14472 # restore ed +14473 89/<- %edx 4/r32/esp +14474 (flush _test-output-buffered-file) +14475 (flush _test-error-buffered-file) +14476 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14482 # check output +14483 (check-stream-equal _test-output-stream "" "F - test-allocate-with-no-inout: output should be empty") +14484 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'allocate' must have a single inout" "F - test-allocate-with-no-inout: error message") +14485 # check that stop(1) was called +14486 (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status") +14487 # don't restore from ebp +14488 81 0/subop/add %esp 8/imm32 +14489 # . epilogue +14490 5d/pop-to-ebp +14491 c3/return +14492 +14493 test-allocate-with-too-many-inouts: +14494 # . prologue +14495 55/push-ebp +14496 89/<- %ebp 4/r32/esp +14497 # setup +14498 (clear-stream _test-input-stream) +14499 (clear-stream $_test-input-buffered-file->buffer) +14500 (clear-stream _test-output-stream) +14501 (clear-stream $_test-output-buffered-file->buffer) +14502 (clear-stream _test-error-stream) +14503 (clear-stream $_test-error-buffered-file->buffer) +14504 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14505 68/push 0/imm32 +14506 68/push 0/imm32 +14507 89/<- %edx 4/r32/esp +14508 (tailor-exit-descriptor %edx 0x10) +14509 # +14510 (write _test-input-stream "fn foo {\n") +14511 (write _test-input-stream " var x: (addr handle int)\n") +14512 (write _test-input-stream " allocate x, 0\n") +14513 (write _test-input-stream "}\n") +14514 # convert +14515 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14516 # registers except esp clobbered at this point +14517 # restore ed +14518 89/<- %edx 4/r32/esp +14519 (flush _test-output-buffered-file) +14520 (flush _test-error-buffered-file) +14521 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14527 # check output +14528 (check-stream-equal _test-output-stream "" "F - test-allocate-with-too-many-inouts: output should be empty") +14529 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'allocate' must have a single inout" "F - test-allocate-with-too-many-inouts: error message") +14530 # check that stop(1) was called +14531 (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status") +14532 # don't restore from ebp +14533 81 0/subop/add %esp 8/imm32 +14534 # . epilogue +14535 5d/pop-to-ebp +14536 c3/return +14537 +14538 test-allocate-with-output: +14539 # . prologue +14540 55/push-ebp +14541 89/<- %ebp 4/r32/esp +14542 # setup +14543 (clear-stream _test-input-stream) +14544 (clear-stream $_test-input-buffered-file->buffer) +14545 (clear-stream _test-output-stream) +14546 (clear-stream $_test-output-buffered-file->buffer) +14547 (clear-stream _test-error-stream) +14548 (clear-stream $_test-error-buffered-file->buffer) +14549 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14550 68/push 0/imm32 +14551 68/push 0/imm32 +14552 89/<- %edx 4/r32/esp +14553 (tailor-exit-descriptor %edx 0x10) +14554 # +14555 (write _test-input-stream "fn foo {\n") +14556 (write _test-input-stream " var x/eax: boolean <- copy 0\n") +14557 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") +14558 (write _test-input-stream " x <- allocate y\n") +14559 (write _test-input-stream "}\n") +14560 # convert +14561 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14562 # registers except esp clobbered at this point +14563 # restore ed +14564 89/<- %edx 4/r32/esp +14565 (flush _test-output-buffered-file) +14566 (flush _test-error-buffered-file) +14567 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14573 # check output +14574 (check-stream-equal _test-output-stream "" "F - test-allocate-with-output: output should be empty") +14575 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'allocate' must not have any outputs" "F - test-allocate-with-output: error message") +14576 # check that stop(1) was called +14577 (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status") +14578 # don't restore from ebp +14579 81 0/subop/add %esp 8/imm32 +14580 # . epilogue +14581 5d/pop-to-ebp +14582 c3/return +14583 +14584 test-allocate-non-addr: +14585 # . prologue +14586 55/push-ebp +14587 89/<- %ebp 4/r32/esp +14588 # setup +14589 (clear-stream _test-input-stream) +14590 (clear-stream $_test-input-buffered-file->buffer) +14591 (clear-stream _test-output-stream) +14592 (clear-stream $_test-output-buffered-file->buffer) +14593 (clear-stream _test-error-stream) +14594 (clear-stream $_test-error-buffered-file->buffer) +14595 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14596 68/push 0/imm32 +14597 68/push 0/imm32 +14598 89/<- %edx 4/r32/esp +14599 (tailor-exit-descriptor %edx 0x10) +14600 # +14601 (write _test-input-stream "fn foo {\n") +14602 (write _test-input-stream " var y: (handle int)\n") +14603 (write _test-input-stream " allocate y\n") +14604 (write _test-input-stream "}\n") +14605 # convert +14606 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14607 # registers except esp clobbered at this point +14608 # restore ed +14609 89/<- %edx 4/r32/esp +14610 (flush _test-output-buffered-file) +14611 (flush _test-error-buffered-file) +14612 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14618 # check output +14619 (check-stream-equal _test-output-stream "" "F - test-allocate-non-addr: output must be empty") +14620 (check-next-stream-line-equal _test-error-stream "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)" "F - test-allocate-non-addr: error message") +14621 # check that stop(1) was called +14622 (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status") +14623 # don't restore from ebp +14624 81 0/subop/add %esp 8/imm32 +14625 # . epilogue +14626 5d/pop-to-ebp +14627 c3/return +14628 +14629 test-allocate-non-addr-handle: +14630 # . prologue +14631 55/push-ebp +14632 89/<- %ebp 4/r32/esp +14633 # setup +14634 (clear-stream _test-input-stream) +14635 (clear-stream $_test-input-buffered-file->buffer) +14636 (clear-stream _test-output-stream) +14637 (clear-stream $_test-output-buffered-file->buffer) +14638 (clear-stream _test-error-stream) +14639 (clear-stream $_test-error-buffered-file->buffer) +14640 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14641 68/push 0/imm32 +14642 68/push 0/imm32 +14643 89/<- %edx 4/r32/esp +14644 (tailor-exit-descriptor %edx 0x10) +14645 # +14646 (write _test-input-stream "fn foo {\n") +14647 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") +14648 (write _test-input-stream " allocate y\n") +14649 (write _test-input-stream "}\n") +14650 # convert +14651 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14652 # registers except esp clobbered at this point +14653 # restore ed +14654 89/<- %edx 4/r32/esp +14655 (flush _test-output-buffered-file) +14656 (flush _test-error-buffered-file) +14657 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14663 # check output +14664 (check-stream-equal _test-output-stream "" "F - test-allocate-non-addr-handle: output should be empty") +14665 (check-next-stream-line-equal _test-error-stream "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)" "F - test-allocate-non-addr-handle: error message") +14666 # check that stop(1) was called +14667 (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status") +14668 # don't restore from ebp +14669 81 0/subop/add %esp 8/imm32 14670 # . epilogue 14671 5d/pop-to-ebp 14672 c3/return 14673 -14674 test-populate-with-no-inout: +14674 test-allocate-deref-address: 14675 # . prologue 14676 55/push-ebp 14677 89/<- %ebp 4/r32/esp @@ -13297,260 +13297,260 @@ if ('onhashchange' in window) { 14680 (clear-stream $_test-input-buffered-file->buffer) 14681 (clear-stream _test-output-stream) 14682 (clear-stream $_test-output-buffered-file->buffer) -14683 (clear-stream _test-error-stream) -14684 (clear-stream $_test-error-buffered-file->buffer) -14685 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14686 68/push 0/imm32 -14687 68/push 0/imm32 -14688 89/<- %edx 4/r32/esp -14689 (tailor-exit-descriptor %edx 0x10) -14690 # -14691 (write _test-input-stream "fn foo {\n") -14692 (write _test-input-stream " populate\n") -14693 (write _test-input-stream "}\n") -14694 # convert -14695 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14696 # registers except esp clobbered at this point -14697 # restore ed -14698 89/<- %edx 4/r32/esp -14699 (flush _test-output-buffered-file) -14700 (flush _test-error-buffered-file) -14701 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14707 # check output -14708 (check-stream-equal _test-output-stream "" "F - test-populate-with-no-inout: output should be empty") -14709 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate' must have two inouts" "F - test-populate-with-no-inout: error message") -14710 # check that stop(1) was called -14711 (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status") -14712 # don't restore from ebp -14713 81 0/subop/add %esp 8/imm32 -14714 # . epilogue -14715 5d/pop-to-ebp -14716 c3/return -14717 -14718 test-populate-with-too-many-inouts: -14719 # . prologue -14720 55/push-ebp -14721 89/<- %ebp 4/r32/esp -14722 # setup -14723 (clear-stream _test-input-stream) -14724 (clear-stream $_test-input-buffered-file->buffer) -14725 (clear-stream _test-output-stream) -14726 (clear-stream $_test-output-buffered-file->buffer) -14727 (clear-stream _test-error-stream) -14728 (clear-stream $_test-error-buffered-file->buffer) -14729 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14730 68/push 0/imm32 -14731 68/push 0/imm32 -14732 89/<- %edx 4/r32/esp -14733 (tailor-exit-descriptor %edx 0x10) -14734 # -14735 (write _test-input-stream "fn foo {\n") -14736 (write _test-input-stream " var x: (addr handle int)\n") -14737 (write _test-input-stream " populate x, 3, 0\n") -14738 (write _test-input-stream "}\n") -14739 # convert -14740 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14741 # registers except esp clobbered at this point -14742 # restore ed -14743 89/<- %edx 4/r32/esp -14744 (flush _test-output-buffered-file) -14745 (flush _test-error-buffered-file) -14746 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14752 # check output -14753 (check-stream-equal _test-output-stream "" "F - test-populate-with-too-many-inouts: output should be empty") -14754 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate' must have two inouts" "F - test-populate-with-too-many-inouts: error message") -14755 # check that stop(1) was called -14756 (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status") -14757 # don't restore from ebp -14758 81 0/subop/add %esp 8/imm32 -14759 # . epilogue -14760 5d/pop-to-ebp -14761 c3/return -14762 -14763 test-populate-with-output: -14764 # . prologue -14765 55/push-ebp -14766 89/<- %ebp 4/r32/esp -14767 # setup -14768 (clear-stream _test-input-stream) -14769 (clear-stream $_test-input-buffered-file->buffer) -14770 (clear-stream _test-output-stream) -14771 (clear-stream $_test-output-buffered-file->buffer) -14772 (clear-stream _test-error-stream) -14773 (clear-stream $_test-error-buffered-file->buffer) -14774 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14775 68/push 0/imm32 -14776 68/push 0/imm32 -14777 89/<- %edx 4/r32/esp -14778 (tailor-exit-descriptor %edx 0x10) -14779 # -14780 (write _test-input-stream "fn foo {\n") -14781 (write _test-input-stream " var x/eax: boolean <- copy 0\n") -14782 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") -14783 (write _test-input-stream " x <- populate y\n") -14784 (write _test-input-stream "}\n") -14785 # convert -14786 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14787 # registers except esp clobbered at this point -14788 # restore ed -14789 89/<- %edx 4/r32/esp -14790 (flush _test-output-buffered-file) -14791 (flush _test-error-buffered-file) -14792 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14798 # check output -14799 (check-stream-equal _test-output-stream "" "F - test-populate-with-output: output should be empty") -14800 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate' must not have any outputs" "F - test-populate-with-output: error message") -14801 # check that stop(1) was called -14802 (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status") -14803 # don't restore from ebp -14804 81 0/subop/add %esp 8/imm32 -14805 # . epilogue -14806 5d/pop-to-ebp -14807 c3/return -14808 -14809 test-populate-non-addr: -14810 # . prologue -14811 55/push-ebp -14812 89/<- %ebp 4/r32/esp -14813 # setup -14814 (clear-stream _test-input-stream) -14815 (clear-stream $_test-input-buffered-file->buffer) -14816 (clear-stream _test-output-stream) -14817 (clear-stream $_test-output-buffered-file->buffer) -14818 (clear-stream _test-error-stream) -14819 (clear-stream $_test-error-buffered-file->buffer) -14820 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14821 68/push 0/imm32 -14822 68/push 0/imm32 -14823 89/<- %edx 4/r32/esp -14824 (tailor-exit-descriptor %edx 0x10) -14825 # -14826 (write _test-input-stream "fn foo {\n") -14827 (write _test-input-stream " var y: (handle int)\n") -14828 (write _test-input-stream " populate y, 3\n") -14829 (write _test-input-stream "}\n") -14830 # convert -14831 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14832 # registers except esp clobbered at this point -14833 # restore ed -14834 89/<- %edx 4/r32/esp -14835 (flush _test-output-buffered-file) -14836 (flush _test-error-buffered-file) -14837 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14843 # check output -14844 (check-stream-equal _test-output-stream "" "F - test-populate-non-addr: output must be empty") -14845 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)" "F - test-populate-non-addr: error message") -14846 # check that stop(1) was called -14847 (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status") -14848 # don't restore from ebp -14849 81 0/subop/add %esp 8/imm32 -14850 # . epilogue -14851 5d/pop-to-ebp -14852 c3/return -14853 -14854 test-populate-non-addr-handle: -14855 # . prologue -14856 55/push-ebp -14857 89/<- %ebp 4/r32/esp -14858 # setup -14859 (clear-stream _test-input-stream) -14860 (clear-stream $_test-input-buffered-file->buffer) -14861 (clear-stream _test-output-stream) -14862 (clear-stream $_test-output-buffered-file->buffer) -14863 (clear-stream _test-error-stream) -14864 (clear-stream $_test-error-buffered-file->buffer) -14865 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14866 68/push 0/imm32 -14867 68/push 0/imm32 -14868 89/<- %edx 4/r32/esp -14869 (tailor-exit-descriptor %edx 0x10) -14870 # -14871 (write _test-input-stream "fn foo {\n") -14872 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") -14873 (write _test-input-stream " populate y, 3\n") -14874 (write _test-input-stream "}\n") -14875 # convert -14876 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14877 # registers except esp clobbered at this point -14878 # restore ed -14879 89/<- %edx 4/r32/esp -14880 (flush _test-output-buffered-file) -14881 (flush _test-error-buffered-file) -14882 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14888 # check output -14889 (check-stream-equal _test-output-stream "" "F - test-populate-non-addr-handle: output should be empty") -14890 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)" "F - test-populate-non-addr-handle: error message") -14891 # check that stop(1) was called -14892 (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status") -14893 # don't restore from ebp -14894 81 0/subop/add %esp 8/imm32 -14895 # . epilogue -14896 5d/pop-to-ebp -14897 c3/return -14898 -14899 test-populate-non-addr-handle-array: -14900 # . prologue -14901 55/push-ebp -14902 89/<- %ebp 4/r32/esp -14903 # setup -14904 (clear-stream _test-input-stream) -14905 (clear-stream $_test-input-buffered-file->buffer) -14906 (clear-stream _test-output-stream) -14907 (clear-stream $_test-output-buffered-file->buffer) -14908 (clear-stream _test-error-stream) -14909 (clear-stream $_test-error-buffered-file->buffer) -14910 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14911 68/push 0/imm32 -14912 68/push 0/imm32 -14913 89/<- %edx 4/r32/esp -14914 (tailor-exit-descriptor %edx 0x10) -14915 # -14916 (write _test-input-stream "fn foo {\n") -14917 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") -14918 (write _test-input-stream " populate y, 3\n") -14919 (write _test-input-stream "}\n") -14920 # convert -14921 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14922 # registers except esp clobbered at this point -14923 # restore ed -14924 89/<- %edx 4/r32/esp -14925 (flush _test-output-buffered-file) -14926 (flush _test-error-buffered-file) -14927 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14933 # check output -14934 (check-stream-equal _test-output-stream "" "F - test-populate-non-addr-handle-array: output should be empty") -14935 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)" "F - test-populate-non-addr-handle-array: error message") -14936 # check that stop(1) was called -14937 (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status") -14938 # don't restore from ebp -14939 81 0/subop/add %esp 8/imm32 -14940 # . epilogue -14941 5d/pop-to-ebp -14942 c3/return -14943 -14944 test-populate-deref-address: -14945 # . prologue -14946 55/push-ebp -14947 89/<- %ebp 4/r32/esp -14948 # setup -14949 (clear-stream _test-input-stream) -14950 (clear-stream $_test-input-buffered-file->buffer) -14951 (clear-stream _test-output-stream) -14952 (clear-stream $_test-output-buffered-file->buffer) -14953 # -14954 (write _test-input-stream "fn foo {\n") -14955 (write _test-input-stream " var y/ecx: (addr addr handle array int) <- copy 0\n") -14956 (write _test-input-stream " populate *y, 3\n") -14957 (write _test-input-stream "}\n") -14958 # convert -14959 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -14960 (flush _test-output-buffered-file) -14961 # no errors +14683 # +14684 (write _test-input-stream "fn foo {\n") +14685 (write _test-input-stream " var y/ecx: (addr addr handle int) <- copy 0\n") +14686 (write _test-input-stream " allocate *y\n") +14687 (write _test-input-stream "}\n") +14688 # convert +14689 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +14690 (flush _test-output-buffered-file) +14691 # no errors +14692 # . epilogue +14693 5d/pop-to-ebp +14694 c3/return +14695 +14696 test-populate-with-no-inout: +14697 # . prologue +14698 55/push-ebp +14699 89/<- %ebp 4/r32/esp +14700 # setup +14701 (clear-stream _test-input-stream) +14702 (clear-stream $_test-input-buffered-file->buffer) +14703 (clear-stream _test-output-stream) +14704 (clear-stream $_test-output-buffered-file->buffer) +14705 (clear-stream _test-error-stream) +14706 (clear-stream $_test-error-buffered-file->buffer) +14707 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14708 68/push 0/imm32 +14709 68/push 0/imm32 +14710 89/<- %edx 4/r32/esp +14711 (tailor-exit-descriptor %edx 0x10) +14712 # +14713 (write _test-input-stream "fn foo {\n") +14714 (write _test-input-stream " populate\n") +14715 (write _test-input-stream "}\n") +14716 # convert +14717 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14718 # registers except esp clobbered at this point +14719 # restore ed +14720 89/<- %edx 4/r32/esp +14721 (flush _test-output-buffered-file) +14722 (flush _test-error-buffered-file) +14723 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14729 # check output +14730 (check-stream-equal _test-output-stream "" "F - test-populate-with-no-inout: output should be empty") +14731 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate' must have two inouts" "F - test-populate-with-no-inout: error message") +14732 # check that stop(1) was called +14733 (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status") +14734 # don't restore from ebp +14735 81 0/subop/add %esp 8/imm32 +14736 # . epilogue +14737 5d/pop-to-ebp +14738 c3/return +14739 +14740 test-populate-with-too-many-inouts: +14741 # . prologue +14742 55/push-ebp +14743 89/<- %ebp 4/r32/esp +14744 # setup +14745 (clear-stream _test-input-stream) +14746 (clear-stream $_test-input-buffered-file->buffer) +14747 (clear-stream _test-output-stream) +14748 (clear-stream $_test-output-buffered-file->buffer) +14749 (clear-stream _test-error-stream) +14750 (clear-stream $_test-error-buffered-file->buffer) +14751 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14752 68/push 0/imm32 +14753 68/push 0/imm32 +14754 89/<- %edx 4/r32/esp +14755 (tailor-exit-descriptor %edx 0x10) +14756 # +14757 (write _test-input-stream "fn foo {\n") +14758 (write _test-input-stream " var x: (addr handle int)\n") +14759 (write _test-input-stream " populate x, 3, 0\n") +14760 (write _test-input-stream "}\n") +14761 # convert +14762 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14763 # registers except esp clobbered at this point +14764 # restore ed +14765 89/<- %edx 4/r32/esp +14766 (flush _test-output-buffered-file) +14767 (flush _test-error-buffered-file) +14768 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14774 # check output +14775 (check-stream-equal _test-output-stream "" "F - test-populate-with-too-many-inouts: output should be empty") +14776 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate' must have two inouts" "F - test-populate-with-too-many-inouts: error message") +14777 # check that stop(1) was called +14778 (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status") +14779 # don't restore from ebp +14780 81 0/subop/add %esp 8/imm32 +14781 # . epilogue +14782 5d/pop-to-ebp +14783 c3/return +14784 +14785 test-populate-with-output: +14786 # . prologue +14787 55/push-ebp +14788 89/<- %ebp 4/r32/esp +14789 # setup +14790 (clear-stream _test-input-stream) +14791 (clear-stream $_test-input-buffered-file->buffer) +14792 (clear-stream _test-output-stream) +14793 (clear-stream $_test-output-buffered-file->buffer) +14794 (clear-stream _test-error-stream) +14795 (clear-stream $_test-error-buffered-file->buffer) +14796 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14797 68/push 0/imm32 +14798 68/push 0/imm32 +14799 89/<- %edx 4/r32/esp +14800 (tailor-exit-descriptor %edx 0x10) +14801 # +14802 (write _test-input-stream "fn foo {\n") +14803 (write _test-input-stream " var x/eax: boolean <- copy 0\n") +14804 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") +14805 (write _test-input-stream " x <- populate y\n") +14806 (write _test-input-stream "}\n") +14807 # convert +14808 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14809 # registers except esp clobbered at this point +14810 # restore ed +14811 89/<- %edx 4/r32/esp +14812 (flush _test-output-buffered-file) +14813 (flush _test-error-buffered-file) +14814 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14820 # check output +14821 (check-stream-equal _test-output-stream "" "F - test-populate-with-output: output should be empty") +14822 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate' must not have any outputs" "F - test-populate-with-output: error message") +14823 # check that stop(1) was called +14824 (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status") +14825 # don't restore from ebp +14826 81 0/subop/add %esp 8/imm32 +14827 # . epilogue +14828 5d/pop-to-ebp +14829 c3/return +14830 +14831 test-populate-non-addr: +14832 # . prologue +14833 55/push-ebp +14834 89/<- %ebp 4/r32/esp +14835 # setup +14836 (clear-stream _test-input-stream) +14837 (clear-stream $_test-input-buffered-file->buffer) +14838 (clear-stream _test-output-stream) +14839 (clear-stream $_test-output-buffered-file->buffer) +14840 (clear-stream _test-error-stream) +14841 (clear-stream $_test-error-buffered-file->buffer) +14842 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14843 68/push 0/imm32 +14844 68/push 0/imm32 +14845 89/<- %edx 4/r32/esp +14846 (tailor-exit-descriptor %edx 0x10) +14847 # +14848 (write _test-input-stream "fn foo {\n") +14849 (write _test-input-stream " var y: (handle int)\n") +14850 (write _test-input-stream " populate y, 3\n") +14851 (write _test-input-stream "}\n") +14852 # convert +14853 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14854 # registers except esp clobbered at this point +14855 # restore ed +14856 89/<- %edx 4/r32/esp +14857 (flush _test-output-buffered-file) +14858 (flush _test-error-buffered-file) +14859 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14865 # check output +14866 (check-stream-equal _test-output-stream "" "F - test-populate-non-addr: output must be empty") +14867 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)" "F - test-populate-non-addr: error message") +14868 # check that stop(1) was called +14869 (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status") +14870 # don't restore from ebp +14871 81 0/subop/add %esp 8/imm32 +14872 # . epilogue +14873 5d/pop-to-ebp +14874 c3/return +14875 +14876 test-populate-non-addr-handle: +14877 # . prologue +14878 55/push-ebp +14879 89/<- %ebp 4/r32/esp +14880 # setup +14881 (clear-stream _test-input-stream) +14882 (clear-stream $_test-input-buffered-file->buffer) +14883 (clear-stream _test-output-stream) +14884 (clear-stream $_test-output-buffered-file->buffer) +14885 (clear-stream _test-error-stream) +14886 (clear-stream $_test-error-buffered-file->buffer) +14887 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14888 68/push 0/imm32 +14889 68/push 0/imm32 +14890 89/<- %edx 4/r32/esp +14891 (tailor-exit-descriptor %edx 0x10) +14892 # +14893 (write _test-input-stream "fn foo {\n") +14894 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") +14895 (write _test-input-stream " populate y, 3\n") +14896 (write _test-input-stream "}\n") +14897 # convert +14898 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14899 # registers except esp clobbered at this point +14900 # restore ed +14901 89/<- %edx 4/r32/esp +14902 (flush _test-output-buffered-file) +14903 (flush _test-error-buffered-file) +14904 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14910 # check output +14911 (check-stream-equal _test-output-stream "" "F - test-populate-non-addr-handle: output should be empty") +14912 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)" "F - test-populate-non-addr-handle: error message") +14913 # check that stop(1) was called +14914 (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status") +14915 # don't restore from ebp +14916 81 0/subop/add %esp 8/imm32 +14917 # . epilogue +14918 5d/pop-to-ebp +14919 c3/return +14920 +14921 test-populate-non-addr-handle-array: +14922 # . prologue +14923 55/push-ebp +14924 89/<- %ebp 4/r32/esp +14925 # setup +14926 (clear-stream _test-input-stream) +14927 (clear-stream $_test-input-buffered-file->buffer) +14928 (clear-stream _test-output-stream) +14929 (clear-stream $_test-output-buffered-file->buffer) +14930 (clear-stream _test-error-stream) +14931 (clear-stream $_test-error-buffered-file->buffer) +14932 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +14933 68/push 0/imm32 +14934 68/push 0/imm32 +14935 89/<- %edx 4/r32/esp +14936 (tailor-exit-descriptor %edx 0x10) +14937 # +14938 (write _test-input-stream "fn foo {\n") +14939 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") +14940 (write _test-input-stream " populate y, 3\n") +14941 (write _test-input-stream "}\n") +14942 # convert +14943 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +14944 # registers except esp clobbered at this point +14945 # restore ed +14946 89/<- %edx 4/r32/esp +14947 (flush _test-output-buffered-file) +14948 (flush _test-error-buffered-file) +14949 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +14955 # check output +14956 (check-stream-equal _test-output-stream "" "F - test-populate-non-addr-handle-array: output should be empty") +14957 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)" "F - test-populate-non-addr-handle-array: error message") +14958 # check that stop(1) was called +14959 (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status") +14960 # don't restore from ebp +14961 81 0/subop/add %esp 8/imm32 14962 # . epilogue 14963 5d/pop-to-ebp 14964 c3/return 14965 -14966 test-populate-stream-with-no-inout: +14966 test-populate-deref-address: 14967 # . prologue 14968 55/push-ebp 14969 89/<- %ebp 4/r32/esp @@ -13559,260 +13559,260 @@ if ('onhashchange' in window) { 14972 (clear-stream $_test-input-buffered-file->buffer) 14973 (clear-stream _test-output-stream) 14974 (clear-stream $_test-output-buffered-file->buffer) -14975 (clear-stream _test-error-stream) -14976 (clear-stream $_test-error-buffered-file->buffer) -14977 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -14978 68/push 0/imm32 -14979 68/push 0/imm32 -14980 89/<- %edx 4/r32/esp -14981 (tailor-exit-descriptor %edx 0x10) -14982 # -14983 (write _test-input-stream "fn foo {\n") -14984 (write _test-input-stream " populate-stream\n") -14985 (write _test-input-stream "}\n") -14986 # convert -14987 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -14988 # registers except esp clobbered at this point -14989 # restore ed -14990 89/<- %edx 4/r32/esp -14991 (flush _test-output-buffered-file) -14992 (flush _test-error-buffered-file) -14993 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -14999 # check output -15000 (check-stream-equal _test-output-stream "" "F - test-populate-stream-with-no-inout: output should be empty") -15001 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate-stream' must have two inouts" "F - test-populate-stream-with-no-inout: error message") -15002 # check that stop(1) was called -15003 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status") -15004 # don't restore from ebp -15005 81 0/subop/add %esp 8/imm32 -15006 # . epilogue -15007 5d/pop-to-ebp -15008 c3/return -15009 -15010 test-populate-stream-with-too-many-inouts: -15011 # . prologue -15012 55/push-ebp -15013 89/<- %ebp 4/r32/esp -15014 # setup -15015 (clear-stream _test-input-stream) -15016 (clear-stream $_test-input-buffered-file->buffer) -15017 (clear-stream _test-output-stream) -15018 (clear-stream $_test-output-buffered-file->buffer) -15019 (clear-stream _test-error-stream) -15020 (clear-stream $_test-error-buffered-file->buffer) -15021 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15022 68/push 0/imm32 -15023 68/push 0/imm32 -15024 89/<- %edx 4/r32/esp -15025 (tailor-exit-descriptor %edx 0x10) -15026 # -15027 (write _test-input-stream "fn foo {\n") -15028 (write _test-input-stream " var x: (addr handle int)\n") -15029 (write _test-input-stream " populate-stream x, 3, 0\n") -15030 (write _test-input-stream "}\n") -15031 # convert -15032 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15033 # registers except esp clobbered at this point -15034 # restore ed -15035 89/<- %edx 4/r32/esp -15036 (flush _test-output-buffered-file) -15037 (flush _test-error-buffered-file) -15038 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15044 # check output -15045 (check-stream-equal _test-output-stream "" "F - test-populate-stream-with-too-many-inouts: output should be empty") -15046 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate-stream' must have two inouts" "F - test-populate-stream-with-too-many-inouts: error message") -15047 # check that stop(1) was called -15048 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status") -15049 # don't restore from ebp -15050 81 0/subop/add %esp 8/imm32 -15051 # . epilogue -15052 5d/pop-to-ebp -15053 c3/return -15054 -15055 test-populate-stream-with-output: -15056 # . prologue -15057 55/push-ebp -15058 89/<- %ebp 4/r32/esp -15059 # setup -15060 (clear-stream _test-input-stream) -15061 (clear-stream $_test-input-buffered-file->buffer) -15062 (clear-stream _test-output-stream) -15063 (clear-stream $_test-output-buffered-file->buffer) -15064 (clear-stream _test-error-stream) -15065 (clear-stream $_test-error-buffered-file->buffer) -15066 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15067 68/push 0/imm32 -15068 68/push 0/imm32 -15069 89/<- %edx 4/r32/esp -15070 (tailor-exit-descriptor %edx 0x10) -15071 # -15072 (write _test-input-stream "fn foo {\n") -15073 (write _test-input-stream " var x/eax: boolean <- copy 0\n") -15074 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") -15075 (write _test-input-stream " x <- populate-stream y\n") -15076 (write _test-input-stream "}\n") -15077 # convert -15078 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15079 # registers except esp clobbered at this point -15080 # restore ed -15081 89/<- %edx 4/r32/esp -15082 (flush _test-output-buffered-file) -15083 (flush _test-error-buffered-file) -15084 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15090 # check output -15091 (check-stream-equal _test-output-stream "" "F - test-populate-stream-with-output: output should be empty") -15092 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate-stream' must not have any outputs" "F - test-populate-stream-with-output: error message") -15093 # check that stop(1) was called -15094 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status") -15095 # don't restore from ebp -15096 81 0/subop/add %esp 8/imm32 -15097 # . epilogue -15098 5d/pop-to-ebp -15099 c3/return -15100 -15101 test-populate-stream-non-addr: -15102 # . prologue -15103 55/push-ebp -15104 89/<- %ebp 4/r32/esp -15105 # setup -15106 (clear-stream _test-input-stream) -15107 (clear-stream $_test-input-buffered-file->buffer) -15108 (clear-stream _test-output-stream) -15109 (clear-stream $_test-output-buffered-file->buffer) -15110 (clear-stream _test-error-stream) -15111 (clear-stream $_test-error-buffered-file->buffer) -15112 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15113 68/push 0/imm32 -15114 68/push 0/imm32 -15115 89/<- %edx 4/r32/esp -15116 (tailor-exit-descriptor %edx 0x10) -15117 # -15118 (write _test-input-stream "fn foo {\n") -15119 (write _test-input-stream " var y: (handle int)\n") -15120 (write _test-input-stream " populate-stream y, 3\n") -15121 (write _test-input-stream "}\n") -15122 # convert -15123 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15124 # registers except esp clobbered at this point -15125 # restore ed -15126 89/<- %edx 4/r32/esp -15127 (flush _test-output-buffered-file) -15128 (flush _test-error-buffered-file) -15129 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15135 # check output -15136 (check-stream-equal _test-output-stream "" "F - test-populate-stream-non-addr: output must be empty") -15137 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)" "F - test-populate-stream-non-addr: error message") -15138 # check that stop(1) was called -15139 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status") -15140 # don't restore from ebp -15141 81 0/subop/add %esp 8/imm32 -15142 # . epilogue -15143 5d/pop-to-ebp -15144 c3/return -15145 -15146 test-populate-stream-non-addr-handle: -15147 # . prologue -15148 55/push-ebp -15149 89/<- %ebp 4/r32/esp -15150 # setup -15151 (clear-stream _test-input-stream) -15152 (clear-stream $_test-input-buffered-file->buffer) -15153 (clear-stream _test-output-stream) -15154 (clear-stream $_test-output-buffered-file->buffer) -15155 (clear-stream _test-error-stream) -15156 (clear-stream $_test-error-buffered-file->buffer) -15157 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15158 68/push 0/imm32 -15159 68/push 0/imm32 -15160 89/<- %edx 4/r32/esp -15161 (tailor-exit-descriptor %edx 0x10) -15162 # -15163 (write _test-input-stream "fn foo {\n") -15164 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") -15165 (write _test-input-stream " populate-stream y, 3\n") -15166 (write _test-input-stream "}\n") -15167 # convert -15168 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15169 # registers except esp clobbered at this point -15170 # restore ed -15171 89/<- %edx 4/r32/esp -15172 (flush _test-output-buffered-file) -15173 (flush _test-error-buffered-file) -15174 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15180 # check output -15181 (check-stream-equal _test-output-stream "" "F - test-populate-stream-non-addr-handle: output should be empty") -15182 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)" "F - test-populate-stream-non-addr-handle: error message") -15183 # check that stop(1) was called -15184 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status") -15185 # don't restore from ebp -15186 81 0/subop/add %esp 8/imm32 -15187 # . epilogue -15188 5d/pop-to-ebp -15189 c3/return -15190 -15191 test-populate-stream-non-addr-handle-stream: -15192 # . prologue -15193 55/push-ebp -15194 89/<- %ebp 4/r32/esp -15195 # setup -15196 (clear-stream _test-input-stream) -15197 (clear-stream $_test-input-buffered-file->buffer) -15198 (clear-stream _test-output-stream) -15199 (clear-stream $_test-output-buffered-file->buffer) -15200 (clear-stream _test-error-stream) -15201 (clear-stream $_test-error-buffered-file->buffer) -15202 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15203 68/push 0/imm32 -15204 68/push 0/imm32 -15205 89/<- %edx 4/r32/esp -15206 (tailor-exit-descriptor %edx 0x10) -15207 # -15208 (write _test-input-stream "fn foo {\n") -15209 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") -15210 (write _test-input-stream " populate-stream y, 3\n") -15211 (write _test-input-stream "}\n") -15212 # convert -15213 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15214 # registers except esp clobbered at this point -15215 # restore ed -15216 89/<- %edx 4/r32/esp -15217 (flush _test-output-buffered-file) -15218 (flush _test-error-buffered-file) -15219 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15225 # check output -15226 (check-stream-equal _test-output-stream "" "F - test-populate-stream-non-addr-handle-stream: output should be empty") -15227 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)" "F - test-populate-stream-non-addr-handle-stream: error message") -15228 # check that stop(1) was called -15229 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status") -15230 # don't restore from ebp -15231 81 0/subop/add %esp 8/imm32 -15232 # . epilogue -15233 5d/pop-to-ebp -15234 c3/return -15235 -15236 test-populate-stream-deref-address: -15237 # . prologue -15238 55/push-ebp -15239 89/<- %ebp 4/r32/esp -15240 # setup -15241 (clear-stream _test-input-stream) -15242 (clear-stream $_test-input-buffered-file->buffer) -15243 (clear-stream _test-output-stream) -15244 (clear-stream $_test-output-buffered-file->buffer) -15245 # -15246 (write _test-input-stream "fn foo {\n") -15247 (write _test-input-stream " var y/ecx: (addr addr handle stream int) <- copy 0\n") -15248 (write _test-input-stream " populate-stream *y, 3\n") -15249 (write _test-input-stream "}\n") -15250 # convert -15251 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -15252 (flush _test-output-buffered-file) -15253 # no errors +14975 # +14976 (write _test-input-stream "fn foo {\n") +14977 (write _test-input-stream " var y/ecx: (addr addr handle array int) <- copy 0\n") +14978 (write _test-input-stream " populate *y, 3\n") +14979 (write _test-input-stream "}\n") +14980 # convert +14981 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +14982 (flush _test-output-buffered-file) +14983 # no errors +14984 # . epilogue +14985 5d/pop-to-ebp +14986 c3/return +14987 +14988 test-populate-stream-with-no-inout: +14989 # . prologue +14990 55/push-ebp +14991 89/<- %ebp 4/r32/esp +14992 # setup +14993 (clear-stream _test-input-stream) +14994 (clear-stream $_test-input-buffered-file->buffer) +14995 (clear-stream _test-output-stream) +14996 (clear-stream $_test-output-buffered-file->buffer) +14997 (clear-stream _test-error-stream) +14998 (clear-stream $_test-error-buffered-file->buffer) +14999 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15000 68/push 0/imm32 +15001 68/push 0/imm32 +15002 89/<- %edx 4/r32/esp +15003 (tailor-exit-descriptor %edx 0x10) +15004 # +15005 (write _test-input-stream "fn foo {\n") +15006 (write _test-input-stream " populate-stream\n") +15007 (write _test-input-stream "}\n") +15008 # convert +15009 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15010 # registers except esp clobbered at this point +15011 # restore ed +15012 89/<- %edx 4/r32/esp +15013 (flush _test-output-buffered-file) +15014 (flush _test-error-buffered-file) +15015 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15021 # check output +15022 (check-stream-equal _test-output-stream "" "F - test-populate-stream-with-no-inout: output should be empty") +15023 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate-stream' must have two inouts" "F - test-populate-stream-with-no-inout: error message") +15024 # check that stop(1) was called +15025 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status") +15026 # don't restore from ebp +15027 81 0/subop/add %esp 8/imm32 +15028 # . epilogue +15029 5d/pop-to-ebp +15030 c3/return +15031 +15032 test-populate-stream-with-too-many-inouts: +15033 # . prologue +15034 55/push-ebp +15035 89/<- %ebp 4/r32/esp +15036 # setup +15037 (clear-stream _test-input-stream) +15038 (clear-stream $_test-input-buffered-file->buffer) +15039 (clear-stream _test-output-stream) +15040 (clear-stream $_test-output-buffered-file->buffer) +15041 (clear-stream _test-error-stream) +15042 (clear-stream $_test-error-buffered-file->buffer) +15043 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15044 68/push 0/imm32 +15045 68/push 0/imm32 +15046 89/<- %edx 4/r32/esp +15047 (tailor-exit-descriptor %edx 0x10) +15048 # +15049 (write _test-input-stream "fn foo {\n") +15050 (write _test-input-stream " var x: (addr handle int)\n") +15051 (write _test-input-stream " populate-stream x, 3, 0\n") +15052 (write _test-input-stream "}\n") +15053 # convert +15054 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15055 # registers except esp clobbered at this point +15056 # restore ed +15057 89/<- %edx 4/r32/esp +15058 (flush _test-output-buffered-file) +15059 (flush _test-error-buffered-file) +15060 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15066 # check output +15067 (check-stream-equal _test-output-stream "" "F - test-populate-stream-with-too-many-inouts: output should be empty") +15068 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate-stream' must have two inouts" "F - test-populate-stream-with-too-many-inouts: error message") +15069 # check that stop(1) was called +15070 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status") +15071 # don't restore from ebp +15072 81 0/subop/add %esp 8/imm32 +15073 # . epilogue +15074 5d/pop-to-ebp +15075 c3/return +15076 +15077 test-populate-stream-with-output: +15078 # . prologue +15079 55/push-ebp +15080 89/<- %ebp 4/r32/esp +15081 # setup +15082 (clear-stream _test-input-stream) +15083 (clear-stream $_test-input-buffered-file->buffer) +15084 (clear-stream _test-output-stream) +15085 (clear-stream $_test-output-buffered-file->buffer) +15086 (clear-stream _test-error-stream) +15087 (clear-stream $_test-error-buffered-file->buffer) +15088 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15089 68/push 0/imm32 +15090 68/push 0/imm32 +15091 89/<- %edx 4/r32/esp +15092 (tailor-exit-descriptor %edx 0x10) +15093 # +15094 (write _test-input-stream "fn foo {\n") +15095 (write _test-input-stream " var x/eax: boolean <- copy 0\n") +15096 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") +15097 (write _test-input-stream " x <- populate-stream y\n") +15098 (write _test-input-stream "}\n") +15099 # convert +15100 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15101 # registers except esp clobbered at this point +15102 # restore ed +15103 89/<- %edx 4/r32/esp +15104 (flush _test-output-buffered-file) +15105 (flush _test-error-buffered-file) +15106 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15112 # check output +15113 (check-stream-equal _test-output-stream "" "F - test-populate-stream-with-output: output should be empty") +15114 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'populate-stream' must not have any outputs" "F - test-populate-stream-with-output: error message") +15115 # check that stop(1) was called +15116 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status") +15117 # don't restore from ebp +15118 81 0/subop/add %esp 8/imm32 +15119 # . epilogue +15120 5d/pop-to-ebp +15121 c3/return +15122 +15123 test-populate-stream-non-addr: +15124 # . prologue +15125 55/push-ebp +15126 89/<- %ebp 4/r32/esp +15127 # setup +15128 (clear-stream _test-input-stream) +15129 (clear-stream $_test-input-buffered-file->buffer) +15130 (clear-stream _test-output-stream) +15131 (clear-stream $_test-output-buffered-file->buffer) +15132 (clear-stream _test-error-stream) +15133 (clear-stream $_test-error-buffered-file->buffer) +15134 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15135 68/push 0/imm32 +15136 68/push 0/imm32 +15137 89/<- %edx 4/r32/esp +15138 (tailor-exit-descriptor %edx 0x10) +15139 # +15140 (write _test-input-stream "fn foo {\n") +15141 (write _test-input-stream " var y: (handle int)\n") +15142 (write _test-input-stream " populate-stream y, 3\n") +15143 (write _test-input-stream "}\n") +15144 # convert +15145 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15146 # registers except esp clobbered at this point +15147 # restore ed +15148 89/<- %edx 4/r32/esp +15149 (flush _test-output-buffered-file) +15150 (flush _test-error-buffered-file) +15151 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15157 # check output +15158 (check-stream-equal _test-output-stream "" "F - test-populate-stream-non-addr: output must be empty") +15159 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)" "F - test-populate-stream-non-addr: error message") +15160 # check that stop(1) was called +15161 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status") +15162 # don't restore from ebp +15163 81 0/subop/add %esp 8/imm32 +15164 # . epilogue +15165 5d/pop-to-ebp +15166 c3/return +15167 +15168 test-populate-stream-non-addr-handle: +15169 # . prologue +15170 55/push-ebp +15171 89/<- %ebp 4/r32/esp +15172 # setup +15173 (clear-stream _test-input-stream) +15174 (clear-stream $_test-input-buffered-file->buffer) +15175 (clear-stream _test-output-stream) +15176 (clear-stream $_test-output-buffered-file->buffer) +15177 (clear-stream _test-error-stream) +15178 (clear-stream $_test-error-buffered-file->buffer) +15179 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15180 68/push 0/imm32 +15181 68/push 0/imm32 +15182 89/<- %edx 4/r32/esp +15183 (tailor-exit-descriptor %edx 0x10) +15184 # +15185 (write _test-input-stream "fn foo {\n") +15186 (write _test-input-stream " var y/ecx: (addr int) <- copy 0\n") +15187 (write _test-input-stream " populate-stream y, 3\n") +15188 (write _test-input-stream "}\n") +15189 # convert +15190 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15191 # registers except esp clobbered at this point +15192 # restore ed +15193 89/<- %edx 4/r32/esp +15194 (flush _test-output-buffered-file) +15195 (flush _test-error-buffered-file) +15196 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15202 # check output +15203 (check-stream-equal _test-output-stream "" "F - test-populate-stream-non-addr-handle: output should be empty") +15204 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)" "F - test-populate-stream-non-addr-handle: error message") +15205 # check that stop(1) was called +15206 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status") +15207 # don't restore from ebp +15208 81 0/subop/add %esp 8/imm32 +15209 # . epilogue +15210 5d/pop-to-ebp +15211 c3/return +15212 +15213 test-populate-stream-non-addr-handle-stream: +15214 # . prologue +15215 55/push-ebp +15216 89/<- %ebp 4/r32/esp +15217 # setup +15218 (clear-stream _test-input-stream) +15219 (clear-stream $_test-input-buffered-file->buffer) +15220 (clear-stream _test-output-stream) +15221 (clear-stream $_test-output-buffered-file->buffer) +15222 (clear-stream _test-error-stream) +15223 (clear-stream $_test-error-buffered-file->buffer) +15224 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15225 68/push 0/imm32 +15226 68/push 0/imm32 +15227 89/<- %edx 4/r32/esp +15228 (tailor-exit-descriptor %edx 0x10) +15229 # +15230 (write _test-input-stream "fn foo {\n") +15231 (write _test-input-stream " var y/ecx: (addr handle int) <- copy 0\n") +15232 (write _test-input-stream " populate-stream y, 3\n") +15233 (write _test-input-stream "}\n") +15234 # convert +15235 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15236 # registers except esp clobbered at this point +15237 # restore ed +15238 89/<- %edx 4/r32/esp +15239 (flush _test-output-buffered-file) +15240 (flush _test-error-buffered-file) +15241 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15247 # check output +15248 (check-stream-equal _test-output-stream "" "F - test-populate-stream-non-addr-handle-stream: output should be empty") +15249 (check-next-stream-line-equal _test-error-stream "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)" "F - test-populate-stream-non-addr-handle-stream: error message") +15250 # check that stop(1) was called +15251 (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status") +15252 # don't restore from ebp +15253 81 0/subop/add %esp 8/imm32 15254 # . epilogue 15255 5d/pop-to-ebp 15256 c3/return 15257 -15258 test-convert-with-no-inout: +15258 test-populate-stream-deref-address: 15259 # . prologue 15260 55/push-ebp 15261 89/<- %ebp 4/r32/esp @@ -13821,178 +13821,178 @@ if ('onhashchange' in window) { 15264 (clear-stream $_test-input-buffered-file->buffer) 15265 (clear-stream _test-output-stream) 15266 (clear-stream $_test-output-buffered-file->buffer) -15267 (clear-stream _test-error-stream) -15268 (clear-stream $_test-error-buffered-file->buffer) -15269 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15270 68/push 0/imm32 -15271 68/push 0/imm32 -15272 89/<- %edx 4/r32/esp -15273 (tailor-exit-descriptor %edx 0x10) -15274 # -15275 (write _test-input-stream "fn foo {\n") -15276 (write _test-input-stream " var x/eax: int <- convert\n") -15277 (write _test-input-stream "}\n") -15278 # convert -15279 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15280 # registers except esp clobbered at this point -15281 # restore ed -15282 89/<- %edx 4/r32/esp -15283 (flush _test-output-buffered-file) -15284 (flush _test-error-buffered-file) -15285 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15291 # check output -15292 (check-stream-equal _test-output-stream "" "F - test-convert-with-no-inout: output should be empty") -15293 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' expects an inout" "F - test-convert-with-no-inout: error message") -15294 # check that stop(1) was called -15295 (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status") -15296 # don't restore from ebp -15297 81 0/subop/add %esp 8/imm32 -15298 # . epilogue -15299 5d/pop-to-ebp -15300 c3/return -15301 -15302 test-convert-with-multiple-inouts: -15303 # . prologue -15304 55/push-ebp -15305 89/<- %ebp 4/r32/esp -15306 # setup -15307 (clear-stream _test-input-stream) -15308 (clear-stream $_test-input-buffered-file->buffer) -15309 (clear-stream _test-output-stream) -15310 (clear-stream $_test-output-buffered-file->buffer) -15311 (clear-stream _test-error-stream) -15312 (clear-stream $_test-error-buffered-file->buffer) -15313 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15314 68/push 0/imm32 -15315 68/push 0/imm32 -15316 89/<- %edx 4/r32/esp -15317 (tailor-exit-descriptor %edx 0x10) -15318 # -15319 (write _test-input-stream "fn foo {\n") -15320 (write _test-input-stream " var x/eax: int <- convert 0, 0\n") -15321 (write _test-input-stream "}\n") -15322 # convert -15323 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15324 # registers except esp clobbered at this point -15325 # restore ed -15326 89/<- %edx 4/r32/esp -15327 (flush _test-output-buffered-file) -15328 (flush _test-error-buffered-file) -15329 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15335 # check output -15336 (check-stream-equal _test-output-stream "" "F - test-convert-with-multiple-inouts: output should be empty") -15337 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' must have just one inout" "F - test-convert-with-multiple-inouts: error message") -15338 # check that stop(1) was called -15339 (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status") -15340 # don't restore from ebp -15341 81 0/subop/add %esp 8/imm32 -15342 # . epilogue -15343 5d/pop-to-ebp -15344 c3/return -15345 -15346 test-convert-with-no-output: -15347 # . prologue -15348 55/push-ebp -15349 89/<- %ebp 4/r32/esp -15350 # setup -15351 (clear-stream _test-input-stream) -15352 (clear-stream $_test-input-buffered-file->buffer) -15353 (clear-stream _test-output-stream) -15354 (clear-stream $_test-output-buffered-file->buffer) -15355 (clear-stream _test-error-stream) -15356 (clear-stream $_test-error-buffered-file->buffer) -15357 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15358 68/push 0/imm32 -15359 68/push 0/imm32 -15360 89/<- %edx 4/r32/esp -15361 (tailor-exit-descriptor %edx 0x10) -15362 # -15363 (write _test-input-stream "fn foo {\n") -15364 (write _test-input-stream " convert 0\n") -15365 (write _test-input-stream "}\n") -15366 # convert -15367 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15368 # registers except esp clobbered at this point -15369 # restore ed -15370 89/<- %edx 4/r32/esp -15371 (flush _test-output-buffered-file) -15372 (flush _test-error-buffered-file) -15373 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15379 # check output -15380 (check-stream-equal _test-output-stream "" "F - test-convert-with-no-output: output should be empty") -15381 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' expects an output" "F - test-convert-with-no-output: error message") -15382 # check that stop(1) was called -15383 (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status") -15384 # don't restore from ebp -15385 81 0/subop/add %esp 8/imm32 -15386 # . epilogue -15387 5d/pop-to-ebp -15388 c3/return -15389 -15390 test-convert-with-multiple-outputs: -15391 # . prologue -15392 55/push-ebp -15393 89/<- %ebp 4/r32/esp -15394 # setup -15395 (clear-stream _test-input-stream) -15396 (clear-stream $_test-input-buffered-file->buffer) -15397 (clear-stream _test-output-stream) -15398 (clear-stream $_test-output-buffered-file->buffer) -15399 (clear-stream _test-error-stream) -15400 (clear-stream $_test-error-buffered-file->buffer) -15401 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15402 68/push 0/imm32 -15403 68/push 0/imm32 -15404 89/<- %edx 4/r32/esp -15405 (tailor-exit-descriptor %edx 0x10) -15406 # -15407 (write _test-input-stream "fn foo {\n") -15408 (write _test-input-stream " var x/eax: int <- copy 0\n") -15409 (write _test-input-stream " var y/ecx: int <- copy 0\n") -15410 (write _test-input-stream " x, y <- convert 0\n") -15411 (write _test-input-stream "}\n") -15412 # convert -15413 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15414 # registers except esp clobbered at this point -15415 # restore ed -15416 89/<- %edx 4/r32/esp -15417 (flush _test-output-buffered-file) -15418 (flush _test-error-buffered-file) -15419 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15425 # check output -15426 (check-stream-equal _test-output-stream "" "F - test-convert-with-multiple-outputs: output should be empty") -15427 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' must have just one output" "F - test-convert-with-multiple-outputs: error message") -15428 # check that stop(1) was called -15429 (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status") -15430 # don't restore from ebp -15431 81 0/subop/add %esp 8/imm32 -15432 # . epilogue -15433 5d/pop-to-ebp -15434 c3/return -15435 -15436 test-convert-deref-address: -15437 # . prologue -15438 55/push-ebp -15439 89/<- %ebp 4/r32/esp -15440 # setup -15441 (clear-stream _test-input-stream) -15442 (clear-stream $_test-input-buffered-file->buffer) -15443 (clear-stream _test-output-stream) -15444 (clear-stream $_test-output-buffered-file->buffer) -15445 # -15446 (write _test-input-stream "fn foo {\n") -15447 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") -15448 (write _test-input-stream " var y/xmm4: float <- convert *x\n") -15449 (write _test-input-stream "}\n") -15450 # convert -15451 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) -15452 (flush _test-output-buffered-file) -15453 # no errors +15267 # +15268 (write _test-input-stream "fn foo {\n") +15269 (write _test-input-stream " var y/ecx: (addr addr handle stream int) <- copy 0\n") +15270 (write _test-input-stream " populate-stream *y, 3\n") +15271 (write _test-input-stream "}\n") +15272 # convert +15273 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +15274 (flush _test-output-buffered-file) +15275 # no errors +15276 # . epilogue +15277 5d/pop-to-ebp +15278 c3/return +15279 +15280 test-convert-with-no-inout: +15281 # . prologue +15282 55/push-ebp +15283 89/<- %ebp 4/r32/esp +15284 # setup +15285 (clear-stream _test-input-stream) +15286 (clear-stream $_test-input-buffered-file->buffer) +15287 (clear-stream _test-output-stream) +15288 (clear-stream $_test-output-buffered-file->buffer) +15289 (clear-stream _test-error-stream) +15290 (clear-stream $_test-error-buffered-file->buffer) +15291 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15292 68/push 0/imm32 +15293 68/push 0/imm32 +15294 89/<- %edx 4/r32/esp +15295 (tailor-exit-descriptor %edx 0x10) +15296 # +15297 (write _test-input-stream "fn foo {\n") +15298 (write _test-input-stream " var x/eax: int <- convert\n") +15299 (write _test-input-stream "}\n") +15300 # convert +15301 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15302 # registers except esp clobbered at this point +15303 # restore ed +15304 89/<- %edx 4/r32/esp +15305 (flush _test-output-buffered-file) +15306 (flush _test-error-buffered-file) +15307 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15313 # check output +15314 (check-stream-equal _test-output-stream "" "F - test-convert-with-no-inout: output should be empty") +15315 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' expects an inout" "F - test-convert-with-no-inout: error message") +15316 # check that stop(1) was called +15317 (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status") +15318 # don't restore from ebp +15319 81 0/subop/add %esp 8/imm32 +15320 # . epilogue +15321 5d/pop-to-ebp +15322 c3/return +15323 +15324 test-convert-with-multiple-inouts: +15325 # . prologue +15326 55/push-ebp +15327 89/<- %ebp 4/r32/esp +15328 # setup +15329 (clear-stream _test-input-stream) +15330 (clear-stream $_test-input-buffered-file->buffer) +15331 (clear-stream _test-output-stream) +15332 (clear-stream $_test-output-buffered-file->buffer) +15333 (clear-stream _test-error-stream) +15334 (clear-stream $_test-error-buffered-file->buffer) +15335 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15336 68/push 0/imm32 +15337 68/push 0/imm32 +15338 89/<- %edx 4/r32/esp +15339 (tailor-exit-descriptor %edx 0x10) +15340 # +15341 (write _test-input-stream "fn foo {\n") +15342 (write _test-input-stream " var x/eax: int <- convert 0, 0\n") +15343 (write _test-input-stream "}\n") +15344 # convert +15345 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15346 # registers except esp clobbered at this point +15347 # restore ed +15348 89/<- %edx 4/r32/esp +15349 (flush _test-output-buffered-file) +15350 (flush _test-error-buffered-file) +15351 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15357 # check output +15358 (check-stream-equal _test-output-stream "" "F - test-convert-with-multiple-inouts: output should be empty") +15359 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' must have just one inout" "F - test-convert-with-multiple-inouts: error message") +15360 # check that stop(1) was called +15361 (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status") +15362 # don't restore from ebp +15363 81 0/subop/add %esp 8/imm32 +15364 # . epilogue +15365 5d/pop-to-ebp +15366 c3/return +15367 +15368 test-convert-with-no-output: +15369 # . prologue +15370 55/push-ebp +15371 89/<- %ebp 4/r32/esp +15372 # setup +15373 (clear-stream _test-input-stream) +15374 (clear-stream $_test-input-buffered-file->buffer) +15375 (clear-stream _test-output-stream) +15376 (clear-stream $_test-output-buffered-file->buffer) +15377 (clear-stream _test-error-stream) +15378 (clear-stream $_test-error-buffered-file->buffer) +15379 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15380 68/push 0/imm32 +15381 68/push 0/imm32 +15382 89/<- %edx 4/r32/esp +15383 (tailor-exit-descriptor %edx 0x10) +15384 # +15385 (write _test-input-stream "fn foo {\n") +15386 (write _test-input-stream " convert 0\n") +15387 (write _test-input-stream "}\n") +15388 # convert +15389 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15390 # registers except esp clobbered at this point +15391 # restore ed +15392 89/<- %edx 4/r32/esp +15393 (flush _test-output-buffered-file) +15394 (flush _test-error-buffered-file) +15395 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15401 # check output +15402 (check-stream-equal _test-output-stream "" "F - test-convert-with-no-output: output should be empty") +15403 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' expects an output" "F - test-convert-with-no-output: error message") +15404 # check that stop(1) was called +15405 (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status") +15406 # don't restore from ebp +15407 81 0/subop/add %esp 8/imm32 +15408 # . epilogue +15409 5d/pop-to-ebp +15410 c3/return +15411 +15412 test-convert-with-multiple-outputs: +15413 # . prologue +15414 55/push-ebp +15415 89/<- %ebp 4/r32/esp +15416 # setup +15417 (clear-stream _test-input-stream) +15418 (clear-stream $_test-input-buffered-file->buffer) +15419 (clear-stream _test-output-stream) +15420 (clear-stream $_test-output-buffered-file->buffer) +15421 (clear-stream _test-error-stream) +15422 (clear-stream $_test-error-buffered-file->buffer) +15423 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15424 68/push 0/imm32 +15425 68/push 0/imm32 +15426 89/<- %edx 4/r32/esp +15427 (tailor-exit-descriptor %edx 0x10) +15428 # +15429 (write _test-input-stream "fn foo {\n") +15430 (write _test-input-stream " var x/eax: int <- copy 0\n") +15431 (write _test-input-stream " var y/ecx: int <- copy 0\n") +15432 (write _test-input-stream " x, y <- convert 0\n") +15433 (write _test-input-stream "}\n") +15434 # convert +15435 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15436 # registers except esp clobbered at this point +15437 # restore ed +15438 89/<- %edx 4/r32/esp +15439 (flush _test-output-buffered-file) +15440 (flush _test-error-buffered-file) +15441 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15447 # check output +15448 (check-stream-equal _test-output-stream "" "F - test-convert-with-multiple-outputs: output should be empty") +15449 (check-next-stream-line-equal _test-error-stream "fn foo: stmt 'convert' must have just one output" "F - test-convert-with-multiple-outputs: error message") +15450 # check that stop(1) was called +15451 (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status") +15452 # don't restore from ebp +15453 81 0/subop/add %esp 8/imm32 15454 # . epilogue 15455 5d/pop-to-ebp 15456 c3/return 15457 -15458 test-convert-to-non-register: +15458 test-convert-deref-address: 15459 # . prologue 15460 55/push-ebp 15461 89/<- %ebp 4/r32/esp @@ -14001,1159 +14001,1159 @@ if ('onhashchange' in window) { 15464 (clear-stream $_test-input-buffered-file->buffer) 15465 (clear-stream _test-output-stream) 15466 (clear-stream $_test-output-buffered-file->buffer) -15467 (clear-stream _test-error-stream) -15468 (clear-stream $_test-error-buffered-file->buffer) -15469 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15470 68/push 0/imm32 -15471 68/push 0/imm32 -15472 89/<- %edx 4/r32/esp -15473 (tailor-exit-descriptor %edx 0x10) -15474 # -15475 (write _test-input-stream "fn foo {\n") -15476 (write _test-input-stream " var x: float\n") -15477 (write _test-input-stream " var y: int\n") -15478 (write _test-input-stream " x <- convert y\n") -15479 (write _test-input-stream "}\n") -15480 # convert -15481 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15482 # registers except esp clobbered at this point -15483 # restore ed -15484 89/<- %edx 4/r32/esp -15485 (flush _test-output-buffered-file) -15486 (flush _test-error-buffered-file) -15487 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15493 # check output -15494 (check-stream-equal _test-output-stream "" "F - test-convert-to-non-register: output should be empty") -15495 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: output 'x' not in a register" "F - test-convert-to-non-register: error message") -15496 # check that stop(1) was called -15497 (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status") -15498 # don't restore from ebp -15499 81 0/subop/add %esp 8/imm32 -15500 # . epilogue -15501 5d/pop-to-ebp -15502 c3/return -15503 -15504 test-convert-invalid-inout-type: -15505 # . prologue -15506 55/push-ebp -15507 89/<- %ebp 4/r32/esp -15508 # setup -15509 (clear-stream _test-input-stream) -15510 (clear-stream $_test-input-buffered-file->buffer) -15511 (clear-stream _test-output-stream) -15512 (clear-stream $_test-output-buffered-file->buffer) -15513 (clear-stream _test-error-stream) -15514 (clear-stream $_test-error-buffered-file->buffer) -15515 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15516 68/push 0/imm32 -15517 68/push 0/imm32 -15518 89/<- %edx 4/r32/esp -15519 (tailor-exit-descriptor %edx 0x10) -15520 # -15521 (write _test-input-stream "fn foo {\n") -15522 (write _test-input-stream " var x: boolean\n") -15523 (write _test-input-stream " var y/xmm1: float <- convert x\n") -15524 (write _test-input-stream "}\n") -15525 # convert -15526 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15527 # registers except esp clobbered at this point -15528 # restore ed -15529 89/<- %edx 4/r32/esp -15530 (flush _test-output-buffered-file) -15531 (flush _test-error-buffered-file) -15532 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15538 # check output -15539 (check-stream-equal _test-output-stream "" "F - test-convert-invalid-inout-type: output should be empty") -15540 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: inout 'x' must be an int or float" "F - test-convert-invalid-inout-type: error message") -15541 # check that stop(1) was called -15542 (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status") -15543 # don't restore from ebp -15544 81 0/subop/add %esp 8/imm32 -15545 # . epilogue -15546 5d/pop-to-ebp -15547 c3/return -15548 -15549 test-convert-invalid-output-type: -15550 # . prologue -15551 55/push-ebp -15552 89/<- %ebp 4/r32/esp -15553 # setup -15554 (clear-stream _test-input-stream) -15555 (clear-stream $_test-input-buffered-file->buffer) -15556 (clear-stream _test-output-stream) -15557 (clear-stream $_test-output-buffered-file->buffer) -15558 (clear-stream _test-error-stream) -15559 (clear-stream $_test-error-buffered-file->buffer) -15560 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15561 68/push 0/imm32 -15562 68/push 0/imm32 -15563 89/<- %edx 4/r32/esp -15564 (tailor-exit-descriptor %edx 0x10) -15565 # -15566 (write _test-input-stream "fn foo {\n") -15567 (write _test-input-stream " var x: float\n") -15568 (write _test-input-stream " var y/eax: boolean <- convert x\n") -15569 (write _test-input-stream "}\n") -15570 # convert -15571 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15572 # registers except esp clobbered at this point -15573 # restore ed -15574 89/<- %edx 4/r32/esp -15575 (flush _test-output-buffered-file) -15576 (flush _test-error-buffered-file) -15577 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15583 # check output -15584 (check-stream-equal _test-output-stream "" "F - test-convert-invalid-output-type: output should be empty") -15585 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: output 'y' must be an int or float" "F - test-convert-invalid-output-type: error message") -15586 # check that stop(1) was called -15587 (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status") -15588 # don't restore from ebp -15589 81 0/subop/add %esp 8/imm32 -15590 # . epilogue -15591 5d/pop-to-ebp -15592 c3/return -15593 -15594 test-convert-int-to-int: -15595 # . prologue -15596 55/push-ebp -15597 89/<- %ebp 4/r32/esp -15598 # setup -15599 (clear-stream _test-input-stream) -15600 (clear-stream $_test-input-buffered-file->buffer) -15601 (clear-stream _test-output-stream) -15602 (clear-stream $_test-output-buffered-file->buffer) -15603 (clear-stream _test-error-stream) -15604 (clear-stream $_test-error-buffered-file->buffer) -15605 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15606 68/push 0/imm32 -15607 68/push 0/imm32 -15608 89/<- %edx 4/r32/esp -15609 (tailor-exit-descriptor %edx 0x10) -15610 # -15611 (write _test-input-stream "fn foo {\n") -15612 (write _test-input-stream " var x: int\n") -15613 (write _test-input-stream " var y/eax: int <- convert x\n") -15614 (write _test-input-stream "}\n") -15615 # convert -15616 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15617 # registers except esp clobbered at this point -15618 # restore ed -15619 89/<- %edx 4/r32/esp -15620 (flush _test-output-buffered-file) -15621 (flush _test-error-buffered-file) -15622 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15628 # check output -15629 (check-stream-equal _test-output-stream "" "F - test-convert-int-to-int: output should be empty") -15630 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: no need to convert int to int" "F - test-convert-int-to-int: error message") -15631 # check that stop(1) was called -15632 (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status") -15633 # don't restore from ebp -15634 81 0/subop/add %esp 8/imm32 -15635 # . epilogue -15636 5d/pop-to-ebp -15637 c3/return -15638 -15639 test-convert-float-to-float: -15640 # . prologue -15641 55/push-ebp -15642 89/<- %ebp 4/r32/esp -15643 # setup -15644 (clear-stream _test-input-stream) -15645 (clear-stream $_test-input-buffered-file->buffer) -15646 (clear-stream _test-output-stream) -15647 (clear-stream $_test-output-buffered-file->buffer) -15648 (clear-stream _test-error-stream) -15649 (clear-stream $_test-error-buffered-file->buffer) -15650 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) -15651 68/push 0/imm32 -15652 68/push 0/imm32 -15653 89/<- %edx 4/r32/esp -15654 (tailor-exit-descriptor %edx 0x10) -15655 # -15656 (write _test-input-stream "fn foo {\n") -15657 (write _test-input-stream " var x: float\n") -15658 (write _test-input-stream " var y/xmm6: float <- convert x\n") -15659 (write _test-input-stream "}\n") -15660 # convert -15661 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) -15662 # registers except esp clobbered at this point -15663 # restore ed -15664 89/<- %edx 4/r32/esp -15665 (flush _test-output-buffered-file) -15666 (flush _test-error-buffered-file) -15667 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ -15673 # check output -15674 (check-stream-equal _test-output-stream "" "F - test-convert-float-to-float: output should be empty") -15675 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: no need to convert float to float" "F - test-convert-float-to-float: error message") -15676 # check that stop(1) was called -15677 (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status") -15678 # don't restore from ebp -15679 81 0/subop/add %esp 8/imm32 -15680 # . epilogue -15681 5d/pop-to-ebp -15682 c3/return -15683 -15684 ####################################################### -15685 # Parsing -15686 ####################################################### -15687 -15688 == data -15689 -15690 # Global state added to each var record when parsing a function -15691 Next-block-index: # (addr int) -15692 1/imm32 -15693 -15694 Curr-block-depth: # (addr int) -15695 1/imm32 -15696 -15697 == code -15698 -15699 parse-mu: # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) -15700 # pseudocode -15701 # var curr-function: (addr handle function) = Program->functions -15702 # var curr-signature: (addr handle function) = Program->signatures -15703 # var curr-type: (addr handle typeinfo) = Program->types -15704 # var line: (stream byte 512) -15705 # var word-slice: slice -15706 # while true # line loop -15707 # clear-stream(line) -15708 # read-line-buffered(in, line) -15709 # if (line->write == 0) break # end of file -15710 # word-slice = next-mu-token(line) -15711 # if slice-empty?(word-slice) # end of line -15712 # continue -15713 # else if slice-starts-with?(word-slice, "#") # comment -15714 # continue # end of line -15715 # else if slice-equal?(word-slice, "fn") -15716 # var new-function: (handle function) = allocate(function) -15717 # var vars: (stack live-var 256) -15718 # populate-mu-function-header(line, new-function, vars) -15719 # populate-mu-function-body(in, new-function, vars) -15720 # assert(vars->top == 0) -15721 # *curr-function = new-function -15722 # curr-function = &new-function->next -15723 # else if slice-equal?(word-slice, "sig") -15724 # var new-function: (handle function) = allocate(function) -15725 # populate-mu-function-signature(line, new-function) -15726 # *curr-signature = new-function -15727 # curr-signature = &new-function->next -15728 # else if slice-equal?(word-slice, "type") -15729 # word-slice = next-mu-token(line) -15730 # type-id = pos-or-insert-slice(Type-id, word-slice) -15731 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) -15732 # assert(next-word(line) == "{") -15733 # populate-mu-type(in, new-type) -15734 # else -15735 # abort() -15736 # -15737 # . prologue -15738 55/push-ebp -15739 89/<- %ebp 4/r32/esp -15740 # var curr-signature: (addr handle function) at *(ebp-4) -15741 68/push _Program-signatures/imm32 -15742 # . save registers -15743 50/push-eax -15744 51/push-ecx -15745 52/push-edx -15746 53/push-ebx -15747 56/push-esi -15748 57/push-edi -15749 # var line/ecx: (stream byte 512) -15750 81 5/subop/subtract %esp 0x200/imm32 -15751 68/push 0x200/imm32/size -15752 68/push 0/imm32/read -15753 68/push 0/imm32/write -15754 89/<- %ecx 4/r32/esp -15755 # var word-slice/edx: slice -15756 68/push 0/imm32/end -15757 68/push 0/imm32/start -15758 89/<- %edx 4/r32/esp -15759 # var curr-function/edi: (addr handle function) -15760 bf/copy-to-edi _Program-functions/imm32 -15761 # var vars/ebx: (stack live-var 256) -15762 81 5/subop/subtract %esp 0xc00/imm32 -15763 68/push 0xc00/imm32/size -15764 68/push 0/imm32/top -15765 89/<- %ebx 4/r32/esp -15766 { -15767 $parse-mu:line-loop: -15768 (clear-stream %ecx) -15769 (read-line-buffered *(ebp+8) %ecx) -15770 # if (line->write == 0) break -15771 81 7/subop/compare *ecx 0/imm32 -15772 0f 84/jump-if-= break/disp32 -15773 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ -15779 (next-mu-token %ecx %edx) -15780 # if slice-empty?(word-slice) continue -15781 (slice-empty? %edx) # => eax -15782 3d/compare-eax-and 0/imm32/false -15783 0f 85/jump-if-!= loop/disp32 -15784 # if (*word-slice->start == "#") continue -15785 # . eax = *word-slice->start -15786 8b/-> *edx 0/r32/eax -15787 8a/copy-byte *eax 0/r32/AL -15788 81 4/subop/and %eax 0xff/imm32 -15789 # . if (eax == '#') continue -15790 3d/compare-eax-and 0x23/imm32/hash -15791 0f 84/jump-if-= loop/disp32 -15792 # if (slice-equal?(word-slice, "fn")) parse a function -15793 { -15794 $parse-mu:fn: -15795 (slice-equal? %edx "fn") # => eax -15796 3d/compare-eax-and 0/imm32/false -15797 0f 84/jump-if-= break/disp32 -15798 # var new-function/esi: (handle function) -15799 68/push 0/imm32 -15800 68/push 0/imm32 -15801 89/<- %esi 4/r32/esp -15802 # populate-mu-function(line, in, vars, new-function) -15803 (allocate Heap *Function-size %esi) -15804 # var new-function-addr/eax: (addr function) -15805 (lookup *esi *(esi+4)) # => eax -15806 # initialize vars -15807 (clear-stack %ebx) -15808 # -15809 (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10)) -15810 (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10)) -15811 # *curr-function = new-function -15812 8b/-> *esi 0/r32/eax -15813 89/<- *edi 0/r32/eax -15814 8b/-> *(esi+4) 0/r32/eax -15815 89/<- *(edi+4) 0/r32/eax -15816 # curr-function = &new-function->next -15817 # . var tmp/eax: (addr function) = lookup(new-function) -15818 (lookup *esi *(esi+4)) # => eax -15819 # . curr-function = &tmp->next -15820 8d/copy-address *(eax+0x20) 7/r32/edi # Function-next -15821 # reclaim new-function -15822 81 0/subop/add %esp 8/imm32 -15823 # -15824 e9/jump $parse-mu:line-loop/disp32 -15825 } -15826 # if (slice-equal?(word-slice, "sig")) parse a function signature -15827 # Function signatures are for providing types to SubX functions. -15828 { -15829 $parse-mu:sig: -15830 (slice-equal? %edx "sig") # => eax -15831 3d/compare-eax-and 0/imm32/false -15832 0f 84/jump-if-= break/disp32 -15833 # edi = curr-function -15834 57/push-edi -15835 8b/-> *(ebp-4) 7/r32/edi -15836 # var new-function/esi: (handle function) -15837 68/push 0/imm32 -15838 68/push 0/imm32 -15839 89/<- %esi 4/r32/esp -15840 # populate-mu-function(line, in, vars, new-function) -15841 (allocate Heap *Function-size %esi) -15842 # var new-function-addr/eax: (addr function) -15843 (lookup *esi *(esi+4)) # => eax -15844 # -15845 (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10)) -15846 # *curr-signature = new-function -15847 8b/-> *esi 0/r32/eax -15848 89/<- *edi 0/r32/eax -15849 8b/-> *(esi+4) 0/r32/eax -15850 89/<- *(edi+4) 0/r32/eax -15851 # curr-signature = &new-function->next -15852 # . var tmp/eax: (addr function) = lookup(new-function) -15853 (lookup *esi *(esi+4)) # => eax -15854 # . curr-function = &tmp->next -15855 8d/copy-address *(eax+0x20) 7/r32/edi # Function-next -15856 # reclaim new-function -15857 81 0/subop/add %esp 8/imm32 -15858 # save curr-function -15859 89/<- *(ebp-4) 7/r32/edi -15860 # restore edi -15861 5f/pop-to-edi -15862 # -15863 e9/jump $parse-mu:line-loop/disp32 -15864 } -15865 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition -15866 { -15867 $parse-mu:type: -15868 (slice-equal? %edx "type") # => eax -15869 3d/compare-eax-and 0/imm32 -15870 0f 84/jump-if-= break/disp32 -15871 (next-mu-token %ecx %edx) -15872 # var type-id/eax: int -15873 (pos-or-insert-slice Type-id %edx) # => eax -15874 # spill -15875 51/push-ecx -15876 # var new-type/ecx: (handle typeinfo) -15877 68/push 0/imm32 -15878 68/push 0/imm32 -15879 89/<- %ecx 4/r32/esp -15880 (find-or-create-typeinfo %eax %ecx) -15881 # -15882 (lookup *ecx *(ecx+4)) # => eax -15883 # TODO: ensure that 'line' has nothing else but '{' -15884 #? (dump-typeinfos "=== aaa\n") -15885 (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10)) # => eax -15886 #? (dump-typeinfos "=== zzz\n") -15887 # reclaim new-type -15888 81 0/subop/add %esp 8/imm32 -15889 # restore -15890 59/pop-to-ecx -15891 e9/jump $parse-mu:line-loop/disp32 -15892 } -15893 # otherwise abort -15894 e9/jump $parse-mu:error1/disp32 -15895 } # end line loop -15896 $parse-mu:end: -15897 # . reclaim locals -15898 81 0/subop/add %esp 0x20c/imm32 # line -15899 81 0/subop/add %esp 0xc08/imm32 # vars -15900 81 0/subop/add %esp 8/imm32 -15901 # . restore registers -15902 5f/pop-to-edi -15903 5e/pop-to-esi -15904 5b/pop-to-ebx -15905 5a/pop-to-edx -15906 59/pop-to-ecx -15907 58/pop-to-eax -15908 # . reclaim local -15909 81 0/subop/add %esp 4/imm32 -15910 # . epilogue -15911 89/<- %esp 5/r32/ebp -15912 5d/pop-to-ebp -15913 c3/return -15914 -15915 $parse-mu:error1: -15916 # error("unexpected top-level command: " word-slice "\n") -15917 (write-buffered *(ebp+0xc) "unexpected top-level command: ") -15918 (write-slice-buffered *(ebp+0xc) %edx) -15919 (write-buffered *(ebp+0xc) "\n") -15920 (flush *(ebp+0xc)) -15921 (stop *(ebp+0x10) 1) -15922 # never gets here -15923 -15924 $parse-mu:error2: -15925 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -15926 (write-int32-hex-buffered *(ebp+0xc) *ebx) -15927 (write-buffered *(ebp+0xc) " vars not reclaimed after fn '") -15928 (write-slice-buffered *(ebp+0xc) *eax) # Function-name -15929 (write-buffered *(ebp+0xc) "'\n") -15930 (flush *(ebp+0xc)) -15931 (stop *(ebp+0x10) 1) -15932 # never gets here -15933 -15934 # scenarios considered: -15935 # ✗ fn foo # no block -15936 # ✓ fn foo { -15937 # ✗ fn foo { { -15938 # ✗ fn foo { } -15939 # ✗ fn foo { } { -15940 # ✗ fn foo x { -15941 # ✗ fn foo x: { -15942 # ✓ fn foo x: int { -15943 # ✓ fn foo x: int { -15944 # ✓ fn foo x: int -> _/eax: int { -15945 # TODO: -15946 # disallow outputs of type `(... addr ...)` -15947 # disallow inputs of type `(... addr ... addr ...)` -15948 populate-mu-function-header: # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor) -15949 # pseudocode: -15950 # var word-slice: slice -15951 # next-mu-token(first-line, word-slice) -15952 # if slice-empty?(word-slice) abort -15953 # assert(word-slice not in '{' '}' '->') -15954 # out->name = slice-to-string(word-slice) -15955 # ## inouts -15956 # while true -15957 # word-slice = next-mu-token(first-line) -15958 # if slice-empty?(word-slice) abort -15959 # if (word-slice == '{') goto done -15960 # if (word-slice == '->') break -15961 # assert(word-slice != '}') -15962 # var v: (handle var) = parse-var-with-type(word-slice, first-line) -15963 # assert(v->register == null) -15964 # # v->block-depth is implicitly 0 -15965 # out->inouts = append(v, out->inouts) -15966 # push(vars, {v, false}) -15967 # ## outputs -15968 # while true -15969 # word-slice = next-mu-token(first-line) -15970 # if slice-empty?(word-slice) abort -15971 # if (word-slice == '{') break -15972 # assert(word-slice not in '}' '->') -15973 # var v: (handle var) = parse-var-with-type(word-slice, first-line) -15974 # assert(v->register != null) -15975 # assert(v->name == "_") -15976 # out->outputs = append(v, out->outputs) -15977 # done: -15978 # -15979 # . prologue -15980 55/push-ebp -15981 89/<- %ebp 4/r32/esp -15982 # . save registers -15983 50/push-eax -15984 51/push-ecx -15985 52/push-edx -15986 53/push-ebx -15987 57/push-edi -15988 # edi = out -15989 8b/-> *(ebp+0xc) 7/r32/edi -15990 # var word-slice/ecx: slice -15991 68/push 0/imm32/end -15992 68/push 0/imm32/start -15993 89/<- %ecx 4/r32/esp -15994 # var v/ebx: (handle var) -15995 68/push 0/imm32 -15996 68/push 0/imm32 -15997 89/<- %ebx 4/r32/esp -15998 # read function name -15999 (next-mu-token *(ebp+8) %ecx) -16000 # error checking -16001 # if slice-empty?(word-slice) abort -16002 (slice-empty? %ecx) # => eax -16003 3d/compare-eax-and 0/imm32/false -16004 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16005 # if (word-slice == '{') abort -16006 (slice-equal? %ecx "{") # => eax -16007 3d/compare-eax-and 0/imm32/false -16008 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16009 # if (word-slice == '->') abort -16010 (slice-equal? %ecx "->") # => eax -16011 3d/compare-eax-and 0/imm32/false -16012 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16013 # if (word-slice == '}') abort -16014 (slice-equal? %ecx "}") # => eax -16015 3d/compare-eax-and 0/imm32/false -16016 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16017 # if word-slice already defined, abort -16018 (function-exists? %ecx) # => eax -16019 3d/compare-eax-and 0/imm32/false -16020 0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32 -16021 # -16022 (slice-starts-with? %ecx "break") # => eax -16023 3d/compare-eax-and 0/imm32/false -16024 0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32 -16025 (slice-starts-with? %ecx "loop") # => eax -16026 3d/compare-eax-and 0/imm32/false -16027 0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32 -16028 (slice-equal? %ecx "lookup") # => eax +15467 # +15468 (write _test-input-stream "fn foo {\n") +15469 (write _test-input-stream " var x/eax: (addr int) <- copy 0\n") +15470 (write _test-input-stream " var y/xmm4: float <- convert *x\n") +15471 (write _test-input-stream "}\n") +15472 # convert +15473 (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) +15474 (flush _test-output-buffered-file) +15475 # no errors +15476 # . epilogue +15477 5d/pop-to-ebp +15478 c3/return +15479 +15480 test-convert-to-non-register: +15481 # . prologue +15482 55/push-ebp +15483 89/<- %ebp 4/r32/esp +15484 # setup +15485 (clear-stream _test-input-stream) +15486 (clear-stream $_test-input-buffered-file->buffer) +15487 (clear-stream _test-output-stream) +15488 (clear-stream $_test-output-buffered-file->buffer) +15489 (clear-stream _test-error-stream) +15490 (clear-stream $_test-error-buffered-file->buffer) +15491 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15492 68/push 0/imm32 +15493 68/push 0/imm32 +15494 89/<- %edx 4/r32/esp +15495 (tailor-exit-descriptor %edx 0x10) +15496 # +15497 (write _test-input-stream "fn foo {\n") +15498 (write _test-input-stream " var x: float\n") +15499 (write _test-input-stream " var y: int\n") +15500 (write _test-input-stream " x <- convert y\n") +15501 (write _test-input-stream "}\n") +15502 # convert +15503 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15504 # registers except esp clobbered at this point +15505 # restore ed +15506 89/<- %edx 4/r32/esp +15507 (flush _test-output-buffered-file) +15508 (flush _test-error-buffered-file) +15509 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15515 # check output +15516 (check-stream-equal _test-output-stream "" "F - test-convert-to-non-register: output should be empty") +15517 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: output 'x' not in a register" "F - test-convert-to-non-register: error message") +15518 # check that stop(1) was called +15519 (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status") +15520 # don't restore from ebp +15521 81 0/subop/add %esp 8/imm32 +15522 # . epilogue +15523 5d/pop-to-ebp +15524 c3/return +15525 +15526 test-convert-invalid-inout-type: +15527 # . prologue +15528 55/push-ebp +15529 89/<- %ebp 4/r32/esp +15530 # setup +15531 (clear-stream _test-input-stream) +15532 (clear-stream $_test-input-buffered-file->buffer) +15533 (clear-stream _test-output-stream) +15534 (clear-stream $_test-output-buffered-file->buffer) +15535 (clear-stream _test-error-stream) +15536 (clear-stream $_test-error-buffered-file->buffer) +15537 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15538 68/push 0/imm32 +15539 68/push 0/imm32 +15540 89/<- %edx 4/r32/esp +15541 (tailor-exit-descriptor %edx 0x10) +15542 # +15543 (write _test-input-stream "fn foo {\n") +15544 (write _test-input-stream " var x: boolean\n") +15545 (write _test-input-stream " var y/xmm1: float <- convert x\n") +15546 (write _test-input-stream "}\n") +15547 # convert +15548 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15549 # registers except esp clobbered at this point +15550 # restore ed +15551 89/<- %edx 4/r32/esp +15552 (flush _test-output-buffered-file) +15553 (flush _test-error-buffered-file) +15554 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15560 # check output +15561 (check-stream-equal _test-output-stream "" "F - test-convert-invalid-inout-type: output should be empty") +15562 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: inout 'x' must be an int or float" "F - test-convert-invalid-inout-type: error message") +15563 # check that stop(1) was called +15564 (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status") +15565 # don't restore from ebp +15566 81 0/subop/add %esp 8/imm32 +15567 # . epilogue +15568 5d/pop-to-ebp +15569 c3/return +15570 +15571 test-convert-invalid-output-type: +15572 # . prologue +15573 55/push-ebp +15574 89/<- %ebp 4/r32/esp +15575 # setup +15576 (clear-stream _test-input-stream) +15577 (clear-stream $_test-input-buffered-file->buffer) +15578 (clear-stream _test-output-stream) +15579 (clear-stream $_test-output-buffered-file->buffer) +15580 (clear-stream _test-error-stream) +15581 (clear-stream $_test-error-buffered-file->buffer) +15582 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15583 68/push 0/imm32 +15584 68/push 0/imm32 +15585 89/<- %edx 4/r32/esp +15586 (tailor-exit-descriptor %edx 0x10) +15587 # +15588 (write _test-input-stream "fn foo {\n") +15589 (write _test-input-stream " var x: float\n") +15590 (write _test-input-stream " var y/eax: boolean <- convert x\n") +15591 (write _test-input-stream "}\n") +15592 # convert +15593 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15594 # registers except esp clobbered at this point +15595 # restore ed +15596 89/<- %edx 4/r32/esp +15597 (flush _test-output-buffered-file) +15598 (flush _test-error-buffered-file) +15599 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15605 # check output +15606 (check-stream-equal _test-output-stream "" "F - test-convert-invalid-output-type: output should be empty") +15607 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: output 'y' must be an int or float" "F - test-convert-invalid-output-type: error message") +15608 # check that stop(1) was called +15609 (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status") +15610 # don't restore from ebp +15611 81 0/subop/add %esp 8/imm32 +15612 # . epilogue +15613 5d/pop-to-ebp +15614 c3/return +15615 +15616 test-convert-int-to-int: +15617 # . prologue +15618 55/push-ebp +15619 89/<- %ebp 4/r32/esp +15620 # setup +15621 (clear-stream _test-input-stream) +15622 (clear-stream $_test-input-buffered-file->buffer) +15623 (clear-stream _test-output-stream) +15624 (clear-stream $_test-output-buffered-file->buffer) +15625 (clear-stream _test-error-stream) +15626 (clear-stream $_test-error-buffered-file->buffer) +15627 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15628 68/push 0/imm32 +15629 68/push 0/imm32 +15630 89/<- %edx 4/r32/esp +15631 (tailor-exit-descriptor %edx 0x10) +15632 # +15633 (write _test-input-stream "fn foo {\n") +15634 (write _test-input-stream " var x: int\n") +15635 (write _test-input-stream " var y/eax: int <- convert x\n") +15636 (write _test-input-stream "}\n") +15637 # convert +15638 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15639 # registers except esp clobbered at this point +15640 # restore ed +15641 89/<- %edx 4/r32/esp +15642 (flush _test-output-buffered-file) +15643 (flush _test-error-buffered-file) +15644 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15650 # check output +15651 (check-stream-equal _test-output-stream "" "F - test-convert-int-to-int: output should be empty") +15652 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: no need to convert int to int" "F - test-convert-int-to-int: error message") +15653 # check that stop(1) was called +15654 (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status") +15655 # don't restore from ebp +15656 81 0/subop/add %esp 8/imm32 +15657 # . epilogue +15658 5d/pop-to-ebp +15659 c3/return +15660 +15661 test-convert-float-to-float: +15662 # . prologue +15663 55/push-ebp +15664 89/<- %ebp 4/r32/esp +15665 # setup +15666 (clear-stream _test-input-stream) +15667 (clear-stream $_test-input-buffered-file->buffer) +15668 (clear-stream _test-output-stream) +15669 (clear-stream $_test-output-buffered-file->buffer) +15670 (clear-stream _test-error-stream) +15671 (clear-stream $_test-error-buffered-file->buffer) +15672 # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) +15673 68/push 0/imm32 +15674 68/push 0/imm32 +15675 89/<- %edx 4/r32/esp +15676 (tailor-exit-descriptor %edx 0x10) +15677 # +15678 (write _test-input-stream "fn foo {\n") +15679 (write _test-input-stream " var x: float\n") +15680 (write _test-input-stream " var y/xmm6: float <- convert x\n") +15681 (write _test-input-stream "}\n") +15682 # convert +15683 (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) +15684 # registers except esp clobbered at this point +15685 # restore ed +15686 89/<- %edx 4/r32/esp +15687 (flush _test-output-buffered-file) +15688 (flush _test-error-buffered-file) +15689 +-- 6 lines: #? # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------ +15695 # check output +15696 (check-stream-equal _test-output-stream "" "F - test-convert-float-to-float: output should be empty") +15697 (check-next-stream-line-equal _test-error-stream "fn foo: stmt convert: no need to convert float to float" "F - test-convert-float-to-float: error message") +15698 # check that stop(1) was called +15699 (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status") +15700 # don't restore from ebp +15701 81 0/subop/add %esp 8/imm32 +15702 # . epilogue +15703 5d/pop-to-ebp +15704 c3/return +15705 +15706 ####################################################### +15707 # Parsing +15708 ####################################################### +15709 +15710 == data +15711 +15712 # Global state added to each var record when parsing a function +15713 Next-block-index: # (addr int) +15714 1/imm32 +15715 +15716 Curr-block-depth: # (addr int) +15717 1/imm32 +15718 +15719 == code +15720 +15721 parse-mu: # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) +15722 # pseudocode +15723 # var curr-function: (addr handle function) = Program->functions +15724 # var curr-signature: (addr handle function) = Program->signatures +15725 # var curr-type: (addr handle typeinfo) = Program->types +15726 # var line: (stream byte 512) +15727 # var word-slice: slice +15728 # while true # line loop +15729 # clear-stream(line) +15730 # read-line-buffered(in, line) +15731 # if (line->write == 0) break # end of file +15732 # word-slice = next-mu-token(line) +15733 # if slice-empty?(word-slice) # end of line +15734 # continue +15735 # else if slice-starts-with?(word-slice, "#") # comment +15736 # continue # end of line +15737 # else if slice-equal?(word-slice, "fn") +15738 # var new-function: (handle function) = allocate(function) +15739 # var vars: (stack live-var 256) +15740 # populate-mu-function-header(line, new-function, vars) +15741 # populate-mu-function-body(in, new-function, vars) +15742 # assert(vars->top == 0) +15743 # *curr-function = new-function +15744 # curr-function = &new-function->next +15745 # else if slice-equal?(word-slice, "sig") +15746 # var new-function: (handle function) = allocate(function) +15747 # populate-mu-function-signature(line, new-function) +15748 # *curr-signature = new-function +15749 # curr-signature = &new-function->next +15750 # else if slice-equal?(word-slice, "type") +15751 # word-slice = next-mu-token(line) +15752 # type-id = pos-or-insert-slice(Type-id, word-slice) +15753 # var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id) +15754 # assert(next-word(line) == "{") +15755 # populate-mu-type(in, new-type) +15756 # else +15757 # abort() +15758 # +15759 # . prologue +15760 55/push-ebp +15761 89/<- %ebp 4/r32/esp +15762 # var curr-signature: (addr handle function) at *(ebp-4) +15763 68/push _Program-signatures/imm32 +15764 # . save registers +15765 50/push-eax +15766 51/push-ecx +15767 52/push-edx +15768 53/push-ebx +15769 56/push-esi +15770 57/push-edi +15771 # var line/ecx: (stream byte 512) +15772 81 5/subop/subtract %esp 0x200/imm32 +15773 68/push 0x200/imm32/size +15774 68/push 0/imm32/read +15775 68/push 0/imm32/write +15776 89/<- %ecx 4/r32/esp +15777 # var word-slice/edx: slice +15778 68/push 0/imm32/end +15779 68/push 0/imm32/start +15780 89/<- %edx 4/r32/esp +15781 # var curr-function/edi: (addr handle function) +15782 bf/copy-to-edi _Program-functions/imm32 +15783 # var vars/ebx: (stack live-var 256) +15784 81 5/subop/subtract %esp 0xc00/imm32 +15785 68/push 0xc00/imm32/size +15786 68/push 0/imm32/top +15787 89/<- %ebx 4/r32/esp +15788 { +15789 $parse-mu:line-loop: +15790 (clear-stream %ecx) +15791 (read-line-buffered *(ebp+8) %ecx) +15792 # if (line->write == 0) break +15793 81 7/subop/compare *ecx 0/imm32 +15794 0f 84/jump-if-= break/disp32 +15795 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +15801 (next-mu-token %ecx %edx) +15802 # if slice-empty?(word-slice) continue +15803 (slice-empty? %edx) # => eax +15804 3d/compare-eax-and 0/imm32/false +15805 0f 85/jump-if-!= loop/disp32 +15806 # if (*word-slice->start == "#") continue +15807 # . eax = *word-slice->start +15808 8b/-> *edx 0/r32/eax +15809 8a/copy-byte *eax 0/r32/AL +15810 25/and-eax-with 0xff/imm32 +15811 # . if (eax == '#') continue +15812 3d/compare-eax-and 0x23/imm32/hash +15813 0f 84/jump-if-= loop/disp32 +15814 # if (slice-equal?(word-slice, "fn")) parse a function +15815 { +15816 $parse-mu:fn: +15817 (slice-equal? %edx "fn") # => eax +15818 3d/compare-eax-and 0/imm32/false +15819 0f 84/jump-if-= break/disp32 +15820 # var new-function/esi: (handle function) +15821 68/push 0/imm32 +15822 68/push 0/imm32 +15823 89/<- %esi 4/r32/esp +15824 # populate-mu-function(line, in, vars, new-function) +15825 (allocate Heap *Function-size %esi) +15826 # var new-function-addr/eax: (addr function) +15827 (lookup *esi *(esi+4)) # => eax +15828 # initialize vars +15829 (clear-stack %ebx) +15830 # +15831 (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10)) +15832 (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10)) +15833 # *curr-function = new-function +15834 8b/-> *esi 0/r32/eax +15835 89/<- *edi 0/r32/eax +15836 8b/-> *(esi+4) 0/r32/eax +15837 89/<- *(edi+4) 0/r32/eax +15838 # curr-function = &new-function->next +15839 # . var tmp/eax: (addr function) = lookup(new-function) +15840 (lookup *esi *(esi+4)) # => eax +15841 # . curr-function = &tmp->next +15842 8d/copy-address *(eax+0x20) 7/r32/edi # Function-next +15843 # reclaim new-function +15844 81 0/subop/add %esp 8/imm32 +15845 # +15846 e9/jump $parse-mu:line-loop/disp32 +15847 } +15848 # if (slice-equal?(word-slice, "sig")) parse a function signature +15849 # Function signatures are for providing types to SubX functions. +15850 { +15851 $parse-mu:sig: +15852 (slice-equal? %edx "sig") # => eax +15853 3d/compare-eax-and 0/imm32/false +15854 0f 84/jump-if-= break/disp32 +15855 # edi = curr-function +15856 57/push-edi +15857 8b/-> *(ebp-4) 7/r32/edi +15858 # var new-function/esi: (handle function) +15859 68/push 0/imm32 +15860 68/push 0/imm32 +15861 89/<- %esi 4/r32/esp +15862 # populate-mu-function(line, in, vars, new-function) +15863 (allocate Heap *Function-size %esi) +15864 # var new-function-addr/eax: (addr function) +15865 (lookup *esi *(esi+4)) # => eax +15866 # +15867 (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10)) +15868 # *curr-signature = new-function +15869 8b/-> *esi 0/r32/eax +15870 89/<- *edi 0/r32/eax +15871 8b/-> *(esi+4) 0/r32/eax +15872 89/<- *(edi+4) 0/r32/eax +15873 # curr-signature = &new-function->next +15874 # . var tmp/eax: (addr function) = lookup(new-function) +15875 (lookup *esi *(esi+4)) # => eax +15876 # . curr-function = &tmp->next +15877 8d/copy-address *(eax+0x20) 7/r32/edi # Function-next +15878 # reclaim new-function +15879 81 0/subop/add %esp 8/imm32 +15880 # save curr-function +15881 89/<- *(ebp-4) 7/r32/edi +15882 # restore edi +15883 5f/pop-to-edi +15884 # +15885 e9/jump $parse-mu:line-loop/disp32 +15886 } +15887 # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition +15888 { +15889 $parse-mu:type: +15890 (slice-equal? %edx "type") # => eax +15891 3d/compare-eax-and 0/imm32 +15892 0f 84/jump-if-= break/disp32 +15893 (next-mu-token %ecx %edx) +15894 # var type-id/eax: int +15895 (pos-or-insert-slice Type-id %edx) # => eax +15896 # spill +15897 51/push-ecx +15898 # var new-type/ecx: (handle typeinfo) +15899 68/push 0/imm32 +15900 68/push 0/imm32 +15901 89/<- %ecx 4/r32/esp +15902 (find-or-create-typeinfo %eax %ecx) +15903 # +15904 (lookup *ecx *(ecx+4)) # => eax +15905 # TODO: ensure that 'line' has nothing else but '{' +15906 #? (dump-typeinfos "=== aaa\n") +15907 (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10)) # => eax +15908 #? (dump-typeinfos "=== zzz\n") +15909 # reclaim new-type +15910 81 0/subop/add %esp 8/imm32 +15911 # restore +15912 59/pop-to-ecx +15913 e9/jump $parse-mu:line-loop/disp32 +15914 } +15915 # otherwise abort +15916 e9/jump $parse-mu:error1/disp32 +15917 } # end line loop +15918 $parse-mu:end: +15919 # . reclaim locals +15920 81 0/subop/add %esp 0x20c/imm32 # line +15921 81 0/subop/add %esp 0xc08/imm32 # vars +15922 81 0/subop/add %esp 8/imm32 +15923 # . restore registers +15924 5f/pop-to-edi +15925 5e/pop-to-esi +15926 5b/pop-to-ebx +15927 5a/pop-to-edx +15928 59/pop-to-ecx +15929 58/pop-to-eax +15930 # . reclaim local +15931 81 0/subop/add %esp 4/imm32 +15932 # . epilogue +15933 89/<- %esp 5/r32/ebp +15934 5d/pop-to-ebp +15935 c3/return +15936 +15937 $parse-mu:error1: +15938 # error("unexpected top-level command: " word-slice "\n") +15939 (write-buffered *(ebp+0xc) "unexpected top-level command: ") +15940 (write-slice-buffered *(ebp+0xc) %edx) +15941 (write-buffered *(ebp+0xc) "\n") +15942 (flush *(ebp+0xc)) +15943 (stop *(ebp+0x10) 1) +15944 # never gets here +15945 +15946 $parse-mu:error2: +15947 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") +15948 (write-int32-hex-buffered *(ebp+0xc) *ebx) +15949 (write-buffered *(ebp+0xc) " vars not reclaimed after fn '") +15950 (write-slice-buffered *(ebp+0xc) *eax) # Function-name +15951 (write-buffered *(ebp+0xc) "'\n") +15952 (flush *(ebp+0xc)) +15953 (stop *(ebp+0x10) 1) +15954 # never gets here +15955 +15956 # scenarios considered: +15957 # ✗ fn foo # no block +15958 # ✓ fn foo { +15959 # ✗ fn foo { { +15960 # ✗ fn foo { } +15961 # ✗ fn foo { } { +15962 # ✗ fn foo x { +15963 # ✗ fn foo x: { +15964 # ✓ fn foo x: int { +15965 # ✓ fn foo x: int { +15966 # ✓ fn foo x: int -> _/eax: int { +15967 # TODO: +15968 # disallow outputs of type `(... addr ...)` +15969 # disallow inputs of type `(... addr ... addr ...)` +15970 populate-mu-function-header: # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor) +15971 # pseudocode: +15972 # var word-slice: slice +15973 # next-mu-token(first-line, word-slice) +15974 # if slice-empty?(word-slice) abort +15975 # assert(word-slice not in '{' '}' '->') +15976 # out->name = slice-to-string(word-slice) +15977 # ## inouts +15978 # while true +15979 # word-slice = next-mu-token(first-line) +15980 # if slice-empty?(word-slice) abort +15981 # if (word-slice == '{') goto done +15982 # if (word-slice == '->') break +15983 # assert(word-slice != '}') +15984 # var v: (handle var) = parse-var-with-type(word-slice, first-line) +15985 # assert(v->register == null) +15986 # # v->block-depth is implicitly 0 +15987 # out->inouts = append(v, out->inouts) +15988 # push(vars, {v, false}) +15989 # ## outputs +15990 # while true +15991 # word-slice = next-mu-token(first-line) +15992 # if slice-empty?(word-slice) abort +15993 # if (word-slice == '{') break +15994 # assert(word-slice not in '}' '->') +15995 # var v: (handle var) = parse-var-with-type(word-slice, first-line) +15996 # assert(v->register != null) +15997 # assert(v->name == "_") +15998 # out->outputs = append(v, out->outputs) +15999 # done: +16000 # +16001 # . prologue +16002 55/push-ebp +16003 89/<- %ebp 4/r32/esp +16004 # . save registers +16005 50/push-eax +16006 51/push-ecx +16007 52/push-edx +16008 53/push-ebx +16009 57/push-edi +16010 # edi = out +16011 8b/-> *(ebp+0xc) 7/r32/edi +16012 # var word-slice/ecx: slice +16013 68/push 0/imm32/end +16014 68/push 0/imm32/start +16015 89/<- %ecx 4/r32/esp +16016 # var v/ebx: (handle var) +16017 68/push 0/imm32 +16018 68/push 0/imm32 +16019 89/<- %ebx 4/r32/esp +16020 # read function name +16021 (next-mu-token *(ebp+8) %ecx) +16022 # error checking +16023 # if slice-empty?(word-slice) abort +16024 (slice-empty? %ecx) # => eax +16025 3d/compare-eax-and 0/imm32/false +16026 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16027 # if (word-slice == '{') abort +16028 (slice-equal? %ecx "{") # => eax 16029 3d/compare-eax-and 0/imm32/false -16030 0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32 -16031 # save function name -16032 (slice-to-string Heap %ecx %edi) # Function-name -16033 # save function inouts -16034 { -16035 $populate-mu-function-header:check-for-inout: -16036 (next-mu-token *(ebp+8) %ecx) -16037 # if slice-empty?(word-slice) abort -16038 (slice-empty? %ecx) # => eax -16039 3d/compare-eax-and 0/imm32/false -16040 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16041 # if (word-slice == '{') goto done -16042 (slice-equal? %ecx "{") # => eax -16043 3d/compare-eax-and 0/imm32/false -16044 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -16045 # if (word-slice == '->') break -16046 (slice-equal? %ecx "->") # => eax -16047 3d/compare-eax-and 0/imm32/false -16048 0f 85/jump-if-!= break/disp32 -16049 # if (word-slice == '}') abort -16050 (slice-equal? %ecx "}") # => eax -16051 3d/compare-eax-and 0/imm32/false -16052 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16053 # v = parse-var-with-type(word-slice, first-line) -16054 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16055 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18)) -16056 # if (v->register != null) abort -16057 # . eax: (addr var) = lookup(v) -16058 (lookup *ebx *(ebx+4)) # => eax -16059 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -16060 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -16061 # if function name is not "main" -16062 # and v->type contains an 'addr' anywhere except the start, abort -16063 { -16064 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16065 (string-equal? %eax "main") # => eax -16066 3d/compare-eax-and 0/imm32/false -16067 75/jump-if-!= break/disp8 -16068 (lookup *ebx *(ebx+4)) # => eax -16069 (addr-payload-contains-addr? %eax) # => eax -16070 3d/compare-eax-and 0/imm32/false -16071 0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32 -16072 } -16073 # v->block-depth is implicitly 0 -16074 # -16075 # out->inouts = append(v, out->inouts) -16076 8d/copy-address *(edi+8) 0/r32/eax # Function-inouts -16077 (append-list Heap *ebx *(ebx+4) *(edi+8) *(edi+0xc) %eax) # Function-inouts, Function-inouts -16078 # push(vars, {v, false}) -16079 (push *(ebp+0x10) *ebx) -16080 (push *(ebp+0x10) *(ebx+4)) -16081 (push *(ebp+0x10) 0) # false -16082 # -16083 e9/jump loop/disp32 -16084 } -16085 # save function outputs -16086 { -16087 $populate-mu-function-header:check-for-out: -16088 (next-mu-token *(ebp+8) %ecx) -16089 # if slice-empty?(word-slice) abort -16090 (slice-empty? %ecx) # => eax -16091 3d/compare-eax-and 0/imm32/false -16092 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16093 # if (word-slice == '{') break -16094 (slice-equal? %ecx "{") # => eax -16095 3d/compare-eax-and 0/imm32/false -16096 0f 85/jump-if-!= break/disp32 -16097 # if (word-slice == '->') abort -16098 (slice-equal? %ecx "->") # => eax -16099 3d/compare-eax-and 0/imm32/false -16100 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16101 # if (word-slice == '}') abort -16102 (slice-equal? %ecx "}") # => eax -16103 3d/compare-eax-and 0/imm32/false -16104 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -16105 # v = parse-var-with-type(word-slice, first-line) -16106 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16107 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18)) -16108 # assert(var->register != null) -16109 # . eax: (addr var) = lookup(v) -16110 (lookup *ebx *(ebx+4)) # => eax -16111 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -16112 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -16113 # if (var->name != "_") abort -16114 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16115 (string-equal? %eax "_") # => eax -16116 3d/compare-eax-and 0/imm32/false -16117 0f 84/jump-if-= $populate-mu-function-header:error4/disp32 -16118 # if v->type is an addr, abort -16119 (lookup *ebx *(ebx+4)) # => eax -16120 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -16121 (mu-addr-type? %eax) # => eax -16122 3d/compare-eax-and 0/imm32/false -16123 0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32 -16124 # out->outputs = append(v, out->outputs) -16125 8d/copy-address *(edi+0x10) 0/r32/eax # Function-outputs -16126 (append-list Heap *ebx *(ebx+4) *(edi+0x10) *(edi+0x14) %eax) # Function-outputs, Function-outputs -16127 # -16128 e9/jump loop/disp32 -16129 } -16130 $populate-mu-function-header:done: -16131 (check-no-tokens-left *(ebp+8)) -16132 $populate-mu-function-header:end: -16133 # . reclaim locals -16134 81 0/subop/add %esp 0x10/imm32 -16135 # . restore registers -16136 5f/pop-to-edi -16137 5b/pop-to-ebx -16138 5a/pop-to-edx -16139 59/pop-to-ecx -16140 58/pop-to-eax -16141 # . epilogue -16142 89/<- %esp 5/r32/ebp -16143 5d/pop-to-ebp -16144 c3/return -16145 -16146 $populate-mu-function-header:error1: -16147 # error("function header not in form 'fn <name> {'") -16148 (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -16149 (flush *(ebp+0x14)) -16150 (rewind-stream *(ebp+8)) -16151 (write-stream-data *(ebp+0x14) *(ebp+8)) -16152 (write-buffered *(ebp+0x14) "'\n") -16153 (flush *(ebp+0x14)) -16154 (stop *(ebp+0x18) 1) -16155 # never gets here -16156 -16157 $populate-mu-function-header:error2: -16158 # error("fn " fn ": function inout '" var "' cannot be in a register") -16159 (write-buffered *(ebp+0x14) "fn ") -16160 50/push-eax -16161 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16162 (write-buffered *(ebp+0x14) %eax) -16163 58/pop-to-eax -16164 (write-buffered *(ebp+0x14) ": function inout '") -16165 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16166 (write-buffered *(ebp+0x14) %eax) -16167 (write-buffered *(ebp+0x14) "' cannot be in a register") -16168 (flush *(ebp+0x14)) -16169 (stop *(ebp+0x18) 1) -16170 # never gets here -16171 -16172 $populate-mu-function-header:error3: -16173 # error("fn " fn ": function output '" var "' must be in a register") -16174 (write-buffered *(ebp+0x14) "fn ") -16175 50/push-eax -16176 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16177 (write-buffered *(ebp+0x14) %eax) -16178 58/pop-to-eax -16179 (write-buffered *(ebp+0x14) ": function output '") -16180 (lookup *ebx *(ebx+4)) # => eax -16181 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16182 (write-buffered *(ebp+0x14) %eax) -16183 (write-buffered *(ebp+0x14) "' must be in a register, in instruction '") -16184 (rewind-stream *(ebp+8)) -16185 (write-stream-data *(ebp+0x14) *(ebp+8)) -16186 (write-buffered *(ebp+0x14) "'\n") -16187 (flush *(ebp+0x14)) -16188 (stop *(ebp+0x18) 1) -16189 # never gets here -16190 -16191 $populate-mu-function-header:error4: -16192 # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'") -16193 (write-buffered *(ebp+0x14) "fn ") -16194 50/push-eax -16195 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16196 (write-buffered *(ebp+0x14) %eax) -16197 58/pop-to-eax -16198 (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '") -16199 (lookup *ebx *(ebx+4)) # => eax -16200 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16201 (write-buffered *(ebp+0x14) %eax) -16202 (write-buffered *(ebp+0x14) "' in the header to '_'\n") -16203 (flush *(ebp+0x14)) -16204 (stop *(ebp+0x18) 1) -16205 # never gets here -16206 -16207 $populate-mu-function-header:error-duplicate: -16208 (write-buffered *(ebp+0x14) "fn ") -16209 (write-slice-buffered *(ebp+0x14) %ecx) -16210 (write-buffered *(ebp+0x14) " defined more than once\n") -16211 (flush *(ebp+0x14)) -16212 (stop *(ebp+0x18) 1) -16213 # never gets here -16214 -16215 $populate-mu-function-header:error-break: -16216 (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n") -16217 (flush *(ebp+0x14)) -16218 (stop *(ebp+0x18) 1) -16219 # never gets here -16220 -16221 $populate-mu-function-header:error-loop: -16222 (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n") -16223 (flush *(ebp+0x14)) -16224 (stop *(ebp+0x18) 1) -16225 # never gets here -16226 -16227 $populate-mu-function-header:error-lookup: -16228 (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n") -16229 (flush *(ebp+0x14)) -16230 (stop *(ebp+0x18) 1) -16231 # never gets here -16232 -16233 $populate-mu-function-header:error-addr-output: -16234 # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function") -16235 (write-buffered *(ebp+0x14) "fn ") -16236 50/push-eax -16237 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16238 (write-buffered *(ebp+0x14) %eax) -16239 58/pop-to-eax -16240 (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n") -16241 (flush *(ebp+0x14)) -16242 (stop *(ebp+0x18) 1) -16243 # never gets here -16244 -16245 $populate-mu-function-header:error-nested-addr-inout: -16246 # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function") -16247 (write-buffered *(ebp+0x14) "fn ") -16248 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16249 (write-buffered *(ebp+0x14) %eax) -16250 (write-buffered *(ebp+0x14) ": inout '") -16251 (lookup *ebx *(ebx+4)) # => eax -16252 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16253 (write-buffered *(ebp+0x14) %eax) -16254 (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n") -16255 (flush *(ebp+0x14)) -16256 (stop *(ebp+0x18) 1) -16257 # never gets here -16258 -16259 # scenarios considered: -16260 # ✓ fn foo -16261 # ✗ fn foo { -16262 # ✓ fn foo x -16263 # ✓ fn foo x: int -16264 # ✓ fn foo x: int -> _/eax: int -16265 # TODO: -16266 # disallow outputs of type `(... addr ...)` -16267 # disallow inputs of type `(... addr ... addr ...)` -16268 populate-mu-function-signature: # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -16269 # pseudocode: -16270 # var word-slice: slice -16271 # next-mu-token(first-line, word-slice) -16272 # assert(word-slice not in '{' '}' '->') -16273 # out->name = slice-to-string(word-slice) -16274 # ## inouts -16275 # while true -16276 # word-slice = next-mu-token(first-line) -16277 # if slice-empty?(word-slice) break -16278 # if (word-slice == '->') break -16279 # assert(word-slice not in '{' '}') -16280 # var v: (handle var) = parse-var-with-type(word-slice, first-line) -16281 # assert(v->register == null) -16282 # # v->block-depth is implicitly 0 -16283 # out->inouts = append(v, out->inouts) -16284 # ## outputs -16285 # while true -16286 # word-slice = next-mu-token(first-line) -16287 # if slice-empty?(word-slice) break -16288 # assert(word-slice not in '{' '}' '->') -16289 # var v: (handle var) = parse-var-with-type(word-slice, first-line) -16290 # assert(v->register != null) -16291 # out->outputs = append(v, out->outputs) -16292 # -16293 # . prologue -16294 55/push-ebp -16295 89/<- %ebp 4/r32/esp -16296 # . save registers -16297 50/push-eax -16298 51/push-ecx -16299 52/push-edx -16300 53/push-ebx -16301 57/push-edi -16302 # edi = out -16303 8b/-> *(ebp+0xc) 7/r32/edi -16304 # var word-slice/ecx: slice -16305 68/push 0/imm32/end -16306 68/push 0/imm32/start -16307 89/<- %ecx 4/r32/esp -16308 # var v/ebx: (handle var) -16309 68/push 0/imm32 -16310 68/push 0/imm32 -16311 89/<- %ebx 4/r32/esp -16312 # read function name -16313 (next-mu-token *(ebp+8) %ecx) -16314 # error checking -16315 # if (word-slice == '{') abort -16316 (slice-equal? %ecx "{") # => eax -16317 3d/compare-eax-and 0/imm32/false -16318 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16319 # if (word-slice == '->') abort -16320 (slice-equal? %ecx "->") # => eax -16321 3d/compare-eax-and 0/imm32/false -16322 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16323 # if (word-slice == '}') abort -16324 (slice-equal? %ecx "}") # => eax -16325 3d/compare-eax-and 0/imm32/false -16326 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16327 # if word-slice already defined, abort -16328 (function-exists? %ecx) # => eax -16329 3d/compare-eax-and 0/imm32/false -16330 0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32 -16331 # -16332 (slice-starts-with? %ecx "break") # => eax -16333 3d/compare-eax-and 0/imm32/false -16334 0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32 -16335 (slice-starts-with? %ecx "loop") # => eax -16336 3d/compare-eax-and 0/imm32/false -16337 0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32 -16338 # save function name -16339 (slice-to-string Heap %ecx %edi) # Function-name -16340 # save function inouts -16341 { -16342 $populate-mu-function-signature:check-for-inout: -16343 (next-mu-token *(ebp+8) %ecx) -16344 (slice-empty? %ecx) # => eax -16345 3d/compare-eax-and 0/imm32/false -16346 0f 85/jump-if-!= break/disp32 -16347 # if (word-slice == '->') break -16348 (slice-equal? %ecx "->") # => eax -16349 3d/compare-eax-and 0/imm32/false -16350 0f 85/jump-if-!= break/disp32 -16351 # if (word-slice == '{') abort -16352 (slice-equal? %ecx "{") # => eax -16353 3d/compare-eax-and 0/imm32/false -16354 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16355 # if (word-slice == '}') abort -16356 (slice-equal? %ecx "}") # => eax -16357 3d/compare-eax-and 0/imm32/false -16358 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16359 # v = parse-var-with-type(word-slice, first-line) -16360 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16361 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14)) -16362 # if (v->register != null) abort -16363 # . eax: (addr var) = lookup(v) -16364 (lookup *ebx *(ebx+4)) # => eax -16365 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -16366 0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32 -16367 # if function name is not "main" -16368 # and v->type contains an 'addr' anywhere except the start, abort -16369 { -16370 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16371 (string-equal? %eax "main") # => eax -16372 3d/compare-eax-and 0/imm32/false -16373 75/jump-if-!= break/disp8 -16374 (lookup *ebx *(ebx+4)) # => eax -16375 (addr-payload-contains-addr? %eax) # => eax -16376 3d/compare-eax-and 0/imm32/false -16377 0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32 -16378 } -16379 # assert(v->register == null) -16380 # . eax: (addr var) = lookup(v) -16381 (lookup *ebx *(ebx+4)) # => eax -16382 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -16383 0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32 -16384 # v->block-depth is implicitly 0 -16385 # -16386 # out->inouts = append(v, out->inouts) -16387 8d/copy-address *(edi+8) 0/r32/eax # Function-inouts -16388 (append-list Heap *ebx *(ebx+4) *(edi+8) *(edi+0xc) %eax) # Function-inouts, Function-inouts -16389 # -16390 e9/jump loop/disp32 -16391 } -16392 # save function outputs -16393 { -16394 $populate-mu-function-signature:check-for-out: -16395 (next-mu-token *(ebp+8) %ecx) -16396 (slice-empty? %ecx) # => eax -16397 3d/compare-eax-and 0/imm32/false -16398 0f 85/jump-if-!= break/disp32 -16399 # if (word-slice == '{') abort -16400 (slice-equal? %ecx "{") # => eax -16401 3d/compare-eax-and 0/imm32/false -16402 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16403 # if (word-slice == '->') abort -16404 (slice-equal? %ecx "->") # => eax -16405 3d/compare-eax-and 0/imm32/false -16406 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16407 # if (word-slice == '}') abort -16408 (slice-equal? %ecx "}") # => eax -16409 3d/compare-eax-and 0/imm32/false -16410 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 -16411 # v = parse-var-with-type(word-slice, first-line) -16412 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16413 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14)) -16414 # assert(var->register != null) -16415 # . eax: (addr var) = lookup(v) -16416 (lookup *ebx *(ebx+4)) # => eax -16417 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -16418 0f 84/jump-if-= $populate-mu-function-signature:error3/disp32 -16419 # if (var->name != "_") abort -16420 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16421 (string-equal? %eax "_") # => eax -16422 3d/compare-eax-and 0/imm32/false -16423 0f 84/jump-if-= $populate-mu-function-signature:error4/disp32 -16424 # if function name is not "lookup" -16425 # and v->type is an addr, abort -16426 { -16427 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16428 (string-equal? %eax "lookup") # => eax -16429 3d/compare-eax-and 0/imm32/false -16430 75/jump-if-!= break/disp8 -16431 (lookup *ebx *(ebx+4)) # => eax -16432 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -16433 (mu-addr-type? %eax) # => eax -16434 3d/compare-eax-and 0/imm32/false -16435 0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32 -16436 } -16437 # out->outputs = append(v, out->outputs) -16438 8d/copy-address *(edi+0x10) 0/r32/eax # Function-outputs -16439 (append-list Heap *ebx *(ebx+4) *(edi+0x10) *(edi+0x14) %eax) # Function-outputs, Function-outputs -16440 # -16441 e9/jump loop/disp32 -16442 } -16443 $populate-mu-function-signature:done: -16444 (check-no-tokens-left *(ebp+8)) -16445 $populate-mu-function-signature:end: -16446 # . reclaim locals -16447 81 0/subop/add %esp 0x10/imm32 -16448 # . restore registers -16449 5f/pop-to-edi -16450 5b/pop-to-ebx -16451 5a/pop-to-edx -16452 59/pop-to-ecx -16453 58/pop-to-eax -16454 # . epilogue -16455 89/<- %esp 5/r32/ebp -16456 5d/pop-to-ebp -16457 c3/return -16458 -16459 $populate-mu-function-signature:error1: -16460 # error("function signature not in form 'fn <name> {'") -16461 (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '") -16462 (flush *(ebp+0x10)) -16463 (rewind-stream *(ebp+8)) -16464 (write-stream-data *(ebp+0x10) *(ebp+8)) -16465 (write-buffered *(ebp+0x10) "'\n") -16466 (flush *(ebp+0x10)) -16467 (stop *(ebp+0x14) 1) -16468 # never gets here -16469 -16470 $populate-mu-function-signature:error2: -16471 # error("fn " fn ": function inout '" var "' cannot be in a register") -16472 (write-buffered *(ebp+0x10) "fn ") -16473 50/push-eax -16474 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16475 (write-buffered *(ebp+0x10) %eax) -16476 58/pop-to-eax -16477 (write-buffered *(ebp+0x10) ": function inout '") -16478 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16479 (write-buffered *(ebp+0x10) %eax) -16480 (write-buffered *(ebp+0x10) "' cannot be in a register") -16481 (flush *(ebp+0x10)) -16482 (stop *(ebp+0x14) 1) -16483 # never gets here -16484 -16485 $populate-mu-function-signature:error3: -16486 # error("fn " fn ": function output '" var "' must be in a register") -16487 (write-buffered *(ebp+0x10) "fn ") -16488 50/push-eax -16489 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16490 (write-buffered *(ebp+0x10) %eax) -16491 58/pop-to-eax -16492 (write-buffered *(ebp+0x10) ": function output '") -16493 (lookup *ebx *(ebx+4)) # => eax -16494 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16495 (write-buffered *(ebp+0x10) %eax) -16496 (write-buffered *(ebp+0x10) "' must be in a register, in instruction '") -16497 (rewind-stream *(ebp+8)) -16498 (write-stream-data *(ebp+0x10) *(ebp+8)) -16499 (write-buffered *(ebp+0x10) "'\n") -16500 (flush *(ebp+0x10)) -16501 (stop *(ebp+0x14) 1) -16502 # never gets here -16503 -16504 $populate-mu-function-signature:error4: -16505 # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'") -16506 (write-buffered *(ebp+0x10) "fn ") -16507 50/push-eax -16508 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16509 (write-buffered *(ebp+0x10) %eax) -16510 58/pop-to-eax -16511 (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '") -16512 (lookup *ebx *(ebx+4)) # => eax -16513 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16514 (write-buffered *(ebp+0x10) %eax) -16515 (write-buffered *(ebp+0x10) "' in the header to '_'\n") -16516 (flush *(ebp+0x10)) -16517 (stop *(ebp+0x14) 1) -16518 # never gets here -16519 -16520 $populate-mu-function-signature:error-duplicate: -16521 (write-buffered *(ebp+0x10) "fn ") -16522 (write-slice-buffered *(ebp+0x10) %ecx) -16523 (write-buffered *(ebp+0x10) " defined more than once\n") -16524 (flush *(ebp+0x10)) -16525 (stop *(ebp+0x14) 1) -16526 # never gets here -16527 -16528 $populate-mu-function-signature:error-break: -16529 (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n") -16530 (flush *(ebp+0x10)) -16531 (stop *(ebp+0x14) 1) -16532 # never gets here -16533 -16534 $populate-mu-function-signature:error-loop: -16535 (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n") -16536 (flush *(ebp+0x10)) -16537 (stop *(ebp+0x14) 1) -16538 # never gets here -16539 -16540 $populate-mu-function-signature:error-addr-output: -16541 # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function") -16542 (write-buffered *(ebp+0x10) "fn ") -16543 50/push-eax -16544 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16545 (write-buffered *(ebp+0x10) %eax) -16546 58/pop-to-eax -16547 (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n") -16548 (flush *(ebp+0x10)) -16549 (stop *(ebp+0x14) 1) -16550 # never gets here -16551 -16552 $populate-mu-function-signature:error-nested-addr-inout: -16553 # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function") -16554 (write-buffered *(ebp+0x10) "fn ") -16555 (lookup *edi *(edi+4)) # Function-name Function-name => eax -16556 (write-buffered *(ebp+0x10) %eax) -16557 (write-buffered *(ebp+0x10) ": inout '") -16558 (lookup *ebx *(ebx+4)) # => eax -16559 (lookup *eax *(eax+4)) # Var-name Var-name => eax -16560 (write-buffered *(ebp+0x10) %eax) -16561 (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n") -16562 (flush *(ebp+0x10)) -16563 (stop *(ebp+0x14) 1) -16564 # never gets here -16565 -16566 addr-payload-contains-addr?: # v: (addr var) -> result/eax: boolean -16567 # . prologue -16568 55/push-ebp -16569 89/<- %ebp 4/r32/esp -16570 # var t/eax: (addr type-tree) = v->type -16571 8b/-> *(ebp+8) 0/r32/eax -16572 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -16573 # if t->right contains addr, return true -16574 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -16575 (type-tree-contains? %eax 2) # addr => eax -16576 # we don't have to look at t->left as long as it's guaranteed to be an atom -16577 $addr-payload-contains-addr?:end: -16578 # . epilogue -16579 89/<- %esp 5/r32/ebp -16580 5d/pop-to-ebp -16581 c3/return -16582 -16583 type-tree-contains?: # t: (addr type-tree), n: type-id -> result/eax: boolean -16584 # . prologue -16585 55/push-ebp -16586 89/<- %ebp 4/r32/esp -16587 # . save registers -16588 51/push-ecx -16589 # if t is null, return false -16590 8b/-> *(ebp+8) 0/r32/eax -16591 3d/compare-eax-and 0/imm32 -16592 0f 84/jump-if-= $type-tree-contains?:end/disp32 # eax changes type -16593 # if t is an atom, return (t->value == n) -16594 81 7/subop/compare *eax 0/imm32/false -16595 { -16596 74/jump-if-= break/disp8 -16597 8b/-> *(ebp+0xc) 1/r32/ecx -16598 39/compare *(eax+4) 1/r32/ecx # Type-tree-value -16599 0f 94/set-if-= %al -16600 81 4/subop/and %eax 0xff/imm32 -16601 eb/jump $type-tree-contains?:end/disp8 -16602 } -16603 # if t->left contains n, return true -16604 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -16605 (type-tree-contains? %eax *(ebp+0xc)) # => eax -16606 3d/compare-eax-and 0/imm32/false -16607 75/jump-if-!= $type-tree-contains?:end/disp8 -16608 # otherwise return whether t->right contains n -16609 8b/-> *(ebp+8) 0/r32/eax -16610 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -16611 (type-tree-contains? %eax *(ebp+0xc)) # => eax -16612 $type-tree-contains?:end: -16613 # . restore registers -16614 59/pop-to-ecx -16615 # . epilogue -16616 89/<- %esp 5/r32/ebp -16617 5d/pop-to-ebp -16618 c3/return -16619 -16620 function-exists?: # s: (addr slice) -> result/eax: boolean -16621 # . prologue -16622 55/push-ebp -16623 89/<- %ebp 4/r32/esp -16624 # . save registers -16625 51/push-ecx -16626 # var curr/ecx: (addr function) = functions -16627 (lookup *_Program-functions *_Program-functions->payload) # => eax -16628 89/<- %ecx 0/r32/eax -16629 { -16630 # if (curr == null) break -16631 81 7/subop/compare %ecx 0/imm32 -16632 74/jump-if-= break/disp8 -16633 # if (curr->name == s) return true -16634 { -16635 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax -16636 (slice-equal? *(ebp+8) %eax) # => eax -16637 3d/compare-eax-and 0/imm32/false -16638 74/jump-if-= break/disp8 -16639 b8/copy-to-eax 1/imm32/true -16640 e9/jump $function-exists?:end/disp32 -16641 } -16642 # curr = curr->next -16643 (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax -16644 89/<- %ecx 0/r32/eax -16645 # -16646 eb/jump loop/disp8 -16647 } -16648 # var curr/ecx: (addr function) = signatures -16649 (lookup *_Program-signatures *_Program-signatures->payload) # => eax +16030 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16031 # if (word-slice == '->') abort +16032 (slice-equal? %ecx "->") # => eax +16033 3d/compare-eax-and 0/imm32/false +16034 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16035 # if (word-slice == '}') abort +16036 (slice-equal? %ecx "}") # => eax +16037 3d/compare-eax-and 0/imm32/false +16038 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16039 # if word-slice already defined, abort +16040 (function-exists? %ecx) # => eax +16041 3d/compare-eax-and 0/imm32/false +16042 0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32 +16043 # +16044 (slice-starts-with? %ecx "break") # => eax +16045 3d/compare-eax-and 0/imm32/false +16046 0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32 +16047 (slice-starts-with? %ecx "loop") # => eax +16048 3d/compare-eax-and 0/imm32/false +16049 0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32 +16050 (slice-equal? %ecx "lookup") # => eax +16051 3d/compare-eax-and 0/imm32/false +16052 0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32 +16053 # save function name +16054 (slice-to-string Heap %ecx %edi) # Function-name +16055 # save function inouts +16056 { +16057 $populate-mu-function-header:check-for-inout: +16058 (next-mu-token *(ebp+8) %ecx) +16059 # if slice-empty?(word-slice) abort +16060 (slice-empty? %ecx) # => eax +16061 3d/compare-eax-and 0/imm32/false +16062 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16063 # if (word-slice == '{') goto done +16064 (slice-equal? %ecx "{") # => eax +16065 3d/compare-eax-and 0/imm32/false +16066 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 +16067 # if (word-slice == '->') break +16068 (slice-equal? %ecx "->") # => eax +16069 3d/compare-eax-and 0/imm32/false +16070 0f 85/jump-if-!= break/disp32 +16071 # if (word-slice == '}') abort +16072 (slice-equal? %ecx "}") # => eax +16073 3d/compare-eax-and 0/imm32/false +16074 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16075 # v = parse-var-with-type(word-slice, first-line) +16076 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16077 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18)) +16078 # if (v->register != null) abort +16079 # . eax: (addr var) = lookup(v) +16080 (lookup *ebx *(ebx+4)) # => eax +16081 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +16082 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 +16083 # if function name is not "main" +16084 # and v->type contains an 'addr' anywhere except the start, abort +16085 { +16086 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16087 (string-equal? %eax "main") # => eax +16088 3d/compare-eax-and 0/imm32/false +16089 75/jump-if-!= break/disp8 +16090 (lookup *ebx *(ebx+4)) # => eax +16091 (addr-payload-contains-addr? %eax) # => eax +16092 3d/compare-eax-and 0/imm32/false +16093 0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32 +16094 } +16095 # v->block-depth is implicitly 0 +16096 # +16097 # out->inouts = append(v, out->inouts) +16098 8d/copy-address *(edi+8) 0/r32/eax # Function-inouts +16099 (append-list Heap *ebx *(ebx+4) *(edi+8) *(edi+0xc) %eax) # Function-inouts, Function-inouts +16100 # push(vars, {v, false}) +16101 (push *(ebp+0x10) *ebx) +16102 (push *(ebp+0x10) *(ebx+4)) +16103 (push *(ebp+0x10) 0) # false +16104 # +16105 e9/jump loop/disp32 +16106 } +16107 # save function outputs +16108 { +16109 $populate-mu-function-header:check-for-out: +16110 (next-mu-token *(ebp+8) %ecx) +16111 # if slice-empty?(word-slice) abort +16112 (slice-empty? %ecx) # => eax +16113 3d/compare-eax-and 0/imm32/false +16114 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16115 # if (word-slice == '{') break +16116 (slice-equal? %ecx "{") # => eax +16117 3d/compare-eax-and 0/imm32/false +16118 0f 85/jump-if-!= break/disp32 +16119 # if (word-slice == '->') abort +16120 (slice-equal? %ecx "->") # => eax +16121 3d/compare-eax-and 0/imm32/false +16122 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16123 # if (word-slice == '}') abort +16124 (slice-equal? %ecx "}") # => eax +16125 3d/compare-eax-and 0/imm32/false +16126 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +16127 # v = parse-var-with-type(word-slice, first-line) +16128 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16129 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18)) +16130 # assert(var->register != null) +16131 # . eax: (addr var) = lookup(v) +16132 (lookup *ebx *(ebx+4)) # => eax +16133 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +16134 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 +16135 # if (var->name != "_") abort +16136 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16137 (string-equal? %eax "_") # => eax +16138 3d/compare-eax-and 0/imm32/false +16139 0f 84/jump-if-= $populate-mu-function-header:error4/disp32 +16140 # if v->type is an addr, abort +16141 (lookup *ebx *(ebx+4)) # => eax +16142 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +16143 (mu-addr-type? %eax) # => eax +16144 3d/compare-eax-and 0/imm32/false +16145 0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32 +16146 # out->outputs = append(v, out->outputs) +16147 8d/copy-address *(edi+0x10) 0/r32/eax # Function-outputs +16148 (append-list Heap *ebx *(ebx+4) *(edi+0x10) *(edi+0x14) %eax) # Function-outputs, Function-outputs +16149 # +16150 e9/jump loop/disp32 +16151 } +16152 $populate-mu-function-header:done: +16153 (check-no-tokens-left *(ebp+8)) +16154 $populate-mu-function-header:end: +16155 # . reclaim locals +16156 81 0/subop/add %esp 0x10/imm32 +16157 # . restore registers +16158 5f/pop-to-edi +16159 5b/pop-to-ebx +16160 5a/pop-to-edx +16161 59/pop-to-ecx +16162 58/pop-to-eax +16163 # . epilogue +16164 89/<- %esp 5/r32/ebp +16165 5d/pop-to-ebp +16166 c3/return +16167 +16168 $populate-mu-function-header:error1: +16169 # error("function header not in form 'fn <name> {'") +16170 (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") +16171 (flush *(ebp+0x14)) +16172 (rewind-stream *(ebp+8)) +16173 (write-stream-data *(ebp+0x14) *(ebp+8)) +16174 (write-buffered *(ebp+0x14) "'\n") +16175 (flush *(ebp+0x14)) +16176 (stop *(ebp+0x18) 1) +16177 # never gets here +16178 +16179 $populate-mu-function-header:error2: +16180 # error("fn " fn ": function inout '" var "' cannot be in a register") +16181 (write-buffered *(ebp+0x14) "fn ") +16182 50/push-eax +16183 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16184 (write-buffered *(ebp+0x14) %eax) +16185 58/pop-to-eax +16186 (write-buffered *(ebp+0x14) ": function inout '") +16187 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16188 (write-buffered *(ebp+0x14) %eax) +16189 (write-buffered *(ebp+0x14) "' cannot be in a register") +16190 (flush *(ebp+0x14)) +16191 (stop *(ebp+0x18) 1) +16192 # never gets here +16193 +16194 $populate-mu-function-header:error3: +16195 # error("fn " fn ": function output '" var "' must be in a register") +16196 (write-buffered *(ebp+0x14) "fn ") +16197 50/push-eax +16198 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16199 (write-buffered *(ebp+0x14) %eax) +16200 58/pop-to-eax +16201 (write-buffered *(ebp+0x14) ": function output '") +16202 (lookup *ebx *(ebx+4)) # => eax +16203 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16204 (write-buffered *(ebp+0x14) %eax) +16205 (write-buffered *(ebp+0x14) "' must be in a register, in instruction '") +16206 (rewind-stream *(ebp+8)) +16207 (write-stream-data *(ebp+0x14) *(ebp+8)) +16208 (write-buffered *(ebp+0x14) "'\n") +16209 (flush *(ebp+0x14)) +16210 (stop *(ebp+0x18) 1) +16211 # never gets here +16212 +16213 $populate-mu-function-header:error4: +16214 # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'") +16215 (write-buffered *(ebp+0x14) "fn ") +16216 50/push-eax +16217 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16218 (write-buffered *(ebp+0x14) %eax) +16219 58/pop-to-eax +16220 (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '") +16221 (lookup *ebx *(ebx+4)) # => eax +16222 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16223 (write-buffered *(ebp+0x14) %eax) +16224 (write-buffered *(ebp+0x14) "' in the header to '_'\n") +16225 (flush *(ebp+0x14)) +16226 (stop *(ebp+0x18) 1) +16227 # never gets here +16228 +16229 $populate-mu-function-header:error-duplicate: +16230 (write-buffered *(ebp+0x14) "fn ") +16231 (write-slice-buffered *(ebp+0x14) %ecx) +16232 (write-buffered *(ebp+0x14) " defined more than once\n") +16233 (flush *(ebp+0x14)) +16234 (stop *(ebp+0x18) 1) +16235 # never gets here +16236 +16237 $populate-mu-function-header:error-break: +16238 (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n") +16239 (flush *(ebp+0x14)) +16240 (stop *(ebp+0x18) 1) +16241 # never gets here +16242 +16243 $populate-mu-function-header:error-loop: +16244 (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n") +16245 (flush *(ebp+0x14)) +16246 (stop *(ebp+0x18) 1) +16247 # never gets here +16248 +16249 $populate-mu-function-header:error-lookup: +16250 (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n") +16251 (flush *(ebp+0x14)) +16252 (stop *(ebp+0x18) 1) +16253 # never gets here +16254 +16255 $populate-mu-function-header:error-addr-output: +16256 # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function") +16257 (write-buffered *(ebp+0x14) "fn ") +16258 50/push-eax +16259 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16260 (write-buffered *(ebp+0x14) %eax) +16261 58/pop-to-eax +16262 (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n") +16263 (flush *(ebp+0x14)) +16264 (stop *(ebp+0x18) 1) +16265 # never gets here +16266 +16267 $populate-mu-function-header:error-nested-addr-inout: +16268 # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function") +16269 (write-buffered *(ebp+0x14) "fn ") +16270 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16271 (write-buffered *(ebp+0x14) %eax) +16272 (write-buffered *(ebp+0x14) ": inout '") +16273 (lookup *ebx *(ebx+4)) # => eax +16274 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16275 (write-buffered *(ebp+0x14) %eax) +16276 (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n") +16277 (flush *(ebp+0x14)) +16278 (stop *(ebp+0x18) 1) +16279 # never gets here +16280 +16281 # scenarios considered: +16282 # ✓ fn foo +16283 # ✗ fn foo { +16284 # ✓ fn foo x +16285 # ✓ fn foo x: int +16286 # ✓ fn foo x: int -> _/eax: int +16287 # TODO: +16288 # disallow outputs of type `(... addr ...)` +16289 # disallow inputs of type `(... addr ... addr ...)` +16290 populate-mu-function-signature: # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +16291 # pseudocode: +16292 # var word-slice: slice +16293 # next-mu-token(first-line, word-slice) +16294 # assert(word-slice not in '{' '}' '->') +16295 # out->name = slice-to-string(word-slice) +16296 # ## inouts +16297 # while true +16298 # word-slice = next-mu-token(first-line) +16299 # if slice-empty?(word-slice) break +16300 # if (word-slice == '->') break +16301 # assert(word-slice not in '{' '}') +16302 # var v: (handle var) = parse-var-with-type(word-slice, first-line) +16303 # assert(v->register == null) +16304 # # v->block-depth is implicitly 0 +16305 # out->inouts = append(v, out->inouts) +16306 # ## outputs +16307 # while true +16308 # word-slice = next-mu-token(first-line) +16309 # if slice-empty?(word-slice) break +16310 # assert(word-slice not in '{' '}' '->') +16311 # var v: (handle var) = parse-var-with-type(word-slice, first-line) +16312 # assert(v->register != null) +16313 # out->outputs = append(v, out->outputs) +16314 # +16315 # . prologue +16316 55/push-ebp +16317 89/<- %ebp 4/r32/esp +16318 # . save registers +16319 50/push-eax +16320 51/push-ecx +16321 52/push-edx +16322 53/push-ebx +16323 57/push-edi +16324 # edi = out +16325 8b/-> *(ebp+0xc) 7/r32/edi +16326 # var word-slice/ecx: slice +16327 68/push 0/imm32/end +16328 68/push 0/imm32/start +16329 89/<- %ecx 4/r32/esp +16330 # var v/ebx: (handle var) +16331 68/push 0/imm32 +16332 68/push 0/imm32 +16333 89/<- %ebx 4/r32/esp +16334 # read function name +16335 (next-mu-token *(ebp+8) %ecx) +16336 # error checking +16337 # if (word-slice == '{') abort +16338 (slice-equal? %ecx "{") # => eax +16339 3d/compare-eax-and 0/imm32/false +16340 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16341 # if (word-slice == '->') abort +16342 (slice-equal? %ecx "->") # => eax +16343 3d/compare-eax-and 0/imm32/false +16344 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16345 # if (word-slice == '}') abort +16346 (slice-equal? %ecx "}") # => eax +16347 3d/compare-eax-and 0/imm32/false +16348 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16349 # if word-slice already defined, abort +16350 (function-exists? %ecx) # => eax +16351 3d/compare-eax-and 0/imm32/false +16352 0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32 +16353 # +16354 (slice-starts-with? %ecx "break") # => eax +16355 3d/compare-eax-and 0/imm32/false +16356 0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32 +16357 (slice-starts-with? %ecx "loop") # => eax +16358 3d/compare-eax-and 0/imm32/false +16359 0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32 +16360 # save function name +16361 (slice-to-string Heap %ecx %edi) # Function-name +16362 # save function inouts +16363 { +16364 $populate-mu-function-signature:check-for-inout: +16365 (next-mu-token *(ebp+8) %ecx) +16366 (slice-empty? %ecx) # => eax +16367 3d/compare-eax-and 0/imm32/false +16368 0f 85/jump-if-!= break/disp32 +16369 # if (word-slice == '->') break +16370 (slice-equal? %ecx "->") # => eax +16371 3d/compare-eax-and 0/imm32/false +16372 0f 85/jump-if-!= break/disp32 +16373 # if (word-slice == '{') abort +16374 (slice-equal? %ecx "{") # => eax +16375 3d/compare-eax-and 0/imm32/false +16376 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16377 # if (word-slice == '}') abort +16378 (slice-equal? %ecx "}") # => eax +16379 3d/compare-eax-and 0/imm32/false +16380 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16381 # v = parse-var-with-type(word-slice, first-line) +16382 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16383 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14)) +16384 # if (v->register != null) abort +16385 # . eax: (addr var) = lookup(v) +16386 (lookup *ebx *(ebx+4)) # => eax +16387 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +16388 0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32 +16389 # if function name is not "main" +16390 # and v->type contains an 'addr' anywhere except the start, abort +16391 { +16392 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16393 (string-equal? %eax "main") # => eax +16394 3d/compare-eax-and 0/imm32/false +16395 75/jump-if-!= break/disp8 +16396 (lookup *ebx *(ebx+4)) # => eax +16397 (addr-payload-contains-addr? %eax) # => eax +16398 3d/compare-eax-and 0/imm32/false +16399 0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32 +16400 } +16401 # assert(v->register == null) +16402 # . eax: (addr var) = lookup(v) +16403 (lookup *ebx *(ebx+4)) # => eax +16404 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +16405 0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32 +16406 # v->block-depth is implicitly 0 +16407 # +16408 # out->inouts = append(v, out->inouts) +16409 8d/copy-address *(edi+8) 0/r32/eax # Function-inouts +16410 (append-list Heap *ebx *(ebx+4) *(edi+8) *(edi+0xc) %eax) # Function-inouts, Function-inouts +16411 # +16412 e9/jump loop/disp32 +16413 } +16414 # save function outputs +16415 { +16416 $populate-mu-function-signature:check-for-out: +16417 (next-mu-token *(ebp+8) %ecx) +16418 (slice-empty? %ecx) # => eax +16419 3d/compare-eax-and 0/imm32/false +16420 0f 85/jump-if-!= break/disp32 +16421 # if (word-slice == '{') abort +16422 (slice-equal? %ecx "{") # => eax +16423 3d/compare-eax-and 0/imm32/false +16424 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16425 # if (word-slice == '->') abort +16426 (slice-equal? %ecx "->") # => eax +16427 3d/compare-eax-and 0/imm32/false +16428 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16429 # if (word-slice == '}') abort +16430 (slice-equal? %ecx "}") # => eax +16431 3d/compare-eax-and 0/imm32/false +16432 0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32 +16433 # v = parse-var-with-type(word-slice, first-line) +16434 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16435 (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14)) +16436 # assert(var->register != null) +16437 # . eax: (addr var) = lookup(v) +16438 (lookup *ebx *(ebx+4)) # => eax +16439 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +16440 0f 84/jump-if-= $populate-mu-function-signature:error3/disp32 +16441 # if (var->name != "_") abort +16442 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16443 (string-equal? %eax "_") # => eax +16444 3d/compare-eax-and 0/imm32/false +16445 0f 84/jump-if-= $populate-mu-function-signature:error4/disp32 +16446 # if function name is not "lookup" +16447 # and v->type is an addr, abort +16448 { +16449 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16450 (string-equal? %eax "lookup") # => eax +16451 3d/compare-eax-and 0/imm32/false +16452 75/jump-if-!= break/disp8 +16453 (lookup *ebx *(ebx+4)) # => eax +16454 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +16455 (mu-addr-type? %eax) # => eax +16456 3d/compare-eax-and 0/imm32/false +16457 0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32 +16458 } +16459 # out->outputs = append(v, out->outputs) +16460 8d/copy-address *(edi+0x10) 0/r32/eax # Function-outputs +16461 (append-list Heap *ebx *(ebx+4) *(edi+0x10) *(edi+0x14) %eax) # Function-outputs, Function-outputs +16462 # +16463 e9/jump loop/disp32 +16464 } +16465 $populate-mu-function-signature:done: +16466 (check-no-tokens-left *(ebp+8)) +16467 $populate-mu-function-signature:end: +16468 # . reclaim locals +16469 81 0/subop/add %esp 0x10/imm32 +16470 # . restore registers +16471 5f/pop-to-edi +16472 5b/pop-to-ebx +16473 5a/pop-to-edx +16474 59/pop-to-ecx +16475 58/pop-to-eax +16476 # . epilogue +16477 89/<- %esp 5/r32/ebp +16478 5d/pop-to-ebp +16479 c3/return +16480 +16481 $populate-mu-function-signature:error1: +16482 # error("function signature not in form 'fn <name> {'") +16483 (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '") +16484 (flush *(ebp+0x10)) +16485 (rewind-stream *(ebp+8)) +16486 (write-stream-data *(ebp+0x10) *(ebp+8)) +16487 (write-buffered *(ebp+0x10) "'\n") +16488 (flush *(ebp+0x10)) +16489 (stop *(ebp+0x14) 1) +16490 # never gets here +16491 +16492 $populate-mu-function-signature:error2: +16493 # error("fn " fn ": function inout '" var "' cannot be in a register") +16494 (write-buffered *(ebp+0x10) "fn ") +16495 50/push-eax +16496 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16497 (write-buffered *(ebp+0x10) %eax) +16498 58/pop-to-eax +16499 (write-buffered *(ebp+0x10) ": function inout '") +16500 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16501 (write-buffered *(ebp+0x10) %eax) +16502 (write-buffered *(ebp+0x10) "' cannot be in a register") +16503 (flush *(ebp+0x10)) +16504 (stop *(ebp+0x14) 1) +16505 # never gets here +16506 +16507 $populate-mu-function-signature:error3: +16508 # error("fn " fn ": function output '" var "' must be in a register") +16509 (write-buffered *(ebp+0x10) "fn ") +16510 50/push-eax +16511 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16512 (write-buffered *(ebp+0x10) %eax) +16513 58/pop-to-eax +16514 (write-buffered *(ebp+0x10) ": function output '") +16515 (lookup *ebx *(ebx+4)) # => eax +16516 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16517 (write-buffered *(ebp+0x10) %eax) +16518 (write-buffered *(ebp+0x10) "' must be in a register, in instruction '") +16519 (rewind-stream *(ebp+8)) +16520 (write-stream-data *(ebp+0x10) *(ebp+8)) +16521 (write-buffered *(ebp+0x10) "'\n") +16522 (flush *(ebp+0x10)) +16523 (stop *(ebp+0x14) 1) +16524 # never gets here +16525 +16526 $populate-mu-function-signature:error4: +16527 # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'") +16528 (write-buffered *(ebp+0x10) "fn ") +16529 50/push-eax +16530 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16531 (write-buffered *(ebp+0x10) %eax) +16532 58/pop-to-eax +16533 (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '") +16534 (lookup *ebx *(ebx+4)) # => eax +16535 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16536 (write-buffered *(ebp+0x10) %eax) +16537 (write-buffered *(ebp+0x10) "' in the header to '_'\n") +16538 (flush *(ebp+0x10)) +16539 (stop *(ebp+0x14) 1) +16540 # never gets here +16541 +16542 $populate-mu-function-signature:error-duplicate: +16543 (write-buffered *(ebp+0x10) "fn ") +16544 (write-slice-buffered *(ebp+0x10) %ecx) +16545 (write-buffered *(ebp+0x10) " defined more than once\n") +16546 (flush *(ebp+0x10)) +16547 (stop *(ebp+0x14) 1) +16548 # never gets here +16549 +16550 $populate-mu-function-signature:error-break: +16551 (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n") +16552 (flush *(ebp+0x10)) +16553 (stop *(ebp+0x14) 1) +16554 # never gets here +16555 +16556 $populate-mu-function-signature:error-loop: +16557 (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n") +16558 (flush *(ebp+0x10)) +16559 (stop *(ebp+0x14) 1) +16560 # never gets here +16561 +16562 $populate-mu-function-signature:error-addr-output: +16563 # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function") +16564 (write-buffered *(ebp+0x10) "fn ") +16565 50/push-eax +16566 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16567 (write-buffered *(ebp+0x10) %eax) +16568 58/pop-to-eax +16569 (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n") +16570 (flush *(ebp+0x10)) +16571 (stop *(ebp+0x14) 1) +16572 # never gets here +16573 +16574 $populate-mu-function-signature:error-nested-addr-inout: +16575 # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function") +16576 (write-buffered *(ebp+0x10) "fn ") +16577 (lookup *edi *(edi+4)) # Function-name Function-name => eax +16578 (write-buffered *(ebp+0x10) %eax) +16579 (write-buffered *(ebp+0x10) ": inout '") +16580 (lookup *ebx *(ebx+4)) # => eax +16581 (lookup *eax *(eax+4)) # Var-name Var-name => eax +16582 (write-buffered *(ebp+0x10) %eax) +16583 (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n") +16584 (flush *(ebp+0x10)) +16585 (stop *(ebp+0x14) 1) +16586 # never gets here +16587 +16588 addr-payload-contains-addr?: # v: (addr var) -> result/eax: boolean +16589 # . prologue +16590 55/push-ebp +16591 89/<- %ebp 4/r32/esp +16592 # var t/eax: (addr type-tree) = v->type +16593 8b/-> *(ebp+8) 0/r32/eax +16594 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +16595 # if t->right contains addr, return true +16596 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +16597 (type-tree-contains? %eax 2) # addr => eax +16598 # we don't have to look at t->left as long as it's guaranteed to be an atom +16599 $addr-payload-contains-addr?:end: +16600 # . epilogue +16601 89/<- %esp 5/r32/ebp +16602 5d/pop-to-ebp +16603 c3/return +16604 +16605 type-tree-contains?: # t: (addr type-tree), n: type-id -> result/eax: boolean +16606 # . prologue +16607 55/push-ebp +16608 89/<- %ebp 4/r32/esp +16609 # . save registers +16610 51/push-ecx +16611 # if t is null, return false +16612 8b/-> *(ebp+8) 0/r32/eax +16613 3d/compare-eax-and 0/imm32 +16614 0f 84/jump-if-= $type-tree-contains?:end/disp32 # eax changes type +16615 # if t is an atom, return (t->value == n) +16616 81 7/subop/compare *eax 0/imm32/false +16617 { +16618 74/jump-if-= break/disp8 +16619 8b/-> *(ebp+0xc) 1/r32/ecx +16620 39/compare *(eax+4) 1/r32/ecx # Type-tree-value +16621 0f 94/set-if-= %al +16622 25/and-eax-with 0xff/imm32 +16623 eb/jump $type-tree-contains?:end/disp8 +16624 } +16625 # if t->left contains n, return true +16626 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +16627 (type-tree-contains? %eax *(ebp+0xc)) # => eax +16628 3d/compare-eax-and 0/imm32/false +16629 75/jump-if-!= $type-tree-contains?:end/disp8 +16630 # otherwise return whether t->right contains n +16631 8b/-> *(ebp+8) 0/r32/eax +16632 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +16633 (type-tree-contains? %eax *(ebp+0xc)) # => eax +16634 $type-tree-contains?:end: +16635 # . restore registers +16636 59/pop-to-ecx +16637 # . epilogue +16638 89/<- %esp 5/r32/ebp +16639 5d/pop-to-ebp +16640 c3/return +16641 +16642 function-exists?: # s: (addr slice) -> result/eax: boolean +16643 # . prologue +16644 55/push-ebp +16645 89/<- %ebp 4/r32/esp +16646 # . save registers +16647 51/push-ecx +16648 # var curr/ecx: (addr function) = functions +16649 (lookup *_Program-functions *_Program-functions->payload) # => eax 16650 89/<- %ecx 0/r32/eax 16651 { 16652 # if (curr == null) break @@ -15166,7 +15166,7 @@ if ('onhashchange' in window) { 16659 3d/compare-eax-and 0/imm32/false 16660 74/jump-if-= break/disp8 16661 b8/copy-to-eax 1/imm32/true -16662 eb/jump $function-exists?:end/disp8 +16662 e9/jump $function-exists?:end/disp32 16663 } 16664 # curr = curr->next 16665 (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax @@ -15174,1277 +15174,1277 @@ if ('onhashchange' in window) { 16667 # 16668 eb/jump loop/disp8 16669 } -16670 # return false -16671 b8/copy-to-eax 0/imm32/false -16672 $function-exists?:end: -16673 # . restore registers -16674 59/pop-to-ecx -16675 # . epilogue -16676 89/<- %esp 5/r32/ebp -16677 5d/pop-to-ebp -16678 c3/return -16679 -16680 test-function-header-with-arg: -16681 # . prologue -16682 55/push-ebp -16683 89/<- %ebp 4/r32/esp -16684 # setup -16685 8b/-> *Primitive-type-ids 0/r32/eax -16686 89/<- *Type-id 0/r32/eax # stream-write -16687 c7 0/subop/copy *_Program-functions 0/imm32 -16688 c7 0/subop/copy *_Program-functions->payload 0/imm32 -16689 c7 0/subop/copy *_Program-types 0/imm32 -16690 c7 0/subop/copy *_Program-types->payload 0/imm32 -16691 c7 0/subop/copy *_Program-signatures 0/imm32 -16692 c7 0/subop/copy *_Program-signatures->payload 0/imm32 -16693 (clear-stream _test-input-stream) -16694 (write _test-input-stream "foo n: int {\n") -16695 # var result/ecx: function -16696 2b/subtract *Function-size 4/r32/esp -16697 89/<- %ecx 4/r32/esp -16698 (zero-out %ecx *Function-size) -16699 # var vars/ebx: (stack live-var 16) -16700 81 5/subop/subtract %esp 0xc0/imm32 -16701 68/push 0xc0/imm32/size -16702 68/push 0/imm32/top -16703 89/<- %ebx 4/r32/esp -16704 # convert -16705 (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0) -16706 # check result->name -16707 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax -16708 (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name") -16709 # var v/edx: (addr var) = result->inouts->value -16710 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax -16711 (lookup *eax *(eax+4)) # List-value List-value => eax -16712 89/<- %edx 0/r32/eax -16713 # check v->name -16714 (lookup *edx *(edx+4)) # Var-name Var-name => eax -16715 (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0") -16716 # check v->type -16717 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -16718 (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0") # Type-tree-is-atom -16719 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1") # Type-tree-value -16720 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2") # Type-tree-right -16721 # . epilogue -16722 89/<- %esp 5/r32/ebp -16723 5d/pop-to-ebp -16724 c3/return -16725 -16726 test-function-header-with-multiple-args: -16727 # . prologue -16728 55/push-ebp -16729 89/<- %ebp 4/r32/esp -16730 # setup -16731 8b/-> *Primitive-type-ids 0/r32/eax -16732 89/<- *Type-id 0/r32/eax # stream-write -16733 c7 0/subop/copy *_Program-functions 0/imm32 -16734 c7 0/subop/copy *_Program-functions->payload 0/imm32 -16735 c7 0/subop/copy *_Program-types 0/imm32 -16736 c7 0/subop/copy *_Program-types->payload 0/imm32 -16737 c7 0/subop/copy *_Program-signatures 0/imm32 -16738 c7 0/subop/copy *_Program-signatures->payload 0/imm32 -16739 (clear-stream _test-input-stream) -16740 (write _test-input-stream "foo a: int, b: int c: int {\n") -16741 # result/ecx: function -16742 2b/subtract *Function-size 4/r32/esp -16743 89/<- %ecx 4/r32/esp -16744 (zero-out %ecx *Function-size) -16745 # var vars/ebx: (stack live-var 16) -16746 81 5/subop/subtract %esp 0xc0/imm32 -16747 68/push 0xc0/imm32/size -16748 68/push 0/imm32/top -16749 89/<- %ebx 4/r32/esp -16750 # convert -16751 (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0) -16752 # check result->name -16753 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax -16754 (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name") -16755 # var inouts/edx: (addr list var) = lookup(result->inouts) -16756 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax -16757 89/<- %edx 0/r32/eax -16758 $test-function-header-with-multiple-args:inout0: -16759 # var v/ebx: (addr var) = lookup(inouts->value) -16760 (lookup *edx *(edx+4)) # List-value List-value => eax -16761 89/<- %ebx 0/r32/eax -16762 # check v->name -16763 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16764 (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -16765 # check v->type -16766 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16767 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Type-tree-is-atom -16768 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1") # Type-tree-value -16769 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2") # Type-tree-right -16770 $test-function-header-with-multiple-args:inout1: -16771 # inouts = lookup(inouts->next) -16772 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -16773 89/<- %edx 0/r32/eax -16774 # v = lookup(inouts->value) -16775 (lookup *edx *(edx+4)) # List-value List-value => eax -16776 89/<- %ebx 0/r32/eax -16777 # check v->name -16778 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16779 (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -16780 # check v->type -16781 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16782 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Type-tree-is-atom -16783 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1") # Type-tree-value -16784 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2") # Type-tree-right -16785 $test-function-header-with-multiple-args:inout2: -16786 # inouts = lookup(inouts->next) -16787 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -16788 89/<- %edx 0/r32/eax -16789 # v = lookup(inouts->value) -16790 (lookup *edx *(edx+4)) # List-value List-value => eax -16791 89/<- %ebx 0/r32/eax -16792 # check v->name -16793 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16794 (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -16795 # check v->type -16796 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16797 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Type-tree-is-atom -16798 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1") # Type-tree-value -16799 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2") # Type-tree-right -16800 # . epilogue -16801 89/<- %esp 5/r32/ebp -16802 5d/pop-to-ebp -16803 c3/return -16804 -16805 test-function-header-with-multiple-args-and-outputs: -16806 # . prologue -16807 55/push-ebp -16808 89/<- %ebp 4/r32/esp -16809 # setup -16810 8b/-> *Primitive-type-ids 0/r32/eax -16811 89/<- *Type-id 0/r32/eax # stream-write -16812 c7 0/subop/copy *_Program-functions 0/imm32 -16813 c7 0/subop/copy *_Program-functions->payload 0/imm32 -16814 c7 0/subop/copy *_Program-types 0/imm32 -16815 c7 0/subop/copy *_Program-types->payload 0/imm32 -16816 c7 0/subop/copy *_Program-signatures 0/imm32 -16817 c7 0/subop/copy *_Program-signatures->payload 0/imm32 -16818 (clear-stream _test-input-stream) -16819 (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n") -16820 # result/ecx: function -16821 2b/subtract *Function-size 4/r32/esp -16822 89/<- %ecx 4/r32/esp -16823 (zero-out %ecx *Function-size) -16824 # var vars/ebx: (stack live-var 16) -16825 81 5/subop/subtract %esp 0xc0/imm32 -16826 68/push 0xc0/imm32/size -16827 68/push 0/imm32/top -16828 89/<- %ebx 4/r32/esp -16829 # convert -16830 (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0) -16831 # check result->name -16832 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax -16833 (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name") -16834 # var inouts/edx: (addr list var) = lookup(result->inouts) -16835 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax -16836 89/<- %edx 0/r32/eax -16837 $test-function-header-with-multiple-args-and-outputs:inout0: -16838 # var v/ebx: (addr var) = lookup(inouts->value) -16839 (lookup *edx *(edx+4)) # List-value List-value => eax -16840 89/<- %ebx 0/r32/eax -16841 # check v->name -16842 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16843 (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") -16844 # check v->type -16845 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16846 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Type-tree-is-atom -16847 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Type-tree-value -16848 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2") # Type-tree-right -16849 $test-function-header-with-multiple-args-and-outputs:inout1: -16850 # inouts = lookup(inouts->next) -16851 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -16852 89/<- %edx 0/r32/eax -16853 # v = lookup(inouts->value) -16854 (lookup *edx *(edx+4)) # List-value List-value => eax -16855 89/<- %ebx 0/r32/eax -16856 # check v->name -16857 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16858 (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") -16859 # check v->type -16860 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16861 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Type-tree-is-atom -16862 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Type-tree-value -16863 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2") # Type-tree-right -16864 $test-function-header-with-multiple-args-and-outputs:inout2: -16865 # inouts = lookup(inouts->next) -16866 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -16867 89/<- %edx 0/r32/eax -16868 # v = lookup(inouts->value) -16869 (lookup *edx *(edx+4)) # List-value List-value => eax -16870 89/<- %ebx 0/r32/eax -16871 # check v->name -16872 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16873 (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") -16874 # check v->type -16875 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16876 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Type-tree-is-atom -16877 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Type-tree-value -16878 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2") # Type-tree-right -16879 $test-function-header-with-multiple-args-and-outputs:out0: -16880 # var outputs/edx: (addr list var) = lookup(result->outputs) -16881 (lookup *(ecx+0x10) *(ecx+0x14)) # Function-outputs Function-outputs => eax -16882 89/<- %edx 0/r32/eax -16883 # v = lookup(outputs->value) -16884 (lookup *edx *(edx+4)) # List-value List-value => eax -16885 89/<- %ebx 0/r32/eax -16886 # check v->name -16887 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16888 (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0") -16889 # check v->register -16890 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -16891 (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") -16892 # check v->type -16893 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16894 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0") # Type-tree-is-atom -16895 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Type-tree-value -16896 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2") # Type-tree-right -16897 $test-function-header-with-multiple-args-and-outputs:out1: -16898 # outputs = lookup(outputs->next) -16899 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -16900 89/<- %edx 0/r32/eax -16901 # v = lookup(inouts->value) -16902 (lookup *edx *(edx+4)) # List-value List-value => eax -16903 89/<- %ebx 0/r32/eax -16904 # check v->name -16905 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -16906 (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1") -16907 # check v->register -16908 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -16909 (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register") -16910 # check v->type -16911 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax -16912 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0") # Type-tree-is-atom -16913 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Type-tree-value -16914 (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2") # Type-tree-right -16915 # . epilogue -16916 89/<- %esp 5/r32/ebp -16917 5d/pop-to-ebp -16918 c3/return -16919 -16920 # format for variables with types -16921 # x: int -16922 # x: int, -16923 # x/eax: int -16924 # x/eax: int, -16925 # ignores at most one trailing comma -16926 # does not support other, non-register metadata -16927 # WARNING: modifies name -16928 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor) -16929 # pseudocode: -16930 # var s: slice -16931 # if (!slice-ends-with(name, ":")) -16932 # abort -16933 # --name->end to skip ':' -16934 # next-token-from-slice(name->start, name->end, '/', s) -16935 # new-var-from-slice(s, out) -16936 # ## register -16937 # next-token-from-slice(s->end, name->end, '/', s) -16938 # if (!slice-empty?(s)) -16939 # out->register = slice-to-string(s) -16940 # ## type -16941 # var type: (handle type-tree) = parse-type(first-line) -16942 # out->type = type -16943 # -16944 # . prologue -16945 55/push-ebp -16946 89/<- %ebp 4/r32/esp -16947 # . save registers -16948 50/push-eax -16949 51/push-ecx -16950 52/push-edx -16951 53/push-ebx -16952 56/push-esi -16953 57/push-edi -16954 # esi = name -16955 8b/-> *(ebp+8) 6/r32/esi -16956 # if (!slice-ends-with?(name, ":")) abort -16957 8b/-> *(esi+4) 1/r32/ecx # Slice-end -16958 49/decrement-ecx -16959 8a/copy-byte *ecx 1/r32/CL -16960 81 4/subop/and %ecx 0xff/imm32 -16961 81 7/subop/compare %ecx 0x3a/imm32/colon -16962 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 -16963 # --name->end to skip ':' -16964 ff 1/subop/decrement *(esi+4) -16965 # var s/ecx: slice -16966 68/push 0/imm32/end -16967 68/push 0/imm32/start -16968 89/<- %ecx 4/r32/esp -16969 $parse-var-with-type:parse-name: -16970 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -16971 $parse-var-with-type:create-var: -16972 # new-var-from-slice(s, out) -16973 (new-var-from-slice Heap %ecx *(ebp+0x10)) -16974 # save out->register -16975 $parse-var-with-type:save-register: -16976 # . var out-addr/edi: (addr var) = lookup(*out) -16977 8b/-> *(ebp+0x10) 7/r32/edi -16978 (lookup *edi *(edi+4)) # => eax -16979 89/<- %edi 0/r32/eax -16980 # . s = next-token(...) -16981 (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx) # s->end, name->end, '/' -16982 # . if (!slice-empty?(s)) out->register = slice-to-string(s) -16983 { -16984 $parse-var-with-type:write-register: -16985 (slice-empty? %ecx) # => eax -16986 3d/compare-eax-and 0/imm32/false -16987 75/jump-if-!= break/disp8 -16988 # out->register = slice-to-string(s) -16989 8d/copy-address *(edi+0x18) 0/r32/eax # Var-register -16990 (slice-to-string Heap %ecx %eax) -16991 } -16992 $parse-var-with-type:save-type: -16993 8d/copy-address *(edi+8) 0/r32/eax # Var-type -16994 (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c)) -16995 $parse-var-with-type:check-register: -16996 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax -16997 3d/compare-eax-and 0/imm32 -16998 74/jump-if-= $parse-var-with-type:end/disp8 -16999 (float-register? %eax) # => eax -17000 { -17001 3d/compare-eax-and 0/imm32/false -17002 74/jump-if-= break/disp8 -17003 # var is in a float register; ensure type is float -17004 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -17005 (simple-mu-type? %eax 0xf) # float => eax -17006 3d/compare-eax-and 0/imm32/false -17007 0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32 -17008 eb/jump $parse-var-with-type:end/disp8 -17009 } -17010 # var is not in a float register; ensure type is not float -17011 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -17012 (simple-mu-type? %eax 0xf) # float => eax -17013 3d/compare-eax-and 0/imm32/false -17014 0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32 -17015 $parse-var-with-type:end: -17016 # . reclaim locals -17017 81 0/subop/add %esp 8/imm32 -17018 # . restore registers -17019 5f/pop-to-edi -17020 5e/pop-to-esi -17021 5b/pop-to-ebx -17022 5a/pop-to-edx -17023 59/pop-to-ecx -17024 58/pop-to-eax -17025 # . epilogue -17026 89/<- %esp 5/r32/ebp -17027 5d/pop-to-ebp -17028 c3/return -17029 -17030 $parse-var-with-type:abort: -17031 # error("fn " fn ": var should have form 'name: type' in '" line "'\n") -17032 (write-buffered *(ebp+0x18) "fn ") -17033 (write-buffered *(ebp+0x18) *(ebp+0x14)) -17034 (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '") -17035 (flush *(ebp+0x18)) -17036 (rewind-stream *(ebp+0xc)) -17037 (write-stream-data *(ebp+0x18) *(ebp+0xc)) -17038 (write-buffered *(ebp+0x18) "'\n") -17039 (flush *(ebp+0x18)) -17040 (stop *(ebp+0x1c) 1) -17041 # never gets here -17042 -17043 $parse-var-with-type:error-float-in-integer-register: -17044 # error("fn " fn ": float var '" var "' should be in a floating-point register\n") -17045 (write-buffered *(ebp+0x18) "fn ") -17046 (write-buffered *(ebp+0x18) *(ebp+0x14)) -17047 (write-buffered *(ebp+0x18) ": float var '") -17048 (lookup *edi *(edi+4)) # Var-name Var-name => eax -17049 (write-buffered *(ebp+0x18) %eax) -17050 (write-buffered *(ebp+0x18) "' should be in a floating-point register\n") -17051 (flush *(ebp+0x18)) -17052 (stop *(ebp+0x1c) 1) -17053 # never gets here -17054 -17055 $parse-var-with-type:error-non-float-in-floating-point-register: -17056 # error("fn " fn ": non-float var '" var "' should be in an integer register\n") -17057 (write-buffered *(ebp+0x18) "fn ") -17058 (write-buffered *(ebp+0x18) *(ebp+0x14)) -17059 (write-buffered *(ebp+0x18) ": non-float var '") -17060 (lookup *edi *(edi+4)) # Var-name Var-name => eax -17061 (write-buffered *(ebp+0x18) %eax) -17062 (write-buffered *(ebp+0x18) "' should be in an integer register\n") -17063 (flush *(ebp+0x18)) -17064 (stop *(ebp+0x1c) 1) -17065 # never gets here -17066 -17067 float-register?: # r: (addr array byte) -> result/eax: boolean -17068 # . prologue -17069 55/push-ebp -17070 89/<- %ebp 4/r32/esp -17071 # -17072 (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique") # => eax -17073 81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers -17074 0f 9d/set-if->= %al -17075 81 4/subop/and %eax 0xff/imm32 -17076 $float-register?:end: -17077 # . epilogue -17078 89/<- %esp 5/r32/ebp -17079 5d/pop-to-ebp -17080 c3/return -17081 -17082 parse-type: # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -17083 # pseudocode: -17084 # var s: slice = next-mu-token(in) -17085 # assert s != "" -17086 # assert s != "->" -17087 # assert s != "{" -17088 # assert s != "}" -17089 # if s == ")" -17090 # return -17091 # out = allocate(Type-tree) -17092 # if s != "(" -17093 # HACK: if s is an int, parse and return it -17094 # out->is-atom? = true -17095 # if (s[0] == "_") -17096 # out->value = type-parameter -17097 # out->parameter-name = slice-to-string(ad, s) -17098 # else -17099 # out->value = pos-or-insert-slice(Type-id, s) -17100 # return -17101 # out->left = parse-type(ad, in) -17102 # out->right = parse-type-tree(ad, in) -17103 # -17104 # . prologue -17105 55/push-ebp -17106 89/<- %ebp 4/r32/esp -17107 # . save registers -17108 50/push-eax -17109 51/push-ecx -17110 52/push-edx -17111 # clear out -17112 (zero-out *(ebp+0x10) *Handle-size) -17113 # var s/ecx: slice -17114 68/push 0/imm32 -17115 68/push 0/imm32 -17116 89/<- %ecx 4/r32/esp -17117 # s = next-mu-token(in) -17118 (next-mu-token *(ebp+0xc) %ecx) -17119 #? (write-buffered Stderr "tok: ") -17120 #? (write-slice-buffered Stderr %ecx) -17121 #? (write-buffered Stderr "$\n") -17122 #? (flush Stderr) -17123 # assert s != "" -17124 (slice-equal? %ecx "") # => eax -17125 3d/compare-eax-and 0/imm32/false -17126 0f 85/jump-if-!= $parse-type:abort/disp32 -17127 # assert s != "{" -17128 (slice-equal? %ecx "{") # => eax -17129 3d/compare-eax-and 0/imm32/false -17130 0f 85/jump-if-!= $parse-type:abort/disp32 -17131 # assert s != "}" -17132 (slice-equal? %ecx "}") # => eax -17133 3d/compare-eax-and 0/imm32/false -17134 0f 85/jump-if-!= $parse-type:abort/disp32 -17135 # assert s != "->" -17136 (slice-equal? %ecx "->") # => eax -17137 3d/compare-eax-and 0/imm32/false -17138 0f 85/jump-if-!= $parse-type:abort/disp32 -17139 # if (s == ")") return -17140 (slice-equal? %ecx ")") # => eax -17141 3d/compare-eax-and 0/imm32/false -17142 0f 85/jump-if-!= $parse-type:end/disp32 -17143 # out = new tree -17144 (allocate *(ebp+8) *Type-tree-size *(ebp+0x10)) -17145 # var out-addr/edx: (addr type-tree) = lookup(*out) -17146 8b/-> *(ebp+0x10) 2/r32/edx -17147 (lookup *edx *(edx+4)) # => eax -17148 89/<- %edx 0/r32/eax -17149 { -17150 # if (s != "(") break -17151 (slice-equal? %ecx "(") # => eax -17152 3d/compare-eax-and 0/imm32/false -17153 0f 85/jump-if-!= break/disp32 -17154 # if s is a number, store it in the type's size field -17155 { -17156 $parse-type:check-for-int: -17157 # var tmp/eax: byte = *s->slice -17158 8b/-> *ecx 0/r32/eax -17159 8a/copy-byte *eax 0/r32/AL -17160 81 4/subop/and %eax 0xff/imm32 -17161 # TODO: raise an error on `var x: (array int a)` -17162 (decimal-digit? %eax) # => eax -17163 3d/compare-eax-and 0/imm32/false -17164 74/jump-if-= break/disp8 -17165 $parse-type:int: -17166 # strip out metadata -17167 (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx) -17168 # -17169 (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18)) -17170 (parse-hex-int-from-slice %ecx) # => eax -17171 c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity # Type-tree-value -17172 89/<- *(edx+8) 0/r32/eax # Type-tree-value-size -17173 e9/jump $parse-type:end/disp32 -17174 } -17175 $parse-type:atom: -17176 # out->is-atom? = true -17177 c7 0/subop/copy *edx 1/imm32/true # Type-tree-is-atom -17178 { -17179 $parse-type:check-for-type-parameter: -17180 # var tmp/eax: byte = *s->slice -17181 8b/-> *ecx 0/r32/eax -17182 8a/copy-byte *eax 0/r32/AL -17183 81 4/subop/and %eax 0xff/imm32 -17184 # if (tmp != '_') break -17185 3d/compare-eax-and 0x5f/imm32/_ -17186 75/jump-if-!= break/disp8 -17187 $parse-type:type-parameter: -17188 # out->value = type-parameter -17189 c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter # Type-tree-value -17190 # out->parameter-name = slice-to-string(ad, s) -17191 8d/copy-address *(edx+8) 0/r32/eax # Type-tree-parameter-name -17192 (slice-to-string *(ebp+8) %ecx %eax) -17193 e9/jump $parse-type:end/disp32 -17194 } -17195 $parse-type:non-type-parameter: -17196 # out->value = pos-or-insert-slice(Type-id, s) -17197 (pos-or-insert-slice Type-id %ecx) # => eax -17198 89/<- *(edx+4) 0/r32/eax # Type-tree-value -17199 e9/jump $parse-type:end/disp32 -17200 } -17201 $parse-type:non-atom: -17202 # otherwise s == "(" -17203 # out->left = parse-type(ad, in) -17204 8d/copy-address *(edx+4) 0/r32/eax # Type-tree-left -17205 (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18)) -17206 # out->right = parse-type-tree(ad, in) -17207 8d/copy-address *(edx+0xc) 0/r32/eax # Type-tree-right -17208 (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18)) -17209 $parse-type:end: -17210 # . reclaim locals -17211 81 0/subop/add %esp 8/imm32 -17212 # . restore registers -17213 5a/pop-to-edx -17214 59/pop-to-ecx -17215 58/pop-to-eax -17216 # . epilogue -17217 89/<- %esp 5/r32/ebp -17218 5d/pop-to-ebp -17219 c3/return -17220 -17221 $parse-type:abort: -17222 # error("unexpected token when parsing type: '" s "'\n") -17223 (write-buffered *(ebp+0x14) "unexpected token when parsing type: '") -17224 (write-slice-buffered *(ebp+0x14) %ecx) -17225 (write-buffered *(ebp+0x14) "'\n") -17226 (flush *(ebp+0x14)) -17227 (stop *(ebp+0x18) 1) -17228 # never gets here -17229 -17230 parse-type-tree: # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -17231 # pseudocode: -17232 # var tmp: (handle type-tree) = parse-type(ad, in) -17233 # if tmp == 0 -17234 # return 0 -17235 # out = allocate(Type-tree) -17236 # out->left = tmp -17237 # out->right = parse-type-tree(ad, in) -17238 # -17239 # . prologue -17240 55/push-ebp -17241 89/<- %ebp 4/r32/esp -17242 # . save registers -17243 50/push-eax -17244 51/push-ecx -17245 52/push-edx -17246 # -17247 (zero-out *(ebp+0x10) *Handle-size) -17248 # var tmp/ecx: (handle type-tree) -17249 68/push 0/imm32 -17250 68/push 0/imm32 -17251 89/<- %ecx 4/r32/esp -17252 # tmp = parse-type(ad, in) -17253 (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18)) -17254 # if (tmp == 0) return -17255 81 7/subop/compare *ecx 0/imm32 -17256 74/jump-if-= $parse-type-tree:end/disp8 -17257 # out = new tree -17258 (allocate *(ebp+8) *Type-tree-size *(ebp+0x10)) -17259 # var out-addr/edx: (addr tree) = lookup(*out) -17260 8b/-> *(ebp+0x10) 2/r32/edx -17261 (lookup *edx *(edx+4)) # => eax -17262 89/<- %edx 0/r32/eax -17263 # out->left = tmp -17264 8b/-> *ecx 0/r32/eax -17265 89/<- *(edx+4) 0/r32/eax # Type-tree-left -17266 8b/-> *(ecx+4) 0/r32/eax -17267 89/<- *(edx+8) 0/r32/eax # Type-tree-left -17268 # out->right = parse-type-tree(ad, in) -17269 8d/copy-address *(edx+0xc) 0/r32/eax # Type-tree-right -17270 (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18)) -17271 $parse-type-tree:end: -17272 # . reclaim locals -17273 81 0/subop/add %esp 8/imm32 -17274 # . restore registers -17275 5a/pop-to-edx -17276 59/pop-to-ecx -17277 58/pop-to-eax -17278 # . epilogue -17279 89/<- %esp 5/r32/ebp -17280 5d/pop-to-ebp -17281 c3/return -17282 -17283 next-mu-token: # in: (addr stream byte), out: (addr slice) -17284 # pseudocode: -17285 # start: -17286 # skip-chars-matching-whitespace(in) -17287 # if in->read >= in->write # end of in -17288 # out = {0, 0} -17289 # return -17290 # out->start = &in->data[in->read] -17291 # var curr-byte/eax: byte = in->data[in->read] -17292 # if curr->byte == ',' # comment token -17293 # ++in->read -17294 # goto start -17295 # if curr-byte == '#' # comment -17296 # goto done # treat as eof -17297 # if curr-byte == '"' # string literal -17298 # skip-string(in) -17299 # goto done # no metadata -17300 # if curr-byte == '(' -17301 # ++in->read -17302 # goto done -17303 # if curr-byte == ')' -17304 # ++in->read -17305 # goto done -17306 # # read a word -17307 # while true -17308 # if in->read >= in->write -17309 # break -17310 # curr-byte = in->data[in->read] -17311 # if curr-byte == ' ' -17312 # break -17313 # if curr-byte == '\r' -17314 # break -17315 # if curr-byte == '\n' -17316 # break -17317 # if curr-byte == '(' -17318 # break -17319 # if curr-byte == ')' -17320 # break -17321 # if curr-byte == ',' -17322 # break +16670 # var curr/ecx: (addr function) = signatures +16671 (lookup *_Program-signatures *_Program-signatures->payload) # => eax +16672 89/<- %ecx 0/r32/eax +16673 { +16674 # if (curr == null) break +16675 81 7/subop/compare %ecx 0/imm32 +16676 74/jump-if-= break/disp8 +16677 # if (curr->name == s) return true +16678 { +16679 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax +16680 (slice-equal? *(ebp+8) %eax) # => eax +16681 3d/compare-eax-and 0/imm32/false +16682 74/jump-if-= break/disp8 +16683 b8/copy-to-eax 1/imm32/true +16684 eb/jump $function-exists?:end/disp8 +16685 } +16686 # curr = curr->next +16687 (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax +16688 89/<- %ecx 0/r32/eax +16689 # +16690 eb/jump loop/disp8 +16691 } +16692 # return false +16693 b8/copy-to-eax 0/imm32/false +16694 $function-exists?:end: +16695 # . restore registers +16696 59/pop-to-ecx +16697 # . epilogue +16698 89/<- %esp 5/r32/ebp +16699 5d/pop-to-ebp +16700 c3/return +16701 +16702 test-function-header-with-arg: +16703 # . prologue +16704 55/push-ebp +16705 89/<- %ebp 4/r32/esp +16706 # setup +16707 8b/-> *Primitive-type-ids 0/r32/eax +16708 89/<- *Type-id 0/r32/eax # stream-write +16709 c7 0/subop/copy *_Program-functions 0/imm32 +16710 c7 0/subop/copy *_Program-functions->payload 0/imm32 +16711 c7 0/subop/copy *_Program-types 0/imm32 +16712 c7 0/subop/copy *_Program-types->payload 0/imm32 +16713 c7 0/subop/copy *_Program-signatures 0/imm32 +16714 c7 0/subop/copy *_Program-signatures->payload 0/imm32 +16715 (clear-stream _test-input-stream) +16716 (write _test-input-stream "foo n: int {\n") +16717 # var result/ecx: function +16718 2b/subtract *Function-size 4/r32/esp +16719 89/<- %ecx 4/r32/esp +16720 (zero-out %ecx *Function-size) +16721 # var vars/ebx: (stack live-var 16) +16722 81 5/subop/subtract %esp 0xc0/imm32 +16723 68/push 0xc0/imm32/size +16724 68/push 0/imm32/top +16725 89/<- %ebx 4/r32/esp +16726 # convert +16727 (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0) +16728 # check result->name +16729 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax +16730 (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name") +16731 # var v/edx: (addr var) = result->inouts->value +16732 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax +16733 (lookup *eax *(eax+4)) # List-value List-value => eax +16734 89/<- %edx 0/r32/eax +16735 # check v->name +16736 (lookup *edx *(edx+4)) # Var-name Var-name => eax +16737 (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0") +16738 # check v->type +16739 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +16740 (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0") # Type-tree-is-atom +16741 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1") # Type-tree-value +16742 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2") # Type-tree-right +16743 # . epilogue +16744 89/<- %esp 5/r32/ebp +16745 5d/pop-to-ebp +16746 c3/return +16747 +16748 test-function-header-with-multiple-args: +16749 # . prologue +16750 55/push-ebp +16751 89/<- %ebp 4/r32/esp +16752 # setup +16753 8b/-> *Primitive-type-ids 0/r32/eax +16754 89/<- *Type-id 0/r32/eax # stream-write +16755 c7 0/subop/copy *_Program-functions 0/imm32 +16756 c7 0/subop/copy *_Program-functions->payload 0/imm32 +16757 c7 0/subop/copy *_Program-types 0/imm32 +16758 c7 0/subop/copy *_Program-types->payload 0/imm32 +16759 c7 0/subop/copy *_Program-signatures 0/imm32 +16760 c7 0/subop/copy *_Program-signatures->payload 0/imm32 +16761 (clear-stream _test-input-stream) +16762 (write _test-input-stream "foo a: int, b: int c: int {\n") +16763 # result/ecx: function +16764 2b/subtract *Function-size 4/r32/esp +16765 89/<- %ecx 4/r32/esp +16766 (zero-out %ecx *Function-size) +16767 # var vars/ebx: (stack live-var 16) +16768 81 5/subop/subtract %esp 0xc0/imm32 +16769 68/push 0xc0/imm32/size +16770 68/push 0/imm32/top +16771 89/<- %ebx 4/r32/esp +16772 # convert +16773 (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0) +16774 # check result->name +16775 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax +16776 (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name") +16777 # var inouts/edx: (addr list var) = lookup(result->inouts) +16778 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax +16779 89/<- %edx 0/r32/eax +16780 $test-function-header-with-multiple-args:inout0: +16781 # var v/ebx: (addr var) = lookup(inouts->value) +16782 (lookup *edx *(edx+4)) # List-value List-value => eax +16783 89/<- %ebx 0/r32/eax +16784 # check v->name +16785 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16786 (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name +16787 # check v->type +16788 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16789 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Type-tree-is-atom +16790 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1") # Type-tree-value +16791 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2") # Type-tree-right +16792 $test-function-header-with-multiple-args:inout1: +16793 # inouts = lookup(inouts->next) +16794 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +16795 89/<- %edx 0/r32/eax +16796 # v = lookup(inouts->value) +16797 (lookup *edx *(edx+4)) # List-value List-value => eax +16798 89/<- %ebx 0/r32/eax +16799 # check v->name +16800 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16801 (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name +16802 # check v->type +16803 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16804 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Type-tree-is-atom +16805 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1") # Type-tree-value +16806 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2") # Type-tree-right +16807 $test-function-header-with-multiple-args:inout2: +16808 # inouts = lookup(inouts->next) +16809 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +16810 89/<- %edx 0/r32/eax +16811 # v = lookup(inouts->value) +16812 (lookup *edx *(edx+4)) # List-value List-value => eax +16813 89/<- %ebx 0/r32/eax +16814 # check v->name +16815 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16816 (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name +16817 # check v->type +16818 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16819 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Type-tree-is-atom +16820 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1") # Type-tree-value +16821 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2") # Type-tree-right +16822 # . epilogue +16823 89/<- %esp 5/r32/ebp +16824 5d/pop-to-ebp +16825 c3/return +16826 +16827 test-function-header-with-multiple-args-and-outputs: +16828 # . prologue +16829 55/push-ebp +16830 89/<- %ebp 4/r32/esp +16831 # setup +16832 8b/-> *Primitive-type-ids 0/r32/eax +16833 89/<- *Type-id 0/r32/eax # stream-write +16834 c7 0/subop/copy *_Program-functions 0/imm32 +16835 c7 0/subop/copy *_Program-functions->payload 0/imm32 +16836 c7 0/subop/copy *_Program-types 0/imm32 +16837 c7 0/subop/copy *_Program-types->payload 0/imm32 +16838 c7 0/subop/copy *_Program-signatures 0/imm32 +16839 c7 0/subop/copy *_Program-signatures->payload 0/imm32 +16840 (clear-stream _test-input-stream) +16841 (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n") +16842 # result/ecx: function +16843 2b/subtract *Function-size 4/r32/esp +16844 89/<- %ecx 4/r32/esp +16845 (zero-out %ecx *Function-size) +16846 # var vars/ebx: (stack live-var 16) +16847 81 5/subop/subtract %esp 0xc0/imm32 +16848 68/push 0xc0/imm32/size +16849 68/push 0/imm32/top +16850 89/<- %ebx 4/r32/esp +16851 # convert +16852 (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0) +16853 # check result->name +16854 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax +16855 (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name") +16856 # var inouts/edx: (addr list var) = lookup(result->inouts) +16857 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax +16858 89/<- %edx 0/r32/eax +16859 $test-function-header-with-multiple-args-and-outputs:inout0: +16860 # var v/ebx: (addr var) = lookup(inouts->value) +16861 (lookup *edx *(edx+4)) # List-value List-value => eax +16862 89/<- %ebx 0/r32/eax +16863 # check v->name +16864 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16865 (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") +16866 # check v->type +16867 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16868 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Type-tree-is-atom +16869 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Type-tree-value +16870 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2") # Type-tree-right +16871 $test-function-header-with-multiple-args-and-outputs:inout1: +16872 # inouts = lookup(inouts->next) +16873 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +16874 89/<- %edx 0/r32/eax +16875 # v = lookup(inouts->value) +16876 (lookup *edx *(edx+4)) # List-value List-value => eax +16877 89/<- %ebx 0/r32/eax +16878 # check v->name +16879 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16880 (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") +16881 # check v->type +16882 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16883 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Type-tree-is-atom +16884 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Type-tree-value +16885 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2") # Type-tree-right +16886 $test-function-header-with-multiple-args-and-outputs:inout2: +16887 # inouts = lookup(inouts->next) +16888 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +16889 89/<- %edx 0/r32/eax +16890 # v = lookup(inouts->value) +16891 (lookup *edx *(edx+4)) # List-value List-value => eax +16892 89/<- %ebx 0/r32/eax +16893 # check v->name +16894 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16895 (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") +16896 # check v->type +16897 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16898 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Type-tree-is-atom +16899 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Type-tree-value +16900 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2") # Type-tree-right +16901 $test-function-header-with-multiple-args-and-outputs:out0: +16902 # var outputs/edx: (addr list var) = lookup(result->outputs) +16903 (lookup *(ecx+0x10) *(ecx+0x14)) # Function-outputs Function-outputs => eax +16904 89/<- %edx 0/r32/eax +16905 # v = lookup(outputs->value) +16906 (lookup *edx *(edx+4)) # List-value List-value => eax +16907 89/<- %ebx 0/r32/eax +16908 # check v->name +16909 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16910 (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0") +16911 # check v->register +16912 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +16913 (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") +16914 # check v->type +16915 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16916 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0") # Type-tree-is-atom +16917 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Type-tree-value +16918 (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2") # Type-tree-right +16919 $test-function-header-with-multiple-args-and-outputs:out1: +16920 # outputs = lookup(outputs->next) +16921 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +16922 89/<- %edx 0/r32/eax +16923 # v = lookup(inouts->value) +16924 (lookup *edx *(edx+4)) # List-value List-value => eax +16925 89/<- %ebx 0/r32/eax +16926 # check v->name +16927 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +16928 (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1") +16929 # check v->register +16930 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +16931 (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register") +16932 # check v->type +16933 (lookup *(ebx+8) *(ebx+0xc)) # Var-type Var-type => eax +16934 (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0") # Type-tree-is-atom +16935 (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Type-tree-value +16936 (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2") # Type-tree-right +16937 # . epilogue +16938 89/<- %esp 5/r32/ebp +16939 5d/pop-to-ebp +16940 c3/return +16941 +16942 # format for variables with types +16943 # x: int +16944 # x: int, +16945 # x/eax: int +16946 # x/eax: int, +16947 # ignores at most one trailing comma +16948 # does not support other, non-register metadata +16949 # WARNING: modifies name +16950 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor) +16951 # pseudocode: +16952 # var s: slice +16953 # if (!slice-ends-with(name, ":")) +16954 # abort +16955 # --name->end to skip ':' +16956 # next-token-from-slice(name->start, name->end, '/', s) +16957 # new-var-from-slice(s, out) +16958 # ## register +16959 # next-token-from-slice(s->end, name->end, '/', s) +16960 # if (!slice-empty?(s)) +16961 # out->register = slice-to-string(s) +16962 # ## type +16963 # var type: (handle type-tree) = parse-type(first-line) +16964 # out->type = type +16965 # +16966 # . prologue +16967 55/push-ebp +16968 89/<- %ebp 4/r32/esp +16969 # . save registers +16970 50/push-eax +16971 51/push-ecx +16972 52/push-edx +16973 53/push-ebx +16974 56/push-esi +16975 57/push-edi +16976 # esi = name +16977 8b/-> *(ebp+8) 6/r32/esi +16978 # if (!slice-ends-with?(name, ":")) abort +16979 8b/-> *(esi+4) 1/r32/ecx # Slice-end +16980 49/decrement-ecx +16981 8a/copy-byte *ecx 1/r32/CL +16982 81 4/subop/and %ecx 0xff/imm32 +16983 81 7/subop/compare %ecx 0x3a/imm32/colon +16984 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 +16985 # --name->end to skip ':' +16986 ff 1/subop/decrement *(esi+4) +16987 # var s/ecx: slice +16988 68/push 0/imm32/end +16989 68/push 0/imm32/start +16990 89/<- %ecx 4/r32/esp +16991 $parse-var-with-type:parse-name: +16992 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' +16993 $parse-var-with-type:create-var: +16994 # new-var-from-slice(s, out) +16995 (new-var-from-slice Heap %ecx *(ebp+0x10)) +16996 # save out->register +16997 $parse-var-with-type:save-register: +16998 # . var out-addr/edi: (addr var) = lookup(*out) +16999 8b/-> *(ebp+0x10) 7/r32/edi +17000 (lookup *edi *(edi+4)) # => eax +17001 89/<- %edi 0/r32/eax +17002 # . s = next-token(...) +17003 (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx) # s->end, name->end, '/' +17004 # . if (!slice-empty?(s)) out->register = slice-to-string(s) +17005 { +17006 $parse-var-with-type:write-register: +17007 (slice-empty? %ecx) # => eax +17008 3d/compare-eax-and 0/imm32/false +17009 75/jump-if-!= break/disp8 +17010 # out->register = slice-to-string(s) +17011 8d/copy-address *(edi+0x18) 0/r32/eax # Var-register +17012 (slice-to-string Heap %ecx %eax) +17013 } +17014 $parse-var-with-type:save-type: +17015 8d/copy-address *(edi+8) 0/r32/eax # Var-type +17016 (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c)) +17017 $parse-var-with-type:check-register: +17018 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax +17019 3d/compare-eax-and 0/imm32 +17020 74/jump-if-= $parse-var-with-type:end/disp8 +17021 (float-register? %eax) # => eax +17022 { +17023 3d/compare-eax-and 0/imm32/false +17024 74/jump-if-= break/disp8 +17025 # var is in a float register; ensure type is float +17026 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +17027 (simple-mu-type? %eax 0xf) # float => eax +17028 3d/compare-eax-and 0/imm32/false +17029 0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32 +17030 eb/jump $parse-var-with-type:end/disp8 +17031 } +17032 # var is not in a float register; ensure type is not float +17033 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +17034 (simple-mu-type? %eax 0xf) # float => eax +17035 3d/compare-eax-and 0/imm32/false +17036 0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32 +17037 $parse-var-with-type:end: +17038 # . reclaim locals +17039 81 0/subop/add %esp 8/imm32 +17040 # . restore registers +17041 5f/pop-to-edi +17042 5e/pop-to-esi +17043 5b/pop-to-ebx +17044 5a/pop-to-edx +17045 59/pop-to-ecx +17046 58/pop-to-eax +17047 # . epilogue +17048 89/<- %esp 5/r32/ebp +17049 5d/pop-to-ebp +17050 c3/return +17051 +17052 $parse-var-with-type:abort: +17053 # error("fn " fn ": var should have form 'name: type' in '" line "'\n") +17054 (write-buffered *(ebp+0x18) "fn ") +17055 (write-buffered *(ebp+0x18) *(ebp+0x14)) +17056 (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '") +17057 (flush *(ebp+0x18)) +17058 (rewind-stream *(ebp+0xc)) +17059 (write-stream-data *(ebp+0x18) *(ebp+0xc)) +17060 (write-buffered *(ebp+0x18) "'\n") +17061 (flush *(ebp+0x18)) +17062 (stop *(ebp+0x1c) 1) +17063 # never gets here +17064 +17065 $parse-var-with-type:error-float-in-integer-register: +17066 # error("fn " fn ": float var '" var "' should be in a floating-point register\n") +17067 (write-buffered *(ebp+0x18) "fn ") +17068 (write-buffered *(ebp+0x18) *(ebp+0x14)) +17069 (write-buffered *(ebp+0x18) ": float var '") +17070 (lookup *edi *(edi+4)) # Var-name Var-name => eax +17071 (write-buffered *(ebp+0x18) %eax) +17072 (write-buffered *(ebp+0x18) "' should be in a floating-point register\n") +17073 (flush *(ebp+0x18)) +17074 (stop *(ebp+0x1c) 1) +17075 # never gets here +17076 +17077 $parse-var-with-type:error-non-float-in-floating-point-register: +17078 # error("fn " fn ": non-float var '" var "' should be in an integer register\n") +17079 (write-buffered *(ebp+0x18) "fn ") +17080 (write-buffered *(ebp+0x18) *(ebp+0x14)) +17081 (write-buffered *(ebp+0x18) ": non-float var '") +17082 (lookup *edi *(edi+4)) # Var-name Var-name => eax +17083 (write-buffered *(ebp+0x18) %eax) +17084 (write-buffered *(ebp+0x18) "' should be in an integer register\n") +17085 (flush *(ebp+0x18)) +17086 (stop *(ebp+0x1c) 1) +17087 # never gets here +17088 +17089 float-register?: # r: (addr array byte) -> result/eax: boolean +17090 # . prologue +17091 55/push-ebp +17092 89/<- %ebp 4/r32/esp +17093 # +17094 (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique") # => eax +17095 81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers +17096 0f 9d/set-if->= %al +17097 25/and-eax-with 0xff/imm32 +17098 $float-register?:end: +17099 # . epilogue +17100 89/<- %esp 5/r32/ebp +17101 5d/pop-to-ebp +17102 c3/return +17103 +17104 parse-type: # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) +17105 # pseudocode: +17106 # var s: slice = next-mu-token(in) +17107 # assert s != "" +17108 # assert s != "->" +17109 # assert s != "{" +17110 # assert s != "}" +17111 # if s == ")" +17112 # return +17113 # out = allocate(Type-tree) +17114 # if s != "(" +17115 # HACK: if s is an int, parse and return it +17116 # out->is-atom? = true +17117 # if (s[0] == "_") +17118 # out->value = type-parameter +17119 # out->parameter-name = slice-to-string(ad, s) +17120 # else +17121 # out->value = pos-or-insert-slice(Type-id, s) +17122 # return +17123 # out->left = parse-type(ad, in) +17124 # out->right = parse-type-tree(ad, in) +17125 # +17126 # . prologue +17127 55/push-ebp +17128 89/<- %ebp 4/r32/esp +17129 # . save registers +17130 50/push-eax +17131 51/push-ecx +17132 52/push-edx +17133 # clear out +17134 (zero-out *(ebp+0x10) *Handle-size) +17135 # var s/ecx: slice +17136 68/push 0/imm32 +17137 68/push 0/imm32 +17138 89/<- %ecx 4/r32/esp +17139 # s = next-mu-token(in) +17140 (next-mu-token *(ebp+0xc) %ecx) +17141 #? (write-buffered Stderr "tok: ") +17142 #? (write-slice-buffered Stderr %ecx) +17143 #? (write-buffered Stderr "$\n") +17144 #? (flush Stderr) +17145 # assert s != "" +17146 (slice-equal? %ecx "") # => eax +17147 3d/compare-eax-and 0/imm32/false +17148 0f 85/jump-if-!= $parse-type:abort/disp32 +17149 # assert s != "{" +17150 (slice-equal? %ecx "{") # => eax +17151 3d/compare-eax-and 0/imm32/false +17152 0f 85/jump-if-!= $parse-type:abort/disp32 +17153 # assert s != "}" +17154 (slice-equal? %ecx "}") # => eax +17155 3d/compare-eax-and 0/imm32/false +17156 0f 85/jump-if-!= $parse-type:abort/disp32 +17157 # assert s != "->" +17158 (slice-equal? %ecx "->") # => eax +17159 3d/compare-eax-and 0/imm32/false +17160 0f 85/jump-if-!= $parse-type:abort/disp32 +17161 # if (s == ")") return +17162 (slice-equal? %ecx ")") # => eax +17163 3d/compare-eax-and 0/imm32/false +17164 0f 85/jump-if-!= $parse-type:end/disp32 +17165 # out = new tree +17166 (allocate *(ebp+8) *Type-tree-size *(ebp+0x10)) +17167 # var out-addr/edx: (addr type-tree) = lookup(*out) +17168 8b/-> *(ebp+0x10) 2/r32/edx +17169 (lookup *edx *(edx+4)) # => eax +17170 89/<- %edx 0/r32/eax +17171 { +17172 # if (s != "(") break +17173 (slice-equal? %ecx "(") # => eax +17174 3d/compare-eax-and 0/imm32/false +17175 0f 85/jump-if-!= break/disp32 +17176 # if s is a number, store it in the type's size field +17177 { +17178 $parse-type:check-for-int: +17179 # var tmp/eax: byte = *s->slice +17180 8b/-> *ecx 0/r32/eax +17181 8a/copy-byte *eax 0/r32/AL +17182 25/and-eax-with 0xff/imm32 +17183 # TODO: raise an error on `var x: (array int a)` +17184 (decimal-digit? %eax) # => eax +17185 3d/compare-eax-and 0/imm32/false +17186 74/jump-if-= break/disp8 +17187 $parse-type:int: +17188 # strip out metadata +17189 (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx) +17190 # +17191 (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18)) +17192 (parse-hex-int-from-slice %ecx) # => eax +17193 c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity # Type-tree-value +17194 89/<- *(edx+8) 0/r32/eax # Type-tree-value-size +17195 e9/jump $parse-type:end/disp32 +17196 } +17197 $parse-type:atom: +17198 # out->is-atom? = true +17199 c7 0/subop/copy *edx 1/imm32/true # Type-tree-is-atom +17200 { +17201 $parse-type:check-for-type-parameter: +17202 # var tmp/eax: byte = *s->slice +17203 8b/-> *ecx 0/r32/eax +17204 8a/copy-byte *eax 0/r32/AL +17205 25/and-eax-with 0xff/imm32 +17206 # if (tmp != '_') break +17207 3d/compare-eax-and 0x5f/imm32/_ +17208 75/jump-if-!= break/disp8 +17209 $parse-type:type-parameter: +17210 # out->value = type-parameter +17211 c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter # Type-tree-value +17212 # out->parameter-name = slice-to-string(ad, s) +17213 8d/copy-address *(edx+8) 0/r32/eax # Type-tree-parameter-name +17214 (slice-to-string *(ebp+8) %ecx %eax) +17215 e9/jump $parse-type:end/disp32 +17216 } +17217 $parse-type:non-type-parameter: +17218 # out->value = pos-or-insert-slice(Type-id, s) +17219 (pos-or-insert-slice Type-id %ecx) # => eax +17220 89/<- *(edx+4) 0/r32/eax # Type-tree-value +17221 e9/jump $parse-type:end/disp32 +17222 } +17223 $parse-type:non-atom: +17224 # otherwise s == "(" +17225 # out->left = parse-type(ad, in) +17226 8d/copy-address *(edx+4) 0/r32/eax # Type-tree-left +17227 (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18)) +17228 # out->right = parse-type-tree(ad, in) +17229 8d/copy-address *(edx+0xc) 0/r32/eax # Type-tree-right +17230 (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18)) +17231 $parse-type:end: +17232 # . reclaim locals +17233 81 0/subop/add %esp 8/imm32 +17234 # . restore registers +17235 5a/pop-to-edx +17236 59/pop-to-ecx +17237 58/pop-to-eax +17238 # . epilogue +17239 89/<- %esp 5/r32/ebp +17240 5d/pop-to-ebp +17241 c3/return +17242 +17243 $parse-type:abort: +17244 # error("unexpected token when parsing type: '" s "'\n") +17245 (write-buffered *(ebp+0x14) "unexpected token when parsing type: '") +17246 (write-slice-buffered *(ebp+0x14) %ecx) +17247 (write-buffered *(ebp+0x14) "'\n") +17248 (flush *(ebp+0x14)) +17249 (stop *(ebp+0x18) 1) +17250 # never gets here +17251 +17252 parse-type-tree: # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) +17253 # pseudocode: +17254 # var tmp: (handle type-tree) = parse-type(ad, in) +17255 # if tmp == 0 +17256 # return 0 +17257 # out = allocate(Type-tree) +17258 # out->left = tmp +17259 # out->right = parse-type-tree(ad, in) +17260 # +17261 # . prologue +17262 55/push-ebp +17263 89/<- %ebp 4/r32/esp +17264 # . save registers +17265 50/push-eax +17266 51/push-ecx +17267 52/push-edx +17268 # +17269 (zero-out *(ebp+0x10) *Handle-size) +17270 # var tmp/ecx: (handle type-tree) +17271 68/push 0/imm32 +17272 68/push 0/imm32 +17273 89/<- %ecx 4/r32/esp +17274 # tmp = parse-type(ad, in) +17275 (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18)) +17276 # if (tmp == 0) return +17277 81 7/subop/compare *ecx 0/imm32 +17278 74/jump-if-= $parse-type-tree:end/disp8 +17279 # out = new tree +17280 (allocate *(ebp+8) *Type-tree-size *(ebp+0x10)) +17281 # var out-addr/edx: (addr tree) = lookup(*out) +17282 8b/-> *(ebp+0x10) 2/r32/edx +17283 (lookup *edx *(edx+4)) # => eax +17284 89/<- %edx 0/r32/eax +17285 # out->left = tmp +17286 8b/-> *ecx 0/r32/eax +17287 89/<- *(edx+4) 0/r32/eax # Type-tree-left +17288 8b/-> *(ecx+4) 0/r32/eax +17289 89/<- *(edx+8) 0/r32/eax # Type-tree-left +17290 # out->right = parse-type-tree(ad, in) +17291 8d/copy-address *(edx+0xc) 0/r32/eax # Type-tree-right +17292 (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18)) +17293 $parse-type-tree:end: +17294 # . reclaim locals +17295 81 0/subop/add %esp 8/imm32 +17296 # . restore registers +17297 5a/pop-to-edx +17298 59/pop-to-ecx +17299 58/pop-to-eax +17300 # . epilogue +17301 89/<- %esp 5/r32/ebp +17302 5d/pop-to-ebp +17303 c3/return +17304 +17305 next-mu-token: # in: (addr stream byte), out: (addr slice) +17306 # pseudocode: +17307 # start: +17308 # skip-chars-matching-whitespace(in) +17309 # if in->read >= in->write # end of in +17310 # out = {0, 0} +17311 # return +17312 # out->start = &in->data[in->read] +17313 # var curr-byte/eax: byte = in->data[in->read] +17314 # if curr->byte == ',' # comment token +17315 # ++in->read +17316 # goto start +17317 # if curr-byte == '#' # comment +17318 # goto done # treat as eof +17319 # if curr-byte == '"' # string literal +17320 # skip-string(in) +17321 # goto done # no metadata +17322 # if curr-byte == '(' 17323 # ++in->read -17324 # done: -17325 # out->end = &in->data[in->read] -17326 # -17327 # . prologue -17328 55/push-ebp -17329 89/<- %ebp 4/r32/esp -17330 # . save registers -17331 50/push-eax -17332 51/push-ecx -17333 56/push-esi -17334 57/push-edi -17335 # esi = in -17336 8b/-> *(ebp+8) 6/r32/esi -17337 # edi = out -17338 8b/-> *(ebp+0xc) 7/r32/edi -17339 $next-mu-token:start: -17340 (skip-chars-matching-whitespace %esi) -17341 $next-mu-token:check0: -17342 # if (in->read >= in->write) return out = {0, 0} -17343 # . ecx = in->read -17344 8b/-> *(esi+4) 1/r32/ecx -17345 # . if (ecx >= in->write) return out = {0, 0} -17346 3b/compare<- *esi 1/r32/ecx -17347 c7 0/subop/copy *edi 0/imm32 -17348 c7 0/subop/copy *(edi+4) 0/imm32 -17349 0f 8d/jump-if->= $next-mu-token:end/disp32 -17350 # out->start = &in->data[in->read] -17351 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -17352 89/<- *edi 0/r32/eax -17353 # var curr-byte/eax: byte = in->data[in->read] -17354 31/xor-with %eax 0/r32/eax -17355 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -17356 { -17357 $next-mu-token:check-for-comma: -17358 # if (curr-byte != ',') break -17359 3d/compare-eax-and 0x2c/imm32/comma -17360 75/jump-if-!= break/disp8 -17361 # ++in->read -17362 ff 0/subop/increment *(esi+4) -17363 # restart -17364 e9/jump $next-mu-token:start/disp32 -17365 } -17366 { -17367 $next-mu-token:check-for-comment: -17368 # if (curr-byte != '#') break -17369 3d/compare-eax-and 0x23/imm32/pound -17370 75/jump-if-!= break/disp8 -17371 # return eof -17372 e9/jump $next-mu-token:done/disp32 -17373 } -17374 { -17375 $next-mu-token:check-for-string-literal: -17376 # if (curr-byte != '"') break -17377 3d/compare-eax-and 0x22/imm32/dquote -17378 75/jump-if-!= break/disp8 -17379 (skip-string %esi) -17380 # return -17381 e9/jump $next-mu-token:done/disp32 -17382 } -17383 { -17384 $next-mu-token:check-for-open-paren: -17385 # if (curr-byte != '(') break -17386 3d/compare-eax-and 0x28/imm32/open-paren -17387 75/jump-if-!= break/disp8 -17388 # ++in->read -17389 ff 0/subop/increment *(esi+4) -17390 # return -17391 e9/jump $next-mu-token:done/disp32 -17392 } -17393 { -17394 $next-mu-token:check-for-close-paren: -17395 # if (curr-byte != ')') break -17396 3d/compare-eax-and 0x29/imm32/close-paren -17397 75/jump-if-!= break/disp8 -17398 # ++in->read -17399 ff 0/subop/increment *(esi+4) -17400 # return -17401 e9/jump $next-mu-token:done/disp32 -17402 } -17403 { -17404 $next-mu-token:regular-word-without-metadata: -17405 # if (in->read >= in->write) break -17406 # . ecx = in->read -17407 8b/-> *(esi+4) 1/r32/ecx -17408 # . if (ecx >= in->write) break -17409 3b/compare<- *esi 1/r32/ecx -17410 7d/jump-if->= break/disp8 -17411 # var c/eax: byte = in->data[in->read] -17412 31/xor-with %eax 0/r32/eax -17413 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -17414 # if (c == ' ') break -17415 3d/compare-eax-and 0x20/imm32/space -17416 74/jump-if-= break/disp8 -17417 # if (c == '\r') break -17418 3d/compare-eax-and 0xd/imm32/carriage-return -17419 74/jump-if-= break/disp8 -17420 # if (c == '\n') break -17421 3d/compare-eax-and 0xa/imm32/newline -17422 74/jump-if-= break/disp8 -17423 # if (c == '(') break -17424 3d/compare-eax-and 0x28/imm32/open-paren -17425 0f 84/jump-if-= break/disp32 -17426 # if (c == ')') break -17427 3d/compare-eax-and 0x29/imm32/close-paren -17428 0f 84/jump-if-= break/disp32 -17429 # if (c == ',') break -17430 3d/compare-eax-and 0x2c/imm32/comma -17431 0f 84/jump-if-= break/disp32 -17432 # ++in->read -17433 ff 0/subop/increment *(esi+4) -17434 # -17435 e9/jump loop/disp32 -17436 } -17437 $next-mu-token:done: -17438 # out->end = &in->data[in->read] -17439 8b/-> *(esi+4) 1/r32/ecx -17440 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -17441 89/<- *(edi+4) 0/r32/eax -17442 $next-mu-token:end: -17443 # . restore registers -17444 5f/pop-to-edi -17445 5e/pop-to-esi -17446 59/pop-to-ecx -17447 58/pop-to-eax -17448 # . epilogue -17449 89/<- %esp 5/r32/ebp -17450 5d/pop-to-ebp -17451 c3/return -17452 -17453 pos-or-insert-slice: # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int -17454 # . prologue -17455 55/push-ebp -17456 89/<- %ebp 4/r32/esp -17457 # if (pos-slice(arr, s) != -1) return it -17458 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax -17459 3d/compare-eax-and -1/imm32 -17460 75/jump-if-!= $pos-or-insert-slice:end/disp8 -17461 $pos-or-insert-slice:insert: -17462 # var s2/eax: (handle array byte) -17463 68/push 0/imm32 -17464 68/push 0/imm32 -17465 89/<- %eax 4/r32/esp -17466 (slice-to-string Heap *(ebp+0xc) %eax) -17467 # throw away alloc-id -17468 (lookup *eax *(eax+4)) # => eax -17469 (write-int *(ebp+8) %eax) -17470 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax -17471 $pos-or-insert-slice:end: -17472 # . reclaim locals -17473 81 0/subop/add %esp 8/imm32 -17474 # . epilogue -17475 89/<- %esp 5/r32/ebp -17476 5d/pop-to-ebp -17477 c3/return -17478 -17479 # return the index in an array of strings matching 's', -1 if not found -17480 # index is denominated in elements, not bytes -17481 pos-slice: # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int -17482 # . prologue -17483 55/push-ebp -17484 89/<- %ebp 4/r32/esp -17485 # . save registers -17486 51/push-ecx -17487 52/push-edx -17488 53/push-ebx -17489 56/push-esi -17490 #? (write-buffered Stderr "pos-slice: ") -17491 #? (write-slice-buffered Stderr *(ebp+0xc)) -17492 #? (write-buffered Stderr "\n") -17493 #? (flush Stderr) -17494 # esi = arr -17495 8b/-> *(ebp+8) 6/r32/esi -17496 # var index/ecx: int = 0 -17497 b9/copy-to-ecx 0/imm32 -17498 # var curr/edx: (addr (addr array byte)) = arr->data -17499 8d/copy-address *(esi+0xc) 2/r32/edx -17500 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -17501 8b/-> *esi 3/r32/ebx -17502 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -17503 { -17504 #? (write-buffered Stderr " ") -17505 #? (write-int32-hex-buffered Stderr %ecx) -17506 #? (write-buffered Stderr "\n") -17507 #? (flush Stderr) -17508 # if (curr >= max) return -1 -17509 39/compare %edx 3/r32/ebx -17510 b8/copy-to-eax -1/imm32 -17511 73/jump-if-addr>= $pos-slice:end/disp8 -17512 # if (slice-equal?(s, *curr)) break -17513 (slice-equal? *(ebp+0xc) *edx) # => eax -17514 3d/compare-eax-and 0/imm32/false -17515 75/jump-if-!= break/disp8 -17516 # ++index -17517 41/increment-ecx -17518 # curr += 4 -17519 81 0/subop/add %edx 4/imm32 -17520 # -17521 eb/jump loop/disp8 -17522 } -17523 # return index -17524 89/<- %eax 1/r32/ecx -17525 $pos-slice:end: -17526 #? (write-buffered Stderr "=> ") -17527 #? (write-int32-hex-buffered Stderr %eax) -17528 #? (write-buffered Stderr "\n") -17529 # . restore registers -17530 5e/pop-to-esi -17531 5b/pop-to-ebx -17532 5a/pop-to-edx -17533 59/pop-to-ecx -17534 # . epilogue -17535 89/<- %esp 5/r32/ebp -17536 5d/pop-to-ebp -17537 c3/return -17538 -17539 test-parse-var-with-type: -17540 # . prologue -17541 55/push-ebp -17542 89/<- %ebp 4/r32/esp -17543 # setup -17544 8b/-> *Primitive-type-ids 0/r32/eax -17545 89/<- *Type-id 0/r32/eax # stream-write -17546 # (eax..ecx) = "x:" -17547 b8/copy-to-eax "x:"/imm32 -17548 8b/-> *eax 1/r32/ecx -17549 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17550 05/add-to-eax 4/imm32 -17551 # var slice/ecx: slice = {eax, ecx} -17552 51/push-ecx -17553 50/push-eax -17554 89/<- %ecx 4/r32/esp -17555 # _test-input-stream contains "int" -17556 (clear-stream _test-input-stream) -17557 (write _test-input-stream "int") -17558 # var v/edx: (handle var) -17559 68/push 0/imm32 -17560 68/push 0/imm32 -17561 89/<- %edx 4/r32/esp -17562 # -17563 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) -17564 # var v-addr/edx: (addr var) = lookup(v) -17565 (lookup *edx *(edx+4)) # => eax -17566 89/<- %edx 0/r32/eax -17567 # check v-addr->name -17568 (lookup *edx *(edx+4)) # Var-name Var-name => eax -17569 (check-strings-equal %eax "x" "F - test-parse-var-with-type/name") -17570 # check v-addr->type -17571 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -17572 (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0") # Type-tree-is-atom -17573 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1") # Type-tree-value -17574 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2") # Type-tree-right -17575 # . epilogue -17576 89/<- %esp 5/r32/ebp -17577 5d/pop-to-ebp -17578 c3/return -17579 -17580 test-parse-var-with-type-and-register: -17581 # . prologue -17582 55/push-ebp -17583 89/<- %ebp 4/r32/esp -17584 # setup -17585 8b/-> *Primitive-type-ids 0/r32/eax -17586 89/<- *Type-id 0/r32/eax # stream-write -17587 # (eax..ecx) = "x/eax:" -17588 b8/copy-to-eax "x/eax:"/imm32 -17589 8b/-> *eax 1/r32/ecx -17590 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17591 05/add-to-eax 4/imm32 -17592 # var slice/ecx: slice = {eax, ecx} -17593 51/push-ecx -17594 50/push-eax -17595 89/<- %ecx 4/r32/esp -17596 # _test-input-stream contains "int" -17597 (clear-stream _test-input-stream) -17598 (write _test-input-stream "int") -17599 # var v/edx: (handle var) -17600 68/push 0/imm32 -17601 68/push 0/imm32 -17602 89/<- %edx 4/r32/esp -17603 # -17604 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) -17605 # var v-addr/edx: (addr var) = lookup(v) -17606 (lookup *edx *(edx+4)) # => eax -17607 89/<- %edx 0/r32/eax -17608 # check v-addr->name -17609 (lookup *edx *(edx+4)) # Var-name Var-name => eax -17610 (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name") -17611 # check v-addr->register -17612 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -17613 (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register") -17614 # check v-addr->type -17615 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -17616 (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0") # Type-tree-is-atom -17617 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1") # Type-tree-left -17618 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2") # Type-tree-right -17619 # . epilogue -17620 89/<- %esp 5/r32/ebp -17621 5d/pop-to-ebp -17622 c3/return -17623 -17624 test-parse-var-with-trailing-characters: -17625 # . prologue -17626 55/push-ebp -17627 89/<- %ebp 4/r32/esp -17628 # setup -17629 8b/-> *Primitive-type-ids 0/r32/eax -17630 89/<- *Type-id 0/r32/eax # stream-write -17631 # (eax..ecx) = "x:" -17632 b8/copy-to-eax "x:"/imm32 -17633 8b/-> *eax 1/r32/ecx -17634 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17635 05/add-to-eax 4/imm32 -17636 # var slice/ecx: slice = {eax, ecx} -17637 51/push-ecx -17638 50/push-eax -17639 89/<- %ecx 4/r32/esp -17640 # _test-input-stream contains "int," -17641 (clear-stream _test-input-stream) -17642 (write _test-input-stream "int,") -17643 # var v/edx: (handle var) -17644 68/push 0/imm32 -17645 68/push 0/imm32 -17646 89/<- %edx 4/r32/esp -17647 # -17648 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) -17649 # var v-addr/edx: (addr var) = lookup(v) -17650 (lookup *edx *(edx+4)) # => eax -17651 89/<- %edx 0/r32/eax -17652 # check v-addr->name -17653 (lookup *edx *(edx+4)) # Var-name Var-name => eax -17654 (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name") -17655 # check v-addr->register -17656 (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register") # Var-register -17657 # check v-addr->type -17658 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -17659 (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0") # Type-tree-is-atom -17660 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1") # Type-tree-left -17661 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1") # Type-tree-right -17662 # . epilogue -17663 89/<- %esp 5/r32/ebp -17664 5d/pop-to-ebp -17665 c3/return -17666 -17667 test-parse-var-with-register-and-trailing-characters: -17668 # . prologue -17669 55/push-ebp -17670 89/<- %ebp 4/r32/esp -17671 # setup -17672 8b/-> *Primitive-type-ids 0/r32/eax -17673 89/<- *Type-id 0/r32/eax # stream-write -17674 # (eax..ecx) = "x/eax:" -17675 b8/copy-to-eax "x/eax:"/imm32 -17676 8b/-> *eax 1/r32/ecx -17677 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17678 05/add-to-eax 4/imm32 -17679 # var slice/ecx: slice = {eax, ecx} -17680 51/push-ecx -17681 50/push-eax -17682 89/<- %ecx 4/r32/esp -17683 # _test-input-stream contains "int," -17684 (clear-stream _test-input-stream) -17685 (write _test-input-stream "int,") -17686 # var v/edx: (handle var) -17687 68/push 0/imm32 -17688 68/push 0/imm32 -17689 89/<- %edx 4/r32/esp -17690 # -17691 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) -17692 # var v-addr/edx: (addr var) = lookup(v) -17693 (lookup *edx *(edx+4)) # => eax -17694 89/<- %edx 0/r32/eax -17695 # check v-addr->name -17696 (lookup *edx *(edx+4)) # Var-name Var-name => eax -17697 (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name") -17698 # check v-addr->register -17699 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -17700 (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register") -17701 # check v-addr->type -17702 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -17703 (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0") # Type-tree-is-atom -17704 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1") # Type-tree-left -17705 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2") # Type-tree-right -17706 # . epilogue -17707 89/<- %esp 5/r32/ebp -17708 5d/pop-to-ebp -17709 c3/return -17710 -17711 test-parse-var-with-compound-type: -17712 # . prologue -17713 55/push-ebp -17714 89/<- %ebp 4/r32/esp -17715 # setup -17716 8b/-> *Primitive-type-ids 0/r32/eax -17717 89/<- *Type-id 0/r32/eax # stream-write -17718 # (eax..ecx) = "x:" -17719 b8/copy-to-eax "x:"/imm32 -17720 8b/-> *eax 1/r32/ecx -17721 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17722 05/add-to-eax 4/imm32 -17723 # var slice/ecx: slice = {eax, ecx} -17724 51/push-ecx -17725 50/push-eax -17726 89/<- %ecx 4/r32/esp -17727 # _test-input-stream contains "(addr int)" -17728 (clear-stream _test-input-stream) -17729 (write _test-input-stream "(addr int)") -17730 # var v/edx: (handle var) -17731 68/push 0/imm32 -17732 68/push 0/imm32 -17733 89/<- %edx 4/r32/esp -17734 # -17735 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) -17736 # var v-addr/edx: (addr var) = lookup(v) -17737 (lookup *edx *(edx+4)) # => eax -17738 89/<- %edx 0/r32/eax -17739 # check v-addr->name -17740 (lookup *edx *(edx+4)) # Var-name Var-name => eax -17741 (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name") -17742 # check v-addr->register -17743 (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register") # Var-register -17744 # - check v-addr->type -17745 # var type/edx: (addr type-tree) = var->type -17746 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -17747 89/<- %edx 0/r32/eax -17748 # type is a non-atom -17749 (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0") # Type-tree-is-atom -17750 # type->left == atom(addr) -17751 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -17752 (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1") # Type-tree-is-atom -17753 (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2") # Type-tree-value -17754 # type->right->left == atom(int) -17755 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax -17756 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -17757 (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3") # Type-tree-is-atom -17758 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4") # Type-tree-value -17759 # type->right->right == null -17760 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5") # Type-tree-right -17761 # . epilogue -17762 89/<- %esp 5/r32/ebp -17763 5d/pop-to-ebp -17764 c3/return -17765 -17766 # identifier starts with a letter or '$' or '_' -17767 # no constraints at the moment on later letters -17768 # all we really want to do so far is exclude '{', '}' and '->' -17769 identifier?: # in: (addr slice) -> result/eax: boolean -17770 # . prologue -17771 55/push-ebp -17772 89/<- %ebp 4/r32/esp -17773 # if (slice-empty?(in)) return false -17774 (slice-empty? *(ebp+8)) # => eax -17775 3d/compare-eax-and 0/imm32/false -17776 75/jump-if-!= $identifier?:false/disp8 -17777 # var c/eax: byte = *in->start -17778 8b/-> *(ebp+8) 0/r32/eax -17779 8b/-> *eax 0/r32/eax -17780 8a/copy-byte *eax 0/r32/AL -17781 81 4/subop/and %eax 0xff/imm32 -17782 # if (c == '$') return true -17783 3d/compare-eax-and 0x24/imm32/$ -17784 74/jump-if-= $identifier?:true/disp8 -17785 # if (c == '_') return true -17786 3d/compare-eax-and 0x5f/imm32/_ -17787 74/jump-if-= $identifier?:true/disp8 -17788 # drop case -17789 25/and-eax-with 0x5f/imm32 -17790 # if (c < 'A') return false -17791 3d/compare-eax-and 0x41/imm32/A -17792 7c/jump-if-< $identifier?:false/disp8 -17793 # if (c > 'Z') return false -17794 3d/compare-eax-and 0x5a/imm32/Z -17795 7f/jump-if-> $identifier?:false/disp8 -17796 # otherwise return true -17797 $identifier?:true: -17798 b8/copy-to-eax 1/imm32/true -17799 eb/jump $identifier?:end/disp8 -17800 $identifier?:false: -17801 b8/copy-to-eax 0/imm32/false -17802 $identifier?:end: -17803 # . epilogue -17804 89/<- %esp 5/r32/ebp -17805 5d/pop-to-ebp -17806 c3/return -17807 -17808 test-is-identifier-dollar: -17809 # . prologue -17810 55/push-ebp -17811 89/<- %ebp 4/r32/esp -17812 # (eax..ecx) = "$a" -17813 b8/copy-to-eax "$a"/imm32 -17814 8b/-> *eax 1/r32/ecx -17815 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17816 05/add-to-eax 4/imm32 -17817 # var slice/ecx: slice = {eax, ecx} -17818 51/push-ecx -17819 50/push-eax -17820 89/<- %ecx 4/r32/esp -17821 # -17822 (identifier? %ecx) -17823 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -17824 # . epilogue -17825 89/<- %esp 5/r32/ebp -17826 5d/pop-to-ebp -17827 c3/return -17828 -17829 test-is-identifier-underscore: -17830 # . prologue -17831 55/push-ebp -17832 89/<- %ebp 4/r32/esp -17833 # (eax..ecx) = "_a" -17834 b8/copy-to-eax "_a"/imm32 -17835 8b/-> *eax 1/r32/ecx -17836 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17837 05/add-to-eax 4/imm32 -17838 # var slice/ecx: slice = {eax, ecx} -17839 51/push-ecx -17840 50/push-eax -17841 89/<- %ecx 4/r32/esp -17842 # -17843 (identifier? %ecx) -17844 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -17845 # . epilogue -17846 89/<- %esp 5/r32/ebp -17847 5d/pop-to-ebp -17848 c3/return -17849 -17850 test-is-identifier-a: -17851 # . prologue -17852 55/push-ebp -17853 89/<- %ebp 4/r32/esp -17854 # (eax..ecx) = "a$" -17855 b8/copy-to-eax "a$"/imm32 -17856 8b/-> *eax 1/r32/ecx -17857 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17858 05/add-to-eax 4/imm32 -17859 # var slice/ecx: slice = {eax, ecx} -17860 51/push-ecx -17861 50/push-eax -17862 89/<- %ecx 4/r32/esp -17863 # -17864 (identifier? %ecx) -17865 (check-ints-equal %eax 1 "F - test-is-identifier-a") -17866 # . epilogue -17867 89/<- %esp 5/r32/ebp -17868 5d/pop-to-ebp -17869 c3/return -17870 -17871 test-is-identifier-z: -17872 # . prologue -17873 55/push-ebp -17874 89/<- %ebp 4/r32/esp -17875 # (eax..ecx) = "z$" -17876 b8/copy-to-eax "z$"/imm32 -17877 8b/-> *eax 1/r32/ecx -17878 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17879 05/add-to-eax 4/imm32 -17880 # var slice/ecx: slice = {eax, ecx} -17881 51/push-ecx -17882 50/push-eax -17883 89/<- %ecx 4/r32/esp -17884 # -17885 (identifier? %ecx) -17886 (check-ints-equal %eax 1 "F - test-is-identifier-z") -17887 # . epilogue -17888 89/<- %esp 5/r32/ebp -17889 5d/pop-to-ebp -17890 c3/return -17891 -17892 test-is-identifier-A: -17893 # . prologue -17894 55/push-ebp -17895 89/<- %ebp 4/r32/esp -17896 # (eax..ecx) = "A$" -17897 b8/copy-to-eax "A$"/imm32 -17898 8b/-> *eax 1/r32/ecx -17899 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17900 05/add-to-eax 4/imm32 -17901 # var slice/ecx: slice = {eax, ecx} -17902 51/push-ecx -17903 50/push-eax -17904 89/<- %ecx 4/r32/esp -17905 # -17906 (identifier? %ecx) -17907 (check-ints-equal %eax 1 "F - test-is-identifier-A") -17908 # . epilogue -17909 89/<- %esp 5/r32/ebp -17910 5d/pop-to-ebp -17911 c3/return -17912 -17913 test-is-identifier-Z: -17914 # . prologue -17915 55/push-ebp -17916 89/<- %ebp 4/r32/esp -17917 # (eax..ecx) = "Z$" -17918 b8/copy-to-eax "Z$"/imm32 -17919 8b/-> *eax 1/r32/ecx -17920 8d/copy-address *(eax+ecx+4) 1/r32/ecx -17921 05/add-to-eax 4/imm32 -17922 # var slice/ecx: slice = {eax, ecx} -17923 51/push-ecx -17924 50/push-eax -17925 89/<- %ecx 4/r32/esp -17926 # -17927 (identifier? %ecx) -17928 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -17929 # . epilogue -17930 89/<- %esp 5/r32/ebp -17931 5d/pop-to-ebp -17932 c3/return -17933 -17934 test-is-identifier-at: -17935 # character before 'A' is invalid +17324 # goto done +17325 # if curr-byte == ')' +17326 # ++in->read +17327 # goto done +17328 # # read a word +17329 # while true +17330 # if in->read >= in->write +17331 # break +17332 # curr-byte = in->data[in->read] +17333 # if curr-byte == ' ' +17334 # break +17335 # if curr-byte == '\r' +17336 # break +17337 # if curr-byte == '\n' +17338 # break +17339 # if curr-byte == '(' +17340 # break +17341 # if curr-byte == ')' +17342 # break +17343 # if curr-byte == ',' +17344 # break +17345 # ++in->read +17346 # done: +17347 # out->end = &in->data[in->read] +17348 # +17349 # . prologue +17350 55/push-ebp +17351 89/<- %ebp 4/r32/esp +17352 # . save registers +17353 50/push-eax +17354 51/push-ecx +17355 56/push-esi +17356 57/push-edi +17357 # esi = in +17358 8b/-> *(ebp+8) 6/r32/esi +17359 # edi = out +17360 8b/-> *(ebp+0xc) 7/r32/edi +17361 $next-mu-token:start: +17362 (skip-chars-matching-whitespace %esi) +17363 $next-mu-token:check0: +17364 # if (in->read >= in->write) return out = {0, 0} +17365 # . ecx = in->read +17366 8b/-> *(esi+4) 1/r32/ecx +17367 # . if (ecx >= in->write) return out = {0, 0} +17368 3b/compare<- *esi 1/r32/ecx +17369 c7 0/subop/copy *edi 0/imm32 +17370 c7 0/subop/copy *(edi+4) 0/imm32 +17371 0f 8d/jump-if->= $next-mu-token:end/disp32 +17372 # out->start = &in->data[in->read] +17373 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +17374 89/<- *edi 0/r32/eax +17375 # var curr-byte/eax: byte = in->data[in->read] +17376 31/xor-with %eax 0/r32/eax +17377 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +17378 { +17379 $next-mu-token:check-for-comma: +17380 # if (curr-byte != ',') break +17381 3d/compare-eax-and 0x2c/imm32/comma +17382 75/jump-if-!= break/disp8 +17383 # ++in->read +17384 ff 0/subop/increment *(esi+4) +17385 # restart +17386 e9/jump $next-mu-token:start/disp32 +17387 } +17388 { +17389 $next-mu-token:check-for-comment: +17390 # if (curr-byte != '#') break +17391 3d/compare-eax-and 0x23/imm32/pound +17392 75/jump-if-!= break/disp8 +17393 # return eof +17394 e9/jump $next-mu-token:done/disp32 +17395 } +17396 { +17397 $next-mu-token:check-for-string-literal: +17398 # if (curr-byte != '"') break +17399 3d/compare-eax-and 0x22/imm32/dquote +17400 75/jump-if-!= break/disp8 +17401 (skip-string %esi) +17402 # return +17403 e9/jump $next-mu-token:done/disp32 +17404 } +17405 { +17406 $next-mu-token:check-for-open-paren: +17407 # if (curr-byte != '(') break +17408 3d/compare-eax-and 0x28/imm32/open-paren +17409 75/jump-if-!= break/disp8 +17410 # ++in->read +17411 ff 0/subop/increment *(esi+4) +17412 # return +17413 e9/jump $next-mu-token:done/disp32 +17414 } +17415 { +17416 $next-mu-token:check-for-close-paren: +17417 # if (curr-byte != ')') break +17418 3d/compare-eax-and 0x29/imm32/close-paren +17419 75/jump-if-!= break/disp8 +17420 # ++in->read +17421 ff 0/subop/increment *(esi+4) +17422 # return +17423 e9/jump $next-mu-token:done/disp32 +17424 } +17425 { +17426 $next-mu-token:regular-word-without-metadata: +17427 # if (in->read >= in->write) break +17428 # . ecx = in->read +17429 8b/-> *(esi+4) 1/r32/ecx +17430 # . if (ecx >= in->write) break +17431 3b/compare<- *esi 1/r32/ecx +17432 7d/jump-if->= break/disp8 +17433 # var c/eax: byte = in->data[in->read] +17434 31/xor-with %eax 0/r32/eax +17435 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +17436 # if (c == ' ') break +17437 3d/compare-eax-and 0x20/imm32/space +17438 74/jump-if-= break/disp8 +17439 # if (c == '\r') break +17440 3d/compare-eax-and 0xd/imm32/carriage-return +17441 74/jump-if-= break/disp8 +17442 # if (c == '\n') break +17443 3d/compare-eax-and 0xa/imm32/newline +17444 74/jump-if-= break/disp8 +17445 # if (c == '(') break +17446 3d/compare-eax-and 0x28/imm32/open-paren +17447 0f 84/jump-if-= break/disp32 +17448 # if (c == ')') break +17449 3d/compare-eax-and 0x29/imm32/close-paren +17450 0f 84/jump-if-= break/disp32 +17451 # if (c == ',') break +17452 3d/compare-eax-and 0x2c/imm32/comma +17453 0f 84/jump-if-= break/disp32 +17454 # ++in->read +17455 ff 0/subop/increment *(esi+4) +17456 # +17457 e9/jump loop/disp32 +17458 } +17459 $next-mu-token:done: +17460 # out->end = &in->data[in->read] +17461 8b/-> *(esi+4) 1/r32/ecx +17462 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +17463 89/<- *(edi+4) 0/r32/eax +17464 $next-mu-token:end: +17465 # . restore registers +17466 5f/pop-to-edi +17467 5e/pop-to-esi +17468 59/pop-to-ecx +17469 58/pop-to-eax +17470 # . epilogue +17471 89/<- %esp 5/r32/ebp +17472 5d/pop-to-ebp +17473 c3/return +17474 +17475 pos-or-insert-slice: # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int +17476 # . prologue +17477 55/push-ebp +17478 89/<- %ebp 4/r32/esp +17479 # if (pos-slice(arr, s) != -1) return it +17480 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax +17481 3d/compare-eax-and -1/imm32 +17482 75/jump-if-!= $pos-or-insert-slice:end/disp8 +17483 $pos-or-insert-slice:insert: +17484 # var s2/eax: (handle array byte) +17485 68/push 0/imm32 +17486 68/push 0/imm32 +17487 89/<- %eax 4/r32/esp +17488 (slice-to-string Heap *(ebp+0xc) %eax) +17489 # throw away alloc-id +17490 (lookup *eax *(eax+4)) # => eax +17491 (write-int *(ebp+8) %eax) +17492 (pos-slice *(ebp+8) *(ebp+0xc)) # => eax +17493 $pos-or-insert-slice:end: +17494 # . reclaim locals +17495 81 0/subop/add %esp 8/imm32 +17496 # . epilogue +17497 89/<- %esp 5/r32/ebp +17498 5d/pop-to-ebp +17499 c3/return +17500 +17501 # return the index in an array of strings matching 's', -1 if not found +17502 # index is denominated in elements, not bytes +17503 pos-slice: # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int +17504 # . prologue +17505 55/push-ebp +17506 89/<- %ebp 4/r32/esp +17507 # . save registers +17508 51/push-ecx +17509 52/push-edx +17510 53/push-ebx +17511 56/push-esi +17512 #? (write-buffered Stderr "pos-slice: ") +17513 #? (write-slice-buffered Stderr *(ebp+0xc)) +17514 #? (write-buffered Stderr "\n") +17515 #? (flush Stderr) +17516 # esi = arr +17517 8b/-> *(ebp+8) 6/r32/esi +17518 # var index/ecx: int = 0 +17519 b9/copy-to-ecx 0/imm32 +17520 # var curr/edx: (addr (addr array byte)) = arr->data +17521 8d/copy-address *(esi+0xc) 2/r32/edx +17522 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] +17523 8b/-> *esi 3/r32/ebx +17524 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx +17525 { +17526 #? (write-buffered Stderr " ") +17527 #? (write-int32-hex-buffered Stderr %ecx) +17528 #? (write-buffered Stderr "\n") +17529 #? (flush Stderr) +17530 # if (curr >= max) return -1 +17531 39/compare %edx 3/r32/ebx +17532 b8/copy-to-eax -1/imm32 +17533 73/jump-if-addr>= $pos-slice:end/disp8 +17534 # if (slice-equal?(s, *curr)) break +17535 (slice-equal? *(ebp+0xc) *edx) # => eax +17536 3d/compare-eax-and 0/imm32/false +17537 75/jump-if-!= break/disp8 +17538 # ++index +17539 41/increment-ecx +17540 # curr += 4 +17541 81 0/subop/add %edx 4/imm32 +17542 # +17543 eb/jump loop/disp8 +17544 } +17545 # return index +17546 89/<- %eax 1/r32/ecx +17547 $pos-slice:end: +17548 #? (write-buffered Stderr "=> ") +17549 #? (write-int32-hex-buffered Stderr %eax) +17550 #? (write-buffered Stderr "\n") +17551 # . restore registers +17552 5e/pop-to-esi +17553 5b/pop-to-ebx +17554 5a/pop-to-edx +17555 59/pop-to-ecx +17556 # . epilogue +17557 89/<- %esp 5/r32/ebp +17558 5d/pop-to-ebp +17559 c3/return +17560 +17561 test-parse-var-with-type: +17562 # . prologue +17563 55/push-ebp +17564 89/<- %ebp 4/r32/esp +17565 # setup +17566 8b/-> *Primitive-type-ids 0/r32/eax +17567 89/<- *Type-id 0/r32/eax # stream-write +17568 # (eax..ecx) = "x:" +17569 b8/copy-to-eax "x:"/imm32 +17570 8b/-> *eax 1/r32/ecx +17571 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17572 05/add-to-eax 4/imm32 +17573 # var slice/ecx: slice = {eax, ecx} +17574 51/push-ecx +17575 50/push-eax +17576 89/<- %ecx 4/r32/esp +17577 # _test-input-stream contains "int" +17578 (clear-stream _test-input-stream) +17579 (write _test-input-stream "int") +17580 # var v/edx: (handle var) +17581 68/push 0/imm32 +17582 68/push 0/imm32 +17583 89/<- %edx 4/r32/esp +17584 # +17585 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) +17586 # var v-addr/edx: (addr var) = lookup(v) +17587 (lookup *edx *(edx+4)) # => eax +17588 89/<- %edx 0/r32/eax +17589 # check v-addr->name +17590 (lookup *edx *(edx+4)) # Var-name Var-name => eax +17591 (check-strings-equal %eax "x" "F - test-parse-var-with-type/name") +17592 # check v-addr->type +17593 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +17594 (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0") # Type-tree-is-atom +17595 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1") # Type-tree-value +17596 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2") # Type-tree-right +17597 # . epilogue +17598 89/<- %esp 5/r32/ebp +17599 5d/pop-to-ebp +17600 c3/return +17601 +17602 test-parse-var-with-type-and-register: +17603 # . prologue +17604 55/push-ebp +17605 89/<- %ebp 4/r32/esp +17606 # setup +17607 8b/-> *Primitive-type-ids 0/r32/eax +17608 89/<- *Type-id 0/r32/eax # stream-write +17609 # (eax..ecx) = "x/eax:" +17610 b8/copy-to-eax "x/eax:"/imm32 +17611 8b/-> *eax 1/r32/ecx +17612 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17613 05/add-to-eax 4/imm32 +17614 # var slice/ecx: slice = {eax, ecx} +17615 51/push-ecx +17616 50/push-eax +17617 89/<- %ecx 4/r32/esp +17618 # _test-input-stream contains "int" +17619 (clear-stream _test-input-stream) +17620 (write _test-input-stream "int") +17621 # var v/edx: (handle var) +17622 68/push 0/imm32 +17623 68/push 0/imm32 +17624 89/<- %edx 4/r32/esp +17625 # +17626 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) +17627 # var v-addr/edx: (addr var) = lookup(v) +17628 (lookup *edx *(edx+4)) # => eax +17629 89/<- %edx 0/r32/eax +17630 # check v-addr->name +17631 (lookup *edx *(edx+4)) # Var-name Var-name => eax +17632 (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name") +17633 # check v-addr->register +17634 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +17635 (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register") +17636 # check v-addr->type +17637 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +17638 (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0") # Type-tree-is-atom +17639 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1") # Type-tree-left +17640 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2") # Type-tree-right +17641 # . epilogue +17642 89/<- %esp 5/r32/ebp +17643 5d/pop-to-ebp +17644 c3/return +17645 +17646 test-parse-var-with-trailing-characters: +17647 # . prologue +17648 55/push-ebp +17649 89/<- %ebp 4/r32/esp +17650 # setup +17651 8b/-> *Primitive-type-ids 0/r32/eax +17652 89/<- *Type-id 0/r32/eax # stream-write +17653 # (eax..ecx) = "x:" +17654 b8/copy-to-eax "x:"/imm32 +17655 8b/-> *eax 1/r32/ecx +17656 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17657 05/add-to-eax 4/imm32 +17658 # var slice/ecx: slice = {eax, ecx} +17659 51/push-ecx +17660 50/push-eax +17661 89/<- %ecx 4/r32/esp +17662 # _test-input-stream contains "int," +17663 (clear-stream _test-input-stream) +17664 (write _test-input-stream "int,") +17665 # var v/edx: (handle var) +17666 68/push 0/imm32 +17667 68/push 0/imm32 +17668 89/<- %edx 4/r32/esp +17669 # +17670 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) +17671 # var v-addr/edx: (addr var) = lookup(v) +17672 (lookup *edx *(edx+4)) # => eax +17673 89/<- %edx 0/r32/eax +17674 # check v-addr->name +17675 (lookup *edx *(edx+4)) # Var-name Var-name => eax +17676 (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name") +17677 # check v-addr->register +17678 (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register") # Var-register +17679 # check v-addr->type +17680 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +17681 (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0") # Type-tree-is-atom +17682 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1") # Type-tree-left +17683 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1") # Type-tree-right +17684 # . epilogue +17685 89/<- %esp 5/r32/ebp +17686 5d/pop-to-ebp +17687 c3/return +17688 +17689 test-parse-var-with-register-and-trailing-characters: +17690 # . prologue +17691 55/push-ebp +17692 89/<- %ebp 4/r32/esp +17693 # setup +17694 8b/-> *Primitive-type-ids 0/r32/eax +17695 89/<- *Type-id 0/r32/eax # stream-write +17696 # (eax..ecx) = "x/eax:" +17697 b8/copy-to-eax "x/eax:"/imm32 +17698 8b/-> *eax 1/r32/ecx +17699 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17700 05/add-to-eax 4/imm32 +17701 # var slice/ecx: slice = {eax, ecx} +17702 51/push-ecx +17703 50/push-eax +17704 89/<- %ecx 4/r32/esp +17705 # _test-input-stream contains "int," +17706 (clear-stream _test-input-stream) +17707 (write _test-input-stream "int,") +17708 # var v/edx: (handle var) +17709 68/push 0/imm32 +17710 68/push 0/imm32 +17711 89/<- %edx 4/r32/esp +17712 # +17713 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) +17714 # var v-addr/edx: (addr var) = lookup(v) +17715 (lookup *edx *(edx+4)) # => eax +17716 89/<- %edx 0/r32/eax +17717 # check v-addr->name +17718 (lookup *edx *(edx+4)) # Var-name Var-name => eax +17719 (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name") +17720 # check v-addr->register +17721 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +17722 (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register") +17723 # check v-addr->type +17724 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +17725 (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0") # Type-tree-is-atom +17726 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1") # Type-tree-left +17727 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2") # Type-tree-right +17728 # . epilogue +17729 89/<- %esp 5/r32/ebp +17730 5d/pop-to-ebp +17731 c3/return +17732 +17733 test-parse-var-with-compound-type: +17734 # . prologue +17735 55/push-ebp +17736 89/<- %ebp 4/r32/esp +17737 # setup +17738 8b/-> *Primitive-type-ids 0/r32/eax +17739 89/<- *Type-id 0/r32/eax # stream-write +17740 # (eax..ecx) = "x:" +17741 b8/copy-to-eax "x:"/imm32 +17742 8b/-> *eax 1/r32/ecx +17743 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17744 05/add-to-eax 4/imm32 +17745 # var slice/ecx: slice = {eax, ecx} +17746 51/push-ecx +17747 50/push-eax +17748 89/<- %ecx 4/r32/esp +17749 # _test-input-stream contains "(addr int)" +17750 (clear-stream _test-input-stream) +17751 (write _test-input-stream "(addr int)") +17752 # var v/edx: (handle var) +17753 68/push 0/imm32 +17754 68/push 0/imm32 +17755 89/<- %edx 4/r32/esp +17756 # +17757 (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0) +17758 # var v-addr/edx: (addr var) = lookup(v) +17759 (lookup *edx *(edx+4)) # => eax +17760 89/<- %edx 0/r32/eax +17761 # check v-addr->name +17762 (lookup *edx *(edx+4)) # Var-name Var-name => eax +17763 (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name") +17764 # check v-addr->register +17765 (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register") # Var-register +17766 # - check v-addr->type +17767 # var type/edx: (addr type-tree) = var->type +17768 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +17769 89/<- %edx 0/r32/eax +17770 # type is a non-atom +17771 (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0") # Type-tree-is-atom +17772 # type->left == atom(addr) +17773 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +17774 (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1") # Type-tree-is-atom +17775 (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2") # Type-tree-value +17776 # type->right->left == atom(int) +17777 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax +17778 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +17779 (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3") # Type-tree-is-atom +17780 (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4") # Type-tree-value +17781 # type->right->right == null +17782 (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5") # Type-tree-right +17783 # . epilogue +17784 89/<- %esp 5/r32/ebp +17785 5d/pop-to-ebp +17786 c3/return +17787 +17788 # identifier starts with a letter or '$' or '_' +17789 # no constraints at the moment on later letters +17790 # all we really want to do so far is exclude '{', '}' and '->' +17791 identifier?: # in: (addr slice) -> result/eax: boolean +17792 # . prologue +17793 55/push-ebp +17794 89/<- %ebp 4/r32/esp +17795 # if (slice-empty?(in)) return false +17796 (slice-empty? *(ebp+8)) # => eax +17797 3d/compare-eax-and 0/imm32/false +17798 75/jump-if-!= $identifier?:false/disp8 +17799 # var c/eax: byte = *in->start +17800 8b/-> *(ebp+8) 0/r32/eax +17801 8b/-> *eax 0/r32/eax +17802 8a/copy-byte *eax 0/r32/AL +17803 25/and-eax-with 0xff/imm32 +17804 # if (c == '$') return true +17805 3d/compare-eax-and 0x24/imm32/$ +17806 74/jump-if-= $identifier?:true/disp8 +17807 # if (c == '_') return true +17808 3d/compare-eax-and 0x5f/imm32/_ +17809 74/jump-if-= $identifier?:true/disp8 +17810 # drop case +17811 25/and-eax-with 0x5f/imm32 +17812 # if (c < 'A') return false +17813 3d/compare-eax-and 0x41/imm32/A +17814 7c/jump-if-< $identifier?:false/disp8 +17815 # if (c > 'Z') return false +17816 3d/compare-eax-and 0x5a/imm32/Z +17817 7f/jump-if-> $identifier?:false/disp8 +17818 # otherwise return true +17819 $identifier?:true: +17820 b8/copy-to-eax 1/imm32/true +17821 eb/jump $identifier?:end/disp8 +17822 $identifier?:false: +17823 b8/copy-to-eax 0/imm32/false +17824 $identifier?:end: +17825 # . epilogue +17826 89/<- %esp 5/r32/ebp +17827 5d/pop-to-ebp +17828 c3/return +17829 +17830 test-is-identifier-dollar: +17831 # . prologue +17832 55/push-ebp +17833 89/<- %ebp 4/r32/esp +17834 # (eax..ecx) = "$a" +17835 b8/copy-to-eax "$a"/imm32 +17836 8b/-> *eax 1/r32/ecx +17837 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17838 05/add-to-eax 4/imm32 +17839 # var slice/ecx: slice = {eax, ecx} +17840 51/push-ecx +17841 50/push-eax +17842 89/<- %ecx 4/r32/esp +17843 # +17844 (identifier? %ecx) +17845 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") +17846 # . epilogue +17847 89/<- %esp 5/r32/ebp +17848 5d/pop-to-ebp +17849 c3/return +17850 +17851 test-is-identifier-underscore: +17852 # . prologue +17853 55/push-ebp +17854 89/<- %ebp 4/r32/esp +17855 # (eax..ecx) = "_a" +17856 b8/copy-to-eax "_a"/imm32 +17857 8b/-> *eax 1/r32/ecx +17858 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17859 05/add-to-eax 4/imm32 +17860 # var slice/ecx: slice = {eax, ecx} +17861 51/push-ecx +17862 50/push-eax +17863 89/<- %ecx 4/r32/esp +17864 # +17865 (identifier? %ecx) +17866 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") +17867 # . epilogue +17868 89/<- %esp 5/r32/ebp +17869 5d/pop-to-ebp +17870 c3/return +17871 +17872 test-is-identifier-a: +17873 # . prologue +17874 55/push-ebp +17875 89/<- %ebp 4/r32/esp +17876 # (eax..ecx) = "a$" +17877 b8/copy-to-eax "a$"/imm32 +17878 8b/-> *eax 1/r32/ecx +17879 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17880 05/add-to-eax 4/imm32 +17881 # var slice/ecx: slice = {eax, ecx} +17882 51/push-ecx +17883 50/push-eax +17884 89/<- %ecx 4/r32/esp +17885 # +17886 (identifier? %ecx) +17887 (check-ints-equal %eax 1 "F - test-is-identifier-a") +17888 # . epilogue +17889 89/<- %esp 5/r32/ebp +17890 5d/pop-to-ebp +17891 c3/return +17892 +17893 test-is-identifier-z: +17894 # . prologue +17895 55/push-ebp +17896 89/<- %ebp 4/r32/esp +17897 # (eax..ecx) = "z$" +17898 b8/copy-to-eax "z$"/imm32 +17899 8b/-> *eax 1/r32/ecx +17900 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17901 05/add-to-eax 4/imm32 +17902 # var slice/ecx: slice = {eax, ecx} +17903 51/push-ecx +17904 50/push-eax +17905 89/<- %ecx 4/r32/esp +17906 # +17907 (identifier? %ecx) +17908 (check-ints-equal %eax 1 "F - test-is-identifier-z") +17909 # . epilogue +17910 89/<- %esp 5/r32/ebp +17911 5d/pop-to-ebp +17912 c3/return +17913 +17914 test-is-identifier-A: +17915 # . prologue +17916 55/push-ebp +17917 89/<- %ebp 4/r32/esp +17918 # (eax..ecx) = "A$" +17919 b8/copy-to-eax "A$"/imm32 +17920 8b/-> *eax 1/r32/ecx +17921 8d/copy-address *(eax+ecx+4) 1/r32/ecx +17922 05/add-to-eax 4/imm32 +17923 # var slice/ecx: slice = {eax, ecx} +17924 51/push-ecx +17925 50/push-eax +17926 89/<- %ecx 4/r32/esp +17927 # +17928 (identifier? %ecx) +17929 (check-ints-equal %eax 1 "F - test-is-identifier-A") +17930 # . epilogue +17931 89/<- %esp 5/r32/ebp +17932 5d/pop-to-ebp +17933 c3/return +17934 +17935 test-is-identifier-Z: 17936 # . prologue 17937 55/push-ebp 17938 89/<- %ebp 4/r32/esp -17939 # (eax..ecx) = "@a" -17940 b8/copy-to-eax "@a"/imm32 +17939 # (eax..ecx) = "Z$" +17940 b8/copy-to-eax "Z$"/imm32 17941 8b/-> *eax 1/r32/ecx 17942 8d/copy-address *(eax+ecx+4) 1/r32/ecx 17943 05/add-to-eax 4/imm32 @@ -16453,20 +16453,20 @@ if ('onhashchange' in window) { 17946 50/push-eax 17947 89/<- %ecx 4/r32/esp 17948 # -17949 (identifier? %ecx) -17950 (check-ints-equal %eax 0 "F - test-is-identifier-@") +17949 (identifier? %ecx) +17950 (check-ints-equal %eax 1 "F - test-is-identifier-Z") 17951 # . epilogue 17952 89/<- %esp 5/r32/ebp 17953 5d/pop-to-ebp 17954 c3/return 17955 -17956 test-is-identifier-square-bracket: -17957 # character after 'Z' is invalid +17956 test-is-identifier-at: +17957 # character before 'A' is invalid 17958 # . prologue 17959 55/push-ebp 17960 89/<- %ebp 4/r32/esp -17961 # (eax..ecx) = "[a" -17962 b8/copy-to-eax "[a"/imm32 +17961 # (eax..ecx) = "@a" +17962 b8/copy-to-eax "@a"/imm32 17963 8b/-> *eax 1/r32/ecx 17964 8d/copy-address *(eax+ecx+4) 1/r32/ecx 17965 05/add-to-eax 4/imm32 @@ -16475,20 +16475,20 @@ if ('onhashchange' in window) { 17968 50/push-eax 17969 89/<- %ecx 4/r32/esp 17970 # -17971 (identifier? %ecx) +17971 (identifier? %ecx) 17972 (check-ints-equal %eax 0 "F - test-is-identifier-@") 17973 # . epilogue 17974 89/<- %esp 5/r32/ebp 17975 5d/pop-to-ebp 17976 c3/return 17977 -17978 test-is-identifier-backtick: -17979 # character before 'a' is invalid +17978 test-is-identifier-square-bracket: +17979 # character after 'Z' is invalid 17980 # . prologue 17981 55/push-ebp 17982 89/<- %ebp 4/r32/esp -17983 # (eax..ecx) = "`a" -17984 b8/copy-to-eax "`a"/imm32 +17983 # (eax..ecx) = "[a" +17984 b8/copy-to-eax "[a"/imm32 17985 8b/-> *eax 1/r32/ecx 17986 8d/copy-address *(eax+ecx+4) 1/r32/ecx 17987 05/add-to-eax 4/imm32 @@ -16497,20 +16497,20 @@ if ('onhashchange' in window) { 17990 50/push-eax 17991 89/<- %ecx 4/r32/esp 17992 # -17993 (identifier? %ecx) -17994 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +17993 (identifier? %ecx) +17994 (check-ints-equal %eax 0 "F - test-is-identifier-@") 17995 # . epilogue 17996 89/<- %esp 5/r32/ebp 17997 5d/pop-to-ebp 17998 c3/return 17999 -18000 test-is-identifier-curly-brace-open: -18001 # character after 'z' is invalid; also used for blocks +18000 test-is-identifier-backtick: +18001 # character before 'a' is invalid 18002 # . prologue 18003 55/push-ebp 18004 89/<- %ebp 4/r32/esp -18005 # (eax..ecx) = "{a" -18006 b8/copy-to-eax "{a"/imm32 +18005 # (eax..ecx) = "`a" +18006 b8/copy-to-eax "`a"/imm32 18007 8b/-> *eax 1/r32/ecx 18008 8d/copy-address *(eax+ecx+4) 1/r32/ecx 18009 05/add-to-eax 4/imm32 @@ -16519,41 +16519,41 @@ if ('onhashchange' in window) { 18012 50/push-eax 18013 89/<- %ecx 4/r32/esp 18014 # -18015 (identifier? %ecx) -18016 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +18015 (identifier? %ecx) +18016 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") 18017 # . epilogue 18018 89/<- %esp 5/r32/ebp 18019 5d/pop-to-ebp 18020 c3/return 18021 -18022 test-is-identifier-curly-brace-close: -18023 # . prologue -18024 55/push-ebp -18025 89/<- %ebp 4/r32/esp -18026 # (eax..ecx) = "}a" -18027 b8/copy-to-eax "}a"/imm32 -18028 8b/-> *eax 1/r32/ecx -18029 8d/copy-address *(eax+ecx+4) 1/r32/ecx -18030 05/add-to-eax 4/imm32 -18031 # var slice/ecx: slice = {eax, ecx} -18032 51/push-ecx -18033 50/push-eax -18034 89/<- %ecx 4/r32/esp -18035 # -18036 (identifier? %ecx) -18037 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -18038 # . epilogue -18039 89/<- %esp 5/r32/ebp -18040 5d/pop-to-ebp -18041 c3/return -18042 -18043 test-is-identifier-hyphen: -18044 # disallow leading '-' since '->' has special meaning +18022 test-is-identifier-curly-brace-open: +18023 # character after 'z' is invalid; also used for blocks +18024 # . prologue +18025 55/push-ebp +18026 89/<- %ebp 4/r32/esp +18027 # (eax..ecx) = "{a" +18028 b8/copy-to-eax "{a"/imm32 +18029 8b/-> *eax 1/r32/ecx +18030 8d/copy-address *(eax+ecx+4) 1/r32/ecx +18031 05/add-to-eax 4/imm32 +18032 # var slice/ecx: slice = {eax, ecx} +18033 51/push-ecx +18034 50/push-eax +18035 89/<- %ecx 4/r32/esp +18036 # +18037 (identifier? %ecx) +18038 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +18039 # . epilogue +18040 89/<- %esp 5/r32/ebp +18041 5d/pop-to-ebp +18042 c3/return +18043 +18044 test-is-identifier-curly-brace-close: 18045 # . prologue 18046 55/push-ebp 18047 89/<- %ebp 4/r32/esp -18048 # (eax..ecx) = "-a" -18049 b8/copy-to-eax "-a"/imm32 +18048 # (eax..ecx) = "}a" +18049 b8/copy-to-eax "}a"/imm32 18050 8b/-> *eax 1/r32/ecx 18051 8d/copy-address *(eax+ecx+4) 1/r32/ecx 18052 05/add-to-eax 4/imm32 @@ -16562,18911 +16562,18926 @@ if ('onhashchange' in window) { 18055 50/push-eax 18056 89/<- %ecx 4/r32/esp 18057 # -18058 (identifier? %ecx) -18059 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +18058 (identifier? %ecx) +18059 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") 18060 # . epilogue 18061 89/<- %esp 5/r32/ebp 18062 5d/pop-to-ebp 18063 c3/return 18064 -18065 populate-mu-function-body: # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor) -18066 # . prologue -18067 55/push-ebp -18068 89/<- %ebp 4/r32/esp -18069 # . save registers -18070 50/push-eax -18071 56/push-esi -18072 57/push-edi -18073 # esi = in -18074 8b/-> *(ebp+8) 6/r32/esi -18075 # edi = out -18076 8b/-> *(ebp+0xc) 7/r32/edi -18077 # initialize some global state -18078 c7 0/subop/copy *Curr-block-depth 1/imm32 -18079 # parse-mu-block(in, vars, out, out->body) -18080 8d/copy-address *(edi+0x18) 0/r32/eax # Function-body -18081 (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18)) -18082 $populate-mu-function-body:end: -18083 # . restore registers -18084 5f/pop-to-edi -18085 5e/pop-to-esi -18086 58/pop-to-eax -18087 # . epilogue -18088 89/<- %esp 5/r32/ebp -18089 5d/pop-to-ebp -18090 c3/return -18091 -18092 # parses a block, assuming that the leading '{' has already been read by the caller -18093 parse-mu-block: # in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle block), err: (addr buffered-file), ed: (addr exit-descriptor) -18094 # pseudocode: -18095 # var line: (stream byte 512) -18096 # var word-slice: slice -18097 # allocate(Heap, Stmt-size, out) -18098 # var out-addr: (addr block) = lookup(*out) -18099 # out-addr->tag = 0/block -18100 # out-addr->var = some unique name -18101 # push(vars, {out-addr->var, false}) -18102 # while true # line loop -18103 # clear-stream(line) -18104 # read-line-buffered(in, line) -18105 # if (line->write == 0) break # end of file -18106 # word-slice = next-mu-token(line) -18107 # if slice-empty?(word-slice) # end of line -18108 # continue -18109 # else if slice-starts-with?(word-slice, "#") -18110 # continue -18111 # else if slice-equal?(word-slice, "{") -18112 # assert(no-tokens-in(line)) -18113 # block = parse-mu-block(in, vars, fn) -18114 # append-to-block(out-addr, block) -18115 # else if slice-equal?(word-slice, "}") -18116 # break -18117 # else if slice-ends-with?(word-slice, ":") -18118 # # TODO: error-check the rest of 'line' -18119 # --word-slice->end to skip ':' -18120 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -18121 # append-to-block(out-addr, named-block) -18122 # else if slice-equal?(word-slice, "var") -18123 # var-def = parse-mu-var-def(line, vars, fn) -18124 # append-to-block(out-addr, var-def) -18125 # else -18126 # stmt = parse-mu-stmt(line, vars, fn) -18127 # append-to-block(out-addr, stmt) -18128 # pop(vars) -18129 # -18130 # . prologue -18131 55/push-ebp -18132 89/<- %ebp 4/r32/esp -18133 # . save registers -18134 50/push-eax -18135 51/push-ecx -18136 52/push-edx -18137 53/push-ebx -18138 57/push-edi -18139 # var line/ecx: (stream byte 512) -18140 81 5/subop/subtract %esp 0x200/imm32 -18141 68/push 0x200/imm32/size -18142 68/push 0/imm32/read -18143 68/push 0/imm32/write -18144 89/<- %ecx 4/r32/esp -18145 # var word-slice/edx: slice -18146 68/push 0/imm32/end -18147 68/push 0/imm32/start -18148 89/<- %edx 4/r32/esp -18149 # allocate into out -18150 (allocate Heap *Stmt-size *(ebp+0x14)) -18151 # var out-addr/edi: (addr block) = lookup(*out) -18152 8b/-> *(ebp+0x14) 7/r32/edi -18153 (lookup *edi *(edi+4)) # => eax -18154 89/<- %edi 0/r32/eax -18155 # out-addr->tag is 0 (block) by default -18156 # set out-addr->var -18157 8d/copy-address *(edi+0xc) 0/r32/eax # Block-var -18158 (new-block-name *(ebp+0x10) %eax) -18159 # push(vars, out-addr->var) -18160 (push *(ebp+0xc) *(edi+0xc)) # Block-var -18161 (push *(ebp+0xc) *(edi+0x10)) # Block-var -18162 (push *(ebp+0xc) 0) # false -18163 # increment *Curr-block-depth -18164 ff 0/subop/increment *Curr-block-depth -18165 { -18166 $parse-mu-block:line-loop: -18167 # line = read-line-buffered(in) -18168 (clear-stream %ecx) -18169 (read-line-buffered *(ebp+8) %ecx) -18170 #? (write-buffered Stderr "line: ") -18171 #? (write-stream-data Stderr %ecx) -18172 #? #? (write-buffered Stderr Newline) # line has its own newline -18173 #? (flush Stderr) -18174 #? (rewind-stream %ecx) -18175 # if (line->write == 0) break -18176 81 7/subop/compare *ecx 0/imm32 -18177 0f 84/jump-if-= break/disp32 -18178 #? (write-buffered Stderr "vars:\n") -18179 #? (dump-vars *(ebp+0xc)) -18180 # word-slice = next-mu-token(line) -18181 (next-mu-token %ecx %edx) -18182 #? (write-buffered Stderr "word: ") -18183 #? (write-slice-buffered Stderr %edx) -18184 #? (write-buffered Stderr Newline) -18185 #? (flush Stderr) -18186 # if slice-empty?(word-slice) continue -18187 (slice-empty? %edx) -18188 3d/compare-eax-and 0/imm32/false -18189 0f 85/jump-if-!= loop/disp32 -18190 # if (slice-starts-with?(word-slice, '#') continue -18191 # . eax = *word-slice->start -18192 8b/-> *edx 0/r32/eax -18193 8a/copy-byte *eax 0/r32/AL -18194 81 4/subop/and %eax 0xff/imm32 -18195 # . if (eax == '#') continue -18196 3d/compare-eax-and 0x23/imm32/hash -18197 0f 84/jump-if-= loop/disp32 -18198 # if slice-equal?(word-slice, "{") -18199 { -18200 $parse-mu-block:check-for-block: -18201 (slice-equal? %edx "{") -18202 3d/compare-eax-and 0/imm32/false -18203 74/jump-if-= break/disp8 -18204 (check-no-tokens-left %ecx) -18205 # parse new block and append -18206 # . var tmp/eax: (handle block) -18207 68/push 0/imm32 -18208 68/push 0/imm32 -18209 89/<- %eax 4/r32/esp -18210 # . -18211 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c)) -18212 (append-to-block Heap %edi *eax *(eax+4)) -18213 # . reclaim tmp -18214 81 0/subop/add %esp 8/imm32 -18215 # . -18216 e9/jump $parse-mu-block:line-loop/disp32 -18217 } -18218 # if slice-equal?(word-slice, "}") break -18219 $parse-mu-block:check-for-end: -18220 (slice-equal? %edx "}") -18221 3d/compare-eax-and 0/imm32/false -18222 0f 85/jump-if-!= break/disp32 -18223 # if slice-ends-with?(word-slice, ":") parse named block and append -18224 { -18225 $parse-mu-block:check-for-named-block: -18226 # . eax = *(word-slice->end-1) -18227 8b/-> *(edx+4) 0/r32/eax -18228 48/decrement-eax -18229 8a/copy-byte *eax 0/r32/AL -18230 81 4/subop/and %eax 0xff/imm32 -18231 # . if (eax != ':') break -18232 3d/compare-eax-and 0x3a/imm32/colon -18233 0f 85/jump-if-!= break/disp32 -18234 # TODO: error-check the rest of 'line' -18235 # -18236 # skip ':' -18237 ff 1/subop/decrement *(edx+4) # Slice-end -18238 # var tmp/eax: (handle block) -18239 68/push 0/imm32 -18240 68/push 0/imm32 -18241 89/<- %eax 4/r32/esp -18242 # -18243 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c)) -18244 (append-to-block Heap %edi *eax *(eax+4)) -18245 # reclaim tmp -18246 81 0/subop/add %esp 8/imm32 -18247 # -18248 e9/jump $parse-mu-block:line-loop/disp32 -18249 } -18250 # if slice-equal?(word-slice, "var") -18251 { -18252 $parse-mu-block:check-for-var: -18253 (slice-equal? %edx "var") -18254 3d/compare-eax-and 0/imm32/false -18255 74/jump-if-= break/disp8 -18256 # var tmp/eax: (handle block) -18257 68/push 0/imm32 -18258 68/push 0/imm32 -18259 89/<- %eax 4/r32/esp -18260 # -18261 (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) -18262 (append-to-block Heap %edi *eax *(eax+4)) -18263 # reclaim tmp -18264 81 0/subop/add %esp 8/imm32 -18265 # -18266 e9/jump $parse-mu-block:line-loop/disp32 -18267 } -18268 $parse-mu-block:regular-stmt: -18269 # otherwise -18270 # var tmp/eax: (handle block) -18271 68/push 0/imm32 -18272 68/push 0/imm32 -18273 89/<- %eax 4/r32/esp -18274 # -18275 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c)) -18276 (append-to-block Heap %edi *eax *(eax+4)) -18277 # reclaim tmp -18278 81 0/subop/add %esp 8/imm32 -18279 # -18280 e9/jump loop/disp32 -18281 } # end line loop -18282 (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10)) -18283 # decrement *Curr-block-depth -18284 ff 1/subop/decrement *Curr-block-depth -18285 # pop(vars) -18286 (pop *(ebp+0xc)) # => eax -18287 (pop *(ebp+0xc)) # => eax -18288 (pop *(ebp+0xc)) # => eax -18289 $parse-mu-block:end: -18290 # . reclaim locals -18291 81 0/subop/add %esp 0x214/imm32 -18292 # . restore registers -18293 5f/pop-to-edi -18294 5b/pop-to-ebx -18295 5a/pop-to-edx -18296 59/pop-to-ecx -18297 58/pop-to-eax -18298 # . epilogue -18299 89/<- %esp 5/r32/ebp -18300 5d/pop-to-ebp -18301 c3/return -18302 -18303 $parse-mu-block:abort: -18304 # error("'{' or '}' should be on its own line, but got '") -18305 (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '") -18306 (rewind-stream %ecx) -18307 (write-stream-data *(ebp+0x18) %ecx) -18308 (write-buffered *(ebp+0x18) "'\n") -18309 (flush *(ebp+0x18)) -18310 (stop *(ebp+0x1c) 1) -18311 # never gets here -18312 -18313 new-block-name: # fn: (addr function), out: (addr handle var) -18314 # . prologue -18315 55/push-ebp -18316 89/<- %ebp 4/r32/esp -18317 # . save registers -18318 50/push-eax -18319 51/push-ecx -18320 52/push-edx -18321 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' -18322 8b/-> *(ebp+8) 0/r32/eax -18323 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18324 8b/-> *eax 0/r32/eax # String-size -18325 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' -18326 89/<- %ecx 0/r32/eax -18327 # var name/edx: (stream byte n) -18328 29/subtract-from %esp 1/r32/ecx -18329 ff 6/subop/push %ecx -18330 68/push 0/imm32/read -18331 68/push 0/imm32/write -18332 89/<- %edx 4/r32/esp -18333 (clear-stream %edx) -18334 # eax = fn->name -18335 8b/-> *(ebp+8) 0/r32/eax -18336 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18337 # construct result using Next-block-index (and increment it) -18338 (write %edx "$") -18339 (write %edx %eax) -18340 (write %edx ":") -18341 (write-int32-hex %edx *Next-block-index) -18342 ff 0/subop/increment *Next-block-index -18343 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) -18344 # . eax = name->write -18345 8b/-> *edx 0/r32/eax -18346 # . edx = name->data -18347 8d/copy-address *(edx+0xc) 2/r32/edx -18348 # . eax = name->write + name->data -18349 01/add-to %eax 2/r32/edx -18350 # . push {edx, eax} -18351 ff 6/subop/push %eax -18352 ff 6/subop/push %edx -18353 89/<- %eax 4/r32/esp -18354 # out = new literal(s) -18355 (new-literal Heap %eax *(ebp+0xc)) -18356 #? 8b/-> *(ebp+0xc) 0/r32/eax -18357 #? (write-buffered Stderr "type allocid in caller after new-literal: ") -18358 #? (write-int32-hex-buffered Stderr *(eax+8)) -18359 #? (write-buffered Stderr " for var ") -18360 #? (write-int32-hex-buffered Stderr %eax) -18361 #? (write-buffered Stderr Newline) -18362 #? (flush Stderr) -18363 $new-block-name:end: -18364 # . reclaim locals -18365 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} -18366 81 0/subop/add %ecx 8/imm32 # slice -18367 01/add-to %esp 1/r32/ecx -18368 # . restore registers -18369 5a/pop-to-edx -18370 59/pop-to-ecx -18371 58/pop-to-eax -18372 # . epilogue -18373 89/<- %esp 5/r32/ebp -18374 5d/pop-to-ebp -18375 c3/return -18376 -18377 check-no-tokens-left: # line: (addr stream byte) -18378 # . prologue -18379 55/push-ebp -18380 89/<- %ebp 4/r32/esp -18381 # . save registers -18382 50/push-eax -18383 51/push-ecx -18384 # var s/ecx: slice -18385 68/push 0/imm32/end -18386 68/push 0/imm32/start -18387 89/<- %ecx 4/r32/esp -18388 # -18389 (next-mu-token *(ebp+8) %ecx) -18390 # if slice-empty?(s) return -18391 (slice-empty? %ecx) -18392 3d/compare-eax-and 0/imm32/false -18393 75/jump-if-!= $check-no-tokens-left:end/disp8 -18394 # if (slice-starts-with?(s, '#') return -18395 # . eax = *s->start -18396 8b/-> *edx 0/r32/eax -18397 8a/copy-byte *eax 0/r32/AL -18398 81 4/subop/and %eax 0xff/imm32 -18399 # . if (eax == '#') continue -18400 3d/compare-eax-and 0x23/imm32/hash -18401 74/jump-if-= $check-no-tokens-left:end/disp8 -18402 # abort -18403 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -18404 (rewind-stream %ecx) -18405 (write-stream 2 %ecx) -18406 (write-buffered Stderr "'\n") -18407 (flush Stderr) -18408 # . syscall(exit, 1) -18409 bb/copy-to-ebx 1/imm32 -18410 e8/call syscall_exit/disp32 -18411 # never gets here -18412 $check-no-tokens-left:end: -18413 # . reclaim locals -18414 81 0/subop/add %esp 8/imm32 -18415 # . restore registers -18416 59/pop-to-ecx -18417 58/pop-to-eax -18418 # . epilogue -18419 89/<- %esp 5/r32/ebp -18420 5d/pop-to-ebp -18421 c3/return -18422 -18423 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -18424 # pseudocode: -18425 # var v: (handle var) -18426 # new-literal(name, v) -18427 # push(vars, {v, false}) -18428 # parse-mu-block(in, vars, fn, out) -18429 # pop(vars) -18430 # out->tag = block -18431 # out->var = v -18432 # -18433 # . prologue -18434 55/push-ebp -18435 89/<- %ebp 4/r32/esp -18436 # . save registers -18437 50/push-eax -18438 51/push-ecx -18439 57/push-edi -18440 # var v/ecx: (handle var) -18441 68/push 0/imm32 -18442 68/push 0/imm32 -18443 89/<- %ecx 4/r32/esp -18444 # -18445 (new-literal Heap *(ebp+8) %ecx) -18446 # push(vars, v) -18447 (push *(ebp+0x10) *ecx) -18448 (push *(ebp+0x10) *(ecx+4)) -18449 (push *(ebp+0x10) 0) # false -18450 # -18451 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20)) -18452 # pop v off vars -18453 (pop *(ebp+0x10)) # => eax -18454 (pop *(ebp+0x10)) # => eax -18455 (pop *(ebp+0x10)) # => eax -18456 # var out-addr/edi: (addr stmt) = lookup(*out) -18457 8b/-> *(ebp+0x18) 7/r32/edi -18458 (lookup *edi *(edi+4)) # => eax -18459 89/<- %edi 0/r32/eax -18460 # out-addr->tag = named-block -18461 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag -18462 # out-addr->var = v -18463 8b/-> *ecx 0/r32/eax -18464 89/<- *(edi+0xc) 0/r32/eax # Block-var -18465 8b/-> *(ecx+4) 0/r32/eax -18466 89/<- *(edi+0x10) 0/r32/eax # Block-var -18467 $parse-mu-named-block:end: -18468 # . reclaim locals -18469 81 0/subop/add %esp 8/imm32 -18470 # . restore registers -18471 5f/pop-to-edi -18472 59/pop-to-ecx -18473 58/pop-to-eax -18474 # . epilogue -18475 89/<- %esp 5/r32/ebp -18476 5d/pop-to-ebp -18477 c3/return -18478 -18479 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack live-var), out: (addr handle stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -18480 # . prologue -18481 55/push-ebp -18482 89/<- %ebp 4/r32/esp -18483 # . save registers -18484 50/push-eax -18485 51/push-ecx -18486 52/push-edx -18487 56/push-esi -18488 57/push-edi -18489 # edi = out -18490 8b/-> *(ebp+0x10) 7/r32/edi -18491 # var word-slice/ecx: slice -18492 68/push 0/imm32/end -18493 68/push 0/imm32/start -18494 89/<- %ecx 4/r32/esp -18495 # var v/edx: (handle var) -18496 68/push 0/imm32 -18497 68/push 0/imm32 -18498 89/<- %edx 4/r32/esp -18499 # v = parse-var-with-type(next-mu-token(line)) -18500 (next-mu-token *(ebp+8) %ecx) -18501 { -18502 # just for tests, support null fn -18503 8b/-> *(ebp+0x14) 0/r32/eax -18504 3d/compare-eax-and 0/imm32 -18505 74/jump-if-= break/disp8 -18506 (lookup *eax *(eax+4)) # Var-name Var-name => eax -18507 } -18508 (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c)) -18509 # var v-addr/esi: (addr var) -18510 (lookup *edx *(edx+4)) # => eax -18511 89/<- %esi 0/r32/eax -18512 # v->block-depth = *Curr-block-depth -18513 8b/-> *Curr-block-depth 0/r32/eax -18514 89/<- *(esi+0x10) 0/r32/eax # Var-block-depth -18515 # either v has no register and there's no more to this line -18516 81 7/subop/compare *(esi+0x18) 0/imm32 -18517 { -18518 75/jump-if-!= break/disp8 -18519 # if v-addr->type == byte, abort -18520 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax -18521 (simple-mu-type? %eax 8) # byte => eax -18522 3d/compare-eax-and 0/imm32/false -18523 0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32 -18524 # ensure that there's nothing else on this line -18525 (next-mu-token *(ebp+8) %ecx) -18526 (slice-empty? %ecx) # => eax -18527 3d/compare-eax-and 0/imm32/false -18528 0f 84/jump-if-= $parse-mu-var-def:error2/disp32 -18529 # -18530 (new-var-def Heap *edx *(edx+4) %edi) -18531 e9/jump $parse-mu-var-def:update-vars/disp32 -18532 } -18533 # or v has a register and there's more to this line -18534 { -18535 0f 84/jump-if-= break/disp32 -18536 # if v-addr->type == byte, check for unsupported registers -18537 { -18538 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax -18539 (simple-mu-type? %eax 8) # byte => eax -18540 3d/compare-eax-and 0/imm32/false -18541 74/jump-if-= break/disp8 -18542 (lookup *(esi+0x18) *(esi+0x1c)) # => eax -18543 (string-equal? %eax "esi") # => eax -18544 3d/compare-eax-and 0/imm32/false -18545 0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32 -18546 (lookup *(esi+0x18) *(esi+0x1c)) # => eax -18547 (string-equal? %eax "edi") # => eax -18548 3d/compare-eax-and 0/imm32/false -18549 0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32 -18550 } -18551 # TODO: vars of type 'byte' should only be initialized by clearing to 0 -18552 # ensure that the next word is '<-' -18553 (next-mu-token *(ebp+8) %ecx) -18554 (slice-equal? %ecx "<-") # => eax -18555 3d/compare-eax-and 0/imm32/false -18556 0f 84/jump-if-= $parse-mu-var-def:error1/disp32 -18557 # -18558 (new-reg-var-def Heap *edx *(edx+4) %edi) -18559 (lookup *edi *(edi+4)) # => eax -18560 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -18561 } -18562 $parse-mu-var-def:update-vars: -18563 # push 'v' at end of function -18564 (push *(ebp+0xc) *edx) -18565 (push *(ebp+0xc) *(edx+4)) -18566 (push *(ebp+0xc) 0) # Live-var-register-spilled is unused during parsing -18567 $parse-mu-var-def:end: -18568 # . reclaim locals -18569 81 0/subop/add %esp 0x10/imm32 -18570 # . restore registers -18571 5f/pop-to-edi -18572 5e/pop-to-esi -18573 5a/pop-to-edx -18574 59/pop-to-ecx -18575 58/pop-to-eax -18576 # . epilogue -18577 89/<- %esp 5/r32/ebp -18578 5d/pop-to-ebp -18579 c3/return -18580 -18581 $parse-mu-var-def:error1: -18582 (rewind-stream *(ebp+8)) -18583 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -18584 (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '") -18585 (flush *(ebp+0x18)) -18586 (write-stream-data *(ebp+0x18) *(ebp+8)) -18587 (write-buffered *(ebp+0x18) "'\n") -18588 (flush *(ebp+0x18)) -18589 (stop *(ebp+0x1c) 1) -18590 # never gets here -18591 -18592 $parse-mu-var-def:error2: -18593 # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n") -18594 (write-buffered *(ebp+0x18) "fn ") -18595 8b/-> *(ebp+0x14) 0/r32/eax -18596 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18597 (write-buffered *(ebp+0x18) %eax) -18598 (write-buffered *(ebp+0x18) ": var ") -18599 # var v-addr/eax: (addr var) = lookup(v) -18600 (lookup *edx *(edx+4)) # => eax -18601 (lookup *eax *(eax+4)) # Var-name Var-name => eax -18602 (write-buffered *(ebp+0x18) %eax) -18603 (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n") -18604 (flush *(ebp+0x18)) -18605 (stop *(ebp+0x1c) 1) -18606 # never gets here -18607 -18608 $parse-mu-var-def:error-byte-on-stack: -18609 # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n") -18610 (write-buffered *(ebp+0x18) "fn ") -18611 8b/-> *(ebp+0x14) 0/r32/eax -18612 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18613 (write-buffered *(ebp+0x18) %eax) -18614 (write-buffered *(ebp+0x18) ": var '") -18615 # var v-addr/eax: (addr var) = lookup(v) -18616 (lookup *edx *(edx+4)) # => eax -18617 (lookup *eax *(eax+4)) # Var-name Var-name => eax -18618 (write-buffered *(ebp+0x18) %eax) -18619 (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n") -18620 (flush *(ebp+0x18)) -18621 (stop *(ebp+0x1c) 1) -18622 # never gets here -18623 -18624 $parse-mu-var-def:error-byte-registers: -18625 # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n") -18626 (write-buffered *(ebp+0x18) "fn ") -18627 8b/-> *(ebp+0x14) 0/r32/eax -18628 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18629 (write-buffered *(ebp+0x18) %eax) -18630 (write-buffered *(ebp+0x18) ": var '") -18631 # var v-addr/eax: (addr var) = lookup(v) -18632 (lookup *edx *(edx+4)) # => eax -18633 (lookup *eax *(eax+4)) # Var-name Var-name => eax -18634 (write-buffered *(ebp+0x18) %eax) -18635 (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n") -18636 (flush *(ebp+0x18)) -18637 (stop *(ebp+0x1c) 1) -18638 # never gets here -18639 -18640 test-parse-mu-var-def: -18641 # 'var n: int' -18642 # . prologue -18643 55/push-ebp -18644 89/<- %ebp 4/r32/esp -18645 # setup -18646 8b/-> *Primitive-type-ids 0/r32/eax -18647 89/<- *Type-id 0/r32/eax # stream-write -18648 (clear-stream _test-input-stream) -18649 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -18650 c7 0/subop/copy *Curr-block-depth 1/imm32 -18651 # var out/esi: (handle stmt) -18652 68/push 0/imm32 -18653 68/push 0/imm32 -18654 89/<- %esi 4/r32/esp -18655 # var vars/ecx: (stack (addr var) 16) -18656 81 5/subop/subtract %esp 0xc0/imm32 -18657 68/push 0xc0/imm32/size -18658 68/push 0/imm32/top -18659 89/<- %ecx 4/r32/esp -18660 (clear-stack %ecx) -18661 # convert -18662 (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0) -18663 # var out-addr/esi: (addr stmt) -18664 (lookup *esi *(esi+4)) # => eax -18665 89/<- %esi 0/r32/eax -18666 # -18667 (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def -18668 # var v/ecx: (addr var) = lookup(out->var) -18669 (lookup *(esi+4) *(esi+8)) # Vardef-var Vardef-var => eax -18670 89/<- %ecx 0/r32/eax -18671 # v->name -18672 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -18673 (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name") -18674 # v->register -18675 (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register") # Var-register -18676 # v->block-depth -18677 (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth") # Var-block-depth -18678 # v->type == int -18679 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -18680 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Type-tree-is-atom -18681 (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1") # Type-tree-value -18682 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2") # Type-tree-right -18683 # . epilogue -18684 89/<- %esp 5/r32/ebp -18685 5d/pop-to-ebp -18686 c3/return -18687 -18688 test-parse-mu-reg-var-def: -18689 # 'var n/eax: int <- copy 0' -18690 # . prologue -18691 55/push-ebp -18692 89/<- %ebp 4/r32/esp -18693 # setup -18694 8b/-> *Primitive-type-ids 0/r32/eax -18695 89/<- *Type-id 0/r32/eax # stream-write -18696 (clear-stream _test-input-stream) -18697 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -18698 c7 0/subop/copy *Curr-block-depth 1/imm32 -18699 # var out/esi: (handle stmt) -18700 68/push 0/imm32 -18701 68/push 0/imm32 -18702 89/<- %esi 4/r32/esp -18703 # var vars/ecx: (stack (addr var) 16) -18704 81 5/subop/subtract %esp 0xc0/imm32 -18705 68/push 0xc0/imm32/size -18706 68/push 0/imm32/top -18707 89/<- %ecx 4/r32/esp -18708 (clear-stack %ecx) -18709 # convert -18710 (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0) -18711 # var out-addr/esi: (addr stmt) -18712 (lookup *esi *(esi+4)) # => eax -18713 89/<- %esi 0/r32/eax -18714 # -18715 (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def -18716 # var v/ecx: (addr var) = lookup(out->outputs->value) -18717 # . eax: (addr stmt-var) = lookup(out->outputs) -18718 (lookup *(esi+0x14) *(esi+0x18)) # Regvardef-outputs Regvardef-outputs => eax -18719 # . -18720 (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output") # Stmt-var-next -18721 # . eax: (addr var) = lookup(eax->value) -18722 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -18723 # . ecx = eax -18724 89/<- %ecx 0/r32/eax -18725 # v->name -18726 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -18727 (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -18728 # v->register -18729 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax -18730 (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register") -18731 # v->block-depth -18732 (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -18733 # v->type == int -18734 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -18735 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Type-tree-is-atom -18736 (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1") # Type-tree-value -18737 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2") # Type-tree-right -18738 # . epilogue -18739 89/<- %esp 5/r32/ebp -18740 5d/pop-to-ebp -18741 c3/return -18742 -18743 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -18744 # pseudocode: -18745 # var name: slice -18746 # allocate(Heap, Stmt-size, out) -18747 # var out-addr: (addr stmt) = lookup(*out) -18748 # out-addr->tag = stmt -18749 # if stmt-has-outputs?(line) -18750 # while true -18751 # name = next-mu-token(line) -18752 # if (name == '<-') break -18753 # assert(identifier?(name)) -18754 # var v: (handle var) = lookup-var(name, vars) -18755 # out-addr->outputs = append(v, out-addr->outputs) -18756 # add-operation-and-inputs-to-stmt(out-addr, line, vars) -18757 # -18758 # . prologue -18759 55/push-ebp -18760 89/<- %ebp 4/r32/esp -18761 # . save registers -18762 50/push-eax -18763 51/push-ecx -18764 52/push-edx -18765 53/push-ebx -18766 57/push-edi -18767 # var name/ecx: slice -18768 68/push 0/imm32/end -18769 68/push 0/imm32/start -18770 89/<- %ecx 4/r32/esp -18771 # var is-deref?/edx: boolean = false -18772 ba/copy-to-edx 0/imm32/false -18773 # var v: (handle var) -18774 68/push 0/imm32 -18775 68/push 0/imm32 -18776 89/<- %ebx 4/r32/esp -18777 # -18778 (allocate Heap *Stmt-size *(ebp+0x14)) -18779 # var out-addr/edi: (addr stmt) = lookup(*out) -18780 8b/-> *(ebp+0x14) 7/r32/edi -18781 (lookup *edi *(edi+4)) # => eax -18782 89/<- %edi 0/r32/eax -18783 # out-addr->tag = 1/stmt -18784 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -18785 { -18786 (stmt-has-outputs? *(ebp+8)) -18787 3d/compare-eax-and 0/imm32/false -18788 0f 84/jump-if-= break/disp32 -18789 { -18790 $parse-mu-stmt:read-outputs: -18791 # name = next-mu-token(line) -18792 (next-mu-token *(ebp+8) %ecx) -18793 # if slice-empty?(word-slice) break -18794 (slice-empty? %ecx) # => eax -18795 3d/compare-eax-and 0/imm32/false -18796 0f 85/jump-if-!= break/disp32 -18797 # if (name == "<-") break -18798 (slice-equal? %ecx "<-") # => eax -18799 3d/compare-eax-and 0/imm32/false -18800 0f 85/jump-if-!= break/disp32 -18801 # if slice-starts-with?(name, "*") abort -18802 8b/-> *ecx 0/r32/eax # Slice-start -18803 8a/copy-byte *eax 0/r32/AL -18804 81 4/subop/and %eax 0xff/imm32 -18805 3d/compare-eax-and 0x2a/imm32/asterisk -18806 0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32 -18807 # assert(identifier?(name)) -18808 (identifier? %ecx) # => eax -18809 3d/compare-eax-and 0/imm32/false -18810 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -18811 # -18812 (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) -18813 8d/copy-address *(edi+0x14) 0/r32/eax # Stmt1-outputs -18814 (append-stmt-var Heap *ebx *(ebx+4) *(edi+0x14) *(edi+0x18) 0 %eax) # Stmt1-outputs -18815 # -18816 e9/jump loop/disp32 -18817 } -18818 } -18819 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) -18820 $parse-mu-stmt:end: -18821 # . reclaim locals -18822 81 0/subop/add %esp 0x10/imm32 -18823 # . restore registers -18824 5f/pop-to-edi -18825 5b/pop-to-ebx -18826 5a/pop-to-edx -18827 59/pop-to-ecx -18828 58/pop-to-eax -18829 # . epilogue -18830 89/<- %esp 5/r32/ebp -18831 5d/pop-to-ebp -18832 c3/return -18833 -18834 $parse-mu-stmt:abort: -18835 # error("invalid identifier '" name "'\n") -18836 (write-buffered *(ebp+0x18) "fn ") -18837 8b/-> *(ebp+0x10) 0/r32/eax -18838 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18839 (write-buffered *(ebp+0x18) %eax) -18840 (write-buffered *(ebp+0x18) ": invalid identifier '") -18841 (write-slice-buffered *(ebp+0x18) %ecx) -18842 (write-buffered *(ebp+0x18) "'\n") -18843 (flush *(ebp+0x18)) -18844 (stop *(ebp+0x1c) 1) -18845 # never gets here -18846 -18847 $parse-mu-stmt:error-output-dereferenced: -18848 # error("invalid identifier '" name "'\n") -18849 (write-buffered *(ebp+0x18) "fn ") -18850 8b/-> *(ebp+0x10) 0/r32/eax -18851 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18852 (write-buffered *(ebp+0x18) %eax) -18853 (write-buffered *(ebp+0x18) ": output '") -18854 (write-slice-buffered *(ebp+0x18) %ecx) -18855 (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n") -18856 (flush *(ebp+0x18)) -18857 (stop *(ebp+0x1c) 1) -18858 # never gets here -18859 -18860 add-operation-and-inputs-to-stmt: # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -18861 # pseudocode: -18862 # stmt->name = slice-to-string(next-mu-token(line)) -18863 # while true -18864 # name = next-mu-token(line) -18865 # v = lookup-var-or-literal(name) -18866 # stmt->inouts = append(v, stmt->inouts) -18867 # -18868 # . prologue -18869 55/push-ebp -18870 89/<- %ebp 4/r32/esp -18871 # . save registers -18872 50/push-eax -18873 51/push-ecx -18874 52/push-edx -18875 53/push-ebx -18876 56/push-esi -18877 57/push-edi -18878 # edi = stmt -18879 8b/-> *(ebp+8) 7/r32/edi -18880 # var name/ecx: slice -18881 68/push 0/imm32/end -18882 68/push 0/imm32/start -18883 89/<- %ecx 4/r32/esp -18884 # var is-deref?/edx: boolean = false -18885 ba/copy-to-edx 0/imm32/false -18886 # var v/esi: (handle var) -18887 68/push 0/imm32 -18888 68/push 0/imm32 -18889 89/<- %esi 4/r32/esp -18890 $add-operation-and-inputs-to-stmt:read-operation: -18891 (next-mu-token *(ebp+0xc) %ecx) -18892 8d/copy-address *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation -18893 (slice-to-string Heap %ecx %eax) -18894 # var is-get?/ebx: boolean = (name == "get") -18895 (slice-equal? %ecx "get") # => eax -18896 89/<- %ebx 0/r32/eax -18897 { -18898 $add-operation-and-inputs-to-stmt:read-inouts: -18899 # name = next-mu-token(line) -18900 (next-mu-token *(ebp+0xc) %ecx) -18901 # if slice-empty?(word-slice) break -18902 (slice-empty? %ecx) # => eax -18903 3d/compare-eax-and 0/imm32/false -18904 0f 85/jump-if-!= break/disp32 -18905 # if (name == "<-") abort -18906 (slice-equal? %ecx "<-") -18907 3d/compare-eax-and 0/imm32/false -18908 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -18909 # if (get? && second operand) lookup or create offset -18910 { -18911 81 7/subop/compare %ebx 0/imm32/false -18912 74/jump-if-= break/disp8 -18913 (lookup *(edi+0xc) *(edi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -18914 3d/compare-eax-and 0/imm32 -18915 74/jump-if-= break/disp8 -18916 (lookup-or-create-constant %eax %ecx %esi) -18917 #? (lookup *esi *(esi+4)) -18918 #? (write-buffered Stderr "creating new output var ") -18919 #? (write-int32-hex-buffered Stderr %eax) -18920 #? (write-buffered Stderr " for field called ") -18921 #? (write-slice-buffered Stderr %ecx) -18922 #? (write-buffered Stderr "; var name ") -18923 #? (lookup *eax *(eax+4)) # Var-name -18924 #? (write-buffered Stderr %eax) -18925 #? (write-buffered Stderr Newline) -18926 #? (flush Stderr) -18927 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 -18928 } -18929 # is-deref? = false -18930 ba/copy-to-edx 0/imm32/false -18931 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? -18932 8b/-> *ecx 0/r32/eax # Slice-start -18933 8a/copy-byte *eax 0/r32/AL -18934 81 4/subop/and %eax 0xff/imm32 -18935 3d/compare-eax-and 0x2a/imm32/asterisk -18936 { -18937 75/jump-if-!= break/disp8 -18938 $add-operation-and-inputs-to-stmt:inout-is-deref: -18939 ff 0/subop/increment *ecx -18940 ba/copy-to-edx 1/imm32/true -18941 } -18942 (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -18943 # if (deref?) some additional checks -18944 81 7/subop/compare %edx 0/imm32/false -18945 { -18946 74/jump-if-= break/disp8 -18947 # if var is not in register, abort -18948 (lookup *esi *(esi+4)) # => eax -18949 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -18950 0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32 -18951 # if var is not an address, abort -18952 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -18953 (mu-addr-type? %eax) # => eax -18954 3d/compare-eax-and 0/imm32/false -18955 0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32 -18956 } -18957 $add-operation-and-inputs-to-stmt:save-var: -18958 8d/copy-address *(edi+0xc) 0/r32/eax -18959 (append-stmt-var Heap *esi *(esi+4) *(edi+0xc) *(edi+0x10) %edx %eax) # Stmt1-inouts or Regvardef-inouts -18960 # -18961 e9/jump loop/disp32 -18962 } -18963 $add-operation-and-inputs-to-stmt:end: -18964 # . reclaim locals -18965 81 0/subop/add %esp 0x10/imm32 -18966 # . restore registers -18967 5f/pop-to-edi -18968 5e/pop-to-esi -18969 5b/pop-to-ebx -18970 5a/pop-to-edx -18971 59/pop-to-ecx -18972 58/pop-to-eax -18973 # . epilogue -18974 89/<- %esp 5/r32/ebp -18975 5d/pop-to-ebp -18976 c3/return -18977 -18978 $add-operation-and-inputs-to-stmt:abort: -18979 # error("fn ___: invalid identifier in '" line "'\n") -18980 (write-buffered *(ebp+0x18) "fn ") -18981 8b/-> *(ebp+0x14) 0/r32/eax -18982 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18983 (write-buffered *(ebp+0x18) %eax) -18984 (rewind-stream *(ebp+0xc)) -18985 (write-buffered *(ebp+0x18) ": invalid identifier in '") -18986 (write-stream-data *(ebp+0x18) *(ebp+0xc)) -18987 (write-buffered *(ebp+0x18) "'\n") -18988 (flush *(ebp+0x18)) -18989 (stop *(ebp+0x1c) 1) -18990 # never gets here -18991 -18992 $add-operation-and-inputs-to-stmt:error-deref-on-stack: -18993 # error("fn ___: cannot dereference var ___ on stack\n") -18994 (write-buffered *(ebp+0x18) "fn ") -18995 8b/-> *(ebp+0x14) 0/r32/eax -18996 (lookup *eax *(eax+4)) # Function-name Function-name => eax -18997 (write-buffered *(ebp+0x18) %eax) -18998 (rewind-stream *(ebp+0xc)) -18999 (write-buffered *(ebp+0x18) ": cannot dereference var '") -19000 (lookup *esi *(esi+4)) # => eax -19001 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19002 (write-buffered *(ebp+0x18) %eax) -19003 (write-buffered *(ebp+0x18) "' on stack\n") -19004 (flush *(ebp+0x18)) -19005 (stop *(ebp+0x1c) 1) -19006 # never gets here -19007 -19008 $add-operation-and-inputs-to-stmt:error-deref-non-addr: -19009 # error("fn ___: cannot dereference non-addr var ___\n") -19010 (write-buffered *(ebp+0x18) "fn ") -19011 8b/-> *(ebp+0x14) 0/r32/eax -19012 (lookup *eax *(eax+4)) # Function-name Function-name => eax -19013 (write-buffered *(ebp+0x18) %eax) -19014 (rewind-stream *(ebp+0xc)) -19015 (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '") -19016 (lookup *esi *(esi+4)) # => eax -19017 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19018 (write-buffered *(ebp+0x18) %eax) -19019 (write-buffered *(ebp+0x18) "'\n") -19020 (flush *(ebp+0x18)) -19021 (stop *(ebp+0x1c) 1) -19022 # never gets here -19023 -19024 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -19025 # . prologue -19026 55/push-ebp -19027 89/<- %ebp 4/r32/esp -19028 # . save registers -19029 51/push-ecx -19030 # var word-slice/ecx: slice -19031 68/push 0/imm32/end -19032 68/push 0/imm32/start -19033 89/<- %ecx 4/r32/esp -19034 # result = false -19035 b8/copy-to-eax 0/imm32/false -19036 (rewind-stream *(ebp+8)) -19037 { -19038 (next-mu-token *(ebp+8) %ecx) -19039 # if slice-empty?(word-slice) break -19040 (slice-empty? %ecx) -19041 3d/compare-eax-and 0/imm32/false -19042 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -19043 0f 85/jump-if-!= break/disp32 -19044 # if slice-starts-with?(word-slice, '#') break -19045 # . eax = *word-slice->start -19046 8b/-> *ecx 0/r32/eax -19047 8a/copy-byte *eax 0/r32/AL -19048 81 4/subop/and %eax 0xff/imm32 -19049 # . if (eax == '#') break -19050 3d/compare-eax-and 0x23/imm32/hash -19051 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -19052 0f 84/jump-if-= break/disp32 -19053 # if slice-equal?(word-slice, '<-') return true -19054 (slice-equal? %ecx "<-") -19055 3d/compare-eax-and 0/imm32/false -19056 74/jump-if-= loop/disp8 -19057 b8/copy-to-eax 1/imm32/true -19058 } -19059 $stmt-has-outputs:end: -19060 (rewind-stream *(ebp+8)) -19061 # . reclaim locals -19062 81 0/subop/add %esp 8/imm32 -19063 # . restore registers -19064 59/pop-to-ecx -19065 # . epilogue -19066 89/<- %esp 5/r32/ebp -19067 5d/pop-to-ebp -19068 c3/return -19069 -19070 # if 'name' starts with a digit, create a new literal var for it -19071 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -19072 lookup-var-or-literal: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -19073 # . prologue -19074 55/push-ebp -19075 89/<- %ebp 4/r32/esp -19076 # . save registers -19077 50/push-eax -19078 51/push-ecx -19079 56/push-esi -19080 # esi = name -19081 8b/-> *(ebp+8) 6/r32/esi -19082 # if slice-empty?(name) abort -19083 (slice-empty? %esi) # => eax -19084 3d/compare-eax-and 0/imm32/false -19085 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -19086 # var c/ecx: byte = *name->start -19087 8b/-> *esi 1/r32/ecx -19088 8a/copy-byte *ecx 1/r32/CL -19089 81 4/subop/and %ecx 0xff/imm32 -19090 # if (decimal-digit?(c) || c == '-') return new var(name) -19091 { -19092 81 7/subop/compare %ecx 0x2d/imm32/dash -19093 74/jump-if-= $lookup-var-or-literal:literal/disp8 -19094 (decimal-digit? %ecx) # => eax -19095 3d/compare-eax-and 0/imm32/false -19096 74/jump-if-= break/disp8 -19097 $lookup-var-or-literal:literal: -19098 (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -19099 eb/jump $lookup-var-or-literal:end/disp8 -19100 } -19101 # else if (c == '"') return new var(name) -19102 { -19103 81 7/subop/compare %ecx 0x22/imm32/dquote -19104 75/jump-if-!= break/disp8 -19105 $lookup-var-or-literal:literal-string: -19106 (new-literal-string Heap %esi *(ebp+0x10)) -19107 eb/jump $lookup-var-or-literal:end/disp8 -19108 } -19109 # otherwise return lookup-var(name, vars) -19110 { -19111 $lookup-var-or-literal:var: -19112 (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -19113 } -19114 $lookup-var-or-literal:end: -19115 # . restore registers -19116 5e/pop-to-esi -19117 59/pop-to-ecx -19118 58/pop-to-eax -19119 # . epilogue -19120 89/<- %esp 5/r32/ebp -19121 5d/pop-to-ebp -19122 c3/return -19123 -19124 $lookup-var-or-literal:abort: -19125 (write-buffered *(ebp+0x18) "fn ") -19126 8b/-> *(ebp+0x14) 0/r32/eax -19127 (lookup *eax *(eax+4)) # Function-name Function-name => eax -19128 (write-buffered *(ebp+0x18) %eax) -19129 (write-buffered *(ebp+0x18) ": empty variable!") -19130 (flush *(ebp+0x18)) -19131 (stop *(ebp+0x1c) 1) -19132 # never gets here -19133 -19134 # return first 'name' from the top (back) of 'vars' and abort if not found -19135 lookup-var: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -19136 # . prologue -19137 55/push-ebp -19138 89/<- %ebp 4/r32/esp -19139 # . save registers -19140 50/push-eax -19141 # -19142 (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -19143 # if (*out == 0) abort -19144 8b/-> *(ebp+0x10) 0/r32/eax -19145 81 7/subop/compare *eax 0/imm32 -19146 74/jump-if-= $lookup-var:abort/disp8 -19147 $lookup-var:end: -19148 # . restore registers -19149 58/pop-to-eax -19150 # . epilogue -19151 89/<- %esp 5/r32/ebp -19152 5d/pop-to-ebp -19153 c3/return -19154 -19155 $lookup-var:abort: -19156 (write-buffered *(ebp+0x18) "fn ") -19157 8b/-> *(ebp+0x14) 0/r32/eax -19158 (lookup *eax *(eax+4)) # Function-name Function-name => eax -19159 (write-buffered *(ebp+0x18) %eax) -19160 (write-buffered *(ebp+0x18) ": unknown variable '") -19161 (write-slice-buffered *(ebp+0x18) *(ebp+8)) -19162 (write-buffered *(ebp+0x18) "'\n") -19163 (flush *(ebp+0x18)) -19164 (stop *(ebp+0x1c) 1) -19165 # never gets here -19166 -19167 # return first 'name' from the top (back) of 'vars', and 0/null if not found -19168 # ensure that 'name' if in a register is the topmost variable in that register -19169 lookup-var-helper: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -19170 # pseudocode: -19171 # var curr: (addr handle var) = &vars->data[vars->top - 12] -19172 # var min = vars->data -19173 # while curr >= min -19174 # var v: (handle var) = *curr -19175 # if v->name == name -19176 # return -19177 # curr -= 12 -19178 # -19179 # . prologue -19180 55/push-ebp -19181 89/<- %ebp 4/r32/esp -19182 # . save registers -19183 50/push-eax -19184 51/push-ecx -19185 52/push-edx -19186 53/push-ebx -19187 56/push-esi -19188 57/push-edi -19189 # clear out -19190 (zero-out *(ebp+0x10) *Handle-size) -19191 # esi = vars -19192 8b/-> *(ebp+0xc) 6/r32/esi -19193 # ebx = vars->top -19194 8b/-> *esi 3/r32/ebx -19195 # if (vars->top > vars->size) abort -19196 3b/compare<- *(esi+4) 0/r32/eax -19197 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -19198 # var min/edx: (addr handle var) = vars->data -19199 8d/copy-address *(esi+8) 2/r32/edx -19200 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12] -19201 8d/copy-address *(esi+ebx-4) 3/r32/ebx # vars + 8 + vars->type - 12 -19202 # var var-in-reg/edi: 16 addrs -19203 68/push 0/imm32 -19204 68/push 0/imm32 -19205 68/push 0/imm32 -19206 68/push 0/imm32 -19207 68/push 0/imm32 -19208 68/push 0/imm32 -19209 68/push 0/imm32 -19210 68/push 0/imm32 -19211 68/push 0/imm32 -19212 68/push 0/imm32 -19213 68/push 0/imm32 -19214 68/push 0/imm32 -19215 68/push 0/imm32 -19216 68/push 0/imm32 -19217 68/push 0/imm32 -19218 68/push 0/imm32 -19219 89/<- %edi 4/r32/esp -19220 { -19221 $lookup-var-helper:loop: -19222 # if (curr < min) return -19223 39/compare %ebx 2/r32/edx -19224 0f 82/jump-if-addr< break/disp32 -19225 # var v/ecx: (addr var) = lookup(*curr) -19226 (lookup *ebx *(ebx+4)) # => eax -19227 89/<- %ecx 0/r32/eax -19228 # var vn/eax: (addr array byte) = lookup(v->name) -19229 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -19230 # if (vn == name) return curr -19231 (slice-equal? *(ebp+8) %eax) # => eax -19232 3d/compare-eax-and 0/imm32/false -19233 { -19234 74/jump-if-= break/disp8 -19235 $lookup-var-helper:found: -19236 # var vr/eax: (addr array byte) = lookup(v->register) -19237 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax -19238 3d/compare-eax-and 0/imm32 -19239 { -19240 74/jump-if-= break/disp8 -19241 $lookup-var-helper:found-register: -19242 # var reg/eax: int = get(Registers, vr) -19243 (get Mu-registers-unique %eax 0xc "Mu-registers-unique") # => eax -19244 8b/-> *eax 0/r32/eax -19245 # if (var-in-reg[reg]) error -19246 8b/-> *(edi+eax<<2) 0/r32/eax -19247 3d/compare-eax-and 0/imm32 -19248 0f 85/jump-if-!= $lookup-var-helper:error2/disp32 -19249 } -19250 $lookup-var-helper:return: -19251 # esi = out -19252 8b/-> *(ebp+0x10) 6/r32/esi -19253 # *out = *curr -19254 8b/-> *ebx 0/r32/eax -19255 89/<- *esi 0/r32/eax -19256 8b/-> *(ebx+4) 0/r32/eax -19257 89/<- *(esi+4) 0/r32/eax -19258 # return -19259 eb/jump $lookup-var-helper:end/disp8 -19260 } -19261 # 'name' not yet found; update var-in-reg if v in register -19262 # . var vr/eax: (addr array byte) = lookup(v->register) -19263 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax -19264 # . if (vr == 0) continue -19265 3d/compare-eax-and 0/imm32 -19266 74/jump-if-= $lookup-var-helper:continue/disp8 -19267 # . var reg/eax: int = get(Registers, vr) -19268 (get Mu-registers-unique %eax 0xc "Mu-registers-unique") # => eax -19269 8b/-> *eax 0/r32/eax -19270 # . var-in-reg[reg] = v -19271 89/<- *(edi+eax<<2) 1/r32/ecx -19272 $lookup-var-helper:continue: -19273 # curr -= 12 -19274 81 5/subop/subtract %ebx 0xc/imm32 -19275 e9/jump loop/disp32 -19276 } -19277 $lookup-var-helper:end: -19278 # . reclaim locals -19279 81 0/subop/add %esp 0x40/imm32 -19280 # . restore registers -19281 5f/pop-to-edi -19282 5e/pop-to-esi -19283 5b/pop-to-ebx -19284 5a/pop-to-edx -19285 59/pop-to-ecx -19286 58/pop-to-eax -19287 # . epilogue -19288 89/<- %esp 5/r32/ebp -19289 5d/pop-to-ebp -19290 c3/return -19291 -19292 $lookup-var-helper:error1: -19293 (write-buffered *(ebp+0x18) "fn ") -19294 8b/-> *(ebp+0x14) 0/r32/eax -19295 (lookup *eax *(eax+4)) # Function-name Function-name => eax -19296 (write-buffered *(ebp+0x18) %eax) -19297 (write-buffered *(ebp+0x18) ": malformed stack when looking up '") -19298 (write-slice-buffered *(ebp+0x18) *(ebp+8)) -19299 (write-buffered *(ebp+0x18) "'\n") -19300 (flush *(ebp+0x18)) -19301 (stop *(ebp+0x1c) 1) -19302 # never gets here -19303 -19304 $lookup-var-helper:error2: -19305 # eax contains the conflicting var at this point -19306 (write-buffered *(ebp+0x18) "fn ") -19307 50/push-eax -19308 8b/-> *(ebp+0x14) 0/r32/eax -19309 (lookup *eax *(eax+4)) # Function-name Function-name => eax -19310 (write-buffered *(ebp+0x18) %eax) -19311 58/pop-eax -19312 (write-buffered *(ebp+0x18) ": register ") -19313 50/push-eax -19314 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -19315 (write-buffered *(ebp+0x18) %eax) -19316 58/pop-to-eax -19317 (write-buffered *(ebp+0x18) " reads var '") -19318 (write-slice-buffered *(ebp+0x18) *(ebp+8)) -19319 (write-buffered *(ebp+0x18) "' after writing var '") -19320 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19321 (write-buffered *(ebp+0x18) %eax) -19322 (write-buffered *(ebp+0x18) "'\n") -19323 (flush *(ebp+0x18)) -19324 (stop *(ebp+0x1c) 1) -19325 # never gets here -19326 -19327 dump-vars: # vars: (addr stack live-var) -19328 # pseudocode: -19329 # var curr: (addr handle var) = &vars->data[vars->top - 12] -19330 # var min = vars->data -19331 # while curr >= min -19332 # var v: (handle var) = *curr -19333 # print v -19334 # curr -= 12 -19335 # -19336 # . prologue -19337 55/push-ebp -19338 89/<- %ebp 4/r32/esp -19339 # . save registers -19340 52/push-edx -19341 53/push-ebx -19342 56/push-esi -19343 # esi = vars -19344 8b/-> *(ebp+8) 6/r32/esi -19345 # ebx = vars->top -19346 8b/-> *esi 3/r32/ebx -19347 # var min/edx: (addr handle var) = vars->data -19348 8d/copy-address *(esi+8) 2/r32/edx -19349 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12] -19350 8d/copy-address *(esi+ebx-4) 3/r32/ebx # vars + 8 + vars->type - 12 -19351 { -19352 $dump-vars:loop: -19353 # if (curr < min) return -19354 39/compare %ebx 2/r32/edx -19355 0f 82/jump-if-addr< break/disp32 -19356 # -19357 (write-buffered Stderr " var@") -19358 (dump-var 2 %ebx) -19359 # curr -= 12 -19360 81 5/subop/subtract %ebx 0xc/imm32 -19361 e9/jump loop/disp32 -19362 } -19363 $dump-vars:end: -19364 # . restore registers -19365 5e/pop-to-esi -19366 5b/pop-to-ebx -19367 5a/pop-to-edx -19368 # . epilogue -19369 89/<- %esp 5/r32/ebp -19370 5d/pop-to-ebp -19371 c3/return -19372 -19373 == data -19374 # Like Registers, but no esp or ebp -19375 Mu-registers: # (addr stream {(handle array byte), int}) -19376 # a table is a stream -19377 0xa8/imm32/write -19378 0/imm32/read -19379 0xa8/imm32/length -19380 # data -19381 # general-purpose registers -19382 # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them -19383 0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32 -19384 0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32 -19385 0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32 -19386 0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32 -19387 0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32 -19388 0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32 -19389 # floating-point registers -19390 0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32 -19391 0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32 -19392 0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32 -19393 0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32 -19394 0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32 -19395 0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32 -19396 0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32 -19397 0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32 -19398 -19399 # Like Mu-registers, but with unique codes for integer and floating-point -19400 # registers. -19401 # Don't use this for code-generation, only for checking. -19402 Mu-registers-unique: # (addr stream {(handle array byte), int}) -19403 # a table is a stream -19404 0xa8/imm32/write -19405 0/imm32/read -19406 0xa8/imm32/length -19407 # data -19408 # general-purpose registers -19409 0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32 -19410 0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32 -19411 0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32 -19412 0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32 -19413 0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32 -19414 0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32 -19415 # floating-point registers -19416 0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32 -19417 0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32 -19418 0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32 -19419 0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32 -19420 0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32 -19421 0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32 -19422 0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32 -19423 0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32 -19424 -19425 $Mu-register-eax: -19426 0x11/imm32/alloc-id -19427 3/imm32/size -19428 0x65/e 0x61/a 0x78/x -19429 -19430 $Mu-register-ecx: -19431 0x11/imm32/alloc-id -19432 3/imm32/size -19433 0x65/e 0x63/c 0x78/x -19434 -19435 $Mu-register-edx: -19436 0x11/imm32/alloc-id -19437 3/imm32/size -19438 0x65/e 0x64/d 0x78/x -19439 -19440 $Mu-register-ebx: -19441 0x11/imm32/alloc-id -19442 3/imm32/size -19443 0x65/e 0x62/b 0x78/x -19444 -19445 $Mu-register-esi: -19446 0x11/imm32/alloc-id -19447 3/imm32/size -19448 0x65/e 0x73/s 0x69/i -19449 -19450 $Mu-register-edi: -19451 0x11/imm32/alloc-id -19452 3/imm32/size -19453 0x65/e 0x64/d 0x69/i -19454 -19455 $Mu-register-xmm0: -19456 0x11/imm32/alloc-id:fake:payload -19457 # "xmm0" -19458 0x4/imm32/size -19459 0x78/x 0x6d/m 0x6d/m 0x30/0 -19460 -19461 $Mu-register-xmm1: -19462 0x11/imm32/alloc-id:fake:payload -19463 # "xmm1" -19464 0x4/imm32/size -19465 0x78/x 0x6d/m 0x6d/m 0x31/1 +18065 test-is-identifier-hyphen: +18066 # disallow leading '-' since '->' has special meaning +18067 # . prologue +18068 55/push-ebp +18069 89/<- %ebp 4/r32/esp +18070 # (eax..ecx) = "-a" +18071 b8/copy-to-eax "-a"/imm32 +18072 8b/-> *eax 1/r32/ecx +18073 8d/copy-address *(eax+ecx+4) 1/r32/ecx +18074 05/add-to-eax 4/imm32 +18075 # var slice/ecx: slice = {eax, ecx} +18076 51/push-ecx +18077 50/push-eax +18078 89/<- %ecx 4/r32/esp +18079 # +18080 (identifier? %ecx) +18081 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +18082 # . epilogue +18083 89/<- %esp 5/r32/ebp +18084 5d/pop-to-ebp +18085 c3/return +18086 +18087 populate-mu-function-body: # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor) +18088 # . prologue +18089 55/push-ebp +18090 89/<- %ebp 4/r32/esp +18091 # . save registers +18092 50/push-eax +18093 56/push-esi +18094 57/push-edi +18095 # esi = in +18096 8b/-> *(ebp+8) 6/r32/esi +18097 # edi = out +18098 8b/-> *(ebp+0xc) 7/r32/edi +18099 # initialize some global state +18100 c7 0/subop/copy *Curr-block-depth 1/imm32 +18101 # parse-mu-block(in, vars, out, out->body) +18102 8d/copy-address *(edi+0x18) 0/r32/eax # Function-body +18103 (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18)) +18104 $populate-mu-function-body:end: +18105 # . restore registers +18106 5f/pop-to-edi +18107 5e/pop-to-esi +18108 58/pop-to-eax +18109 # . epilogue +18110 89/<- %esp 5/r32/ebp +18111 5d/pop-to-ebp +18112 c3/return +18113 +18114 # parses a block, assuming that the leading '{' has already been read by the caller +18115 parse-mu-block: # in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle block), err: (addr buffered-file), ed: (addr exit-descriptor) +18116 # pseudocode: +18117 # var line: (stream byte 512) +18118 # var word-slice: slice +18119 # allocate(Heap, Stmt-size, out) +18120 # var out-addr: (addr block) = lookup(*out) +18121 # out-addr->tag = 0/block +18122 # out-addr->var = some unique name +18123 # push(vars, {out-addr->var, false}) +18124 # while true # line loop +18125 # clear-stream(line) +18126 # read-line-buffered(in, line) +18127 # if (line->write == 0) break # end of file +18128 # word-slice = next-mu-token(line) +18129 # if slice-empty?(word-slice) # end of line +18130 # continue +18131 # else if slice-starts-with?(word-slice, "#") +18132 # continue +18133 # else if slice-equal?(word-slice, "{") +18134 # assert(no-tokens-in(line)) +18135 # block = parse-mu-block(in, vars, fn) +18136 # append-to-block(out-addr, block) +18137 # else if slice-equal?(word-slice, "}") +18138 # break +18139 # else if slice-ends-with?(word-slice, ":") +18140 # # TODO: error-check the rest of 'line' +18141 # --word-slice->end to skip ':' +18142 # named-block = parse-mu-named-block(word-slice, in, vars, fn) +18143 # append-to-block(out-addr, named-block) +18144 # else if slice-equal?(word-slice, "var") +18145 # var-def = parse-mu-var-def(line, vars, fn) +18146 # append-to-block(out-addr, var-def) +18147 # else +18148 # stmt = parse-mu-stmt(line, vars, fn) +18149 # append-to-block(out-addr, stmt) +18150 # pop(vars) +18151 # +18152 # . prologue +18153 55/push-ebp +18154 89/<- %ebp 4/r32/esp +18155 # . save registers +18156 50/push-eax +18157 51/push-ecx +18158 52/push-edx +18159 53/push-ebx +18160 57/push-edi +18161 # var line/ecx: (stream byte 512) +18162 81 5/subop/subtract %esp 0x200/imm32 +18163 68/push 0x200/imm32/size +18164 68/push 0/imm32/read +18165 68/push 0/imm32/write +18166 89/<- %ecx 4/r32/esp +18167 # var word-slice/edx: slice +18168 68/push 0/imm32/end +18169 68/push 0/imm32/start +18170 89/<- %edx 4/r32/esp +18171 # allocate into out +18172 (allocate Heap *Stmt-size *(ebp+0x14)) +18173 # var out-addr/edi: (addr block) = lookup(*out) +18174 8b/-> *(ebp+0x14) 7/r32/edi +18175 (lookup *edi *(edi+4)) # => eax +18176 89/<- %edi 0/r32/eax +18177 # out-addr->tag is 0 (block) by default +18178 # set out-addr->var +18179 8d/copy-address *(edi+0xc) 0/r32/eax # Block-var +18180 (new-block-name *(ebp+0x10) %eax) +18181 # push(vars, out-addr->var) +18182 (push *(ebp+0xc) *(edi+0xc)) # Block-var +18183 (push *(ebp+0xc) *(edi+0x10)) # Block-var +18184 (push *(ebp+0xc) 0) # false +18185 # increment *Curr-block-depth +18186 ff 0/subop/increment *Curr-block-depth +18187 { +18188 $parse-mu-block:line-loop: +18189 # line = read-line-buffered(in) +18190 (clear-stream %ecx) +18191 (read-line-buffered *(ebp+8) %ecx) +18192 #? (write-buffered Stderr "line: ") +18193 #? (write-stream-data Stderr %ecx) +18194 #? #? (write-buffered Stderr Newline) # line has its own newline +18195 #? (flush Stderr) +18196 #? (rewind-stream %ecx) +18197 # if (line->write == 0) break +18198 81 7/subop/compare *ecx 0/imm32 +18199 0f 84/jump-if-= break/disp32 +18200 #? (write-buffered Stderr "vars:\n") +18201 #? (dump-vars *(ebp+0xc)) +18202 # word-slice = next-mu-token(line) +18203 (next-mu-token %ecx %edx) +18204 #? (write-buffered Stderr "word: ") +18205 #? (write-slice-buffered Stderr %edx) +18206 #? (write-buffered Stderr Newline) +18207 #? (flush Stderr) +18208 # if slice-empty?(word-slice) continue +18209 (slice-empty? %edx) +18210 3d/compare-eax-and 0/imm32/false +18211 0f 85/jump-if-!= loop/disp32 +18212 # if (slice-starts-with?(word-slice, '#') continue +18213 # . eax = *word-slice->start +18214 8b/-> *edx 0/r32/eax +18215 8a/copy-byte *eax 0/r32/AL +18216 25/and-eax-with 0xff/imm32 +18217 # . if (eax == '#') continue +18218 3d/compare-eax-and 0x23/imm32/hash +18219 0f 84/jump-if-= loop/disp32 +18220 # if slice-equal?(word-slice, "{") +18221 { +18222 $parse-mu-block:check-for-block: +18223 (slice-equal? %edx "{") +18224 3d/compare-eax-and 0/imm32/false +18225 74/jump-if-= break/disp8 +18226 (check-no-tokens-left %ecx) +18227 # parse new block and append +18228 # . var tmp/eax: (handle block) +18229 68/push 0/imm32 +18230 68/push 0/imm32 +18231 89/<- %eax 4/r32/esp +18232 # . +18233 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c)) +18234 (append-to-block Heap %edi *eax *(eax+4)) +18235 # . reclaim tmp +18236 81 0/subop/add %esp 8/imm32 +18237 # . +18238 e9/jump $parse-mu-block:line-loop/disp32 +18239 } +18240 # if slice-equal?(word-slice, "}") break +18241 $parse-mu-block:check-for-end: +18242 (slice-equal? %edx "}") +18243 3d/compare-eax-and 0/imm32/false +18244 0f 85/jump-if-!= break/disp32 +18245 # if slice-ends-with?(word-slice, ":") parse named block and append +18246 { +18247 $parse-mu-block:check-for-named-block: +18248 # . eax = *(word-slice->end-1) +18249 8b/-> *(edx+4) 0/r32/eax +18250 48/decrement-eax +18251 8a/copy-byte *eax 0/r32/AL +18252 25/and-eax-with 0xff/imm32 +18253 # . if (eax != ':') break +18254 3d/compare-eax-and 0x3a/imm32/colon +18255 0f 85/jump-if-!= break/disp32 +18256 # TODO: error-check the rest of 'line' +18257 # +18258 # skip ':' +18259 ff 1/subop/decrement *(edx+4) # Slice-end +18260 # var tmp/eax: (handle block) +18261 68/push 0/imm32 +18262 68/push 0/imm32 +18263 89/<- %eax 4/r32/esp +18264 # +18265 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c)) +18266 (append-to-block Heap %edi *eax *(eax+4)) +18267 # reclaim tmp +18268 81 0/subop/add %esp 8/imm32 +18269 # +18270 e9/jump $parse-mu-block:line-loop/disp32 +18271 } +18272 # if slice-equal?(word-slice, "var") +18273 { +18274 $parse-mu-block:check-for-var: +18275 (slice-equal? %edx "var") +18276 3d/compare-eax-and 0/imm32/false +18277 74/jump-if-= break/disp8 +18278 # var tmp/eax: (handle block) +18279 68/push 0/imm32 +18280 68/push 0/imm32 +18281 89/<- %eax 4/r32/esp +18282 # +18283 (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) +18284 (append-to-block Heap %edi *eax *(eax+4)) +18285 # reclaim tmp +18286 81 0/subop/add %esp 8/imm32 +18287 # +18288 e9/jump $parse-mu-block:line-loop/disp32 +18289 } +18290 $parse-mu-block:regular-stmt: +18291 # otherwise +18292 # var tmp/eax: (handle block) +18293 68/push 0/imm32 +18294 68/push 0/imm32 +18295 89/<- %eax 4/r32/esp +18296 # +18297 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c)) +18298 (append-to-block Heap %edi *eax *(eax+4)) +18299 # reclaim tmp +18300 81 0/subop/add %esp 8/imm32 +18301 # +18302 e9/jump loop/disp32 +18303 } # end line loop +18304 (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10)) +18305 # decrement *Curr-block-depth +18306 ff 1/subop/decrement *Curr-block-depth +18307 # pop(vars) +18308 (pop *(ebp+0xc)) # => eax +18309 (pop *(ebp+0xc)) # => eax +18310 (pop *(ebp+0xc)) # => eax +18311 $parse-mu-block:end: +18312 # . reclaim locals +18313 81 0/subop/add %esp 0x214/imm32 +18314 # . restore registers +18315 5f/pop-to-edi +18316 5b/pop-to-ebx +18317 5a/pop-to-edx +18318 59/pop-to-ecx +18319 58/pop-to-eax +18320 # . epilogue +18321 89/<- %esp 5/r32/ebp +18322 5d/pop-to-ebp +18323 c3/return +18324 +18325 $parse-mu-block:abort: +18326 # error("'{' or '}' should be on its own line, but got '") +18327 (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '") +18328 (rewind-stream %ecx) +18329 (write-stream-data *(ebp+0x18) %ecx) +18330 (write-buffered *(ebp+0x18) "'\n") +18331 (flush *(ebp+0x18)) +18332 (stop *(ebp+0x1c) 1) +18333 # never gets here +18334 +18335 new-block-name: # fn: (addr function), out: (addr handle var) +18336 # . prologue +18337 55/push-ebp +18338 89/<- %ebp 4/r32/esp +18339 # . save registers +18340 50/push-eax +18341 51/push-ecx +18342 52/push-edx +18343 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' +18344 8b/-> *(ebp+8) 0/r32/eax +18345 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18346 8b/-> *eax 0/r32/eax # String-size +18347 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' +18348 89/<- %ecx 0/r32/eax +18349 # var name/edx: (stream byte n) +18350 29/subtract-from %esp 1/r32/ecx +18351 ff 6/subop/push %ecx +18352 68/push 0/imm32/read +18353 68/push 0/imm32/write +18354 89/<- %edx 4/r32/esp +18355 (clear-stream %edx) +18356 # eax = fn->name +18357 8b/-> *(ebp+8) 0/r32/eax +18358 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18359 # construct result using Next-block-index (and increment it) +18360 (write %edx "$") +18361 (write %edx %eax) +18362 (write %edx ":") +18363 (write-int32-hex %edx *Next-block-index) +18364 ff 0/subop/increment *Next-block-index +18365 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) +18366 # . eax = name->write +18367 8b/-> *edx 0/r32/eax +18368 # . edx = name->data +18369 8d/copy-address *(edx+0xc) 2/r32/edx +18370 # . eax = name->write + name->data +18371 01/add-to %eax 2/r32/edx +18372 # . push {edx, eax} +18373 ff 6/subop/push %eax +18374 ff 6/subop/push %edx +18375 89/<- %eax 4/r32/esp +18376 # out = new literal(s) +18377 (new-literal Heap %eax *(ebp+0xc)) +18378 #? 8b/-> *(ebp+0xc) 0/r32/eax +18379 #? (write-buffered Stderr "type allocid in caller after new-literal: ") +18380 #? (write-int32-hex-buffered Stderr *(eax+8)) +18381 #? (write-buffered Stderr " for var ") +18382 #? (write-int32-hex-buffered Stderr %eax) +18383 #? (write-buffered Stderr Newline) +18384 #? (flush Stderr) +18385 $new-block-name:end: +18386 # . reclaim locals +18387 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} +18388 81 0/subop/add %ecx 8/imm32 # slice +18389 01/add-to %esp 1/r32/ecx +18390 # . restore registers +18391 5a/pop-to-edx +18392 59/pop-to-ecx +18393 58/pop-to-eax +18394 # . epilogue +18395 89/<- %esp 5/r32/ebp +18396 5d/pop-to-ebp +18397 c3/return +18398 +18399 check-no-tokens-left: # line: (addr stream byte) +18400 # . prologue +18401 55/push-ebp +18402 89/<- %ebp 4/r32/esp +18403 # . save registers +18404 50/push-eax +18405 51/push-ecx +18406 # var s/ecx: slice +18407 68/push 0/imm32/end +18408 68/push 0/imm32/start +18409 89/<- %ecx 4/r32/esp +18410 # +18411 (next-mu-token *(ebp+8) %ecx) +18412 # if slice-empty?(s) return +18413 (slice-empty? %ecx) +18414 3d/compare-eax-and 0/imm32/false +18415 75/jump-if-!= $check-no-tokens-left:end/disp8 +18416 # if (slice-starts-with?(s, '#') return +18417 # . eax = *s->start +18418 8b/-> *edx 0/r32/eax +18419 8a/copy-byte *eax 0/r32/AL +18420 25/and-eax-with 0xff/imm32 +18421 # . if (eax == '#') continue +18422 3d/compare-eax-and 0x23/imm32/hash +18423 74/jump-if-= $check-no-tokens-left:end/disp8 +18424 # abort +18425 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +18426 (rewind-stream %ecx) +18427 (write-stream 2 %ecx) +18428 (write-buffered Stderr "'\n") +18429 (flush Stderr) +18430 # . syscall(exit, 1) +18431 bb/copy-to-ebx 1/imm32 +18432 e8/call syscall_exit/disp32 +18433 # never gets here +18434 $check-no-tokens-left:end: +18435 # . reclaim locals +18436 81 0/subop/add %esp 8/imm32 +18437 # . restore registers +18438 59/pop-to-ecx +18439 58/pop-to-eax +18440 # . epilogue +18441 89/<- %esp 5/r32/ebp +18442 5d/pop-to-ebp +18443 c3/return +18444 +18445 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +18446 # pseudocode: +18447 # var v: (handle var) +18448 # new-literal(name, v) +18449 # push(vars, {v, false}) +18450 # parse-mu-block(in, vars, fn, out) +18451 # pop(vars) +18452 # out->tag = block +18453 # out->var = v +18454 # +18455 # . prologue +18456 55/push-ebp +18457 89/<- %ebp 4/r32/esp +18458 # . save registers +18459 50/push-eax +18460 51/push-ecx +18461 57/push-edi +18462 # var v/ecx: (handle var) +18463 68/push 0/imm32 +18464 68/push 0/imm32 +18465 89/<- %ecx 4/r32/esp +18466 # +18467 (new-literal Heap *(ebp+8) %ecx) +18468 # push(vars, v) +18469 (push *(ebp+0x10) *ecx) +18470 (push *(ebp+0x10) *(ecx+4)) +18471 (push *(ebp+0x10) 0) # false +18472 # +18473 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20)) +18474 # pop v off vars +18475 (pop *(ebp+0x10)) # => eax +18476 (pop *(ebp+0x10)) # => eax +18477 (pop *(ebp+0x10)) # => eax +18478 # var out-addr/edi: (addr stmt) = lookup(*out) +18479 8b/-> *(ebp+0x18) 7/r32/edi +18480 (lookup *edi *(edi+4)) # => eax +18481 89/<- %edi 0/r32/eax +18482 # out-addr->tag = named-block +18483 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag +18484 # out-addr->var = v +18485 8b/-> *ecx 0/r32/eax +18486 89/<- *(edi+0xc) 0/r32/eax # Block-var +18487 8b/-> *(ecx+4) 0/r32/eax +18488 89/<- *(edi+0x10) 0/r32/eax # Block-var +18489 $parse-mu-named-block:end: +18490 # . reclaim locals +18491 81 0/subop/add %esp 8/imm32 +18492 # . restore registers +18493 5f/pop-to-edi +18494 59/pop-to-ecx +18495 58/pop-to-eax +18496 # . epilogue +18497 89/<- %esp 5/r32/ebp +18498 5d/pop-to-ebp +18499 c3/return +18500 +18501 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack live-var), out: (addr handle stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +18502 # . prologue +18503 55/push-ebp +18504 89/<- %ebp 4/r32/esp +18505 # . save registers +18506 50/push-eax +18507 51/push-ecx +18508 52/push-edx +18509 56/push-esi +18510 57/push-edi +18511 # edi = out +18512 8b/-> *(ebp+0x10) 7/r32/edi +18513 # var word-slice/ecx: slice +18514 68/push 0/imm32/end +18515 68/push 0/imm32/start +18516 89/<- %ecx 4/r32/esp +18517 # var v/edx: (handle var) +18518 68/push 0/imm32 +18519 68/push 0/imm32 +18520 89/<- %edx 4/r32/esp +18521 # v = parse-var-with-type(next-mu-token(line)) +18522 (next-mu-token *(ebp+8) %ecx) +18523 { +18524 # just for tests, support null fn +18525 8b/-> *(ebp+0x14) 0/r32/eax +18526 3d/compare-eax-and 0/imm32 +18527 74/jump-if-= break/disp8 +18528 (lookup *eax *(eax+4)) # Var-name Var-name => eax +18529 } +18530 (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c)) +18531 # var v-addr/esi: (addr var) +18532 (lookup *edx *(edx+4)) # => eax +18533 89/<- %esi 0/r32/eax +18534 # v->block-depth = *Curr-block-depth +18535 8b/-> *Curr-block-depth 0/r32/eax +18536 89/<- *(esi+0x10) 0/r32/eax # Var-block-depth +18537 # either v has no register and there's no more to this line +18538 81 7/subop/compare *(esi+0x18) 0/imm32 +18539 { +18540 75/jump-if-!= break/disp8 +18541 # if v-addr->type == byte, abort +18542 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax +18543 (simple-mu-type? %eax 8) # byte => eax +18544 3d/compare-eax-and 0/imm32/false +18545 0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32 +18546 # ensure that there's nothing else on this line +18547 (next-mu-token *(ebp+8) %ecx) +18548 (slice-empty? %ecx) # => eax +18549 3d/compare-eax-and 0/imm32/false +18550 0f 84/jump-if-= $parse-mu-var-def:error2/disp32 +18551 # +18552 (new-var-def Heap *edx *(edx+4) %edi) +18553 e9/jump $parse-mu-var-def:update-vars/disp32 +18554 } +18555 # or v has a register and there's more to this line +18556 { +18557 0f 84/jump-if-= break/disp32 +18558 # if v-addr->type == byte, check for unsupported registers +18559 { +18560 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax +18561 (simple-mu-type? %eax 8) # byte => eax +18562 3d/compare-eax-and 0/imm32/false +18563 74/jump-if-= break/disp8 +18564 (lookup *(esi+0x18) *(esi+0x1c)) # => eax +18565 (string-equal? %eax "esi") # => eax +18566 3d/compare-eax-and 0/imm32/false +18567 0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32 +18568 (lookup *(esi+0x18) *(esi+0x1c)) # => eax +18569 (string-equal? %eax "edi") # => eax +18570 3d/compare-eax-and 0/imm32/false +18571 0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32 +18572 } +18573 # TODO: vars of type 'byte' should only be initialized by clearing to 0 +18574 # ensure that the next word is '<-' +18575 (next-mu-token *(ebp+8) %ecx) +18576 (slice-equal? %ecx "<-") # => eax +18577 3d/compare-eax-and 0/imm32/false +18578 0f 84/jump-if-= $parse-mu-var-def:error1/disp32 +18579 # +18580 (new-reg-var-def Heap *edx *(edx+4) %edi) +18581 (lookup *edi *(edi+4)) # => eax +18582 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +18583 } +18584 $parse-mu-var-def:update-vars: +18585 # push 'v' at end of function +18586 (push *(ebp+0xc) *edx) +18587 (push *(ebp+0xc) *(edx+4)) +18588 (push *(ebp+0xc) 0) # Live-var-register-spilled is unused during parsing +18589 $parse-mu-var-def:end: +18590 # . reclaim locals +18591 81 0/subop/add %esp 0x10/imm32 +18592 # . restore registers +18593 5f/pop-to-edi +18594 5e/pop-to-esi +18595 5a/pop-to-edx +18596 59/pop-to-ecx +18597 58/pop-to-eax +18598 # . epilogue +18599 89/<- %esp 5/r32/ebp +18600 5d/pop-to-ebp +18601 c3/return +18602 +18603 $parse-mu-var-def:error1: +18604 (rewind-stream *(ebp+8)) +18605 # error("register variable requires a valid instruction to initialize but got '" line "'\n") +18606 (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '") +18607 (flush *(ebp+0x18)) +18608 (write-stream-data *(ebp+0x18) *(ebp+8)) +18609 (write-buffered *(ebp+0x18) "'\n") +18610 (flush *(ebp+0x18)) +18611 (stop *(ebp+0x1c) 1) +18612 # never gets here +18613 +18614 $parse-mu-var-def:error2: +18615 # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n") +18616 (write-buffered *(ebp+0x18) "fn ") +18617 8b/-> *(ebp+0x14) 0/r32/eax +18618 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18619 (write-buffered *(ebp+0x18) %eax) +18620 (write-buffered *(ebp+0x18) ": var ") +18621 # var v-addr/eax: (addr var) = lookup(v) +18622 (lookup *edx *(edx+4)) # => eax +18623 (lookup *eax *(eax+4)) # Var-name Var-name => eax +18624 (write-buffered *(ebp+0x18) %eax) +18625 (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n") +18626 (flush *(ebp+0x18)) +18627 (stop *(ebp+0x1c) 1) +18628 # never gets here +18629 +18630 $parse-mu-var-def:error-byte-on-stack: +18631 # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n") +18632 (write-buffered *(ebp+0x18) "fn ") +18633 8b/-> *(ebp+0x14) 0/r32/eax +18634 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18635 (write-buffered *(ebp+0x18) %eax) +18636 (write-buffered *(ebp+0x18) ": var '") +18637 # var v-addr/eax: (addr var) = lookup(v) +18638 (lookup *edx *(edx+4)) # => eax +18639 (lookup *eax *(eax+4)) # Var-name Var-name => eax +18640 (write-buffered *(ebp+0x18) %eax) +18641 (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n") +18642 (flush *(ebp+0x18)) +18643 (stop *(ebp+0x1c) 1) +18644 # never gets here +18645 +18646 $parse-mu-var-def:error-byte-registers: +18647 # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n") +18648 (write-buffered *(ebp+0x18) "fn ") +18649 8b/-> *(ebp+0x14) 0/r32/eax +18650 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18651 (write-buffered *(ebp+0x18) %eax) +18652 (write-buffered *(ebp+0x18) ": var '") +18653 # var v-addr/eax: (addr var) = lookup(v) +18654 (lookup *edx *(edx+4)) # => eax +18655 (lookup *eax *(eax+4)) # Var-name Var-name => eax +18656 (write-buffered *(ebp+0x18) %eax) +18657 (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n") +18658 (flush *(ebp+0x18)) +18659 (stop *(ebp+0x1c) 1) +18660 # never gets here +18661 +18662 test-parse-mu-var-def: +18663 # 'var n: int' +18664 # . prologue +18665 55/push-ebp +18666 89/<- %ebp 4/r32/esp +18667 # setup +18668 8b/-> *Primitive-type-ids 0/r32/eax +18669 89/<- *Type-id 0/r32/eax # stream-write +18670 (clear-stream _test-input-stream) +18671 (write _test-input-stream "n: int\n") # caller has consumed the 'var' +18672 c7 0/subop/copy *Curr-block-depth 1/imm32 +18673 # var out/esi: (handle stmt) +18674 68/push 0/imm32 +18675 68/push 0/imm32 +18676 89/<- %esi 4/r32/esp +18677 # var vars/ecx: (stack (addr var) 16) +18678 81 5/subop/subtract %esp 0xc0/imm32 +18679 68/push 0xc0/imm32/size +18680 68/push 0/imm32/top +18681 89/<- %ecx 4/r32/esp +18682 (clear-stack %ecx) +18683 # convert +18684 (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0) +18685 # var out-addr/esi: (addr stmt) +18686 (lookup *esi *(esi+4)) # => eax +18687 89/<- %esi 0/r32/eax +18688 # +18689 (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is var-def +18690 # var v/ecx: (addr var) = lookup(out->var) +18691 (lookup *(esi+4) *(esi+8)) # Vardef-var Vardef-var => eax +18692 89/<- %ecx 0/r32/eax +18693 # v->name +18694 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +18695 (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name") +18696 # v->register +18697 (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register") # Var-register +18698 # v->block-depth +18699 (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth") # Var-block-depth +18700 # v->type == int +18701 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +18702 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Type-tree-is-atom +18703 (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1") # Type-tree-value +18704 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2") # Type-tree-right +18705 # . epilogue +18706 89/<- %esp 5/r32/ebp +18707 5d/pop-to-ebp +18708 c3/return +18709 +18710 test-parse-mu-reg-var-def: +18711 # 'var n/eax: int <- copy 0' +18712 # . prologue +18713 55/push-ebp +18714 89/<- %ebp 4/r32/esp +18715 # setup +18716 8b/-> *Primitive-type-ids 0/r32/eax +18717 89/<- *Type-id 0/r32/eax # stream-write +18718 (clear-stream _test-input-stream) +18719 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' +18720 c7 0/subop/copy *Curr-block-depth 1/imm32 +18721 # var out/esi: (handle stmt) +18722 68/push 0/imm32 +18723 68/push 0/imm32 +18724 89/<- %esi 4/r32/esp +18725 # var vars/ecx: (stack (addr var) 16) +18726 81 5/subop/subtract %esp 0xc0/imm32 +18727 68/push 0xc0/imm32/size +18728 68/push 0/imm32/top +18729 89/<- %ecx 4/r32/esp +18730 (clear-stack %ecx) +18731 # convert +18732 (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0) +18733 # var out-addr/esi: (addr stmt) +18734 (lookup *esi *(esi+4)) # => eax +18735 89/<- %esi 0/r32/eax +18736 # +18737 (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is reg-var-def +18738 # var v/ecx: (addr var) = lookup(out->outputs->value) +18739 # . eax: (addr stmt-var) = lookup(out->outputs) +18740 (lookup *(esi+0x14) *(esi+0x18)) # Regvardef-outputs Regvardef-outputs => eax +18741 # . +18742 (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output") # Stmt-var-next +18743 # . eax: (addr var) = lookup(eax->value) +18744 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +18745 # . ecx = eax +18746 89/<- %ecx 0/r32/eax +18747 # v->name +18748 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +18749 (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name +18750 # v->register +18751 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax +18752 (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register") +18753 # v->block-depth +18754 (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +18755 # v->type == int +18756 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +18757 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Type-tree-is-atom +18758 (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1") # Type-tree-value +18759 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2") # Type-tree-right +18760 # . epilogue +18761 89/<- %esp 5/r32/ebp +18762 5d/pop-to-ebp +18763 c3/return +18764 +18765 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +18766 # pseudocode: +18767 # var name: slice +18768 # allocate(Heap, Stmt-size, out) +18769 # var out-addr: (addr stmt) = lookup(*out) +18770 # out-addr->tag = stmt +18771 # if stmt-has-outputs?(line) +18772 # while true +18773 # name = next-mu-token(line) +18774 # if (name == '<-') break +18775 # assert(identifier?(name)) +18776 # var v: (handle var) = lookup-var(name, vars) +18777 # out-addr->outputs = append(v, out-addr->outputs) +18778 # add-operation-and-inputs-to-stmt(out-addr, line, vars) +18779 # +18780 # . prologue +18781 55/push-ebp +18782 89/<- %ebp 4/r32/esp +18783 # . save registers +18784 50/push-eax +18785 51/push-ecx +18786 52/push-edx +18787 53/push-ebx +18788 57/push-edi +18789 # var name/ecx: slice +18790 68/push 0/imm32/end +18791 68/push 0/imm32/start +18792 89/<- %ecx 4/r32/esp +18793 # var is-deref?/edx: boolean = false +18794 ba/copy-to-edx 0/imm32/false +18795 # var v: (handle var) +18796 68/push 0/imm32 +18797 68/push 0/imm32 +18798 89/<- %ebx 4/r32/esp +18799 # +18800 (allocate Heap *Stmt-size *(ebp+0x14)) +18801 # var out-addr/edi: (addr stmt) = lookup(*out) +18802 8b/-> *(ebp+0x14) 7/r32/edi +18803 (lookup *edi *(edi+4)) # => eax +18804 89/<- %edi 0/r32/eax +18805 # out-addr->tag = 1/stmt +18806 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag +18807 { +18808 (stmt-has-outputs? *(ebp+8)) +18809 3d/compare-eax-and 0/imm32/false +18810 0f 84/jump-if-= break/disp32 +18811 { +18812 $parse-mu-stmt:read-outputs: +18813 # name = next-mu-token(line) +18814 (next-mu-token *(ebp+8) %ecx) +18815 # if slice-empty?(word-slice) break +18816 (slice-empty? %ecx) # => eax +18817 3d/compare-eax-and 0/imm32/false +18818 0f 85/jump-if-!= break/disp32 +18819 # if (name == "<-") break +18820 (slice-equal? %ecx "<-") # => eax +18821 3d/compare-eax-and 0/imm32/false +18822 0f 85/jump-if-!= break/disp32 +18823 # if slice-starts-with?(name, "*") abort +18824 8b/-> *ecx 0/r32/eax # Slice-start +18825 8a/copy-byte *eax 0/r32/AL +18826 25/and-eax-with 0xff/imm32 +18827 3d/compare-eax-and 0x2a/imm32/asterisk +18828 0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32 +18829 # assert(identifier?(name)) +18830 (identifier? %ecx) # => eax +18831 3d/compare-eax-and 0/imm32/false +18832 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 +18833 # +18834 (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) +18835 8d/copy-address *(edi+0x14) 0/r32/eax # Stmt1-outputs +18836 (append-stmt-var Heap *ebx *(ebx+4) *(edi+0x14) *(edi+0x18) 0 %eax) # Stmt1-outputs +18837 # +18838 e9/jump loop/disp32 +18839 } +18840 } +18841 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c)) +18842 $parse-mu-stmt:end: +18843 # . reclaim locals +18844 81 0/subop/add %esp 0x10/imm32 +18845 # . restore registers +18846 5f/pop-to-edi +18847 5b/pop-to-ebx +18848 5a/pop-to-edx +18849 59/pop-to-ecx +18850 58/pop-to-eax +18851 # . epilogue +18852 89/<- %esp 5/r32/ebp +18853 5d/pop-to-ebp +18854 c3/return +18855 +18856 $parse-mu-stmt:abort: +18857 # error("invalid identifier '" name "'\n") +18858 (write-buffered *(ebp+0x18) "fn ") +18859 8b/-> *(ebp+0x10) 0/r32/eax +18860 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18861 (write-buffered *(ebp+0x18) %eax) +18862 (write-buffered *(ebp+0x18) ": invalid identifier '") +18863 (write-slice-buffered *(ebp+0x18) %ecx) +18864 (write-buffered *(ebp+0x18) "'\n") +18865 (flush *(ebp+0x18)) +18866 (stop *(ebp+0x1c) 1) +18867 # never gets here +18868 +18869 $parse-mu-stmt:error-output-dereferenced: +18870 # error("invalid identifier '" name "'\n") +18871 (write-buffered *(ebp+0x18) "fn ") +18872 8b/-> *(ebp+0x10) 0/r32/eax +18873 (lookup *eax *(eax+4)) # Function-name Function-name => eax +18874 (write-buffered *(ebp+0x18) %eax) +18875 (write-buffered *(ebp+0x18) ": output '") +18876 (write-slice-buffered *(ebp+0x18) %ecx) +18877 (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n") +18878 (flush *(ebp+0x18)) +18879 (stop *(ebp+0x1c) 1) +18880 # never gets here +18881 +18882 add-operation-and-inputs-to-stmt: # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +18883 # pseudocode: +18884 # stmt->name = slice-to-string(next-mu-token(line)) +18885 # while true +18886 # name = next-mu-token(line) +18887 # v = lookup-var-or-literal(name) +18888 # stmt->inouts = append(v, stmt->inouts) +18889 # +18890 # . prologue +18891 55/push-ebp +18892 89/<- %ebp 4/r32/esp +18893 # . save registers +18894 50/push-eax +18895 51/push-ecx +18896 52/push-edx +18897 53/push-ebx +18898 56/push-esi +18899 57/push-edi +18900 # edi = stmt +18901 8b/-> *(ebp+8) 7/r32/edi +18902 # var name/ecx: slice +18903 68/push 0/imm32/end +18904 68/push 0/imm32/start +18905 89/<- %ecx 4/r32/esp +18906 # var is-deref?/edx: boolean = false +18907 ba/copy-to-edx 0/imm32/false +18908 # var v/esi: (handle var) +18909 68/push 0/imm32 +18910 68/push 0/imm32 +18911 89/<- %esi 4/r32/esp +18912 $add-operation-and-inputs-to-stmt:read-operation: +18913 (next-mu-token *(ebp+0xc) %ecx) +18914 8d/copy-address *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation +18915 (slice-to-string Heap %ecx %eax) +18916 # var is-get?/ebx: boolean = (name == "get") +18917 (slice-equal? %ecx "get") # => eax +18918 89/<- %ebx 0/r32/eax +18919 { +18920 $add-operation-and-inputs-to-stmt:read-inouts: +18921 # name = next-mu-token(line) +18922 (next-mu-token *(ebp+0xc) %ecx) +18923 # if slice-empty?(word-slice) break +18924 (slice-empty? %ecx) # => eax +18925 3d/compare-eax-and 0/imm32/false +18926 0f 85/jump-if-!= break/disp32 +18927 # if (name == "<-") abort +18928 (slice-equal? %ecx "<-") +18929 3d/compare-eax-and 0/imm32/false +18930 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 +18931 # if (get? && second operand) lookup or create offset +18932 { +18933 81 7/subop/compare %ebx 0/imm32/false +18934 74/jump-if-= break/disp8 +18935 (lookup *(edi+0xc) *(edi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +18936 3d/compare-eax-and 0/imm32 +18937 74/jump-if-= break/disp8 +18938 (lookup-or-create-constant %eax %ecx %esi) +18939 #? (lookup *esi *(esi+4)) +18940 #? (write-buffered Stderr "creating new output var ") +18941 #? (write-int32-hex-buffered Stderr %eax) +18942 #? (write-buffered Stderr " for field called ") +18943 #? (write-slice-buffered Stderr %ecx) +18944 #? (write-buffered Stderr "; var name ") +18945 #? (lookup *eax *(eax+4)) # Var-name +18946 #? (write-buffered Stderr %eax) +18947 #? (write-buffered Stderr Newline) +18948 #? (flush Stderr) +18949 e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32 +18950 } +18951 # is-deref? = false +18952 ba/copy-to-edx 0/imm32/false +18953 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +18954 8b/-> *ecx 0/r32/eax # Slice-start +18955 8a/copy-byte *eax 0/r32/AL +18956 25/and-eax-with 0xff/imm32 +18957 3d/compare-eax-and 0x2a/imm32/asterisk +18958 { +18959 75/jump-if-!= break/disp8 +18960 $add-operation-and-inputs-to-stmt:inout-is-deref: +18961 ff 0/subop/increment *ecx +18962 ba/copy-to-edx 1/imm32/true +18963 } +18964 (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +18965 # if (deref?) some additional checks +18966 81 7/subop/compare %edx 0/imm32/false +18967 { +18968 74/jump-if-= break/disp8 +18969 # if var is not in register, abort +18970 (lookup *esi *(esi+4)) # => eax +18971 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +18972 0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32 +18973 # if var is not an address, abort +18974 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +18975 (mu-addr-type? %eax) # => eax +18976 3d/compare-eax-and 0/imm32/false +18977 0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32 +18978 } +18979 $add-operation-and-inputs-to-stmt:save-var: +18980 8d/copy-address *(edi+0xc) 0/r32/eax +18981 (append-stmt-var Heap *esi *(esi+4) *(edi+0xc) *(edi+0x10) %edx %eax) # Stmt1-inouts or Regvardef-inouts +18982 # +18983 e9/jump loop/disp32 +18984 } +18985 $add-operation-and-inputs-to-stmt:end: +18986 # . reclaim locals +18987 81 0/subop/add %esp 0x10/imm32 +18988 # . restore registers +18989 5f/pop-to-edi +18990 5e/pop-to-esi +18991 5b/pop-to-ebx +18992 5a/pop-to-edx +18993 59/pop-to-ecx +18994 58/pop-to-eax +18995 # . epilogue +18996 89/<- %esp 5/r32/ebp +18997 5d/pop-to-ebp +18998 c3/return +18999 +19000 $add-operation-and-inputs-to-stmt:abort: +19001 # error("fn ___: invalid identifier in '" line "'\n") +19002 (write-buffered *(ebp+0x18) "fn ") +19003 8b/-> *(ebp+0x14) 0/r32/eax +19004 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19005 (write-buffered *(ebp+0x18) %eax) +19006 (rewind-stream *(ebp+0xc)) +19007 (write-buffered *(ebp+0x18) ": invalid identifier in '") +19008 (write-stream-data *(ebp+0x18) *(ebp+0xc)) +19009 (write-buffered *(ebp+0x18) "'\n") +19010 (flush *(ebp+0x18)) +19011 (stop *(ebp+0x1c) 1) +19012 # never gets here +19013 +19014 $add-operation-and-inputs-to-stmt:error-deref-on-stack: +19015 # error("fn ___: cannot dereference var ___ on stack\n") +19016 (write-buffered *(ebp+0x18) "fn ") +19017 8b/-> *(ebp+0x14) 0/r32/eax +19018 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19019 (write-buffered *(ebp+0x18) %eax) +19020 (rewind-stream *(ebp+0xc)) +19021 (write-buffered *(ebp+0x18) ": cannot dereference var '") +19022 (lookup *esi *(esi+4)) # => eax +19023 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19024 (write-buffered *(ebp+0x18) %eax) +19025 (write-buffered *(ebp+0x18) "' on stack\n") +19026 (flush *(ebp+0x18)) +19027 (stop *(ebp+0x1c) 1) +19028 # never gets here +19029 +19030 $add-operation-and-inputs-to-stmt:error-deref-non-addr: +19031 # error("fn ___: cannot dereference non-addr var ___\n") +19032 (write-buffered *(ebp+0x18) "fn ") +19033 8b/-> *(ebp+0x14) 0/r32/eax +19034 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19035 (write-buffered *(ebp+0x18) %eax) +19036 (rewind-stream *(ebp+0xc)) +19037 (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '") +19038 (lookup *esi *(esi+4)) # => eax +19039 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19040 (write-buffered *(ebp+0x18) %eax) +19041 (write-buffered *(ebp+0x18) "'\n") +19042 (flush *(ebp+0x18)) +19043 (stop *(ebp+0x1c) 1) +19044 # never gets here +19045 +19046 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean +19047 # . prologue +19048 55/push-ebp +19049 89/<- %ebp 4/r32/esp +19050 # . save registers +19051 51/push-ecx +19052 # var word-slice/ecx: slice +19053 68/push 0/imm32/end +19054 68/push 0/imm32/start +19055 89/<- %ecx 4/r32/esp +19056 # result = false +19057 b8/copy-to-eax 0/imm32/false +19058 (rewind-stream *(ebp+8)) +19059 { +19060 (next-mu-token *(ebp+8) %ecx) +19061 # if slice-empty?(word-slice) break +19062 (slice-empty? %ecx) +19063 3d/compare-eax-and 0/imm32/false +19064 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +19065 0f 85/jump-if-!= break/disp32 +19066 # if slice-starts-with?(word-slice, '#') break +19067 # . eax = *word-slice->start +19068 8b/-> *ecx 0/r32/eax +19069 8a/copy-byte *eax 0/r32/AL +19070 25/and-eax-with 0xff/imm32 +19071 # . if (eax == '#') break +19072 3d/compare-eax-and 0x23/imm32/hash +19073 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +19074 0f 84/jump-if-= break/disp32 +19075 # if slice-equal?(word-slice, '<-') return true +19076 (slice-equal? %ecx "<-") +19077 3d/compare-eax-and 0/imm32/false +19078 74/jump-if-= loop/disp8 +19079 b8/copy-to-eax 1/imm32/true +19080 } +19081 $stmt-has-outputs:end: +19082 (rewind-stream *(ebp+8)) +19083 # . reclaim locals +19084 81 0/subop/add %esp 8/imm32 +19085 # . restore registers +19086 59/pop-to-ecx +19087 # . epilogue +19088 89/<- %esp 5/r32/ebp +19089 5d/pop-to-ebp +19090 c3/return +19091 +19092 # if 'name' starts with a digit, create a new literal var for it +19093 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found +19094 lookup-var-or-literal: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +19095 # . prologue +19096 55/push-ebp +19097 89/<- %ebp 4/r32/esp +19098 # . save registers +19099 50/push-eax +19100 51/push-ecx +19101 56/push-esi +19102 # esi = name +19103 8b/-> *(ebp+8) 6/r32/esi +19104 # if slice-empty?(name) abort +19105 (slice-empty? %esi) # => eax +19106 3d/compare-eax-and 0/imm32/false +19107 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 +19108 # var c/ecx: byte = *name->start +19109 8b/-> *esi 1/r32/ecx +19110 8a/copy-byte *ecx 1/r32/CL +19111 81 4/subop/and %ecx 0xff/imm32 +19112 # if (decimal-digit?(c) || c == '-') return new var(name) +19113 { +19114 81 7/subop/compare %ecx 0x2d/imm32/dash +19115 74/jump-if-= $lookup-var-or-literal:literal/disp8 +19116 (decimal-digit? %ecx) # => eax +19117 3d/compare-eax-and 0/imm32/false +19118 74/jump-if-= break/disp8 +19119 $lookup-var-or-literal:literal: +19120 (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +19121 eb/jump $lookup-var-or-literal:end/disp8 +19122 } +19123 # else if (c == '"') return new var(name) +19124 { +19125 81 7/subop/compare %ecx 0x22/imm32/dquote +19126 75/jump-if-!= break/disp8 +19127 $lookup-var-or-literal:literal-string: +19128 (new-literal-string Heap %esi *(ebp+0x10)) +19129 eb/jump $lookup-var-or-literal:end/disp8 +19130 } +19131 # otherwise return lookup-var(name, vars) +19132 { +19133 $lookup-var-or-literal:var: +19134 (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +19135 } +19136 $lookup-var-or-literal:end: +19137 # . restore registers +19138 5e/pop-to-esi +19139 59/pop-to-ecx +19140 58/pop-to-eax +19141 # . epilogue +19142 89/<- %esp 5/r32/ebp +19143 5d/pop-to-ebp +19144 c3/return +19145 +19146 $lookup-var-or-literal:abort: +19147 (write-buffered *(ebp+0x18) "fn ") +19148 8b/-> *(ebp+0x14) 0/r32/eax +19149 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19150 (write-buffered *(ebp+0x18) %eax) +19151 (write-buffered *(ebp+0x18) ": empty variable!") +19152 (flush *(ebp+0x18)) +19153 (stop *(ebp+0x1c) 1) +19154 # never gets here +19155 +19156 # return first 'name' from the top (back) of 'vars' and abort if not found +19157 lookup-var: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +19158 # . prologue +19159 55/push-ebp +19160 89/<- %ebp 4/r32/esp +19161 # . save registers +19162 50/push-eax +19163 # +19164 (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +19165 # if (*out == 0) abort +19166 8b/-> *(ebp+0x10) 0/r32/eax +19167 81 7/subop/compare *eax 0/imm32 +19168 74/jump-if-= $lookup-var:abort/disp8 +19169 $lookup-var:end: +19170 # . restore registers +19171 58/pop-to-eax +19172 # . epilogue +19173 89/<- %esp 5/r32/ebp +19174 5d/pop-to-ebp +19175 c3/return +19176 +19177 $lookup-var:abort: +19178 (write-buffered *(ebp+0x18) "fn ") +19179 8b/-> *(ebp+0x14) 0/r32/eax +19180 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19181 (write-buffered *(ebp+0x18) %eax) +19182 (write-buffered *(ebp+0x18) ": unknown variable '") +19183 (write-slice-buffered *(ebp+0x18) *(ebp+8)) +19184 (write-buffered *(ebp+0x18) "'\n") +19185 (flush *(ebp+0x18)) +19186 (stop *(ebp+0x1c) 1) +19187 # never gets here +19188 +19189 # return first 'name' from the top (back) of 'vars', and 0/null if not found +19190 # ensure that 'name' if in a register is the topmost variable in that register +19191 lookup-var-helper: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +19192 # pseudocode: +19193 # var curr: (addr handle var) = &vars->data[vars->top - 12] +19194 # var min = vars->data +19195 # while curr >= min +19196 # var v: (handle var) = *curr +19197 # if v->name == name +19198 # return +19199 # curr -= 12 +19200 # +19201 # . prologue +19202 55/push-ebp +19203 89/<- %ebp 4/r32/esp +19204 # . save registers +19205 50/push-eax +19206 51/push-ecx +19207 52/push-edx +19208 53/push-ebx +19209 56/push-esi +19210 57/push-edi +19211 # clear out +19212 (zero-out *(ebp+0x10) *Handle-size) +19213 # esi = vars +19214 8b/-> *(ebp+0xc) 6/r32/esi +19215 # ebx = vars->top +19216 8b/-> *esi 3/r32/ebx +19217 # if (vars->top > vars->size) abort +19218 3b/compare<- *(esi+4) 0/r32/eax +19219 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 +19220 # var min/edx: (addr handle var) = vars->data +19221 8d/copy-address *(esi+8) 2/r32/edx +19222 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12] +19223 8d/copy-address *(esi+ebx-4) 3/r32/ebx # vars + 8 + vars->type - 12 +19224 # var var-in-reg/edi: 16 addrs +19225 68/push 0/imm32 +19226 68/push 0/imm32 +19227 68/push 0/imm32 +19228 68/push 0/imm32 +19229 68/push 0/imm32 +19230 68/push 0/imm32 +19231 68/push 0/imm32 +19232 68/push 0/imm32 +19233 68/push 0/imm32 +19234 68/push 0/imm32 +19235 68/push 0/imm32 +19236 68/push 0/imm32 +19237 68/push 0/imm32 +19238 68/push 0/imm32 +19239 68/push 0/imm32 +19240 68/push 0/imm32 +19241 89/<- %edi 4/r32/esp +19242 { +19243 $lookup-var-helper:loop: +19244 # if (curr < min) return +19245 39/compare %ebx 2/r32/edx +19246 0f 82/jump-if-addr< break/disp32 +19247 # var v/ecx: (addr var) = lookup(*curr) +19248 (lookup *ebx *(ebx+4)) # => eax +19249 89/<- %ecx 0/r32/eax +19250 # var vn/eax: (addr array byte) = lookup(v->name) +19251 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +19252 # if (vn == name) return curr +19253 (slice-equal? *(ebp+8) %eax) # => eax +19254 3d/compare-eax-and 0/imm32/false +19255 { +19256 74/jump-if-= break/disp8 +19257 $lookup-var-helper:found: +19258 # var vr/eax: (addr array byte) = lookup(v->register) +19259 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax +19260 3d/compare-eax-and 0/imm32 +19261 { +19262 74/jump-if-= break/disp8 +19263 $lookup-var-helper:found-register: +19264 # var reg/eax: int = get(Registers, vr) +19265 (get Mu-registers-unique %eax 0xc "Mu-registers-unique") # => eax +19266 8b/-> *eax 0/r32/eax +19267 # if (var-in-reg[reg]) error +19268 8b/-> *(edi+eax<<2) 0/r32/eax +19269 3d/compare-eax-and 0/imm32 +19270 0f 85/jump-if-!= $lookup-var-helper:error2/disp32 +19271 } +19272 $lookup-var-helper:return: +19273 # esi = out +19274 8b/-> *(ebp+0x10) 6/r32/esi +19275 # *out = *curr +19276 8b/-> *ebx 0/r32/eax +19277 89/<- *esi 0/r32/eax +19278 8b/-> *(ebx+4) 0/r32/eax +19279 89/<- *(esi+4) 0/r32/eax +19280 # return +19281 eb/jump $lookup-var-helper:end/disp8 +19282 } +19283 # 'name' not yet found; update var-in-reg if v in register +19284 # . var vr/eax: (addr array byte) = lookup(v->register) +19285 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax +19286 # . if (vr == 0) continue +19287 3d/compare-eax-and 0/imm32 +19288 74/jump-if-= $lookup-var-helper:continue/disp8 +19289 # . var reg/eax: int = get(Registers, vr) +19290 (get Mu-registers-unique %eax 0xc "Mu-registers-unique") # => eax +19291 8b/-> *eax 0/r32/eax +19292 # . var-in-reg[reg] = v +19293 89/<- *(edi+eax<<2) 1/r32/ecx +19294 $lookup-var-helper:continue: +19295 # curr -= 12 +19296 81 5/subop/subtract %ebx 0xc/imm32 +19297 e9/jump loop/disp32 +19298 } +19299 $lookup-var-helper:end: +19300 # . reclaim locals +19301 81 0/subop/add %esp 0x40/imm32 +19302 # . restore registers +19303 5f/pop-to-edi +19304 5e/pop-to-esi +19305 5b/pop-to-ebx +19306 5a/pop-to-edx +19307 59/pop-to-ecx +19308 58/pop-to-eax +19309 # . epilogue +19310 89/<- %esp 5/r32/ebp +19311 5d/pop-to-ebp +19312 c3/return +19313 +19314 $lookup-var-helper:error1: +19315 (write-buffered *(ebp+0x18) "fn ") +19316 8b/-> *(ebp+0x14) 0/r32/eax +19317 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19318 (write-buffered *(ebp+0x18) %eax) +19319 (write-buffered *(ebp+0x18) ": malformed stack when looking up '") +19320 (write-slice-buffered *(ebp+0x18) *(ebp+8)) +19321 (write-buffered *(ebp+0x18) "'\n") +19322 (flush *(ebp+0x18)) +19323 (stop *(ebp+0x1c) 1) +19324 # never gets here +19325 +19326 $lookup-var-helper:error2: +19327 # eax contains the conflicting var at this point +19328 (write-buffered *(ebp+0x18) "fn ") +19329 50/push-eax +19330 8b/-> *(ebp+0x14) 0/r32/eax +19331 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19332 (write-buffered *(ebp+0x18) %eax) +19333 58/pop-eax +19334 (write-buffered *(ebp+0x18) ": register ") +19335 50/push-eax +19336 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +19337 (write-buffered *(ebp+0x18) %eax) +19338 58/pop-to-eax +19339 (write-buffered *(ebp+0x18) " reads var '") +19340 (write-slice-buffered *(ebp+0x18) *(ebp+8)) +19341 (write-buffered *(ebp+0x18) "' after writing var '") +19342 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19343 (write-buffered *(ebp+0x18) %eax) +19344 (write-buffered *(ebp+0x18) "'\n") +19345 (flush *(ebp+0x18)) +19346 (stop *(ebp+0x1c) 1) +19347 # never gets here +19348 +19349 dump-vars: # vars: (addr stack live-var) +19350 # pseudocode: +19351 # var curr: (addr handle var) = &vars->data[vars->top - 12] +19352 # var min = vars->data +19353 # while curr >= min +19354 # var v: (handle var) = *curr +19355 # print v +19356 # curr -= 12 +19357 # +19358 # . prologue +19359 55/push-ebp +19360 89/<- %ebp 4/r32/esp +19361 # . save registers +19362 52/push-edx +19363 53/push-ebx +19364 56/push-esi +19365 # esi = vars +19366 8b/-> *(ebp+8) 6/r32/esi +19367 # ebx = vars->top +19368 8b/-> *esi 3/r32/ebx +19369 # var min/edx: (addr handle var) = vars->data +19370 8d/copy-address *(esi+8) 2/r32/edx +19371 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12] +19372 8d/copy-address *(esi+ebx-4) 3/r32/ebx # vars + 8 + vars->type - 12 +19373 { +19374 $dump-vars:loop: +19375 # if (curr < min) return +19376 39/compare %ebx 2/r32/edx +19377 0f 82/jump-if-addr< break/disp32 +19378 # +19379 (write-buffered Stderr " var@") +19380 (dump-var 2 %ebx) +19381 # curr -= 12 +19382 81 5/subop/subtract %ebx 0xc/imm32 +19383 e9/jump loop/disp32 +19384 } +19385 $dump-vars:end: +19386 # . restore registers +19387 5e/pop-to-esi +19388 5b/pop-to-ebx +19389 5a/pop-to-edx +19390 # . epilogue +19391 89/<- %esp 5/r32/ebp +19392 5d/pop-to-ebp +19393 c3/return +19394 +19395 == data +19396 # Like Registers, but no esp or ebp +19397 Mu-registers: # (addr stream {(handle array byte), int}) +19398 # a table is a stream +19399 0xa8/imm32/write +19400 0/imm32/read +19401 0xa8/imm32/length +19402 # data +19403 # general-purpose registers +19404 # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them +19405 0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32 +19406 0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32 +19407 0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32 +19408 0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32 +19409 0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32 +19410 0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32 +19411 # floating-point registers +19412 0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32 +19413 0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32 +19414 0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32 +19415 0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32 +19416 0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32 +19417 0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32 +19418 0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32 +19419 0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32 +19420 +19421 # Like Mu-registers, but with unique codes for integer and floating-point +19422 # registers. +19423 # Don't use this for code-generation, only for checking. +19424 Mu-registers-unique: # (addr stream {(handle array byte), int}) +19425 # a table is a stream +19426 0xa8/imm32/write +19427 0/imm32/read +19428 0xa8/imm32/length +19429 # data +19430 # general-purpose registers +19431 0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32 +19432 0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32 +19433 0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32 +19434 0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32 +19435 0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32 +19436 0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32 +19437 # floating-point registers +19438 0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32 +19439 0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32 +19440 0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32 +19441 0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32 +19442 0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32 +19443 0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32 +19444 0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32 +19445 0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32 +19446 +19447 $Mu-register-eax: +19448 0x11/imm32/alloc-id +19449 3/imm32/size +19450 0x65/e 0x61/a 0x78/x +19451 +19452 $Mu-register-ecx: +19453 0x11/imm32/alloc-id +19454 3/imm32/size +19455 0x65/e 0x63/c 0x78/x +19456 +19457 $Mu-register-edx: +19458 0x11/imm32/alloc-id +19459 3/imm32/size +19460 0x65/e 0x64/d 0x78/x +19461 +19462 $Mu-register-ebx: +19463 0x11/imm32/alloc-id +19464 3/imm32/size +19465 0x65/e 0x62/b 0x78/x 19466 -19467 $Mu-register-xmm2: -19468 0x11/imm32/alloc-id:fake:payload -19469 # "xmm2" -19470 0x4/imm32/size -19471 0x78/x 0x6d/m 0x6d/m 0x32/2 -19472 -19473 $Mu-register-xmm3: -19474 0x11/imm32/alloc-id:fake:payload -19475 # "xmm3" -19476 0x4/imm32/size -19477 0x78/x 0x6d/m 0x6d/m 0x33/3 -19478 -19479 $Mu-register-xmm4: -19480 0x11/imm32/alloc-id:fake:payload -19481 # "xmm4" -19482 0x4/imm32/size -19483 0x78/x 0x6d/m 0x6d/m 0x34/4 -19484 -19485 $Mu-register-xmm5: -19486 0x11/imm32/alloc-id:fake:payload -19487 # "xmm5" -19488 0x4/imm32/size -19489 0x78/x 0x6d/m 0x6d/m 0x35/5 -19490 -19491 $Mu-register-xmm6: -19492 0x11/imm32/alloc-id:fake:payload -19493 # "xmm6" -19494 0x4/imm32/size -19495 0x78/x 0x6d/m 0x6d/m 0x36/6 -19496 -19497 $Mu-register-xmm7: -19498 0x11/imm32/alloc-id:fake:payload -19499 # "xmm7" -19500 0x4/imm32/size -19501 0x78/x 0x6d/m 0x6d/m 0x37/7 -19502 -19503 == code -19504 -19505 # push 'out' to 'vars' if not already there; it's assumed to be a fn output -19506 maybe-define-var: # out: (handle var), vars: (addr stack live-var) -19507 # . prologue -19508 55/push-ebp -19509 89/<- %ebp 4/r32/esp -19510 # . save registers -19511 50/push-eax -19512 # var out-addr/eax: (addr var) -19513 (lookup *(ebp+8) *(ebp+0xc)) # => eax -19514 # -19515 (binding-exists? %eax *(ebp+0x10)) # => eax -19516 3d/compare-eax-and 0/imm32/false -19517 75/jump-if-!= $maybe-define-var:end/disp8 -19518 # otherwise update vars -19519 (push *(ebp+0x10) *(ebp+8)) -19520 (push *(ebp+0x10) *(ebp+0xc)) -19521 (push *(ebp+0x10) 0) # 'out' is always a fn output; never spill it -19522 $maybe-define-var:end: -19523 # . restore registers -19524 58/pop-to-eax -19525 # . epilogue -19526 89/<- %esp 5/r32/ebp -19527 5d/pop-to-ebp -19528 c3/return -19529 -19530 # simpler version of lookup-var-helper -19531 binding-exists?: # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean -19532 # pseudocode: -19533 # var curr: (addr handle var) = &vars->data[vars->top - 12] -19534 # var min = vars->data -19535 # while curr >= min -19536 # var v: (handle var) = *curr -19537 # if v->name == target->name -19538 # return true -19539 # curr -= 12 -19540 # return false -19541 # -19542 # . prologue -19543 55/push-ebp -19544 89/<- %ebp 4/r32/esp -19545 # . save registers -19546 51/push-ecx -19547 52/push-edx -19548 56/push-esi -19549 # var target-name/ecx: (addr array byte) = lookup(target->name) -19550 8b/-> *(ebp+8) 0/r32/eax -19551 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19552 89/<- %ecx 0/r32/eax -19553 # esi = vars -19554 8b/-> *(ebp+0xc) 6/r32/esi -19555 # eax = vars->top -19556 8b/-> *esi 0/r32/eax -19557 # var min/edx: (addr handle var) = vars->data -19558 8d/copy-address *(esi+8) 2/r32/edx -19559 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] -19560 8d/copy-address *(esi+eax-4) 6/r32/esi # vars + 8 + vars->type - 12 -19561 { -19562 $binding-exists?:loop: -19563 # if (curr < min) return -19564 39/compare %esi 2/r32/edx -19565 0f 82/jump-if-addr< break/disp32 -19566 # var v/eax: (addr var) = lookup(*curr) -19567 (lookup *esi *(esi+4)) # => eax -19568 # var vn/eax: (addr array byte) = lookup(v->name) -19569 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19570 # if (vn == target-name) return true -19571 (string-equal? %ecx %eax) # => eax -19572 3d/compare-eax-and 0/imm32/false -19573 75/jump-if-!= $binding-exists?:end/disp8 # eax already contains true -19574 # curr -= 12 -19575 81 5/subop/subtract %esi 0xc/imm32 -19576 e9/jump loop/disp32 -19577 } -19578 b8/copy-to-eax 0/imm32/false -19579 $binding-exists?:end: -19580 # . restore registers -19581 5e/pop-to-esi -19582 5a/pop-to-edx -19583 59/pop-to-ecx -19584 # . epilogue -19585 89/<- %esp 5/r32/ebp -19586 5d/pop-to-ebp -19587 c3/return -19588 -19589 test-parse-mu-stmt: -19590 # . prologue -19591 55/push-ebp -19592 89/<- %ebp 4/r32/esp -19593 # setup -19594 8b/-> *Primitive-type-ids 0/r32/eax -19595 89/<- *Type-id 0/r32/eax # stream-write -19596 (clear-stream _test-input-stream) -19597 (write _test-input-stream "increment n\n") -19598 # var vars/ecx: (stack (addr var) 16) -19599 81 5/subop/subtract %esp 0xc0/imm32 -19600 68/push 0xc0/imm32/size -19601 68/push 0/imm32/top -19602 89/<- %ecx 4/r32/esp -19603 (clear-stack %ecx) -19604 # var v/edx: (handle var) -19605 68/push 0/imm32 -19606 68/push 0/imm32 -19607 89/<- %edx 4/r32/esp -19608 # var s/eax: (handle array byte) -19609 68/push 0/imm32 -19610 68/push 0/imm32 -19611 89/<- %eax 4/r32/esp -19612 # v = new var("n") -19613 (copy-array Heap "n" %eax) -19614 (new-var Heap *eax *(eax+4) %edx) -19615 # -19616 (push %ecx *edx) -19617 (push %ecx *(edx+4)) -19618 (push %ecx 0) -19619 # var out/eax: (handle stmt) -19620 68/push 0/imm32 -19621 68/push 0/imm32 -19622 89/<- %eax 4/r32/esp -19623 # convert -19624 (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0) -19625 # var out-addr/edx: (addr stmt) = lookup(*out) -19626 (lookup *eax *(eax+4)) # => eax -19627 89/<- %edx 0/r32/eax -19628 # out->tag -19629 (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -19630 # out->operation -19631 (lookup *(edx+4) *(edx+8)) # Stmt1-operation Stmt1-operation => eax -19632 (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -19633 # out->inouts->value->name -19634 # . eax = out->inouts -19635 (lookup *(edx+0xc) *(edx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -19636 # . eax = out->inouts->value -19637 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -19638 # . eax = out->inouts->value->name -19639 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19640 # . -19641 (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0") -19642 # . epilogue -19643 89/<- %esp 5/r32/ebp -19644 5d/pop-to-ebp -19645 c3/return -19646 -19647 test-parse-mu-stmt-with-comma: -19648 # . prologue -19649 55/push-ebp -19650 89/<- %ebp 4/r32/esp -19651 # setup -19652 8b/-> *Primitive-type-ids 0/r32/eax -19653 89/<- *Type-id 0/r32/eax # stream-write -19654 (clear-stream _test-input-stream) -19655 (write _test-input-stream "copy-to n, 3\n") -19656 # var vars/ecx: (stack (addr var) 16) -19657 81 5/subop/subtract %esp 0xc0/imm32 -19658 68/push 0xc0/imm32/size -19659 68/push 0/imm32/top -19660 89/<- %ecx 4/r32/esp -19661 (clear-stack %ecx) -19662 # var v/edx: (handle var) -19663 68/push 0/imm32 -19664 68/push 0/imm32 -19665 89/<- %edx 4/r32/esp -19666 # var s/eax: (handle array byte) -19667 68/push 0/imm32 -19668 68/push 0/imm32 -19669 89/<- %eax 4/r32/esp -19670 # v = new var("n") -19671 (copy-array Heap "n" %eax) -19672 (new-var Heap *eax *(eax+4) %edx) -19673 # -19674 (push %ecx *edx) -19675 (push %ecx *(edx+4)) -19676 (push %ecx 0) -19677 # var out/eax: (handle stmt) -19678 68/push 0/imm32 -19679 68/push 0/imm32 -19680 89/<- %eax 4/r32/esp -19681 # convert -19682 (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0) -19683 # var out-addr/edx: (addr stmt) = lookup(*out) -19684 (lookup *eax *(eax+4)) # => eax -19685 89/<- %edx 0/r32/eax -19686 # out->tag -19687 (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -19688 # out->operation -19689 (lookup *(edx+4) *(edx+8)) # Stmt1-operation Stmt1-operation => eax -19690 (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -19691 # out->inouts->value->name -19692 # . eax = out->inouts -19693 (lookup *(edx+0xc) *(edx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -19694 # . eax = out->inouts->value -19695 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -19696 # . eax = out->inouts->value->name -19697 (lookup *eax *(eax+4)) # Var-name Var-name => eax -19698 # . -19699 (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0") -19700 # . epilogue -19701 89/<- %esp 5/r32/ebp -19702 5d/pop-to-ebp -19703 c3/return -19704 -19705 new-var: # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var) -19706 # . prologue -19707 55/push-ebp -19708 89/<- %ebp 4/r32/esp -19709 # . save registers -19710 50/push-eax -19711 51/push-ecx -19712 # ecx = out -19713 8b/-> *(ebp+0x14) 1/r32/ecx -19714 # -19715 (allocate *(ebp+8) *Var-size %ecx) -19716 # var out-addr/eax: (addr var) -19717 (lookup *ecx *(ecx+4)) # => eax -19718 # out-addr->name = name -19719 8b/-> *(ebp+0xc) 1/r32/ecx -19720 89/<- *eax 1/r32/ecx # Var-name -19721 8b/-> *(ebp+0x10) 1/r32/ecx -19722 89/<- *(eax+4) 1/r32/ecx # Var-name -19723 #? (write-buffered Stderr "var ") -19724 #? (lookup *(ebp+0xc) *(ebp+0x10)) -19725 #? (write-buffered Stderr %eax) -19726 #? (write-buffered Stderr " at ") -19727 #? 8b/-> *(ebp+0x14) 1/r32/ecx -19728 #? (lookup *ecx *(ecx+4)) # => eax -19729 #? (write-int32-hex-buffered Stderr %eax) -19730 #? (write-buffered Stderr Newline) -19731 #? (flush Stderr) -19732 $new-var:end: -19733 # . restore registers -19734 59/pop-to-ecx -19735 58/pop-to-eax -19736 # . epilogue -19737 89/<- %esp 5/r32/ebp -19738 5d/pop-to-ebp -19739 c3/return -19740 -19741 # WARNING: modifies name -19742 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -19743 # . prologue -19744 55/push-ebp -19745 89/<- %ebp 4/r32/esp -19746 # . save registers -19747 50/push-eax -19748 51/push-ecx -19749 # first strip out metadata -19750 8b/-> *(ebp+0xc) 1/r32/ecx -19751 (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc)) -19752 # if (!is-hex-int?(name)) abort -19753 (hex-int? *(ebp+0xc)) # => eax -19754 3d/compare-eax-and 0/imm32/false -19755 0f 84/jump-if-= $new-literal-integer:abort/disp32 -19756 # a little more error-checking -19757 (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -19758 # out = new var(s) -19759 (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10)) -19760 # var out-addr/ecx: (addr var) = lookup(*out) -19761 8b/-> *(ebp+0x10) 0/r32/eax -19762 (lookup *eax *(eax+4)) # => eax -19763 89/<- %ecx 0/r32/eax -19764 # out-addr->block-depth = *Curr-block-depth -19765 8b/-> *Curr-block-depth 0/r32/eax -19766 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth -19767 # out-addr->type = new tree() -19768 8d/copy-address *(ecx+8) 0/r32/eax # Var-type -19769 (allocate *(ebp+8) *Type-tree-size %eax) -19770 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -19771 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom -19772 # nothing else to do; default type is 'literal' -19773 $new-literal-integer:end: -19774 # . reclaim locals -19775 81 0/subop/add %esp 8/imm32 -19776 # . restore registers -19777 59/pop-to-ecx -19778 58/pop-to-eax -19779 # . epilogue -19780 89/<- %esp 5/r32/ebp -19781 5d/pop-to-ebp -19782 c3/return -19783 -19784 $new-literal-integer:abort: -19785 (write-buffered *(ebp+0x18) "fn ") -19786 8b/-> *(ebp+0x14) 0/r32/eax -19787 (lookup *eax *(eax+4)) # Function-name Function-name => eax -19788 (write-buffered *(ebp+0x18) %eax) -19789 (write-buffered *(ebp+0x18) ": variable '") -19790 (write-slice-buffered *(ebp+0x18) *(ebp+0xc)) -19791 (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n") -19792 (flush *(ebp+0x18)) -19793 (stop *(ebp+0x1c) 1) -19794 # never gets here -19795 -19796 # precondition: name is a valid hex integer; require a '0x' prefix -19797 check-mu-hex-int: # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor) -19798 # . prologue -19799 55/push-ebp -19800 89/<- %ebp 4/r32/esp -19801 # . save registers -19802 50/push-eax -19803 51/push-ecx -19804 52/push-edx -19805 # ecx = name -19806 8b/-> *(ebp+8) 1/r32/ecx -19807 # var start/edx: (addr byte) = name->start -19808 8b/-> *ecx 2/r32/edx -19809 # if (*start == '-') ++start -19810 b8/copy-to-eax 0/imm32 -19811 8a/copy-byte *edx 0/r32/AL -19812 3d/compare-eax-and 0x2d/imm32/dash -19813 { -19814 75/jump-if-!= break/disp8 -19815 42/increment-edx -19816 } -19817 # var end/ecx: (addr byte) = name->end -19818 8b/-> *(ecx+4) 1/r32/ecx -19819 # var len/eax: int = name->end - name->start -19820 89/<- %eax 1/r32/ecx -19821 29/subtract-from %eax 2/r32/edx -19822 # if (len <= 1) return -19823 3d/compare-eax-with 1/imm32 -19824 0f 8e/jump-if-<= $check-mu-hex-int:end/disp32 -19825 $check-mu-hex-int:length->-1: -19826 # if slice-starts-with?({start, end}, "0x") return -19827 # . var tmp = {start, end} -19828 51/push-ecx -19829 52/push-edx -19830 89/<- %eax 4/r32/esp -19831 # . -19832 (slice-starts-with? %eax "0x") # => eax -19833 # . reclaim tmp -19834 81 0/subop/add %esp 8/imm32 -19835 # . -19836 3d/compare-eax-with 0/imm32/false -19837 75/jump-if-!= $check-mu-hex-int:end/disp8 -19838 $check-mu-hex-int:abort: -19839 # otherwise abort -19840 (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '") -19841 (write-slice-buffered *(ebp+0xc) *(ebp+8)) -19842 (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n") -19843 (flush *(ebp+0xc)) -19844 (stop *(ebp+0x10) 1) -19845 $check-mu-hex-int:end: -19846 # . restore registers -19847 5a/pop-to-edx -19848 59/pop-to-ecx -19849 58/pop-to-eax -19850 # . epilogue -19851 89/<- %esp 5/r32/ebp -19852 5d/pop-to-ebp -19853 c3/return -19854 -19855 new-literal: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var) -19856 # . prologue -19857 55/push-ebp -19858 89/<- %ebp 4/r32/esp -19859 # . save registers -19860 50/push-eax -19861 51/push-ecx -19862 # var s/ecx: (handle array byte) -19863 68/push 0/imm32 -19864 68/push 0/imm32 -19865 89/<- %ecx 4/r32/esp -19866 # s = slice-to-string(name) -19867 (slice-to-string Heap *(ebp+0xc) %ecx) -19868 # allocate to out -19869 (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10)) -19870 # var out-addr/ecx: (addr var) = lookup(*out) -19871 8b/-> *(ebp+0x10) 1/r32/ecx -19872 (lookup *ecx *(ecx+4)) # => eax -19873 89/<- %ecx 0/r32/eax -19874 # out-addr->block-depth = *Curr-block-depth -19875 8b/-> *Curr-block-depth 0/r32/eax -19876 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth -19877 # out-addr->type/eax = new type -19878 8d/copy-address *(ecx+8) 0/r32/eax # Var-type -19879 (allocate *(ebp+8) *Type-tree-size %eax) -19880 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -19881 # nothing else to do; default type is 'literal' -19882 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom -19883 $new-literal:end: -19884 # . reclaim locals -19885 81 0/subop/add %esp 8/imm32 -19886 # . restore registers -19887 59/pop-to-ecx -19888 58/pop-to-eax -19889 # . epilogue -19890 89/<- %esp 5/r32/ebp -19891 5d/pop-to-ebp -19892 c3/return -19893 -19894 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var) -19895 # . prologue -19896 55/push-ebp -19897 89/<- %ebp 4/r32/esp -19898 # . save registers -19899 50/push-eax -19900 51/push-ecx -19901 # var s/ecx: (handle array byte) -19902 68/push 0/imm32 -19903 68/push 0/imm32 -19904 89/<- %ecx 4/r32/esp -19905 # s = slice-to-string(name) -19906 (slice-to-string Heap *(ebp+0xc) %ecx) -19907 # allocate to out -19908 (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10)) -19909 # var out-addr/ecx: (addr var) = lookup(*out) -19910 8b/-> *(ebp+0x10) 1/r32/ecx -19911 (lookup *ecx *(ecx+4)) # => eax -19912 89/<- %ecx 0/r32/eax -19913 # out-addr->block-depth = *Curr-block-depth -19914 8b/-> *Curr-block-depth 0/r32/eax -19915 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth -19916 # out-addr->type/eax = new type -19917 8d/copy-address *(ecx+8) 0/r32/eax # Var-type -19918 (allocate *(ebp+8) *Type-tree-size %eax) -19919 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -19920 # out-addr->type->value = literal-string -19921 c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal # Type-tree-value -19922 # out-addr->type->is-atom? = true -19923 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom -19924 $new-literal-string:end: -19925 # . reclaim locals -19926 81 0/subop/add %esp 8/imm32 -19927 # . restore registers -19928 59/pop-to-ecx -19929 58/pop-to-eax -19930 # . epilogue -19931 89/<- %esp 5/r32/ebp -19932 5d/pop-to-ebp -19933 c3/return -19934 -19935 new-var-from-slice: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var) -19936 # . prologue -19937 55/push-ebp -19938 89/<- %ebp 4/r32/esp -19939 # . save registers -19940 51/push-ecx -19941 # var tmp/ecx: (handle array byte) -19942 68/push 0/imm32 -19943 68/push 0/imm32 -19944 89/<- %ecx 4/r32/esp -19945 # tmp = slice-to-string(name) -19946 (slice-to-string Heap *(ebp+0xc) %ecx) -19947 # out = new-var(tmp) -19948 (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10)) -19949 $new-var-from-slice:end: -19950 # . reclaim locals -19951 81 0/subop/add %esp 8/imm32 -19952 # . restore registers -19953 59/pop-to-ecx -19954 # . epilogue -19955 89/<- %esp 5/r32/ebp -19956 5d/pop-to-ebp -19957 c3/return -19958 -19959 new-var-def: # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt) -19960 # . prologue -19961 55/push-ebp -19962 89/<- %ebp 4/r32/esp -19963 # . save registers -19964 50/push-eax -19965 51/push-ecx -19966 # -19967 (allocate *(ebp+8) *Stmt-size *(ebp+0x14)) -19968 # var out-addr/eax: (addr stmt) = lookup(*out) -19969 8b/-> *(ebp+0x14) 0/r32/eax -19970 (lookup *eax *(eax+4)) # => eax -19971 # out-addr->tag = stmt -19972 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -19973 # result->var = var -19974 8b/-> *(ebp+0xc) 1/r32/ecx -19975 89/<- *(eax+4) 1/r32/ecx # Vardef-var -19976 8b/-> *(ebp+0x10) 1/r32/ecx -19977 89/<- *(eax+8) 1/r32/ecx # Vardef-var -19978 $new-var-def:end: -19979 # . restore registers -19980 59/pop-to-ecx -19981 58/pop-to-eax -19982 # . epilogue -19983 89/<- %esp 5/r32/ebp -19984 5d/pop-to-ebp -19985 c3/return -19986 -19987 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt) -19988 # . prologue -19989 55/push-ebp -19990 89/<- %ebp 4/r32/esp -19991 # . save registers -19992 50/push-eax -19993 # eax = out -19994 8b/-> *(ebp+0x14) 0/r32/eax -19995 # -19996 (allocate *(ebp+8) *Stmt-size %eax) -19997 # var out-addr/eax: (addr stmt) = lookup(*out) -19998 (lookup *eax *(eax+4)) # => eax -19999 # set tag -20000 c7 0/subop/copy *eax 3/imm32/tag/var-in-register # Stmt-tag -20001 # set output -20002 8d/copy-address *(eax+0x14) 0/r32/eax # Regvardef-outputs -20003 (append-stmt-var Heap *(ebp+0xc) *(ebp+0x10) 0 0 0 %eax) -20004 $new-reg-var-def:end: -20005 # . restore registers -20006 58/pop-to-eax -20007 # . epilogue -20008 89/<- %esp 5/r32/ebp -20009 5d/pop-to-ebp -20010 c3/return -20011 -20012 append-list: # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type) -20013 # . prologue -20014 55/push-ebp -20015 89/<- %ebp 4/r32/esp -20016 # . save registers -20017 50/push-eax -20018 51/push-ecx -20019 57/push-edi -20020 # edi = out -20021 8b/-> *(ebp+0x1c) 7/r32/edi -20022 # *out = new list -20023 (allocate *(ebp+8) *List-size %edi) -20024 # var out-addr/edi: (addr list _type) = lookup(*out) -20025 (lookup *edi *(edi+4)) # => eax -20026 89/<- %edi 0/r32/eax -20027 # out-addr->value = value -20028 8b/-> *(ebp+0xc) 0/r32/eax -20029 89/<- *edi 0/r32/eax # List-value -20030 8b/-> *(ebp+0x10) 0/r32/eax -20031 89/<- *(edi+4) 0/r32/eax # List-value -20032 # if (list == null) return -20033 81 7/subop/compare *(ebp+0x14) 0/imm32 -20034 74/jump-if-= $append-list:end/disp8 -20035 # otherwise append -20036 $append-list:non-empty-list: -20037 # var curr/eax: (addr list _type) = lookup(list) -20038 (lookup *(ebp+0x14) *(ebp+0x18)) # => eax -20039 # while (curr->next != null) curr = curr->next -20040 { -20041 81 7/subop/compare *(eax+8) 0/imm32 # List-next -20042 74/jump-if-= break/disp8 -20043 # curr = lookup(curr->next) -20044 (lookup *(eax+8) *(eax+0xc)) # List-next, List-next => eax -20045 # -20046 eb/jump loop/disp8 -20047 } -20048 # edi = out -20049 8b/-> *(ebp+0x1c) 7/r32/edi -20050 # curr->next = out -20051 8b/-> *edi 1/r32/ecx -20052 89/<- *(eax+8) 1/r32/ecx # List-next -20053 8b/-> *(edi+4) 1/r32/ecx -20054 89/<- *(eax+0xc) 1/r32/ecx # List-next -20055 # out = list -20056 8b/-> *(ebp+0x14) 1/r32/ecx -20057 89/<- *edi 1/r32/ecx -20058 8b/-> *(ebp+0x18) 1/r32/ecx -20059 89/<- *(edi+4) 1/r32/ecx -20060 $append-list:end: -20061 # . restore registers -20062 5f/pop-to-edi -20063 59/pop-to-ecx -20064 58/pop-to-eax -20065 # . epilogue -20066 89/<- %esp 5/r32/ebp -20067 5d/pop-to-ebp -20068 c3/return -20069 -20070 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var) -20071 # . prologue -20072 55/push-ebp -20073 89/<- %ebp 4/r32/esp -20074 # . save registers -20075 50/push-eax -20076 51/push-ecx -20077 57/push-edi -20078 # edi = out -20079 8b/-> *(ebp+0x20) 7/r32/edi -20080 # out = new stmt-var -20081 (allocate *(ebp+8) *Stmt-var-size %edi) -20082 # var out-addr/ecx: (addr stmt-var) = lookup(*out) -20083 (lookup *edi *(edi+4)) # => eax -20084 89/<- %ecx 0/r32/eax -20085 # out-addr->value = v -20086 8b/-> *(ebp+0xc) 0/r32/eax -20087 89/<- *ecx 0/r32/eax # Stmt-var-value -20088 8b/-> *(ebp+0x10) 0/r32/eax -20089 89/<- *(ecx+4) 0/r32/eax # Stmt-var-value -20090 # out-addr->is-deref? = is-deref? -20091 8b/-> *(ebp+0x1c) 0/r32/eax -20092 89/<- *(ecx+0x10) 0/r32/eax # Stmt-var-is-deref -20093 # if (vars == null) return result -20094 81 7/subop/compare *(ebp+0x14) 0/imm32/null -20095 74/jump-if-= $append-stmt-var:end/disp8 -20096 # otherwise append -20097 # var curr/eax: (addr stmt-var) = lookup(vars) -20098 (lookup *(ebp+0x14) *(ebp+0x18)) # => eax -20099 # while (curr->next != null) curr = curr->next -20100 { -20101 81 7/subop/compare *(eax+8) 0/imm32 # Stmt-var-next -20102 74/jump-if-= break/disp8 -20103 # curr = lookup(curr->next) -20104 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next, Stmt-var-next => eax -20105 # -20106 eb/jump loop/disp8 -20107 } -20108 # curr->next = out -20109 8b/-> *edi 1/r32/ecx -20110 89/<- *(eax+8) 1/r32/ecx # Stmt-var-next -20111 8b/-> *(edi+4) 1/r32/ecx -20112 89/<- *(eax+0xc) 1/r32/ecx # Stmt-var-next -20113 # out = vars -20114 8b/-> *(ebp+0x14) 1/r32/ecx -20115 89/<- *edi 1/r32/ecx -20116 8b/-> *(ebp+0x18) 1/r32/ecx -20117 89/<- *(edi+4) 1/r32/ecx -20118 $append-stmt-var:end: -20119 # . restore registers -20120 5f/pop-to-edi -20121 59/pop-to-ecx -20122 58/pop-to-eax -20123 # . epilogue -20124 89/<- %esp 5/r32/ebp -20125 5d/pop-to-ebp -20126 c3/return -20127 -20128 append-to-block: # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt) -20129 # . prologue -20130 55/push-ebp -20131 89/<- %ebp 4/r32/esp -20132 # . save registers -20133 50/push-eax -20134 56/push-esi -20135 # esi = block -20136 8b/-> *(ebp+0xc) 6/r32/esi -20137 # block->stmts = append(x, block->stmts) -20138 8d/copy-address *(esi+4) 0/r32/eax # Block-stmts -20139 (append-list *(ebp+8) *(ebp+0x10) *(ebp+0x14) *(esi+4) *(esi+8) %eax) # ad, x, x, Block-stmts, Block-stmts -20140 $append-to-block:end: +19467 $Mu-register-esi: +19468 0x11/imm32/alloc-id +19469 3/imm32/size +19470 0x65/e 0x73/s 0x69/i +19471 +19472 $Mu-register-edi: +19473 0x11/imm32/alloc-id +19474 3/imm32/size +19475 0x65/e 0x64/d 0x69/i +19476 +19477 $Mu-register-xmm0: +19478 0x11/imm32/alloc-id:fake:payload +19479 # "xmm0" +19480 0x4/imm32/size +19481 0x78/x 0x6d/m 0x6d/m 0x30/0 +19482 +19483 $Mu-register-xmm1: +19484 0x11/imm32/alloc-id:fake:payload +19485 # "xmm1" +19486 0x4/imm32/size +19487 0x78/x 0x6d/m 0x6d/m 0x31/1 +19488 +19489 $Mu-register-xmm2: +19490 0x11/imm32/alloc-id:fake:payload +19491 # "xmm2" +19492 0x4/imm32/size +19493 0x78/x 0x6d/m 0x6d/m 0x32/2 +19494 +19495 $Mu-register-xmm3: +19496 0x11/imm32/alloc-id:fake:payload +19497 # "xmm3" +19498 0x4/imm32/size +19499 0x78/x 0x6d/m 0x6d/m 0x33/3 +19500 +19501 $Mu-register-xmm4: +19502 0x11/imm32/alloc-id:fake:payload +19503 # "xmm4" +19504 0x4/imm32/size +19505 0x78/x 0x6d/m 0x6d/m 0x34/4 +19506 +19507 $Mu-register-xmm5: +19508 0x11/imm32/alloc-id:fake:payload +19509 # "xmm5" +19510 0x4/imm32/size +19511 0x78/x 0x6d/m 0x6d/m 0x35/5 +19512 +19513 $Mu-register-xmm6: +19514 0x11/imm32/alloc-id:fake:payload +19515 # "xmm6" +19516 0x4/imm32/size +19517 0x78/x 0x6d/m 0x6d/m 0x36/6 +19518 +19519 $Mu-register-xmm7: +19520 0x11/imm32/alloc-id:fake:payload +19521 # "xmm7" +19522 0x4/imm32/size +19523 0x78/x 0x6d/m 0x6d/m 0x37/7 +19524 +19525 == code +19526 +19527 # push 'out' to 'vars' if not already there; it's assumed to be a fn output +19528 maybe-define-var: # out: (handle var), vars: (addr stack live-var) +19529 # . prologue +19530 55/push-ebp +19531 89/<- %ebp 4/r32/esp +19532 # . save registers +19533 50/push-eax +19534 # var out-addr/eax: (addr var) +19535 (lookup *(ebp+8) *(ebp+0xc)) # => eax +19536 # +19537 (binding-exists? %eax *(ebp+0x10)) # => eax +19538 3d/compare-eax-and 0/imm32/false +19539 75/jump-if-!= $maybe-define-var:end/disp8 +19540 # otherwise update vars +19541 (push *(ebp+0x10) *(ebp+8)) +19542 (push *(ebp+0x10) *(ebp+0xc)) +19543 (push *(ebp+0x10) 0) # 'out' is always a fn output; never spill it +19544 $maybe-define-var:end: +19545 # . restore registers +19546 58/pop-to-eax +19547 # . epilogue +19548 89/<- %esp 5/r32/ebp +19549 5d/pop-to-ebp +19550 c3/return +19551 +19552 # simpler version of lookup-var-helper +19553 binding-exists?: # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean +19554 # pseudocode: +19555 # var curr: (addr handle var) = &vars->data[vars->top - 12] +19556 # var min = vars->data +19557 # while curr >= min +19558 # var v: (handle var) = *curr +19559 # if v->name == target->name +19560 # return true +19561 # curr -= 12 +19562 # return false +19563 # +19564 # . prologue +19565 55/push-ebp +19566 89/<- %ebp 4/r32/esp +19567 # . save registers +19568 51/push-ecx +19569 52/push-edx +19570 56/push-esi +19571 # var target-name/ecx: (addr array byte) = lookup(target->name) +19572 8b/-> *(ebp+8) 0/r32/eax +19573 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19574 89/<- %ecx 0/r32/eax +19575 # esi = vars +19576 8b/-> *(ebp+0xc) 6/r32/esi +19577 # eax = vars->top +19578 8b/-> *esi 0/r32/eax +19579 # var min/edx: (addr handle var) = vars->data +19580 8d/copy-address *(esi+8) 2/r32/edx +19581 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] +19582 8d/copy-address *(esi+eax-4) 6/r32/esi # vars + 8 + vars->type - 12 +19583 { +19584 $binding-exists?:loop: +19585 # if (curr < min) return +19586 39/compare %esi 2/r32/edx +19587 0f 82/jump-if-addr< break/disp32 +19588 # var v/eax: (addr var) = lookup(*curr) +19589 (lookup *esi *(esi+4)) # => eax +19590 # var vn/eax: (addr array byte) = lookup(v->name) +19591 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19592 # if (vn == target-name) return true +19593 (string-equal? %ecx %eax) # => eax +19594 3d/compare-eax-and 0/imm32/false +19595 75/jump-if-!= $binding-exists?:end/disp8 # eax already contains true +19596 # curr -= 12 +19597 81 5/subop/subtract %esi 0xc/imm32 +19598 e9/jump loop/disp32 +19599 } +19600 b8/copy-to-eax 0/imm32/false +19601 $binding-exists?:end: +19602 # . restore registers +19603 5e/pop-to-esi +19604 5a/pop-to-edx +19605 59/pop-to-ecx +19606 # . epilogue +19607 89/<- %esp 5/r32/ebp +19608 5d/pop-to-ebp +19609 c3/return +19610 +19611 test-parse-mu-stmt: +19612 # . prologue +19613 55/push-ebp +19614 89/<- %ebp 4/r32/esp +19615 # setup +19616 8b/-> *Primitive-type-ids 0/r32/eax +19617 89/<- *Type-id 0/r32/eax # stream-write +19618 (clear-stream _test-input-stream) +19619 (write _test-input-stream "increment n\n") +19620 # var vars/ecx: (stack (addr var) 16) +19621 81 5/subop/subtract %esp 0xc0/imm32 +19622 68/push 0xc0/imm32/size +19623 68/push 0/imm32/top +19624 89/<- %ecx 4/r32/esp +19625 (clear-stack %ecx) +19626 # var v/edx: (handle var) +19627 68/push 0/imm32 +19628 68/push 0/imm32 +19629 89/<- %edx 4/r32/esp +19630 # var s/eax: (handle array byte) +19631 68/push 0/imm32 +19632 68/push 0/imm32 +19633 89/<- %eax 4/r32/esp +19634 # v = new var("n") +19635 (copy-array Heap "n" %eax) +19636 (new-var Heap *eax *(eax+4) %edx) +19637 # +19638 (push %ecx *edx) +19639 (push %ecx *(edx+4)) +19640 (push %ecx 0) +19641 # var out/eax: (handle stmt) +19642 68/push 0/imm32 +19643 68/push 0/imm32 +19644 89/<- %eax 4/r32/esp +19645 # convert +19646 (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0) +19647 # var out-addr/edx: (addr stmt) = lookup(*out) +19648 (lookup *eax *(eax+4)) # => eax +19649 89/<- %edx 0/r32/eax +19650 # out->tag +19651 (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 +19652 # out->operation +19653 (lookup *(edx+4) *(edx+8)) # Stmt1-operation Stmt1-operation => eax +19654 (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation +19655 # out->inouts->value->name +19656 # . eax = out->inouts +19657 (lookup *(edx+0xc) *(edx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +19658 # . eax = out->inouts->value +19659 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +19660 # . eax = out->inouts->value->name +19661 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19662 # . +19663 (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0") +19664 # . epilogue +19665 89/<- %esp 5/r32/ebp +19666 5d/pop-to-ebp +19667 c3/return +19668 +19669 test-parse-mu-stmt-with-comma: +19670 # . prologue +19671 55/push-ebp +19672 89/<- %ebp 4/r32/esp +19673 # setup +19674 8b/-> *Primitive-type-ids 0/r32/eax +19675 89/<- *Type-id 0/r32/eax # stream-write +19676 (clear-stream _test-input-stream) +19677 (write _test-input-stream "copy-to n, 3\n") +19678 # var vars/ecx: (stack (addr var) 16) +19679 81 5/subop/subtract %esp 0xc0/imm32 +19680 68/push 0xc0/imm32/size +19681 68/push 0/imm32/top +19682 89/<- %ecx 4/r32/esp +19683 (clear-stack %ecx) +19684 # var v/edx: (handle var) +19685 68/push 0/imm32 +19686 68/push 0/imm32 +19687 89/<- %edx 4/r32/esp +19688 # var s/eax: (handle array byte) +19689 68/push 0/imm32 +19690 68/push 0/imm32 +19691 89/<- %eax 4/r32/esp +19692 # v = new var("n") +19693 (copy-array Heap "n" %eax) +19694 (new-var Heap *eax *(eax+4) %edx) +19695 # +19696 (push %ecx *edx) +19697 (push %ecx *(edx+4)) +19698 (push %ecx 0) +19699 # var out/eax: (handle stmt) +19700 68/push 0/imm32 +19701 68/push 0/imm32 +19702 89/<- %eax 4/r32/esp +19703 # convert +19704 (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0) +19705 # var out-addr/edx: (addr stmt) = lookup(*out) +19706 (lookup *eax *(eax+4)) # => eax +19707 89/<- %edx 0/r32/eax +19708 # out->tag +19709 (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 +19710 # out->operation +19711 (lookup *(edx+4) *(edx+8)) # Stmt1-operation Stmt1-operation => eax +19712 (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation +19713 # out->inouts->value->name +19714 # . eax = out->inouts +19715 (lookup *(edx+0xc) *(edx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +19716 # . eax = out->inouts->value +19717 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +19718 # . eax = out->inouts->value->name +19719 (lookup *eax *(eax+4)) # Var-name Var-name => eax +19720 # . +19721 (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0") +19722 # . epilogue +19723 89/<- %esp 5/r32/ebp +19724 5d/pop-to-ebp +19725 c3/return +19726 +19727 new-var: # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var) +19728 # . prologue +19729 55/push-ebp +19730 89/<- %ebp 4/r32/esp +19731 # . save registers +19732 50/push-eax +19733 51/push-ecx +19734 # ecx = out +19735 8b/-> *(ebp+0x14) 1/r32/ecx +19736 # +19737 (allocate *(ebp+8) *Var-size %ecx) +19738 # var out-addr/eax: (addr var) +19739 (lookup *ecx *(ecx+4)) # => eax +19740 # out-addr->name = name +19741 8b/-> *(ebp+0xc) 1/r32/ecx +19742 89/<- *eax 1/r32/ecx # Var-name +19743 8b/-> *(ebp+0x10) 1/r32/ecx +19744 89/<- *(eax+4) 1/r32/ecx # Var-name +19745 #? (write-buffered Stderr "var ") +19746 #? (lookup *(ebp+0xc) *(ebp+0x10)) +19747 #? (write-buffered Stderr %eax) +19748 #? (write-buffered Stderr " at ") +19749 #? 8b/-> *(ebp+0x14) 1/r32/ecx +19750 #? (lookup *ecx *(ecx+4)) # => eax +19751 #? (write-int32-hex-buffered Stderr %eax) +19752 #? (write-buffered Stderr Newline) +19753 #? (flush Stderr) +19754 $new-var:end: +19755 # . restore registers +19756 59/pop-to-ecx +19757 58/pop-to-eax +19758 # . epilogue +19759 89/<- %esp 5/r32/ebp +19760 5d/pop-to-ebp +19761 c3/return +19762 +19763 # WARNING: modifies name +19764 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +19765 # . prologue +19766 55/push-ebp +19767 89/<- %ebp 4/r32/esp +19768 # . save registers +19769 50/push-eax +19770 51/push-ecx +19771 # first strip out metadata +19772 8b/-> *(ebp+0xc) 1/r32/ecx +19773 (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc)) +19774 # if (!is-hex-int?(name)) abort +19775 (hex-int? *(ebp+0xc)) # => eax +19776 3d/compare-eax-and 0/imm32/false +19777 0f 84/jump-if-= $new-literal-integer:abort/disp32 +19778 # a little more error-checking +19779 (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +19780 # out = new var(s) +19781 (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10)) +19782 # var out-addr/ecx: (addr var) = lookup(*out) +19783 8b/-> *(ebp+0x10) 0/r32/eax +19784 (lookup *eax *(eax+4)) # => eax +19785 89/<- %ecx 0/r32/eax +19786 # out-addr->block-depth = *Curr-block-depth +19787 8b/-> *Curr-block-depth 0/r32/eax +19788 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth +19789 # out-addr->type = new tree() +19790 8d/copy-address *(ecx+8) 0/r32/eax # Var-type +19791 (allocate *(ebp+8) *Type-tree-size %eax) +19792 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +19793 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom +19794 # nothing else to do; default type is 'literal' +19795 $new-literal-integer:end: +19796 # . reclaim locals +19797 81 0/subop/add %esp 8/imm32 +19798 # . restore registers +19799 59/pop-to-ecx +19800 58/pop-to-eax +19801 # . epilogue +19802 89/<- %esp 5/r32/ebp +19803 5d/pop-to-ebp +19804 c3/return +19805 +19806 $new-literal-integer:abort: +19807 (write-buffered *(ebp+0x18) "fn ") +19808 8b/-> *(ebp+0x14) 0/r32/eax +19809 (lookup *eax *(eax+4)) # Function-name Function-name => eax +19810 (write-buffered *(ebp+0x18) %eax) +19811 (write-buffered *(ebp+0x18) ": variable '") +19812 (write-slice-buffered *(ebp+0x18) *(ebp+0xc)) +19813 (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n") +19814 (flush *(ebp+0x18)) +19815 (stop *(ebp+0x1c) 1) +19816 # never gets here +19817 +19818 # precondition: name is a valid hex integer; require a '0x' prefix +19819 check-mu-hex-int: # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor) +19820 # . prologue +19821 55/push-ebp +19822 89/<- %ebp 4/r32/esp +19823 # . save registers +19824 50/push-eax +19825 51/push-ecx +19826 52/push-edx +19827 # ecx = name +19828 8b/-> *(ebp+8) 1/r32/ecx +19829 # var start/edx: (addr byte) = name->start +19830 8b/-> *ecx 2/r32/edx +19831 # if (*start == '-') ++start +19832 b8/copy-to-eax 0/imm32 +19833 8a/copy-byte *edx 0/r32/AL +19834 3d/compare-eax-and 0x2d/imm32/dash +19835 { +19836 75/jump-if-!= break/disp8 +19837 42/increment-edx +19838 } +19839 # var end/ecx: (addr byte) = name->end +19840 8b/-> *(ecx+4) 1/r32/ecx +19841 # var len/eax: int = name->end - name->start +19842 89/<- %eax 1/r32/ecx +19843 29/subtract-from %eax 2/r32/edx +19844 # if (len <= 1) return +19845 3d/compare-eax-with 1/imm32 +19846 0f 8e/jump-if-<= $check-mu-hex-int:end/disp32 +19847 $check-mu-hex-int:length->-1: +19848 # if slice-starts-with?({start, end}, "0x") return +19849 # . var tmp = {start, end} +19850 51/push-ecx +19851 52/push-edx +19852 89/<- %eax 4/r32/esp +19853 # . +19854 (slice-starts-with? %eax "0x") # => eax +19855 # . reclaim tmp +19856 81 0/subop/add %esp 8/imm32 +19857 # . +19858 3d/compare-eax-with 0/imm32/false +19859 75/jump-if-!= $check-mu-hex-int:end/disp8 +19860 $check-mu-hex-int:abort: +19861 # otherwise abort +19862 (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '") +19863 (write-slice-buffered *(ebp+0xc) *(ebp+8)) +19864 (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n") +19865 (flush *(ebp+0xc)) +19866 (stop *(ebp+0x10) 1) +19867 $check-mu-hex-int:end: +19868 # . restore registers +19869 5a/pop-to-edx +19870 59/pop-to-ecx +19871 58/pop-to-eax +19872 # . epilogue +19873 89/<- %esp 5/r32/ebp +19874 5d/pop-to-ebp +19875 c3/return +19876 +19877 new-literal: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var) +19878 # . prologue +19879 55/push-ebp +19880 89/<- %ebp 4/r32/esp +19881 # . save registers +19882 50/push-eax +19883 51/push-ecx +19884 # var s/ecx: (handle array byte) +19885 68/push 0/imm32 +19886 68/push 0/imm32 +19887 89/<- %ecx 4/r32/esp +19888 # s = slice-to-string(name) +19889 (slice-to-string Heap *(ebp+0xc) %ecx) +19890 # allocate to out +19891 (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10)) +19892 # var out-addr/ecx: (addr var) = lookup(*out) +19893 8b/-> *(ebp+0x10) 1/r32/ecx +19894 (lookup *ecx *(ecx+4)) # => eax +19895 89/<- %ecx 0/r32/eax +19896 # out-addr->block-depth = *Curr-block-depth +19897 8b/-> *Curr-block-depth 0/r32/eax +19898 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth +19899 # out-addr->type/eax = new type +19900 8d/copy-address *(ecx+8) 0/r32/eax # Var-type +19901 (allocate *(ebp+8) *Type-tree-size %eax) +19902 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +19903 # nothing else to do; default type is 'literal' +19904 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom +19905 $new-literal:end: +19906 # . reclaim locals +19907 81 0/subop/add %esp 8/imm32 +19908 # . restore registers +19909 59/pop-to-ecx +19910 58/pop-to-eax +19911 # . epilogue +19912 89/<- %esp 5/r32/ebp +19913 5d/pop-to-ebp +19914 c3/return +19915 +19916 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var) +19917 # . prologue +19918 55/push-ebp +19919 89/<- %ebp 4/r32/esp +19920 # . save registers +19921 50/push-eax +19922 51/push-ecx +19923 # var s/ecx: (handle array byte) +19924 68/push 0/imm32 +19925 68/push 0/imm32 +19926 89/<- %ecx 4/r32/esp +19927 # s = slice-to-string(name) +19928 (slice-to-string Heap *(ebp+0xc) %ecx) +19929 # allocate to out +19930 (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10)) +19931 # var out-addr/ecx: (addr var) = lookup(*out) +19932 8b/-> *(ebp+0x10) 1/r32/ecx +19933 (lookup *ecx *(ecx+4)) # => eax +19934 89/<- %ecx 0/r32/eax +19935 # out-addr->block-depth = *Curr-block-depth +19936 8b/-> *Curr-block-depth 0/r32/eax +19937 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth +19938 # out-addr->type/eax = new type +19939 8d/copy-address *(ecx+8) 0/r32/eax # Var-type +19940 (allocate *(ebp+8) *Type-tree-size %eax) +19941 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +19942 # out-addr->type->value = literal-string +19943 c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal # Type-tree-value +19944 # out-addr->type->is-atom? = true +19945 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom +19946 $new-literal-string:end: +19947 # . reclaim locals +19948 81 0/subop/add %esp 8/imm32 +19949 # . restore registers +19950 59/pop-to-ecx +19951 58/pop-to-eax +19952 # . epilogue +19953 89/<- %esp 5/r32/ebp +19954 5d/pop-to-ebp +19955 c3/return +19956 +19957 new-var-from-slice: # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var) +19958 # . prologue +19959 55/push-ebp +19960 89/<- %ebp 4/r32/esp +19961 # . save registers +19962 51/push-ecx +19963 # var tmp/ecx: (handle array byte) +19964 68/push 0/imm32 +19965 68/push 0/imm32 +19966 89/<- %ecx 4/r32/esp +19967 # tmp = slice-to-string(name) +19968 (slice-to-string Heap *(ebp+0xc) %ecx) +19969 # out = new-var(tmp) +19970 (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10)) +19971 $new-var-from-slice:end: +19972 # . reclaim locals +19973 81 0/subop/add %esp 8/imm32 +19974 # . restore registers +19975 59/pop-to-ecx +19976 # . epilogue +19977 89/<- %esp 5/r32/ebp +19978 5d/pop-to-ebp +19979 c3/return +19980 +19981 new-var-def: # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt) +19982 # . prologue +19983 55/push-ebp +19984 89/<- %ebp 4/r32/esp +19985 # . save registers +19986 50/push-eax +19987 51/push-ecx +19988 # +19989 (allocate *(ebp+8) *Stmt-size *(ebp+0x14)) +19990 # var out-addr/eax: (addr stmt) = lookup(*out) +19991 8b/-> *(ebp+0x14) 0/r32/eax +19992 (lookup *eax *(eax+4)) # => eax +19993 # out-addr->tag = stmt +19994 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag +19995 # result->var = var +19996 8b/-> *(ebp+0xc) 1/r32/ecx +19997 89/<- *(eax+4) 1/r32/ecx # Vardef-var +19998 8b/-> *(ebp+0x10) 1/r32/ecx +19999 89/<- *(eax+8) 1/r32/ecx # Vardef-var +20000 $new-var-def:end: +20001 # . restore registers +20002 59/pop-to-ecx +20003 58/pop-to-eax +20004 # . epilogue +20005 89/<- %esp 5/r32/ebp +20006 5d/pop-to-ebp +20007 c3/return +20008 +20009 new-reg-var-def: # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt) +20010 # . prologue +20011 55/push-ebp +20012 89/<- %ebp 4/r32/esp +20013 # . save registers +20014 50/push-eax +20015 # eax = out +20016 8b/-> *(ebp+0x14) 0/r32/eax +20017 # +20018 (allocate *(ebp+8) *Stmt-size %eax) +20019 # var out-addr/eax: (addr stmt) = lookup(*out) +20020 (lookup *eax *(eax+4)) # => eax +20021 # set tag +20022 c7 0/subop/copy *eax 3/imm32/tag/var-in-register # Stmt-tag +20023 # set output +20024 8d/copy-address *(eax+0x14) 0/r32/eax # Regvardef-outputs +20025 (append-stmt-var Heap *(ebp+0xc) *(ebp+0x10) 0 0 0 %eax) +20026 $new-reg-var-def:end: +20027 # . restore registers +20028 58/pop-to-eax +20029 # . epilogue +20030 89/<- %esp 5/r32/ebp +20031 5d/pop-to-ebp +20032 c3/return +20033 +20034 append-list: # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type) +20035 # . prologue +20036 55/push-ebp +20037 89/<- %ebp 4/r32/esp +20038 # . save registers +20039 50/push-eax +20040 51/push-ecx +20041 57/push-edi +20042 # edi = out +20043 8b/-> *(ebp+0x1c) 7/r32/edi +20044 # *out = new list +20045 (allocate *(ebp+8) *List-size %edi) +20046 # var out-addr/edi: (addr list _type) = lookup(*out) +20047 (lookup *edi *(edi+4)) # => eax +20048 89/<- %edi 0/r32/eax +20049 # out-addr->value = value +20050 8b/-> *(ebp+0xc) 0/r32/eax +20051 89/<- *edi 0/r32/eax # List-value +20052 8b/-> *(ebp+0x10) 0/r32/eax +20053 89/<- *(edi+4) 0/r32/eax # List-value +20054 # if (list == null) return +20055 81 7/subop/compare *(ebp+0x14) 0/imm32 +20056 74/jump-if-= $append-list:end/disp8 +20057 # otherwise append +20058 $append-list:non-empty-list: +20059 # var curr/eax: (addr list _type) = lookup(list) +20060 (lookup *(ebp+0x14) *(ebp+0x18)) # => eax +20061 # while (curr->next != null) curr = curr->next +20062 { +20063 81 7/subop/compare *(eax+8) 0/imm32 # List-next +20064 74/jump-if-= break/disp8 +20065 # curr = lookup(curr->next) +20066 (lookup *(eax+8) *(eax+0xc)) # List-next, List-next => eax +20067 # +20068 eb/jump loop/disp8 +20069 } +20070 # edi = out +20071 8b/-> *(ebp+0x1c) 7/r32/edi +20072 # curr->next = out +20073 8b/-> *edi 1/r32/ecx +20074 89/<- *(eax+8) 1/r32/ecx # List-next +20075 8b/-> *(edi+4) 1/r32/ecx +20076 89/<- *(eax+0xc) 1/r32/ecx # List-next +20077 # out = list +20078 8b/-> *(ebp+0x14) 1/r32/ecx +20079 89/<- *edi 1/r32/ecx +20080 8b/-> *(ebp+0x18) 1/r32/ecx +20081 89/<- *(edi+4) 1/r32/ecx +20082 $append-list:end: +20083 # . restore registers +20084 5f/pop-to-edi +20085 59/pop-to-ecx +20086 58/pop-to-eax +20087 # . epilogue +20088 89/<- %esp 5/r32/ebp +20089 5d/pop-to-ebp +20090 c3/return +20091 +20092 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var) +20093 # . prologue +20094 55/push-ebp +20095 89/<- %ebp 4/r32/esp +20096 # . save registers +20097 50/push-eax +20098 51/push-ecx +20099 57/push-edi +20100 # edi = out +20101 8b/-> *(ebp+0x20) 7/r32/edi +20102 # out = new stmt-var +20103 (allocate *(ebp+8) *Stmt-var-size %edi) +20104 # var out-addr/ecx: (addr stmt-var) = lookup(*out) +20105 (lookup *edi *(edi+4)) # => eax +20106 89/<- %ecx 0/r32/eax +20107 # out-addr->value = v +20108 8b/-> *(ebp+0xc) 0/r32/eax +20109 89/<- *ecx 0/r32/eax # Stmt-var-value +20110 8b/-> *(ebp+0x10) 0/r32/eax +20111 89/<- *(ecx+4) 0/r32/eax # Stmt-var-value +20112 # out-addr->is-deref? = is-deref? +20113 8b/-> *(ebp+0x1c) 0/r32/eax +20114 89/<- *(ecx+0x10) 0/r32/eax # Stmt-var-is-deref +20115 # if (vars == null) return result +20116 81 7/subop/compare *(ebp+0x14) 0/imm32/null +20117 74/jump-if-= $append-stmt-var:end/disp8 +20118 # otherwise append +20119 # var curr/eax: (addr stmt-var) = lookup(vars) +20120 (lookup *(ebp+0x14) *(ebp+0x18)) # => eax +20121 # while (curr->next != null) curr = curr->next +20122 { +20123 81 7/subop/compare *(eax+8) 0/imm32 # Stmt-var-next +20124 74/jump-if-= break/disp8 +20125 # curr = lookup(curr->next) +20126 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next, Stmt-var-next => eax +20127 # +20128 eb/jump loop/disp8 +20129 } +20130 # curr->next = out +20131 8b/-> *edi 1/r32/ecx +20132 89/<- *(eax+8) 1/r32/ecx # Stmt-var-next +20133 8b/-> *(edi+4) 1/r32/ecx +20134 89/<- *(eax+0xc) 1/r32/ecx # Stmt-var-next +20135 # out = vars +20136 8b/-> *(ebp+0x14) 1/r32/ecx +20137 89/<- *edi 1/r32/ecx +20138 8b/-> *(ebp+0x18) 1/r32/ecx +20139 89/<- *(edi+4) 1/r32/ecx +20140 $append-stmt-var:end: 20141 # . restore registers -20142 5e/pop-to-esi -20143 58/pop-to-eax -20144 # . epilogue -20145 89/<- %esp 5/r32/ebp -20146 5d/pop-to-ebp -20147 c3/return -20148 -20149 ## Parsing types -20150 # We need to create metadata on user-defined types, and we need to use this -20151 # metadata as we parse instructions. -20152 # However, we also want to allow types to be used before their definitions. -20153 # This means we can't ever assume any type data structures exist. -20154 -20155 lookup-or-create-constant: # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var) -20156 # . prologue -20157 55/push-ebp -20158 89/<- %ebp 4/r32/esp -20159 # . save registers -20160 50/push-eax -20161 56/push-esi -20162 # var container-type/esi: type-id -20163 (container-type *(ebp+8)) # => eax -20164 89/<- %esi 0/r32/eax -20165 # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type) -20166 68/push 0/imm32 -20167 68/push 0/imm32 -20168 89/<- %eax 4/r32/esp -20169 (find-or-create-typeinfo %esi %eax) -20170 # var tmp-addr/eax: (addr typeinfo) = lookup(tmp) -20171 (lookup *eax *(eax+4)) # => eax -20172 # result = find-or-create-typeinfo-output-var(typeinfo, field-name) -20173 #? (write-buffered Stderr "constant: ") -20174 #? (write-slice-buffered Stderr *(ebp+0xc)) -20175 #? (write-buffered Stderr Newline) -20176 #? (flush Stderr) -20177 (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10)) -20178 #? 8b/-> *(ebp+0x10) 0/r32/eax -20179 #? (write-buffered Stderr "@") -20180 #? (lookup *eax *(eax+4)) -20181 #? (write-int32-hex-buffered Stderr %eax) -20182 #? (lookup *eax *(eax+4)) -20183 #? (write-buffered Stderr %eax) -20184 #? (write-buffered Stderr Newline) -20185 #? (flush Stderr) -20186 #? (write-buffered Stderr "offset: ") -20187 #? 8b/-> *(eax+0x14) 0/r32/eax -20188 #? (write-int32-hex-buffered Stderr %eax) -20189 #? (write-buffered Stderr Newline) -20190 #? (flush Stderr) -20191 $lookup-or-create-constant:end: -20192 # . reclaim locals -20193 81 0/subop/add %esp 8/imm32 -20194 # . restore registers -20195 5e/pop-to-esi -20196 58/pop-to-eax -20197 # . epilogue -20198 89/<- %esp 5/r32/ebp -20199 5d/pop-to-ebp -20200 c3/return -20201 -20202 # if addr var: -20203 # container->var->type->right->left->value -20204 # otherwise -20205 # container->var->type->value -20206 container-type: # container: (addr stmt-var) -> result/eax: type-id -20207 # . prologue -20208 55/push-ebp -20209 89/<- %ebp 4/r32/esp -20210 # -20211 8b/-> *(ebp+8) 0/r32/eax -20212 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -20213 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -20214 { -20215 81 7/subop/compare *(eax+8) 0/imm32 # Type-tree-right -20216 74/jump-if-= break/disp8 -20217 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -20218 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -20219 } -20220 8b/-> *(eax+4) 0/r32/eax # Type-tree-value -20221 $container-type:end: -20222 # . epilogue -20223 89/<- %esp 5/r32/ebp -20224 5d/pop-to-ebp -20225 c3/return -20226 -20227 container?: # t: type-id -> result/eax: boolean -20228 # . prologue -20229 55/push-ebp -20230 89/<- %ebp 4/r32/esp -20231 # -20232 8b/-> *(ebp+8) 0/r32/eax -20233 c1/shift 4/subop/left %eax 2/imm8 -20234 3b/compare 0/r32/eax *Primitive-type-ids -20235 0f 9d/set-if->= %al -20236 81 4/subop/and %eax 0xff/imm32 -20237 $container?:end: -20238 # . epilogue -20239 89/<- %esp 5/r32/ebp -20240 5d/pop-to-ebp -20241 c3/return -20242 -20243 find-or-create-typeinfo: # t: type-id, out: (addr handle typeinfo) -20244 # . prologue -20245 55/push-ebp -20246 89/<- %ebp 4/r32/esp -20247 # . save registers -20248 50/push-eax -20249 51/push-ecx -20250 52/push-edx -20251 57/push-edi -20252 # edi = out -20253 8b/-> *(ebp+0xc) 7/r32/edi -20254 # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry)) -20255 68/push 0/imm32 -20256 68/push 0/imm32 -20257 89/<- %ecx 4/r32/esp -20258 # find-typeinfo(t, out) -20259 (find-typeinfo *(ebp+8) %edi) -20260 { -20261 # if (*out != 0) break -20262 81 7/subop/compare *edi 0/imm32 -20263 0f 85/jump-if-!= break/disp32 -20264 $find-or-create-typeinfo:create: -20265 # *out = allocate -20266 (allocate Heap *Typeinfo-size %edi) -20267 # var tmp/eax: (addr typeinfo) = lookup(*out) -20268 (lookup *edi *(edi+4)) # => eax -20269 #? (write-buffered Stderr "created typeinfo at ") -20270 #? (write-int32-hex-buffered Stderr %eax) -20271 #? (write-buffered Stderr " for type-id ") -20272 #? (write-int32-hex-buffered Stderr *(ebp+8)) -20273 #? (write-buffered Stderr Newline) -20274 #? (flush Stderr) -20275 # tmp->id = t -20276 8b/-> *(ebp+8) 2/r32/edx -20277 89/<- *eax 2/r32/edx # Typeinfo-id -20278 # tmp->fields = new table -20279 # . fields = new table -20280 (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx) -20281 # . tmp->fields = fields -20282 8b/-> *ecx 2/r32/edx -20283 89/<- *(eax+4) 2/r32/edx # Typeinfo-fields -20284 8b/-> *(ecx+4) 2/r32/edx -20285 89/<- *(eax+8) 2/r32/edx # Typeinfo-fields -20286 # tmp->next = Program->types -20287 8b/-> *_Program-types 1/r32/ecx -20288 89/<- *(eax+0x10) 1/r32/ecx # Typeinfo-next -20289 8b/-> *_Program-types->payload 1/r32/ecx -20290 89/<- *(eax+0x14) 1/r32/ecx # Typeinfo-next -20291 # Program->types = out -20292 8b/-> *edi 1/r32/ecx -20293 89/<- *_Program-types 1/r32/ecx -20294 8b/-> *(edi+4) 1/r32/ecx -20295 89/<- *_Program-types->payload 1/r32/ecx -20296 } -20297 $find-or-create-typeinfo:end: -20298 # . reclaim locals -20299 81 0/subop/add %esp 8/imm32 -20300 # . restore registers -20301 5f/pop-to-edi -20302 5a/pop-to-edx -20303 59/pop-to-ecx -20304 58/pop-to-eax -20305 # . epilogue -20306 89/<- %esp 5/r32/ebp -20307 5d/pop-to-ebp -20308 c3/return -20309 -20310 find-typeinfo: # t: type-id, out: (addr handle typeinfo) -20311 # . prologue -20312 55/push-ebp -20313 89/<- %ebp 4/r32/esp -20314 # . save registers -20315 50/push-eax -20316 51/push-ecx -20317 52/push-edx -20318 57/push-edi -20319 # ecx = t -20320 8b/-> *(ebp+8) 1/r32/ecx -20321 # edi = out -20322 8b/-> *(ebp+0xc) 7/r32/edi -20323 # *out = Program->types -20324 8b/-> *_Program-types 0/r32/eax -20325 89/<- *edi 0/r32/eax -20326 8b/-> *_Program-types->payload 0/r32/eax -20327 89/<- *(edi+4) 0/r32/eax -20328 { -20329 $find-typeinfo:loop: -20330 # if (*out == 0) break -20331 81 7/subop/compare *edi 0/imm32 -20332 74/jump-if-= break/disp8 -20333 $find-typeinfo:check: -20334 # var tmp/eax: (addr typeinfo) = lookup(*out) -20335 (lookup *edi *(edi+4)) # => eax -20336 # if (tmp->id == t) break -20337 39/compare *eax 1/r32/ecx # Typeinfo-id -20338 74/jump-if-= break/disp8 -20339 $find-typeinfo:continue: -20340 # *out = tmp->next -20341 8b/-> *(eax+0x10) 2/r32/edx # Typeinfo-next -20342 89/<- *edi 2/r32/edx -20343 8b/-> *(eax+0x14) 2/r32/edx # Typeinfo-next -20344 89/<- *(edi+4) 2/r32/edx -20345 # -20346 eb/jump loop/disp8 -20347 } -20348 $find-typeinfo:end: -20349 # . restore registers -20350 5f/pop-to-edi -20351 5a/pop-to-edx -20352 59/pop-to-ecx -20353 58/pop-to-eax -20354 # . epilogue -20355 89/<- %esp 5/r32/ebp -20356 5d/pop-to-ebp -20357 c3/return -20358 -20359 find-or-create-typeinfo-output-var: # T: (addr typeinfo), f: (addr slice), out: (addr handle var) -20360 # . prologue -20361 55/push-ebp -20362 89/<- %ebp 4/r32/esp -20363 # . save registers -20364 50/push-eax -20365 52/push-edx -20366 57/push-edi -20367 # var dest/edi: (handle typeinfo-entry) -20368 68/push 0/imm32 -20369 68/push 0/imm32 -20370 89/<- %edi 4/r32/esp -20371 # find-or-create-typeinfo-fields(T, f, dest) -20372 (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi) -20373 # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest) -20374 (lookup *edi *(edi+4)) # => eax -20375 89/<- %edi 0/r32/eax -20376 # if dest-addr->output-var doesn't exist, create it -20377 { -20378 81 7/subop/compare *(edi+0xc) 0/imm32 # Typeinfo-entry-output-var -20379 0f 85/jump-if-!= break/disp32 -20380 # dest-addr->output-var = new var(dummy name, type, -1 offset) -20381 # . var name/eax: (handle array byte) = "field" -20382 68/push 0/imm32 -20383 68/push 0/imm32 -20384 89/<- %eax 4/r32/esp -20385 (slice-to-string Heap *(ebp+0xc) %eax) -20386 # . new var -20387 8d/copy-address *(edi+0xc) 2/r32/edx -20388 (new-var Heap *eax *(eax+4) %edx) -20389 # . reclaim name -20390 81 0/subop/add %esp 8/imm32 -20391 # var result/edx: (addr var) = lookup(dest-addr->output-var) -20392 (lookup *(edi+0xc) *(edi+0x10)) # => eax -20393 89/<- %edx 0/r32/eax -20394 # result->type = new constant type -20395 8d/copy-address *(edx+8) 0/r32/eax # Var-type -20396 (allocate Heap *Type-tree-size %eax) -20397 (lookup *(edx+8) *(edx+0xc)) # => eax -20398 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom -20399 c7 0/subop/copy *(eax+4) 6/imm32/constant # Type-tree-value -20400 c7 0/subop/copy *(eax+8) 0/imm32 # Type-tree-left -20401 c7 0/subop/copy *(eax+0xc) 0/imm32 # Type-tree-right -20402 c7 0/subop/copy *(eax+0x10) 0/imm32 # Type-tree-right -20403 # result->offset isn't filled out yet -20404 c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized # Var-offset -20405 } -20406 # out = dest-addr->output-var -20407 8b/-> *(ebp+0x10) 2/r32/edx -20408 8b/-> *(edi+0xc) 0/r32/eax # Typeinfo-entry-output-var -20409 89/<- *edx 0/r32/eax -20410 8b/-> *(edi+0x10) 0/r32/eax # Typeinfo-entry-output-var -20411 89/<- *(edx+4) 0/r32/eax -20412 $find-or-create-typeinfo-output-var:end: -20413 # . reclaim locals -20414 81 0/subop/add %esp 8/imm32 -20415 # . restore registers -20416 5f/pop-to-edi -20417 5a/pop-to-edx -20418 58/pop-to-eax -20419 # . epilogue -20420 89/<- %esp 5/r32/ebp -20421 5d/pop-to-ebp -20422 c3/return -20423 -20424 find-or-create-typeinfo-fields: # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry) -20425 # . prologue -20426 55/push-ebp -20427 89/<- %ebp 4/r32/esp -20428 # . save registers -20429 50/push-eax -20430 56/push-esi -20431 57/push-edi -20432 # eax = lookup(T->fields) -20433 8b/-> *(ebp+8) 0/r32/eax -20434 (lookup *(eax+4) *(eax+8)) # Typeinfo-fields Typeinfo-fields => eax -20435 # edi = out -20436 8b/-> *(ebp+0x10) 7/r32/edi -20437 # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f) -20438 (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap) # => eax -20439 89/<- %esi 0/r32/eax -20440 # if src doesn't exist, allocate it -20441 { -20442 81 7/subop/compare *esi 0/imm32 -20443 75/jump-if-!= break/disp8 -20444 (allocate Heap *Typeinfo-entry-size %esi) -20445 #? (write-buffered Stderr "handle at ") -20446 #? (write-int32-hex-buffered Stderr %esi) -20447 #? (write-buffered Stderr ": ") -20448 #? (write-int32-hex-buffered Stderr *esi) -20449 #? (write-buffered Stderr " ") -20450 #? (write-int32-hex-buffered Stderr *(esi+4)) -20451 #? (write-buffered Stderr Newline) -20452 #? (flush Stderr) -20453 #? (lookup *esi *(esi+4)) -20454 #? (write-buffered Stderr "created typeinfo fields at ") -20455 #? (write-int32-hex-buffered Stderr %esi) -20456 #? (write-buffered Stderr " for ") -20457 #? (write-int32-hex-buffered Stderr *(ebp+8)) -20458 #? (write-buffered Stderr Newline) -20459 #? (flush Stderr) -20460 } -20461 # *out = src -20462 # . *edi = *src -20463 8b/-> *esi 0/r32/eax -20464 89/<- *edi 0/r32/eax -20465 8b/-> *(esi+4) 0/r32/eax -20466 89/<- *(edi+4) 0/r32/eax -20467 $find-or-create-typeinfo-fields:end: -20468 # . restore registers -20469 5f/pop-to-edi -20470 5e/pop-to-esi -20471 58/pop-to-eax -20472 # . epilogue -20473 89/<- %esp 5/r32/ebp -20474 5d/pop-to-ebp -20475 c3/return -20476 -20477 populate-mu-type: # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor) -20478 # pseudocode: -20479 # var line: (stream byte 512) -20480 # curr-index = 0 -20481 # while true -20482 # clear-stream(line) -20483 # read-line-buffered(in, line) -20484 # if line->write == 0 -20485 # abort -20486 # word-slice = next-mu-token(line) -20487 # if slice-empty?(word-slice) # end of line -20488 # continue -20489 # if slice-equal?(word-slice, "}") -20490 # break -20491 # var v: (handle var) = parse-var-with-type(word-slice, line) -20492 # var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name) -20493 # TODO: ensure that r->first is null -20494 # r->index = curr-index -20495 # curr-index++ -20496 # r->input-var = v -20497 # if r->output-var == 0 -20498 # r->output-var = new literal -20499 # TODO: ensure nothing else in line -20500 # t->total-size-in-bytes = -2 (not yet initialized) -20501 # -20502 # . prologue -20503 55/push-ebp -20504 89/<- %ebp 4/r32/esp -20505 # var curr-index: int at *(ebp-4) -20506 68/push 0/imm32 -20507 # . save registers -20508 50/push-eax -20509 51/push-ecx -20510 52/push-edx -20511 53/push-ebx -20512 56/push-esi -20513 57/push-edi -20514 # edi = t -20515 8b/-> *(ebp+0xc) 7/r32/edi -20516 # var line/ecx: (stream byte 512) -20517 81 5/subop/subtract %esp 0x200/imm32 -20518 68/push 0x200/imm32/size -20519 68/push 0/imm32/read -20520 68/push 0/imm32/write -20521 89/<- %ecx 4/r32/esp -20522 # var word-slice/edx: slice -20523 68/push 0/imm32/end -20524 68/push 0/imm32/start -20525 89/<- %edx 4/r32/esp -20526 # var v/esi: (handle var) -20527 68/push 0/imm32 +20142 5f/pop-to-edi +20143 59/pop-to-ecx +20144 58/pop-to-eax +20145 # . epilogue +20146 89/<- %esp 5/r32/ebp +20147 5d/pop-to-ebp +20148 c3/return +20149 +20150 append-to-block: # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt) +20151 # . prologue +20152 55/push-ebp +20153 89/<- %ebp 4/r32/esp +20154 # . save registers +20155 50/push-eax +20156 56/push-esi +20157 # esi = block +20158 8b/-> *(ebp+0xc) 6/r32/esi +20159 # block->stmts = append(x, block->stmts) +20160 8d/copy-address *(esi+4) 0/r32/eax # Block-stmts +20161 (append-list *(ebp+8) *(ebp+0x10) *(ebp+0x14) *(esi+4) *(esi+8) %eax) # ad, x, x, Block-stmts, Block-stmts +20162 $append-to-block:end: +20163 # . restore registers +20164 5e/pop-to-esi +20165 58/pop-to-eax +20166 # . epilogue +20167 89/<- %esp 5/r32/ebp +20168 5d/pop-to-ebp +20169 c3/return +20170 +20171 ## Parsing types +20172 # We need to create metadata on user-defined types, and we need to use this +20173 # metadata as we parse instructions. +20174 # However, we also want to allow types to be used before their definitions. +20175 # This means we can't ever assume any type data structures exist. +20176 +20177 lookup-or-create-constant: # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var) +20178 # . prologue +20179 55/push-ebp +20180 89/<- %ebp 4/r32/esp +20181 # . save registers +20182 50/push-eax +20183 56/push-esi +20184 # var container-type/esi: type-id +20185 (container-type *(ebp+8)) # => eax +20186 89/<- %esi 0/r32/eax +20187 # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type) +20188 68/push 0/imm32 +20189 68/push 0/imm32 +20190 89/<- %eax 4/r32/esp +20191 (find-or-create-typeinfo %esi %eax) +20192 # var tmp-addr/eax: (addr typeinfo) = lookup(tmp) +20193 (lookup *eax *(eax+4)) # => eax +20194 # result = find-or-create-typeinfo-output-var(typeinfo, field-name) +20195 #? (write-buffered Stderr "constant: ") +20196 #? (write-slice-buffered Stderr *(ebp+0xc)) +20197 #? (write-buffered Stderr Newline) +20198 #? (flush Stderr) +20199 (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10)) +20200 #? 8b/-> *(ebp+0x10) 0/r32/eax +20201 #? (write-buffered Stderr "@") +20202 #? (lookup *eax *(eax+4)) +20203 #? (write-int32-hex-buffered Stderr %eax) +20204 #? (lookup *eax *(eax+4)) +20205 #? (write-buffered Stderr %eax) +20206 #? (write-buffered Stderr Newline) +20207 #? (flush Stderr) +20208 #? (write-buffered Stderr "offset: ") +20209 #? 8b/-> *(eax+0x14) 0/r32/eax +20210 #? (write-int32-hex-buffered Stderr %eax) +20211 #? (write-buffered Stderr Newline) +20212 #? (flush Stderr) +20213 $lookup-or-create-constant:end: +20214 # . reclaim locals +20215 81 0/subop/add %esp 8/imm32 +20216 # . restore registers +20217 5e/pop-to-esi +20218 58/pop-to-eax +20219 # . epilogue +20220 89/<- %esp 5/r32/ebp +20221 5d/pop-to-ebp +20222 c3/return +20223 +20224 # if addr var: +20225 # container->var->type->right->left->value +20226 # otherwise +20227 # container->var->type->value +20228 container-type: # container: (addr stmt-var) -> result/eax: type-id +20229 # . prologue +20230 55/push-ebp +20231 89/<- %ebp 4/r32/esp +20232 # +20233 8b/-> *(ebp+8) 0/r32/eax +20234 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +20235 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +20236 { +20237 81 7/subop/compare *(eax+8) 0/imm32 # Type-tree-right +20238 74/jump-if-= break/disp8 +20239 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +20240 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +20241 } +20242 8b/-> *(eax+4) 0/r32/eax # Type-tree-value +20243 $container-type:end: +20244 # . epilogue +20245 89/<- %esp 5/r32/ebp +20246 5d/pop-to-ebp +20247 c3/return +20248 +20249 container?: # t: type-id -> result/eax: boolean +20250 # . prologue +20251 55/push-ebp +20252 89/<- %ebp 4/r32/esp +20253 # +20254 8b/-> *(ebp+8) 0/r32/eax +20255 c1/shift 4/subop/left %eax 2/imm8 +20256 3b/compare 0/r32/eax *Primitive-type-ids +20257 0f 9d/set-if->= %al +20258 25/and-eax-with 0xff/imm32 +20259 $container?:end: +20260 # . epilogue +20261 89/<- %esp 5/r32/ebp +20262 5d/pop-to-ebp +20263 c3/return +20264 +20265 find-or-create-typeinfo: # t: type-id, out: (addr handle typeinfo) +20266 # . prologue +20267 55/push-ebp +20268 89/<- %ebp 4/r32/esp +20269 # . save registers +20270 50/push-eax +20271 51/push-ecx +20272 52/push-edx +20273 57/push-edi +20274 # edi = out +20275 8b/-> *(ebp+0xc) 7/r32/edi +20276 # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry)) +20277 68/push 0/imm32 +20278 68/push 0/imm32 +20279 89/<- %ecx 4/r32/esp +20280 # find-typeinfo(t, out) +20281 (find-typeinfo *(ebp+8) %edi) +20282 { +20283 # if (*out != 0) break +20284 81 7/subop/compare *edi 0/imm32 +20285 0f 85/jump-if-!= break/disp32 +20286 $find-or-create-typeinfo:create: +20287 # *out = allocate +20288 (allocate Heap *Typeinfo-size %edi) +20289 # var tmp/eax: (addr typeinfo) = lookup(*out) +20290 (lookup *edi *(edi+4)) # => eax +20291 #? (write-buffered Stderr "created typeinfo at ") +20292 #? (write-int32-hex-buffered Stderr %eax) +20293 #? (write-buffered Stderr " for type-id ") +20294 #? (write-int32-hex-buffered Stderr *(ebp+8)) +20295 #? (write-buffered Stderr Newline) +20296 #? (flush Stderr) +20297 # tmp->id = t +20298 8b/-> *(ebp+8) 2/r32/edx +20299 89/<- *eax 2/r32/edx # Typeinfo-id +20300 # tmp->fields = new table +20301 # . fields = new table +20302 (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx) +20303 # . tmp->fields = fields +20304 8b/-> *ecx 2/r32/edx +20305 89/<- *(eax+4) 2/r32/edx # Typeinfo-fields +20306 8b/-> *(ecx+4) 2/r32/edx +20307 89/<- *(eax+8) 2/r32/edx # Typeinfo-fields +20308 # tmp->next = Program->types +20309 8b/-> *_Program-types 1/r32/ecx +20310 89/<- *(eax+0x10) 1/r32/ecx # Typeinfo-next +20311 8b/-> *_Program-types->payload 1/r32/ecx +20312 89/<- *(eax+0x14) 1/r32/ecx # Typeinfo-next +20313 # Program->types = out +20314 8b/-> *edi 1/r32/ecx +20315 89/<- *_Program-types 1/r32/ecx +20316 8b/-> *(edi+4) 1/r32/ecx +20317 89/<- *_Program-types->payload 1/r32/ecx +20318 } +20319 $find-or-create-typeinfo:end: +20320 # . reclaim locals +20321 81 0/subop/add %esp 8/imm32 +20322 # . restore registers +20323 5f/pop-to-edi +20324 5a/pop-to-edx +20325 59/pop-to-ecx +20326 58/pop-to-eax +20327 # . epilogue +20328 89/<- %esp 5/r32/ebp +20329 5d/pop-to-ebp +20330 c3/return +20331 +20332 find-typeinfo: # t: type-id, out: (addr handle typeinfo) +20333 # . prologue +20334 55/push-ebp +20335 89/<- %ebp 4/r32/esp +20336 # . save registers +20337 50/push-eax +20338 51/push-ecx +20339 52/push-edx +20340 57/push-edi +20341 # ecx = t +20342 8b/-> *(ebp+8) 1/r32/ecx +20343 # edi = out +20344 8b/-> *(ebp+0xc) 7/r32/edi +20345 # *out = Program->types +20346 8b/-> *_Program-types 0/r32/eax +20347 89/<- *edi 0/r32/eax +20348 8b/-> *_Program-types->payload 0/r32/eax +20349 89/<- *(edi+4) 0/r32/eax +20350 { +20351 $find-typeinfo:loop: +20352 # if (*out == 0) break +20353 81 7/subop/compare *edi 0/imm32 +20354 74/jump-if-= break/disp8 +20355 $find-typeinfo:check: +20356 # var tmp/eax: (addr typeinfo) = lookup(*out) +20357 (lookup *edi *(edi+4)) # => eax +20358 # if (tmp->id == t) break +20359 39/compare *eax 1/r32/ecx # Typeinfo-id +20360 74/jump-if-= break/disp8 +20361 $find-typeinfo:continue: +20362 # *out = tmp->next +20363 8b/-> *(eax+0x10) 2/r32/edx # Typeinfo-next +20364 89/<- *edi 2/r32/edx +20365 8b/-> *(eax+0x14) 2/r32/edx # Typeinfo-next +20366 89/<- *(edi+4) 2/r32/edx +20367 # +20368 eb/jump loop/disp8 +20369 } +20370 $find-typeinfo:end: +20371 # . restore registers +20372 5f/pop-to-edi +20373 5a/pop-to-edx +20374 59/pop-to-ecx +20375 58/pop-to-eax +20376 # . epilogue +20377 89/<- %esp 5/r32/ebp +20378 5d/pop-to-ebp +20379 c3/return +20380 +20381 find-or-create-typeinfo-output-var: # T: (addr typeinfo), f: (addr slice), out: (addr handle var) +20382 # . prologue +20383 55/push-ebp +20384 89/<- %ebp 4/r32/esp +20385 # . save registers +20386 50/push-eax +20387 52/push-edx +20388 57/push-edi +20389 # var dest/edi: (handle typeinfo-entry) +20390 68/push 0/imm32 +20391 68/push 0/imm32 +20392 89/<- %edi 4/r32/esp +20393 # find-or-create-typeinfo-fields(T, f, dest) +20394 (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi) +20395 # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest) +20396 (lookup *edi *(edi+4)) # => eax +20397 89/<- %edi 0/r32/eax +20398 # if dest-addr->output-var doesn't exist, create it +20399 { +20400 81 7/subop/compare *(edi+0xc) 0/imm32 # Typeinfo-entry-output-var +20401 0f 85/jump-if-!= break/disp32 +20402 # dest-addr->output-var = new var(dummy name, type, -1 offset) +20403 # . var name/eax: (handle array byte) = "field" +20404 68/push 0/imm32 +20405 68/push 0/imm32 +20406 89/<- %eax 4/r32/esp +20407 (slice-to-string Heap *(ebp+0xc) %eax) +20408 # . new var +20409 8d/copy-address *(edi+0xc) 2/r32/edx +20410 (new-var Heap *eax *(eax+4) %edx) +20411 # . reclaim name +20412 81 0/subop/add %esp 8/imm32 +20413 # var result/edx: (addr var) = lookup(dest-addr->output-var) +20414 (lookup *(edi+0xc) *(edi+0x10)) # => eax +20415 89/<- %edx 0/r32/eax +20416 # result->type = new constant type +20417 8d/copy-address *(edx+8) 0/r32/eax # Var-type +20418 (allocate Heap *Type-tree-size %eax) +20419 (lookup *(edx+8) *(edx+0xc)) # => eax +20420 c7 0/subop/copy *eax 1/imm32/true # Type-tree-is-atom +20421 c7 0/subop/copy *(eax+4) 6/imm32/constant # Type-tree-value +20422 c7 0/subop/copy *(eax+8) 0/imm32 # Type-tree-left +20423 c7 0/subop/copy *(eax+0xc) 0/imm32 # Type-tree-right +20424 c7 0/subop/copy *(eax+0x10) 0/imm32 # Type-tree-right +20425 # result->offset isn't filled out yet +20426 c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized # Var-offset +20427 } +20428 # out = dest-addr->output-var +20429 8b/-> *(ebp+0x10) 2/r32/edx +20430 8b/-> *(edi+0xc) 0/r32/eax # Typeinfo-entry-output-var +20431 89/<- *edx 0/r32/eax +20432 8b/-> *(edi+0x10) 0/r32/eax # Typeinfo-entry-output-var +20433 89/<- *(edx+4) 0/r32/eax +20434 $find-or-create-typeinfo-output-var:end: +20435 # . reclaim locals +20436 81 0/subop/add %esp 8/imm32 +20437 # . restore registers +20438 5f/pop-to-edi +20439 5a/pop-to-edx +20440 58/pop-to-eax +20441 # . epilogue +20442 89/<- %esp 5/r32/ebp +20443 5d/pop-to-ebp +20444 c3/return +20445 +20446 find-or-create-typeinfo-fields: # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry) +20447 # . prologue +20448 55/push-ebp +20449 89/<- %ebp 4/r32/esp +20450 # . save registers +20451 50/push-eax +20452 56/push-esi +20453 57/push-edi +20454 # eax = lookup(T->fields) +20455 8b/-> *(ebp+8) 0/r32/eax +20456 (lookup *(eax+4) *(eax+8)) # Typeinfo-fields Typeinfo-fields => eax +20457 # edi = out +20458 8b/-> *(ebp+0x10) 7/r32/edi +20459 # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f) +20460 (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap) # => eax +20461 89/<- %esi 0/r32/eax +20462 # if src doesn't exist, allocate it +20463 { +20464 81 7/subop/compare *esi 0/imm32 +20465 75/jump-if-!= break/disp8 +20466 (allocate Heap *Typeinfo-entry-size %esi) +20467 #? (write-buffered Stderr "handle at ") +20468 #? (write-int32-hex-buffered Stderr %esi) +20469 #? (write-buffered Stderr ": ") +20470 #? (write-int32-hex-buffered Stderr *esi) +20471 #? (write-buffered Stderr " ") +20472 #? (write-int32-hex-buffered Stderr *(esi+4)) +20473 #? (write-buffered Stderr Newline) +20474 #? (flush Stderr) +20475 #? (lookup *esi *(esi+4)) +20476 #? (write-buffered Stderr "created typeinfo fields at ") +20477 #? (write-int32-hex-buffered Stderr %esi) +20478 #? (write-buffered Stderr " for ") +20479 #? (write-int32-hex-buffered Stderr *(ebp+8)) +20480 #? (write-buffered Stderr Newline) +20481 #? (flush Stderr) +20482 } +20483 # *out = src +20484 # . *edi = *src +20485 8b/-> *esi 0/r32/eax +20486 89/<- *edi 0/r32/eax +20487 8b/-> *(esi+4) 0/r32/eax +20488 89/<- *(edi+4) 0/r32/eax +20489 $find-or-create-typeinfo-fields:end: +20490 # . restore registers +20491 5f/pop-to-edi +20492 5e/pop-to-esi +20493 58/pop-to-eax +20494 # . epilogue +20495 89/<- %esp 5/r32/ebp +20496 5d/pop-to-ebp +20497 c3/return +20498 +20499 populate-mu-type: # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor) +20500 # pseudocode: +20501 # var line: (stream byte 512) +20502 # curr-index = 0 +20503 # while true +20504 # clear-stream(line) +20505 # read-line-buffered(in, line) +20506 # if line->write == 0 +20507 # abort +20508 # word-slice = next-mu-token(line) +20509 # if slice-empty?(word-slice) # end of line +20510 # continue +20511 # if slice-equal?(word-slice, "}") +20512 # break +20513 # var v: (handle var) = parse-var-with-type(word-slice, line) +20514 # var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name) +20515 # TODO: ensure that r->first is null +20516 # r->index = curr-index +20517 # curr-index++ +20518 # r->input-var = v +20519 # if r->output-var == 0 +20520 # r->output-var = new literal +20521 # TODO: ensure nothing else in line +20522 # t->total-size-in-bytes = -2 (not yet initialized) +20523 # +20524 # . prologue +20525 55/push-ebp +20526 89/<- %ebp 4/r32/esp +20527 # var curr-index: int at *(ebp-4) 20528 68/push 0/imm32 -20529 89/<- %esi 4/r32/esp -20530 # var r/ebx: (handle typeinfo-entry) -20531 68/push 0/imm32 -20532 68/push 0/imm32 -20533 89/<- %ebx 4/r32/esp -20534 { -20535 $populate-mu-type:line-loop: -20536 (clear-stream %ecx) -20537 (read-line-buffered *(ebp+8) %ecx) -20538 # if (line->write == 0) abort -20539 81 7/subop/compare *ecx 0/imm32 -20540 0f 84/jump-if-= $populate-mu-type:error1/disp32 -20541 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ -20547 (next-mu-token %ecx %edx) -20548 # if slice-empty?(word-slice) continue -20549 (slice-empty? %edx) # => eax -20550 3d/compare-eax-and 0/imm32 -20551 0f 85/jump-if-!= loop/disp32 -20552 # if slice-equal?(word-slice, "}") break -20553 (slice-equal? %edx "}") -20554 3d/compare-eax-and 0/imm32 -20555 0f 85/jump-if-!= break/disp32 -20556 $populate-mu-type:parse-element: -20557 # v = parse-var-with-type(word-slice, first-line) -20558 # must do this first to strip the trailing ':' from word-slice before -20559 # using it in find-or-create-typeinfo-fields below -20560 # TODO: clean up that mutation in parse-var-with-type -20561 (type-name *edi) # Typeinfo-id => eax -20562 (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14)) -20563 # if v is an addr, abort -20564 (lookup *esi *(esi+4)) # => eax -20565 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -20566 (mu-addr-type? %eax) # => eax -20567 3d/compare-eax-and 0/imm32/false -20568 0f 85/jump-if-!= $populate-mu-type:error2/disp32 -20569 # if v is an array, abort (we could support it, but initialization gets complex) -20570 (lookup *esi *(esi+4)) # => eax -20571 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -20572 (mu-array-type? %eax) # => eax -20573 3d/compare-eax-and 0/imm32/false -20574 0f 85/jump-if-!= $populate-mu-type:error3/disp32 -20575 # if v is a byte, abort -20576 (lookup *esi *(esi+4)) # => eax -20577 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -20578 (simple-mu-type? %eax 8) # byte => eax -20579 3d/compare-eax-and 0/imm32/false -20580 0f 85/jump-if-!= $populate-mu-type:error4/disp32 -20581 # if v is a slice, abort -20582 (lookup *esi *(esi+4)) # => eax -20583 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -20584 (simple-mu-type? %eax 0xc) # slice => eax -20585 3d/compare-eax-and 0/imm32/false -20586 0f 85/jump-if-!= $populate-mu-type:error5/disp32 -20587 # if v is a stream, abort (we could support it, but initialization gets even more complex) -20588 (lookup *esi *(esi+4)) # => eax -20589 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -20590 (mu-stream-type? %eax) # => eax -20591 3d/compare-eax-and 0/imm32/false -20592 0f 85/jump-if-!= $populate-mu-type:error6/disp32 -20593 # var tmp/ecx -20594 51/push-ecx -20595 $populate-mu-type:create-typeinfo-fields: -20596 # var r/ebx: (handle typeinfo-entry) -20597 (find-or-create-typeinfo-fields %edi %edx %ebx) -20598 # r->index = curr-index -20599 (lookup *ebx *(ebx+4)) # => eax -20600 8b/-> *(ebp-4) 1/r32/ecx -20601 #? (write-buffered Stderr "saving index ") -20602 #? (write-int32-hex-buffered Stderr %ecx) -20603 #? (write-buffered Stderr " at ") -20604 #? (write-int32-hex-buffered Stderr %edi) -20605 #? (write-buffered Stderr Newline) -20606 #? (flush Stderr) -20607 89/<- *(eax+8) 1/r32/ecx # Typeinfo-entry-index -20608 # ++curr-index -20609 ff 0/subop/increment *(ebp-4) -20610 $populate-mu-type:set-input-type: -20611 # r->input-var = v -20612 8b/-> *esi 1/r32/ecx -20613 89/<- *eax 1/r32/ecx # Typeinfo-entry-input-var -20614 8b/-> *(esi+4) 1/r32/ecx -20615 89/<- *(eax+4) 1/r32/ecx # Typeinfo-entry-input-var -20616 # restore line -20617 59/pop-to-ecx -20618 { -20619 $populate-mu-type:create-output-type: -20620 # if (r->output-var == 0) create a new var with some placeholder data -20621 81 7/subop/compare *(eax+0xc) 0/imm32 # Typeinfo-entry-output-var -20622 75/jump-if-!= break/disp8 -20623 8d/copy-address *(eax+0xc) 0/r32/eax # Typeinfo-entry-output-var -20624 (new-literal Heap %edx %eax) -20625 } -20626 e9/jump loop/disp32 -20627 } -20628 $populate-mu-type:invalidate-total-size-in-bytes: -20629 # Offsets and total size may not be accurate here since we may not yet -20630 # have encountered the element types. -20631 # We'll recompute them separately after parsing the entire program. -20632 c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized # Typeinfo-total-size-in-bytes -20633 $populate-mu-type:end: -20634 # . reclaim locals -20635 81 0/subop/add %esp 0x224/imm32 -20636 # . restore registers -20637 5f/pop-to-edi -20638 5e/pop-to-esi -20639 5b/pop-to-ebx -20640 5a/pop-to-edx -20641 59/pop-to-ecx -20642 58/pop-to-eax -20643 # reclaim curr-index -20644 81 0/subop/add %esp 4/imm32 -20645 # . epilogue -20646 89/<- %esp 5/r32/ebp -20647 5d/pop-to-ebp -20648 c3/return -20649 -20650 $populate-mu-type:error1: -20651 # error("incomplete type definition '" t->name "'\n") -20652 (write-buffered *(ebp+0x10) "incomplete type definition '") -20653 (type-name *edi) # Typeinfo-id => eax -20654 (write-buffered *(ebp+0x10) %eax) -20655 (write-buffered *(ebp+0x10) "\n") -20656 (flush *(ebp+0x10)) -20657 (stop *(ebp+0x14) 1) -20658 # never gets here -20659 -20660 $populate-mu-type:error2: -20661 (write-buffered *(ebp+0x10) "type ") -20662 (type-name *edi) # Typeinfo-id => eax -20663 (write-buffered *(ebp+0x10) %eax) -20664 (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n") -20665 (flush *(ebp+0x10)) -20666 (stop *(ebp+0x14) 1) -20667 # never gets here -20668 -20669 $populate-mu-type:error3: -20670 (write-buffered *(ebp+0x10) "type ") -20671 (type-name *edi) # Typeinfo-id => eax -20672 (write-buffered *(ebp+0x10) %eax) -20673 (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n") -20674 (flush *(ebp+0x10)) -20675 (stop *(ebp+0x14) 1) -20676 # never gets here -20677 -20678 $populate-mu-type:error4: -20679 (write-buffered *(ebp+0x10) "type ") -20680 (type-name *edi) # Typeinfo-id => eax -20681 (write-buffered *(ebp+0x10) %eax) -20682 (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n") -20683 (flush *(ebp+0x10)) -20684 (stop *(ebp+0x14) 1) -20685 # never gets here -20686 -20687 $populate-mu-type:error5: -20688 (write-buffered *(ebp+0x10) "type ") -20689 (type-name *edi) # Typeinfo-id => eax -20690 (write-buffered *(ebp+0x10) %eax) -20691 (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n") -20692 (flush *(ebp+0x10)) -20693 (stop *(ebp+0x14) 1) -20694 # never gets here -20695 -20696 $populate-mu-type:error6: -20697 (write-buffered *(ebp+0x10) "type ") -20698 (type-name *edi) # Typeinfo-id => eax -20699 (write-buffered *(ebp+0x10) %eax) -20700 (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n") -20701 (flush *(ebp+0x10)) -20702 (stop *(ebp+0x14) 1) -20703 # never gets here -20704 -20705 type-name: # index: int -> result/eax: (addr array byte) -20706 # . prologue -20707 55/push-ebp -20708 89/<- %ebp 4/r32/esp -20709 # -20710 (index Type-id *(ebp+8)) -20711 $type-name:end: -20712 # . epilogue -20713 89/<- %esp 5/r32/ebp -20714 5d/pop-to-ebp -20715 c3/return -20716 -20717 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) -20718 # . prologue -20719 55/push-ebp -20720 89/<- %ebp 4/r32/esp -20721 # . save registers -20722 56/push-esi -20723 # TODO: bounds-check index -20724 # esi = arr -20725 8b/-> *(ebp+8) 6/r32/esi -20726 # eax = index -20727 8b/-> *(ebp+0xc) 0/r32/eax -20728 # eax = *(arr + 12 + index) -20729 8b/-> *(esi+eax<<2+0xc) 0/r32/eax -20730 $index:end: -20731 # . restore registers -20732 5e/pop-to-esi -20733 # . epilogue -20734 89/<- %esp 5/r32/ebp -20735 5d/pop-to-ebp -20736 c3/return -20737 -20738 ####################################################### -20739 # Compute type sizes -20740 ####################################################### -20741 -20742 # Compute the sizes of all user-defined types. -20743 # We'll need the sizes of their elements, which may be other user-defined -20744 # types, which we will compute as needed. -20745 -20746 # Initially, all user-defined types have their sizes set to -2 (invalid) -20747 populate-mu-type-sizes: # err: (addr buffered-file), ed: (addr exit-descriptor) -20748 # . prologue -20749 55/push-ebp -20750 89/<- %ebp 4/r32/esp -20751 $populate-mu-type-sizes:total-sizes: -20752 # var curr/eax: (addr typeinfo) = lookup(Program->types) -20753 (lookup *_Program-types *_Program-types->payload) # => eax -20754 { -20755 # if (curr == null) break -20756 3d/compare-eax-and 0/imm32/null -20757 74/jump-if-= break/disp8 -20758 (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc)) -20759 # curr = lookup(curr->next) -20760 (lookup *(eax+0x10) *(eax+0x14)) # Typeinfo-next Typeinfo-next => eax -20761 eb/jump loop/disp8 -20762 } -20763 $populate-mu-type-sizes:offsets: -20764 # curr = *Program->types -20765 (lookup *_Program-types *_Program-types->payload) # => eax -20766 { -20767 # if (curr == null) break -20768 3d/compare-eax-and 0/imm32/null -20769 74/jump-if-= break/disp8 -20770 (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc)) -20771 # curr = curr->next -20772 (lookup *(eax+0x10) *(eax+0x14)) # Typeinfo-next Typeinfo-next => eax -20773 eb/jump loop/disp8 -20774 } -20775 $populate-mu-type-sizes:end: -20776 # . epilogue -20777 89/<- %esp 5/r32/ebp -20778 5d/pop-to-ebp -20779 c3/return -20780 -20781 # compute sizes of all fields, recursing as necessary -20782 # sum up all their sizes to arrive at total size -20783 # fields may be out of order, but that doesn't affect the answer -20784 populate-mu-type-sizes-in-type: # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor) -20785 # . prologue -20786 55/push-ebp -20787 89/<- %ebp 4/r32/esp -20788 # . save registers -20789 50/push-eax -20790 51/push-ecx -20791 52/push-edx -20792 56/push-esi -20793 57/push-edi -20794 # esi = T -20795 8b/-> *(ebp+8) 6/r32/esi -20796 # if T is already computed, return -20797 81 7/subop/compare *(esi+0xc) 0/imm32 # Typeinfo-total-size-in-bytes -20798 0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32 -20799 # if T is being computed, abort -20800 81 7/subop/compare *(esi+0xc) -1/imm32/being-computed # Typeinfo-total-size-in-bytes -20801 0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32 -20802 # tag T (-2 to -1) to avoid infinite recursion -20803 c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed # Typeinfo-total-size-in-bytes -20804 # var total-size/edi: int = 0 -20805 bf/copy-to-edi 0/imm32 -20806 # - for every field, if it's a user-defined type, compute its size -20807 # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields) -20808 (lookup *(esi+4) *(esi+8)) # Typeinfo-fields Typeinfo-fields => eax -20809 89/<- %ecx 0/r32/eax -20810 # var table-size/edx: int = table->write -20811 8b/-> *ecx 2/r32/edx # stream-write -20812 # var curr/ecx: (addr table_row) = table->data -20813 8d/copy-address *(ecx+0xc) 1/r32/ecx -20814 # var max/edx: (addr table_row) = table->data + table->write -20815 8d/copy-address *(ecx+edx) 2/r32/edx -20816 { -20817 $populate-mu-type-sizes-in-type:loop: -20818 # if (curr >= max) break -20819 39/compare %ecx 2/r32/edx -20820 73/jump-if-addr>= break/disp8 -20821 # var t/eax: (addr typeinfo-entry) = lookup(curr->value) -20822 (lookup *(ecx+8) *(ecx+0xc)) # => eax -20823 # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking -20824 81 7/subop/compare *eax 0/imm32 # Typeinfo-entry-input-var -20825 74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8 -20826 # compute size of t->input-var -20827 (lookup *eax *(eax+4)) # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax -20828 (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10)) # => eax -20829 # result += eax -20830 01/add-to %edi 0/r32/eax -20831 # curr += row-size -20832 81 0/subop/add %ecx 0x10/imm32 # Typeinfo-fields-row-size -20833 # -20834 eb/jump loop/disp8 -20835 } -20836 # - save result -20837 89/<- *(esi+0xc) 7/r32/edi # Typeinfo-total-size-in-bytes -20838 $populate-mu-type-sizes-in-type:end: -20839 # . restore registers -20840 5f/pop-to-edi -20841 5e/pop-to-esi -20842 5a/pop-to-edx -20843 59/pop-to-ecx -20844 58/pop-to-eax -20845 # . epilogue -20846 89/<- %esp 5/r32/ebp -20847 5d/pop-to-ebp -20848 c3/return -20849 -20850 $populate-mu-type-sizes-in-type:abort: -20851 (write-buffered *(ebp+0xc) "cycle in type definitions\n") -20852 (flush *(ebp+0xc)) -20853 (stop *(ebp+0x10) 1) -20854 # never gets here -20855 -20856 # Analogous to size-of, except we need to compute what size-of can just read -20857 # off the right data structures. -20858 compute-size-of-var: # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -20859 # . prologue -20860 55/push-ebp -20861 89/<- %ebp 4/r32/esp -20862 # . push registers -20863 51/push-ecx -20864 # var t/ecx: (addr type-tree) = lookup(v->type) -20865 8b/-> *(ebp+8) 1/r32/ecx -20866 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -20867 89/<- %ecx 0/r32/eax -20868 # if (t->is-atom == false) t = lookup(t->left) -20869 { -20870 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -20871 75/jump-if-!= break/disp8 -20872 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -20873 89/<- %ecx 0/r32/eax -20874 } -20875 # TODO: ensure t is an atom -20876 (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10)) # Type-tree-value => eax -20877 $compute-size-of-var:end: -20878 # . restore registers -20879 59/pop-to-ecx -20880 # . epilogue -20881 89/<- %esp 5/r32/ebp -20882 5d/pop-to-ebp -20883 c3/return -20884 -20885 compute-size-of-type-id: # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -20886 # . prologue -20887 55/push-ebp -20888 89/<- %ebp 4/r32/esp -20889 # . save registers -20890 51/push-ecx -20891 # var out/ecx: (handle typeinfo) -20892 68/push 0/imm32 -20893 68/push 0/imm32 -20894 89/<- %ecx 4/r32/esp -20895 # eax = t -20896 8b/-> *(ebp+8) 0/r32/eax -20897 # if t is a literal, return 0 -20898 3d/compare-eax-and 0/imm32/literal -20899 0f 84/jump-if-= $compute-size-of-type-id:end/disp32 # eax changes type from type-id to int -20900 # if t is a byte, return 4 (because we don't really support non-multiples of 4) -20901 3d/compare-eax-and 8/imm32/byte -20902 { -20903 75/jump-if-!= break/disp8 -20904 b8/copy-to-eax 4/imm32 -20905 eb/jump $compute-size-of-type-id:end/disp8 -20906 } -20907 # if t is a handle, return 8 -20908 3d/compare-eax-and 4/imm32/handle -20909 { -20910 75/jump-if-!= break/disp8 -20911 b8/copy-to-eax 8/imm32 -20912 eb/jump $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int -20913 } -20914 # if t is a slice, return 8 -20915 3d/compare-eax-and 0xc/imm32/slice -20916 { -20917 75/jump-if-!= break/disp8 -20918 b8/copy-to-eax 8/imm32 -20919 eb/jump $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int -20920 } -20921 # if t is a user-defined type, compute its size -20922 # TODO: support non-atom type -20923 (find-typeinfo %eax %ecx) +20529 # . save registers +20530 50/push-eax +20531 51/push-ecx +20532 52/push-edx +20533 53/push-ebx +20534 56/push-esi +20535 57/push-edi +20536 # edi = t +20537 8b/-> *(ebp+0xc) 7/r32/edi +20538 # var line/ecx: (stream byte 512) +20539 81 5/subop/subtract %esp 0x200/imm32 +20540 68/push 0x200/imm32/size +20541 68/push 0/imm32/read +20542 68/push 0/imm32/write +20543 89/<- %ecx 4/r32/esp +20544 # var word-slice/edx: slice +20545 68/push 0/imm32/end +20546 68/push 0/imm32/start +20547 89/<- %edx 4/r32/esp +20548 # var v/esi: (handle var) +20549 68/push 0/imm32 +20550 68/push 0/imm32 +20551 89/<- %esi 4/r32/esp +20552 # var r/ebx: (handle typeinfo-entry) +20553 68/push 0/imm32 +20554 68/push 0/imm32 +20555 89/<- %ebx 4/r32/esp +20556 { +20557 $populate-mu-type:line-loop: +20558 (clear-stream %ecx) +20559 (read-line-buffered *(ebp+8) %ecx) +20560 # if (line->write == 0) abort +20561 81 7/subop/compare *ecx 0/imm32 +20562 0f 84/jump-if-= $populate-mu-type:error1/disp32 +20563 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +20569 (next-mu-token %ecx %edx) +20570 # if slice-empty?(word-slice) continue +20571 (slice-empty? %edx) # => eax +20572 3d/compare-eax-and 0/imm32 +20573 0f 85/jump-if-!= loop/disp32 +20574 # if slice-equal?(word-slice, "}") break +20575 (slice-equal? %edx "}") +20576 3d/compare-eax-and 0/imm32 +20577 0f 85/jump-if-!= break/disp32 +20578 $populate-mu-type:parse-element: +20579 # v = parse-var-with-type(word-slice, first-line) +20580 # must do this first to strip the trailing ':' from word-slice before +20581 # using it in find-or-create-typeinfo-fields below +20582 # TODO: clean up that mutation in parse-var-with-type +20583 (type-name *edi) # Typeinfo-id => eax +20584 (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14)) +20585 # if v is an addr, abort +20586 (lookup *esi *(esi+4)) # => eax +20587 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +20588 (mu-addr-type? %eax) # => eax +20589 3d/compare-eax-and 0/imm32/false +20590 0f 85/jump-if-!= $populate-mu-type:error2/disp32 +20591 # if v is an array, abort (we could support it, but initialization gets complex) +20592 (lookup *esi *(esi+4)) # => eax +20593 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +20594 (mu-array-type? %eax) # => eax +20595 3d/compare-eax-and 0/imm32/false +20596 0f 85/jump-if-!= $populate-mu-type:error3/disp32 +20597 # if v is a byte, abort +20598 (lookup *esi *(esi+4)) # => eax +20599 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +20600 (simple-mu-type? %eax 8) # byte => eax +20601 3d/compare-eax-and 0/imm32/false +20602 0f 85/jump-if-!= $populate-mu-type:error4/disp32 +20603 # if v is a slice, abort +20604 (lookup *esi *(esi+4)) # => eax +20605 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +20606 (simple-mu-type? %eax 0xc) # slice => eax +20607 3d/compare-eax-and 0/imm32/false +20608 0f 85/jump-if-!= $populate-mu-type:error5/disp32 +20609 # if v is a stream, abort (we could support it, but initialization gets even more complex) +20610 (lookup *esi *(esi+4)) # => eax +20611 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +20612 (mu-stream-type? %eax) # => eax +20613 3d/compare-eax-and 0/imm32/false +20614 0f 85/jump-if-!= $populate-mu-type:error6/disp32 +20615 # var tmp/ecx +20616 51/push-ecx +20617 $populate-mu-type:create-typeinfo-fields: +20618 # var r/ebx: (handle typeinfo-entry) +20619 (find-or-create-typeinfo-fields %edi %edx %ebx) +20620 # r->index = curr-index +20621 (lookup *ebx *(ebx+4)) # => eax +20622 8b/-> *(ebp-4) 1/r32/ecx +20623 #? (write-buffered Stderr "saving index ") +20624 #? (write-int32-hex-buffered Stderr %ecx) +20625 #? (write-buffered Stderr " at ") +20626 #? (write-int32-hex-buffered Stderr %edi) +20627 #? (write-buffered Stderr Newline) +20628 #? (flush Stderr) +20629 89/<- *(eax+8) 1/r32/ecx # Typeinfo-entry-index +20630 # ++curr-index +20631 ff 0/subop/increment *(ebp-4) +20632 $populate-mu-type:set-input-type: +20633 # r->input-var = v +20634 8b/-> *esi 1/r32/ecx +20635 89/<- *eax 1/r32/ecx # Typeinfo-entry-input-var +20636 8b/-> *(esi+4) 1/r32/ecx +20637 89/<- *(eax+4) 1/r32/ecx # Typeinfo-entry-input-var +20638 # restore line +20639 59/pop-to-ecx +20640 { +20641 $populate-mu-type:create-output-type: +20642 # if (r->output-var == 0) create a new var with some placeholder data +20643 81 7/subop/compare *(eax+0xc) 0/imm32 # Typeinfo-entry-output-var +20644 75/jump-if-!= break/disp8 +20645 8d/copy-address *(eax+0xc) 0/r32/eax # Typeinfo-entry-output-var +20646 (new-literal Heap %edx %eax) +20647 } +20648 e9/jump loop/disp32 +20649 } +20650 $populate-mu-type:invalidate-total-size-in-bytes: +20651 # Offsets and total size may not be accurate here since we may not yet +20652 # have encountered the element types. +20653 # We'll recompute them separately after parsing the entire program. +20654 c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized # Typeinfo-total-size-in-bytes +20655 $populate-mu-type:end: +20656 # . reclaim locals +20657 81 0/subop/add %esp 0x224/imm32 +20658 # . restore registers +20659 5f/pop-to-edi +20660 5e/pop-to-esi +20661 5b/pop-to-ebx +20662 5a/pop-to-edx +20663 59/pop-to-ecx +20664 58/pop-to-eax +20665 # reclaim curr-index +20666 81 0/subop/add %esp 4/imm32 +20667 # . epilogue +20668 89/<- %esp 5/r32/ebp +20669 5d/pop-to-ebp +20670 c3/return +20671 +20672 $populate-mu-type:error1: +20673 # error("incomplete type definition '" t->name "'\n") +20674 (write-buffered *(ebp+0x10) "incomplete type definition '") +20675 (type-name *edi) # Typeinfo-id => eax +20676 (write-buffered *(ebp+0x10) %eax) +20677 (write-buffered *(ebp+0x10) "\n") +20678 (flush *(ebp+0x10)) +20679 (stop *(ebp+0x14) 1) +20680 # never gets here +20681 +20682 $populate-mu-type:error2: +20683 (write-buffered *(ebp+0x10) "type ") +20684 (type-name *edi) # Typeinfo-id => eax +20685 (write-buffered *(ebp+0x10) %eax) +20686 (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n") +20687 (flush *(ebp+0x10)) +20688 (stop *(ebp+0x14) 1) +20689 # never gets here +20690 +20691 $populate-mu-type:error3: +20692 (write-buffered *(ebp+0x10) "type ") +20693 (type-name *edi) # Typeinfo-id => eax +20694 (write-buffered *(ebp+0x10) %eax) +20695 (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n") +20696 (flush *(ebp+0x10)) +20697 (stop *(ebp+0x14) 1) +20698 # never gets here +20699 +20700 $populate-mu-type:error4: +20701 (write-buffered *(ebp+0x10) "type ") +20702 (type-name *edi) # Typeinfo-id => eax +20703 (write-buffered *(ebp+0x10) %eax) +20704 (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n") +20705 (flush *(ebp+0x10)) +20706 (stop *(ebp+0x14) 1) +20707 # never gets here +20708 +20709 $populate-mu-type:error5: +20710 (write-buffered *(ebp+0x10) "type ") +20711 (type-name *edi) # Typeinfo-id => eax +20712 (write-buffered *(ebp+0x10) %eax) +20713 (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n") +20714 (flush *(ebp+0x10)) +20715 (stop *(ebp+0x14) 1) +20716 # never gets here +20717 +20718 $populate-mu-type:error6: +20719 (write-buffered *(ebp+0x10) "type ") +20720 (type-name *edi) # Typeinfo-id => eax +20721 (write-buffered *(ebp+0x10) %eax) +20722 (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n") +20723 (flush *(ebp+0x10)) +20724 (stop *(ebp+0x14) 1) +20725 # never gets here +20726 +20727 type-name: # index: int -> result/eax: (addr array byte) +20728 # . prologue +20729 55/push-ebp +20730 89/<- %ebp 4/r32/esp +20731 # +20732 (index Type-id *(ebp+8)) +20733 $type-name:end: +20734 # . epilogue +20735 89/<- %esp 5/r32/ebp +20736 5d/pop-to-ebp +20737 c3/return +20738 +20739 index: # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte) +20740 # . prologue +20741 55/push-ebp +20742 89/<- %ebp 4/r32/esp +20743 # . save registers +20744 56/push-esi +20745 # TODO: bounds-check index +20746 # esi = arr +20747 8b/-> *(ebp+8) 6/r32/esi +20748 # eax = index +20749 8b/-> *(ebp+0xc) 0/r32/eax +20750 # eax = *(arr + 12 + index) +20751 8b/-> *(esi+eax<<2+0xc) 0/r32/eax +20752 $index:end: +20753 # . restore registers +20754 5e/pop-to-esi +20755 # . epilogue +20756 89/<- %esp 5/r32/ebp +20757 5d/pop-to-ebp +20758 c3/return +20759 +20760 ####################################################### +20761 # Compute type sizes +20762 ####################################################### +20763 +20764 # Compute the sizes of all user-defined types. +20765 # We'll need the sizes of their elements, which may be other user-defined +20766 # types, which we will compute as needed. +20767 +20768 # Initially, all user-defined types have their sizes set to -2 (invalid) +20769 populate-mu-type-sizes: # err: (addr buffered-file), ed: (addr exit-descriptor) +20770 # . prologue +20771 55/push-ebp +20772 89/<- %ebp 4/r32/esp +20773 $populate-mu-type-sizes:total-sizes: +20774 # var curr/eax: (addr typeinfo) = lookup(Program->types) +20775 (lookup *_Program-types *_Program-types->payload) # => eax +20776 { +20777 # if (curr == null) break +20778 3d/compare-eax-and 0/imm32/null +20779 74/jump-if-= break/disp8 +20780 (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc)) +20781 # curr = lookup(curr->next) +20782 (lookup *(eax+0x10) *(eax+0x14)) # Typeinfo-next Typeinfo-next => eax +20783 eb/jump loop/disp8 +20784 } +20785 $populate-mu-type-sizes:offsets: +20786 # curr = *Program->types +20787 (lookup *_Program-types *_Program-types->payload) # => eax +20788 { +20789 # if (curr == null) break +20790 3d/compare-eax-and 0/imm32/null +20791 74/jump-if-= break/disp8 +20792 (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc)) +20793 # curr = curr->next +20794 (lookup *(eax+0x10) *(eax+0x14)) # Typeinfo-next Typeinfo-next => eax +20795 eb/jump loop/disp8 +20796 } +20797 $populate-mu-type-sizes:end: +20798 # . epilogue +20799 89/<- %esp 5/r32/ebp +20800 5d/pop-to-ebp +20801 c3/return +20802 +20803 # compute sizes of all fields, recursing as necessary +20804 # sum up all their sizes to arrive at total size +20805 # fields may be out of order, but that doesn't affect the answer +20806 populate-mu-type-sizes-in-type: # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor) +20807 # . prologue +20808 55/push-ebp +20809 89/<- %ebp 4/r32/esp +20810 # . save registers +20811 50/push-eax +20812 51/push-ecx +20813 52/push-edx +20814 56/push-esi +20815 57/push-edi +20816 # esi = T +20817 8b/-> *(ebp+8) 6/r32/esi +20818 # if T is already computed, return +20819 81 7/subop/compare *(esi+0xc) 0/imm32 # Typeinfo-total-size-in-bytes +20820 0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32 +20821 # if T is being computed, abort +20822 81 7/subop/compare *(esi+0xc) -1/imm32/being-computed # Typeinfo-total-size-in-bytes +20823 0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32 +20824 # tag T (-2 to -1) to avoid infinite recursion +20825 c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed # Typeinfo-total-size-in-bytes +20826 # var total-size/edi: int = 0 +20827 bf/copy-to-edi 0/imm32 +20828 # - for every field, if it's a user-defined type, compute its size +20829 # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields) +20830 (lookup *(esi+4) *(esi+8)) # Typeinfo-fields Typeinfo-fields => eax +20831 89/<- %ecx 0/r32/eax +20832 # var table-size/edx: int = table->write +20833 8b/-> *ecx 2/r32/edx # stream-write +20834 # var curr/ecx: (addr table_row) = table->data +20835 8d/copy-address *(ecx+0xc) 1/r32/ecx +20836 # var max/edx: (addr table_row) = table->data + table->write +20837 8d/copy-address *(ecx+edx) 2/r32/edx +20838 { +20839 $populate-mu-type-sizes-in-type:loop: +20840 # if (curr >= max) break +20841 39/compare %ecx 2/r32/edx +20842 73/jump-if-addr>= break/disp8 +20843 # var t/eax: (addr typeinfo-entry) = lookup(curr->value) +20844 (lookup *(ecx+8) *(ecx+0xc)) # => eax +20845 # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking +20846 81 7/subop/compare *eax 0/imm32 # Typeinfo-entry-input-var +20847 74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8 +20848 # compute size of t->input-var +20849 (lookup *eax *(eax+4)) # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax +20850 (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10)) # => eax +20851 # result += eax +20852 01/add-to %edi 0/r32/eax +20853 # curr += row-size +20854 81 0/subop/add %ecx 0x10/imm32 # Typeinfo-fields-row-size +20855 # +20856 eb/jump loop/disp8 +20857 } +20858 # - save result +20859 89/<- *(esi+0xc) 7/r32/edi # Typeinfo-total-size-in-bytes +20860 $populate-mu-type-sizes-in-type:end: +20861 # . restore registers +20862 5f/pop-to-edi +20863 5e/pop-to-esi +20864 5a/pop-to-edx +20865 59/pop-to-ecx +20866 58/pop-to-eax +20867 # . epilogue +20868 89/<- %esp 5/r32/ebp +20869 5d/pop-to-ebp +20870 c3/return +20871 +20872 $populate-mu-type-sizes-in-type:abort: +20873 (write-buffered *(ebp+0xc) "cycle in type definitions\n") +20874 (flush *(ebp+0xc)) +20875 (stop *(ebp+0x10) 1) +20876 # never gets here +20877 +20878 # Analogous to size-of, except we need to compute what size-of can just read +20879 # off the right data structures. +20880 compute-size-of-var: # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +20881 # . prologue +20882 55/push-ebp +20883 89/<- %ebp 4/r32/esp +20884 # . push registers +20885 51/push-ecx +20886 # var t/ecx: (addr type-tree) = lookup(v->type) +20887 8b/-> *(ebp+8) 1/r32/ecx +20888 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +20889 89/<- %ecx 0/r32/eax +20890 # if (t->is-atom == false) t = lookup(t->left) +20891 { +20892 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +20893 75/jump-if-!= break/disp8 +20894 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +20895 89/<- %ecx 0/r32/eax +20896 } +20897 # TODO: ensure t is an atom +20898 (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10)) # Type-tree-value => eax +20899 $compute-size-of-var:end: +20900 # . restore registers +20901 59/pop-to-ecx +20902 # . epilogue +20903 89/<- %esp 5/r32/ebp +20904 5d/pop-to-ebp +20905 c3/return +20906 +20907 compute-size-of-type-id: # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +20908 # . prologue +20909 55/push-ebp +20910 89/<- %ebp 4/r32/esp +20911 # . save registers +20912 51/push-ecx +20913 # var out/ecx: (handle typeinfo) +20914 68/push 0/imm32 +20915 68/push 0/imm32 +20916 89/<- %ecx 4/r32/esp +20917 # eax = t +20918 8b/-> *(ebp+8) 0/r32/eax +20919 # if t is a literal, return 0 +20920 3d/compare-eax-and 0/imm32/literal +20921 0f 84/jump-if-= $compute-size-of-type-id:end/disp32 # eax changes type from type-id to int +20922 # if t is a byte, return 4 (because we don't really support non-multiples of 4) +20923 3d/compare-eax-and 8/imm32/byte 20924 { -20925 81 7/subop/compare *ecx 0/imm32 -20926 74/jump-if-= break/disp8 -20927 $compute-size-of-type-id:user-defined: -20928 (lookup *ecx *(ecx+4)) # => eax -20929 (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10)) -20930 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-total-size-in-bytes -20931 eb/jump $compute-size-of-type-id:end/disp8 -20932 } -20933 # otherwise return the word size -20934 b8/copy-to-eax 4/imm32 -20935 $compute-size-of-type-id:end: -20936 # . reclaim locals -20937 81 0/subop/add %esp 8/imm32 -20938 # . restore registers -20939 59/pop-to-ecx -20940 # . epilogue -20941 89/<- %esp 5/r32/ebp -20942 5d/pop-to-ebp -20943 c3/return -20944 -20945 # at this point we have total sizes for all user-defined types -20946 # compute offsets for each element -20947 # complication: fields may be out of order -20948 populate-mu-type-offsets: # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor) -20949 # . prologue -20950 55/push-ebp -20951 89/<- %ebp 4/r32/esp -20952 # . save registers -20953 50/push-eax -20954 51/push-ecx -20955 52/push-edx -20956 53/push-ebx -20957 56/push-esi -20958 57/push-edi -20959 #? (dump-typeinfos "aaa\n") -20960 # var curr-offset/edi: int = 0 -20961 bf/copy-to-edi 0/imm32 -20962 # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields) -20963 8b/-> *(ebp+8) 1/r32/ecx -20964 (lookup *(ecx+4) *(ecx+8)) # Typeinfo-fields Typeinfo-fields => eax -20965 89/<- %ecx 0/r32/eax -20966 # var num-elems/edx: int = table->write / Typeinfo-fields-row-size -20967 8b/-> *ecx 2/r32/edx # stream-write -20968 c1 5/subop/shift-right-logical %edx 4/imm8 -20969 # var i/ebx: int = 0 -20970 bb/copy-to-ebx 0/imm32 -20971 { -20972 $populate-mu-type-offsets:loop: -20973 39/compare %ebx 2/r32/edx -20974 0f 8d/jump-if->= break/disp32 -20975 #? (write-buffered Stderr "looking up index ") -20976 #? (write-int32-hex-buffered Stderr %ebx) -20977 #? (write-buffered Stderr " in ") -20978 #? (write-int32-hex-buffered Stderr *(ebp+8)) -20979 #? (write-buffered Stderr Newline) -20980 #? (flush Stderr) -20981 # var v/esi: (addr typeinfo-entry) -20982 (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10)) # => eax -20983 89/<- %esi 0/r32/eax -20984 # if v is null, silently move on; we'll emit a nice error message while type-checking -20985 81 7/subop/compare %esi 0/imm32 # Typeinfo-entry-input-var -20986 74/jump-if-= $populate-mu-type-offsets:end/disp8 -20987 # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking -20988 81 7/subop/compare *esi 0/imm32 # Typeinfo-entry-input-var -20989 74/jump-if-= $populate-mu-type-offsets:end/disp8 -20990 # v->output-var->offset = curr-offset -20991 # . eax: (addr var) -20992 (lookup *(esi+0xc) *(esi+0x10)) # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax -20993 89/<- *(eax+0x14) 7/r32/edi # Var-offset -20994 # curr-offset += size-of(v->input-var) -20995 (lookup *esi *(esi+4)) # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax -20996 (size-of %eax) # => eax -20997 01/add-to %edi 0/r32/eax -20998 # ++i -20999 43/increment-ebx -21000 e9/jump loop/disp32 -21001 } -21002 $populate-mu-type-offsets:end: -21003 # . restore registers -21004 5f/pop-to-edi -21005 5e/pop-to-esi -21006 5b/pop-to-ebx -21007 5a/pop-to-edx -21008 59/pop-to-ecx -21009 58/pop-to-eax -21010 # . epilogue -21011 89/<- %esp 5/r32/ebp -21012 5d/pop-to-ebp -21013 c3/return -21014 -21015 locate-typeinfo-entry-with-index: # table: (addr table (handle array byte) (handle typeinfo-entry)), idx: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: (addr typeinfo-entry) -21016 # . prologue -21017 55/push-ebp -21018 89/<- %ebp 4/r32/esp -21019 # . save registers -21020 51/push-ecx -21021 52/push-edx -21022 53/push-ebx -21023 56/push-esi -21024 57/push-edi -21025 # esi = table -21026 8b/-> *(ebp+8) 6/r32/esi -21027 # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data -21028 8d/copy-address *(esi+0xc) 1/r32/ecx -21029 # var max/edx: (addr byte) = &table->data[table->write] -21030 8b/-> *esi 2/r32/edx -21031 8d/copy-address *(ecx+edx) 2/r32/edx -21032 { -21033 $locate-typeinfo-entry-with-index:loop: -21034 39/compare %ecx 2/r32/edx -21035 73/jump-if-addr>= break/disp8 -21036 # var v/eax: (addr typeinfo-entry) -21037 (lookup *(ecx+8) *(ecx+0xc)) # => eax -21038 # if (v->index == idx) return v -21039 8b/-> *(eax+8) 3/r32/ebx # Typeinfo-entry-index -21040 #? (write-buffered Stderr "comparing ") -21041 #? (write-int32-hex-buffered Stderr %ebx) -21042 #? (write-buffered Stderr " and ") -21043 #? (write-int32-hex-buffered Stderr *(ebp+0xc)) -21044 #? (write-buffered Stderr Newline) -21045 #? (flush Stderr) -21046 39/compare *(ebp+0xc) 3/r32/ebx -21047 74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8 -21048 # curr += Typeinfo-entry-size -21049 81 0/subop/add %ecx 0x10/imm32 # Typeinfo-entry-size -21050 # -21051 eb/jump loop/disp8 -21052 } -21053 # return 0 -21054 b8/copy-to-eax 0/imm32 -21055 $locate-typeinfo-entry-with-index:end: -21056 #? (write-buffered Stderr "returning ") -21057 #? (write-int32-hex-buffered Stderr %eax) -21058 #? (write-buffered Stderr Newline) -21059 #? (flush Stderr) -21060 # . restore registers -21061 5f/pop-to-edi -21062 5e/pop-to-esi -21063 5b/pop-to-ebx -21064 5a/pop-to-edx -21065 59/pop-to-ecx -21066 # . epilogue -21067 89/<- %esp 5/r32/ebp -21068 5d/pop-to-ebp -21069 c3/return -21070 -21071 dump-typeinfos: # hdr: (addr array byte) -21072 # . prologue -21073 55/push-ebp -21074 89/<- %ebp 4/r32/esp -21075 # . save registers -21076 50/push-eax -21077 # -21078 (write-buffered Stderr *(ebp+8)) -21079 (flush Stderr) -21080 # var curr/eax: (addr typeinfo) = lookup(Program->types) -21081 (lookup *_Program-types *_Program-types->payload) # => eax -21082 { -21083 # if (curr == null) break -21084 3d/compare-eax-and 0/imm32 -21085 74/jump-if-= break/disp8 -21086 (write-buffered Stderr "---\n") -21087 (flush Stderr) -21088 (dump-typeinfo %eax) -21089 # curr = lookup(curr->next) -21090 (lookup *(eax+0x10) *(eax+0x14)) # Typeinfo-next Typeinfo-next => eax -21091 eb/jump loop/disp8 -21092 } -21093 $dump-typeinfos:end: -21094 # . restore registers -21095 58/pop-to-eax -21096 # . epilogue -21097 89/<- %esp 5/r32/ebp -21098 5d/pop-to-ebp -21099 c3/return -21100 -21101 dump-typeinfo: # in: (addr typeinfo) -21102 # . prologue -21103 55/push-ebp -21104 89/<- %ebp 4/r32/esp -21105 # . save registers -21106 50/push-eax -21107 51/push-ecx -21108 52/push-edx -21109 53/push-ebx -21110 56/push-esi -21111 57/push-edi -21112 # esi = in -21113 8b/-> *(ebp+8) 6/r32/esi -21114 # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields) -21115 (lookup *(esi+4) *(esi+8)) # Typeinfo-fields Typeinfo-fields => eax -21116 89/<- %ecx 0/r32/eax -21117 (write-buffered Stderr "id:") -21118 (write-int32-hex-buffered Stderr *esi) -21119 (write-buffered Stderr "\n") -21120 (write-buffered Stderr "fields @ ") -21121 (write-int32-hex-buffered Stderr %ecx) -21122 (write-buffered Stderr Newline) -21123 (flush Stderr) -21124 (write-buffered Stderr " write: ") -21125 (write-int32-hex-buffered Stderr *ecx) -21126 (write-buffered Stderr Newline) -21127 (flush Stderr) -21128 (write-buffered Stderr " read: ") -21129 (write-int32-hex-buffered Stderr *(ecx+4)) -21130 (write-buffered Stderr Newline) -21131 (flush Stderr) -21132 (write-buffered Stderr " size: ") -21133 (write-int32-hex-buffered Stderr *(ecx+8)) -21134 (write-buffered Stderr Newline) -21135 (flush Stderr) -21136 # var table-size/edx: int = table->write -21137 8b/-> *ecx 2/r32/edx # stream-write -21138 # var curr/ecx: (addr table_row) = table->data -21139 8d/copy-address *(ecx+0xc) 1/r32/ecx -21140 # var max/edx: (addr table_row) = table->data + table->write -21141 8d/copy-address *(ecx+edx) 2/r32/edx -21142 { -21143 $dump-typeinfo:loop: -21144 # if (curr >= max) break -21145 39/compare %ecx 2/r32/edx -21146 0f 83/jump-if-addr>= break/disp32 -21147 (write-buffered Stderr " row:\n") -21148 (write-buffered Stderr " key: ") -21149 (write-int32-hex-buffered Stderr *ecx) -21150 (write-buffered Stderr ",") -21151 (write-int32-hex-buffered Stderr *(ecx+4)) -21152 (write-buffered Stderr " = '") -21153 (lookup *ecx *(ecx+4)) -21154 (write-buffered Stderr %eax) -21155 (write-buffered Stderr "' @ ") -21156 (write-int32-hex-buffered Stderr %eax) -21157 (write-buffered Stderr Newline) -21158 (flush Stderr) -21159 (write-buffered Stderr " value: ") -21160 (write-int32-hex-buffered Stderr *(ecx+8)) -21161 (write-buffered Stderr ",") -21162 (write-int32-hex-buffered Stderr *(ecx+0xc)) -21163 (write-buffered Stderr " = typeinfo-entry@") -21164 (lookup *(ecx+8) *(ecx+0xc)) -21165 (write-int32-hex-buffered Stderr %eax) -21166 (write-buffered Stderr Newline) -21167 (flush Stderr) -21168 (write-buffered Stderr " input var@") -21169 (dump-var 5 %eax) -21170 (lookup *(ecx+8) *(ecx+0xc)) -21171 (write-buffered Stderr " index: ") -21172 (write-int32-hex-buffered Stderr *(eax+8)) -21173 (write-buffered Stderr Newline) -21174 (flush Stderr) -21175 (write-buffered Stderr " output var@") -21176 8d/copy-address *(eax+0xc) 0/r32/eax # Typeinfo-entry-output-var -21177 (dump-var 5 %eax) -21178 (flush Stderr) -21179 # curr += row-size -21180 81 0/subop/add %ecx 0x10/imm32 # Typeinfo-fields-row-size -21181 # -21182 e9/jump loop/disp32 -21183 } -21184 $dump-typeinfo:end: -21185 # . restore registers -21186 5f/pop-to-edi -21187 5e/pop-to-esi -21188 5b/pop-to-ebx -21189 5a/pop-to-edx -21190 59/pop-to-ecx -21191 58/pop-to-eax -21192 # . epilogue -21193 89/<- %esp 5/r32/ebp -21194 5d/pop-to-ebp -21195 c3/return -21196 -21197 dump-var: # indent: int, v: (addr handle var) -21198 # . prologue -21199 55/push-ebp -21200 89/<- %ebp 4/r32/esp -21201 # . save registers -21202 50/push-eax -21203 53/push-ebx -21204 # eax = v -21205 8b/-> *(ebp+0xc) 0/r32/eax -21206 # -21207 (write-int32-hex-buffered Stderr *eax) -21208 (write-buffered Stderr ",") -21209 (write-int32-hex-buffered Stderr *(eax+4)) -21210 (write-buffered Stderr "->") -21211 (lookup *eax *(eax+4)) -21212 (write-int32-hex-buffered Stderr %eax) -21213 (write-buffered Stderr Newline) -21214 (flush Stderr) -21215 { -21216 3d/compare-eax-and 0/imm32 -21217 0f 84/jump-if-= break/disp32 -21218 (emit-indent Stderr *(ebp+8)) -21219 (write-buffered Stderr "name: ") -21220 89/<- %ebx 0/r32/eax -21221 (write-int32-hex-buffered Stderr *ebx) # Var-name -21222 (write-buffered Stderr ",") -21223 (write-int32-hex-buffered Stderr *(ebx+4)) # Var-name -21224 (write-buffered Stderr "->") -21225 (lookup *ebx *(ebx+4)) # Var-name -21226 (write-int32-hex-buffered Stderr %eax) -21227 { -21228 3d/compare-eax-and 0/imm32 -21229 74/jump-if-= break/disp8 -21230 (write-buffered Stderr Space) -21231 (write-buffered Stderr %eax) -21232 } -21233 (write-buffered Stderr Newline) -21234 (flush Stderr) -21235 (emit-indent Stderr *(ebp+8)) -21236 (write-buffered Stderr "block depth: ") -21237 (write-int32-hex-buffered Stderr *(ebx+0x10)) # Var-block-depth -21238 (write-buffered Stderr Newline) -21239 (flush Stderr) -21240 (emit-indent Stderr *(ebp+8)) -21241 (write-buffered Stderr "stack offset: ") -21242 (write-int32-hex-buffered Stderr *(ebx+0x14)) # Var-offset -21243 (write-buffered Stderr Newline) -21244 (flush Stderr) -21245 (emit-indent Stderr *(ebp+8)) -21246 (write-buffered Stderr "reg: ") -21247 (write-int32-hex-buffered Stderr *(ebx+0x18)) # Var-register -21248 (write-buffered Stderr ",") -21249 (write-int32-hex-buffered Stderr *(ebx+0x1c)) # Var-register -21250 (write-buffered Stderr "->") -21251 (flush Stderr) -21252 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register -21253 (write-int32-hex-buffered Stderr %eax) -21254 { -21255 3d/compare-eax-and 0/imm32 -21256 74/jump-if-= break/disp8 -21257 (write-buffered Stderr Space) -21258 (write-buffered Stderr %eax) -21259 } +20925 75/jump-if-!= break/disp8 +20926 b8/copy-to-eax 4/imm32 +20927 eb/jump $compute-size-of-type-id:end/disp8 +20928 } +20929 # if t is a handle, return 8 +20930 3d/compare-eax-and 4/imm32/handle +20931 { +20932 75/jump-if-!= break/disp8 +20933 b8/copy-to-eax 8/imm32 +20934 eb/jump $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int +20935 } +20936 # if t is a slice, return 8 +20937 3d/compare-eax-and 0xc/imm32/slice +20938 { +20939 75/jump-if-!= break/disp8 +20940 b8/copy-to-eax 8/imm32 +20941 eb/jump $compute-size-of-type-id:end/disp8 # eax changes type from type-id to int +20942 } +20943 # if t is a user-defined type, compute its size +20944 # TODO: support non-atom type +20945 (find-typeinfo %eax %ecx) +20946 { +20947 81 7/subop/compare *ecx 0/imm32 +20948 74/jump-if-= break/disp8 +20949 $compute-size-of-type-id:user-defined: +20950 (lookup *ecx *(ecx+4)) # => eax +20951 (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10)) +20952 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-total-size-in-bytes +20953 eb/jump $compute-size-of-type-id:end/disp8 +20954 } +20955 # otherwise return the word size +20956 b8/copy-to-eax 4/imm32 +20957 $compute-size-of-type-id:end: +20958 # . reclaim locals +20959 81 0/subop/add %esp 8/imm32 +20960 # . restore registers +20961 59/pop-to-ecx +20962 # . epilogue +20963 89/<- %esp 5/r32/ebp +20964 5d/pop-to-ebp +20965 c3/return +20966 +20967 # at this point we have total sizes for all user-defined types +20968 # compute offsets for each element +20969 # complication: fields may be out of order +20970 populate-mu-type-offsets: # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor) +20971 # . prologue +20972 55/push-ebp +20973 89/<- %ebp 4/r32/esp +20974 # . save registers +20975 50/push-eax +20976 51/push-ecx +20977 52/push-edx +20978 53/push-ebx +20979 56/push-esi +20980 57/push-edi +20981 #? (dump-typeinfos "aaa\n") +20982 # var curr-offset/edi: int = 0 +20983 bf/copy-to-edi 0/imm32 +20984 # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields) +20985 8b/-> *(ebp+8) 1/r32/ecx +20986 (lookup *(ecx+4) *(ecx+8)) # Typeinfo-fields Typeinfo-fields => eax +20987 89/<- %ecx 0/r32/eax +20988 # var num-elems/edx: int = table->write / Typeinfo-fields-row-size +20989 8b/-> *ecx 2/r32/edx # stream-write +20990 c1 5/subop/shift-right-logical %edx 4/imm8 +20991 # var i/ebx: int = 0 +20992 bb/copy-to-ebx 0/imm32 +20993 { +20994 $populate-mu-type-offsets:loop: +20995 39/compare %ebx 2/r32/edx +20996 0f 8d/jump-if->= break/disp32 +20997 #? (write-buffered Stderr "looking up index ") +20998 #? (write-int32-hex-buffered Stderr %ebx) +20999 #? (write-buffered Stderr " in ") +21000 #? (write-int32-hex-buffered Stderr *(ebp+8)) +21001 #? (write-buffered Stderr Newline) +21002 #? (flush Stderr) +21003 # var v/esi: (addr typeinfo-entry) +21004 (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10)) # => eax +21005 89/<- %esi 0/r32/eax +21006 # if v is null, silently move on; we'll emit a nice error message while type-checking +21007 81 7/subop/compare %esi 0/imm32 # Typeinfo-entry-input-var +21008 74/jump-if-= $populate-mu-type-offsets:end/disp8 +21009 # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking +21010 81 7/subop/compare *esi 0/imm32 # Typeinfo-entry-input-var +21011 74/jump-if-= $populate-mu-type-offsets:end/disp8 +21012 # v->output-var->offset = curr-offset +21013 # . eax: (addr var) +21014 (lookup *(esi+0xc) *(esi+0x10)) # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax +21015 89/<- *(eax+0x14) 7/r32/edi # Var-offset +21016 # curr-offset += size-of(v->input-var) +21017 (lookup *esi *(esi+4)) # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax +21018 (size-of %eax) # => eax +21019 01/add-to %edi 0/r32/eax +21020 # ++i +21021 43/increment-ebx +21022 e9/jump loop/disp32 +21023 } +21024 $populate-mu-type-offsets:end: +21025 # . restore registers +21026 5f/pop-to-edi +21027 5e/pop-to-esi +21028 5b/pop-to-ebx +21029 5a/pop-to-edx +21030 59/pop-to-ecx +21031 58/pop-to-eax +21032 # . epilogue +21033 89/<- %esp 5/r32/ebp +21034 5d/pop-to-ebp +21035 c3/return +21036 +21037 locate-typeinfo-entry-with-index: # table: (addr table (handle array byte) (handle typeinfo-entry)), idx: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: (addr typeinfo-entry) +21038 # . prologue +21039 55/push-ebp +21040 89/<- %ebp 4/r32/esp +21041 # . save registers +21042 51/push-ecx +21043 52/push-edx +21044 53/push-ebx +21045 56/push-esi +21046 57/push-edi +21047 # esi = table +21048 8b/-> *(ebp+8) 6/r32/esi +21049 # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data +21050 8d/copy-address *(esi+0xc) 1/r32/ecx +21051 # var max/edx: (addr byte) = &table->data[table->write] +21052 8b/-> *esi 2/r32/edx +21053 8d/copy-address *(ecx+edx) 2/r32/edx +21054 { +21055 $locate-typeinfo-entry-with-index:loop: +21056 39/compare %ecx 2/r32/edx +21057 73/jump-if-addr>= break/disp8 +21058 # var v/eax: (addr typeinfo-entry) +21059 (lookup *(ecx+8) *(ecx+0xc)) # => eax +21060 # if (v->index == idx) return v +21061 8b/-> *(eax+8) 3/r32/ebx # Typeinfo-entry-index +21062 #? (write-buffered Stderr "comparing ") +21063 #? (write-int32-hex-buffered Stderr %ebx) +21064 #? (write-buffered Stderr " and ") +21065 #? (write-int32-hex-buffered Stderr *(ebp+0xc)) +21066 #? (write-buffered Stderr Newline) +21067 #? (flush Stderr) +21068 39/compare *(ebp+0xc) 3/r32/ebx +21069 74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8 +21070 # curr += Typeinfo-entry-size +21071 81 0/subop/add %ecx 0x10/imm32 # Typeinfo-entry-size +21072 # +21073 eb/jump loop/disp8 +21074 } +21075 # return 0 +21076 b8/copy-to-eax 0/imm32 +21077 $locate-typeinfo-entry-with-index:end: +21078 #? (write-buffered Stderr "returning ") +21079 #? (write-int32-hex-buffered Stderr %eax) +21080 #? (write-buffered Stderr Newline) +21081 #? (flush Stderr) +21082 # . restore registers +21083 5f/pop-to-edi +21084 5e/pop-to-esi +21085 5b/pop-to-ebx +21086 5a/pop-to-edx +21087 59/pop-to-ecx +21088 # . epilogue +21089 89/<- %esp 5/r32/ebp +21090 5d/pop-to-ebp +21091 c3/return +21092 +21093 dump-typeinfos: # hdr: (addr array byte) +21094 # . prologue +21095 55/push-ebp +21096 89/<- %ebp 4/r32/esp +21097 # . save registers +21098 50/push-eax +21099 # +21100 (write-buffered Stderr *(ebp+8)) +21101 (flush Stderr) +21102 # var curr/eax: (addr typeinfo) = lookup(Program->types) +21103 (lookup *_Program-types *_Program-types->payload) # => eax +21104 { +21105 # if (curr == null) break +21106 3d/compare-eax-and 0/imm32 +21107 74/jump-if-= break/disp8 +21108 (write-buffered Stderr "---\n") +21109 (flush Stderr) +21110 (dump-typeinfo %eax) +21111 # curr = lookup(curr->next) +21112 (lookup *(eax+0x10) *(eax+0x14)) # Typeinfo-next Typeinfo-next => eax +21113 eb/jump loop/disp8 +21114 } +21115 $dump-typeinfos:end: +21116 # . restore registers +21117 58/pop-to-eax +21118 # . epilogue +21119 89/<- %esp 5/r32/ebp +21120 5d/pop-to-ebp +21121 c3/return +21122 +21123 dump-typeinfo: # in: (addr typeinfo) +21124 # . prologue +21125 55/push-ebp +21126 89/<- %ebp 4/r32/esp +21127 # . save registers +21128 50/push-eax +21129 51/push-ecx +21130 52/push-edx +21131 53/push-ebx +21132 56/push-esi +21133 57/push-edi +21134 # esi = in +21135 8b/-> *(ebp+8) 6/r32/esi +21136 # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields) +21137 (lookup *(esi+4) *(esi+8)) # Typeinfo-fields Typeinfo-fields => eax +21138 89/<- %ecx 0/r32/eax +21139 (write-buffered Stderr "id:") +21140 (write-int32-hex-buffered Stderr *esi) +21141 (write-buffered Stderr "\n") +21142 (write-buffered Stderr "fields @ ") +21143 (write-int32-hex-buffered Stderr %ecx) +21144 (write-buffered Stderr Newline) +21145 (flush Stderr) +21146 (write-buffered Stderr " write: ") +21147 (write-int32-hex-buffered Stderr *ecx) +21148 (write-buffered Stderr Newline) +21149 (flush Stderr) +21150 (write-buffered Stderr " read: ") +21151 (write-int32-hex-buffered Stderr *(ecx+4)) +21152 (write-buffered Stderr Newline) +21153 (flush Stderr) +21154 (write-buffered Stderr " size: ") +21155 (write-int32-hex-buffered Stderr *(ecx+8)) +21156 (write-buffered Stderr Newline) +21157 (flush Stderr) +21158 # var table-size/edx: int = table->write +21159 8b/-> *ecx 2/r32/edx # stream-write +21160 # var curr/ecx: (addr table_row) = table->data +21161 8d/copy-address *(ecx+0xc) 1/r32/ecx +21162 # var max/edx: (addr table_row) = table->data + table->write +21163 8d/copy-address *(ecx+edx) 2/r32/edx +21164 { +21165 $dump-typeinfo:loop: +21166 # if (curr >= max) break +21167 39/compare %ecx 2/r32/edx +21168 0f 83/jump-if-addr>= break/disp32 +21169 (write-buffered Stderr " row:\n") +21170 (write-buffered Stderr " key: ") +21171 (write-int32-hex-buffered Stderr *ecx) +21172 (write-buffered Stderr ",") +21173 (write-int32-hex-buffered Stderr *(ecx+4)) +21174 (write-buffered Stderr " = '") +21175 (lookup *ecx *(ecx+4)) +21176 (write-buffered Stderr %eax) +21177 (write-buffered Stderr "' @ ") +21178 (write-int32-hex-buffered Stderr %eax) +21179 (write-buffered Stderr Newline) +21180 (flush Stderr) +21181 (write-buffered Stderr " value: ") +21182 (write-int32-hex-buffered Stderr *(ecx+8)) +21183 (write-buffered Stderr ",") +21184 (write-int32-hex-buffered Stderr *(ecx+0xc)) +21185 (write-buffered Stderr " = typeinfo-entry@") +21186 (lookup *(ecx+8) *(ecx+0xc)) +21187 (write-int32-hex-buffered Stderr %eax) +21188 (write-buffered Stderr Newline) +21189 (flush Stderr) +21190 (write-buffered Stderr " input var@") +21191 (dump-var 5 %eax) +21192 (lookup *(ecx+8) *(ecx+0xc)) +21193 (write-buffered Stderr " index: ") +21194 (write-int32-hex-buffered Stderr *(eax+8)) +21195 (write-buffered Stderr Newline) +21196 (flush Stderr) +21197 (write-buffered Stderr " output var@") +21198 8d/copy-address *(eax+0xc) 0/r32/eax # Typeinfo-entry-output-var +21199 (dump-var 5 %eax) +21200 (flush Stderr) +21201 # curr += row-size +21202 81 0/subop/add %ecx 0x10/imm32 # Typeinfo-fields-row-size +21203 # +21204 e9/jump loop/disp32 +21205 } +21206 $dump-typeinfo:end: +21207 # . restore registers +21208 5f/pop-to-edi +21209 5e/pop-to-esi +21210 5b/pop-to-ebx +21211 5a/pop-to-edx +21212 59/pop-to-ecx +21213 58/pop-to-eax +21214 # . epilogue +21215 89/<- %esp 5/r32/ebp +21216 5d/pop-to-ebp +21217 c3/return +21218 +21219 dump-var: # indent: int, v: (addr handle var) +21220 # . prologue +21221 55/push-ebp +21222 89/<- %ebp 4/r32/esp +21223 # . save registers +21224 50/push-eax +21225 53/push-ebx +21226 # eax = v +21227 8b/-> *(ebp+0xc) 0/r32/eax +21228 # +21229 (write-int32-hex-buffered Stderr *eax) +21230 (write-buffered Stderr ",") +21231 (write-int32-hex-buffered Stderr *(eax+4)) +21232 (write-buffered Stderr "->") +21233 (lookup *eax *(eax+4)) +21234 (write-int32-hex-buffered Stderr %eax) +21235 (write-buffered Stderr Newline) +21236 (flush Stderr) +21237 { +21238 3d/compare-eax-and 0/imm32 +21239 0f 84/jump-if-= break/disp32 +21240 (emit-indent Stderr *(ebp+8)) +21241 (write-buffered Stderr "name: ") +21242 89/<- %ebx 0/r32/eax +21243 (write-int32-hex-buffered Stderr *ebx) # Var-name +21244 (write-buffered Stderr ",") +21245 (write-int32-hex-buffered Stderr *(ebx+4)) # Var-name +21246 (write-buffered Stderr "->") +21247 (lookup *ebx *(ebx+4)) # Var-name +21248 (write-int32-hex-buffered Stderr %eax) +21249 { +21250 3d/compare-eax-and 0/imm32 +21251 74/jump-if-= break/disp8 +21252 (write-buffered Stderr Space) +21253 (write-buffered Stderr %eax) +21254 } +21255 (write-buffered Stderr Newline) +21256 (flush Stderr) +21257 (emit-indent Stderr *(ebp+8)) +21258 (write-buffered Stderr "block depth: ") +21259 (write-int32-hex-buffered Stderr *(ebx+0x10)) # Var-block-depth 21260 (write-buffered Stderr Newline) 21261 (flush Stderr) -21262 } -21263 $dump-var:end: -21264 # . restore registers -21265 5b/pop-to-ebx -21266 58/pop-to-eax -21267 # . epilogue -21268 89/<- %esp 5/r32/ebp -21269 5d/pop-to-ebp -21270 c3/return -21271 -21272 ####################################################### -21273 # Type-checking -21274 ####################################################### -21275 -21276 check-mu-types: # err: (addr buffered-file), ed: (addr exit-descriptor) -21277 # . prologue -21278 55/push-ebp -21279 89/<- %ebp 4/r32/esp -21280 # . save registers -21281 50/push-eax -21282 # var curr/eax: (addr function) = lookup(Program->functions) -21283 (lookup *_Program-functions *_Program-functions->payload) # => eax -21284 { -21285 $check-mu-types:loop: -21286 # if (curr == null) break -21287 3d/compare-eax-and 0/imm32 -21288 0f 84/jump-if-= break/disp32 -21289 +-- 8 lines: #? # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------ -21297 (check-mu-function %eax *(ebp+8) *(ebp+0xc)) -21298 # curr = lookup(curr->next) -21299 (lookup *(eax+0x20) *(eax+0x24)) # Function-next Function-next => eax -21300 e9/jump loop/disp32 -21301 } -21302 $check-mu-types:end: -21303 # . restore registers -21304 58/pop-to-eax -21305 # . epilogue -21306 89/<- %esp 5/r32/ebp -21307 5d/pop-to-ebp -21308 c3/return -21309 -21310 check-mu-function: # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21311 # . prologue -21312 55/push-ebp -21313 89/<- %ebp 4/r32/esp -21314 # . save registers -21315 50/push-eax -21316 56/push-esi -21317 # esi = f -21318 8b/-> *(ebp+8) 6/r32/esi -21319 # outputs -21320 (lookup *(esi+0x10) *(esi+0x14)) # Function-outputs Function-outputs => eax -21321 (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10)) -21322 # body -21323 (lookup *(esi+0x18) *(esi+0x1c)) # Function-body Function-body => eax -21324 (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10)) -21325 # if function has no outputs, we're done -21326 81 7/subop/compare *(esi+0x10) 0/imm32 -21327 74/jump-if-= $check-mu-function:end/disp8 -21328 # some final checks on body -21329 (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10)) -21330 (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10)) -21331 $check-mu-function:end: -21332 # . restore registers -21333 5e/pop-to-esi -21334 58/pop-to-eax -21335 # . epilogue -21336 89/<- %esp 5/r32/ebp -21337 5d/pop-to-ebp -21338 c3/return -21339 -21340 check-mu-block: # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21341 # . prologue -21342 55/push-ebp -21343 89/<- %ebp 4/r32/esp -21344 # . save registers -21345 50/push-eax -21346 # eax = block -21347 8b/-> *(ebp+8) 0/r32/eax -21348 # var stmts/eax: (addr list stmt) = lookup(block->statements) -21349 (lookup *(eax+4) *(eax+8)) # Block-stmts Block-stmts => eax -21350 # -21351 { -21352 $check-mu-block:check-empty: -21353 3d/compare-eax-and 0/imm32 -21354 0f 84/jump-if-= break/disp32 -21355 # emit block->statements -21356 (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21357 } -21358 $check-mu-block:end: -21359 # . restore registers -21360 58/pop-to-eax -21361 # . epilogue -21362 89/<- %esp 5/r32/ebp -21363 5d/pop-to-ebp -21364 c3/return -21365 -21366 check-mu-stmt-list: # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21367 # . prologue -21368 55/push-ebp -21369 89/<- %ebp 4/r32/esp -21370 # . save registers -21371 50/push-eax -21372 56/push-esi -21373 # esi = stmts -21374 8b/-> *(ebp+8) 6/r32/esi -21375 { -21376 $check-mu-stmt-list:loop: -21377 81 7/subop/compare %esi 0/imm32 -21378 0f 84/jump-if-= break/disp32 -21379 # var curr-stmt/eax: (addr stmt) = lookup(stmts->value) -21380 (lookup *esi *(esi+4)) # List-value List-value => eax -21381 { -21382 $check-mu-stmt-list:check-for-block: -21383 81 7/subop/compare *eax 0/imm32/block # Stmt-tag -21384 75/jump-if-!= break/disp8 -21385 $check-mu-stmt-list:block: -21386 (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21387 eb/jump $check-mu-stmt-list:continue/disp8 -21388 } -21389 { -21390 $check-mu-stmt-list:check-for-stmt1: -21391 81 7/subop/compare *eax 1/imm32/stmt1 # Stmt-tag -21392 0f 85/jump-if-!= break/disp32 -21393 $check-mu-stmt-list:stmt1: -21394 (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21395 eb/jump $check-mu-stmt-list:continue/disp8 -21396 } -21397 { -21398 $check-mu-stmt-list:check-for-reg-var-def: -21399 81 7/subop/compare *eax 3/imm32/reg-var-def # Stmt-tag -21400 0f 85/jump-if-!= break/disp32 -21401 $check-mu-stmt-list:reg-var-def: -21402 (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21403 eb/jump $check-mu-stmt-list:continue/disp8 -21404 } -21405 $check-mu-stmt-list:continue: -21406 # TODO: raise an error on unrecognized Stmt-tag -21407 (lookup *(esi+8) *(esi+0xc)) # List-next List-next => eax -21408 89/<- %esi 0/r32/eax -21409 e9/jump loop/disp32 -21410 } -21411 $check-mu-stmt-list:end: -21412 # . restore registers -21413 5e/pop-to-esi -21414 58/pop-to-eax -21415 # . epilogue -21416 89/<- %esp 5/r32/ebp -21417 5d/pop-to-ebp -21418 c3/return -21419 -21420 check-mu-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21421 # . prologue -21422 55/push-ebp -21423 89/<- %ebp 4/r32/esp -21424 # . save registers -21425 50/push-eax -21426 # - if stmt's operation matches a primitive, check against it -21427 (has-primitive-name? *(ebp+8)) # => eax -21428 3d/compare-eax-and 0/imm32/false -21429 { -21430 74/jump-if-= break/disp8 -21431 (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21432 e9/jump $check-mu-stmt:end/disp32 -21433 } -21434 # - otherwise find a function to check against -21435 # var f/eax: (addr function) = lookup(*Program->functions) -21436 (lookup *_Program-functions *_Program-functions->payload) # => eax -21437 (find-matching-function %eax *(ebp+8)) # => eax -21438 3d/compare-eax-and 0/imm32 -21439 { -21440 74/jump-if-= break/disp8 -21441 (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21442 eb/jump $check-mu-stmt:end/disp8 -21443 } -21444 # var f/eax: (addr function) = lookup(*Program->signatures) -21445 (lookup *_Program-signatures *_Program-signatures->payload) # => eax -21446 (find-matching-function %eax *(ebp+8)) # => eax -21447 3d/compare-eax-and 0/imm32 -21448 { -21449 74/jump-if-= break/disp8 -21450 (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21451 eb/jump $check-mu-stmt:end/disp8 -21452 } -21453 # - otherwise abort -21454 e9/jump $check-mu-stmt:unknown-call/disp32 -21455 $check-mu-stmt:end: -21456 # . restore registers -21457 58/pop-to-eax -21458 # . epilogue -21459 89/<- %esp 5/r32/ebp -21460 5d/pop-to-ebp -21461 c3/return -21462 -21463 $check-mu-stmt:unknown-call: -21464 (write-buffered *(ebp+0x10) "unknown function '") -21465 8b/-> *(ebp+8) 0/r32/eax -21466 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -21467 (write-buffered *(ebp+0x10) %eax) -21468 (write-buffered *(ebp+0x10) "'\n") -21469 (flush *(ebp+0x10)) -21470 (stop *(ebp+0x14) 1) -21471 # never gets here -21472 -21473 has-primitive-name?: # stmt: (addr stmt) -> result/eax: boolean -21474 # . prologue -21475 55/push-ebp -21476 89/<- %ebp 4/r32/esp -21477 # . save registers -21478 51/push-ecx -21479 56/push-esi -21480 # var name/esi: (addr array byte) = lookup(stmt->operation) -21481 8b/-> *(ebp+8) 6/r32/esi -21482 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax -21483 89/<- %esi 0/r32/eax -21484 # if (name == "return") return true -21485 (string-equal? %esi "return") # => eax -21486 3d/compare-eax-and 0/imm32/false -21487 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21488 # if (name == "get") return true -21489 (string-equal? %esi "get") # => eax -21490 3d/compare-eax-and 0/imm32/false -21491 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21492 # if (name == "index") return true -21493 (string-equal? %esi "index") # => eax -21494 3d/compare-eax-and 0/imm32/false -21495 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21496 # if (name == "length") return true -21497 (string-equal? %esi "length") # => eax -21498 3d/compare-eax-and 0/imm32/false -21499 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21500 # if (name == "compute-offset") return true -21501 (string-equal? %esi "compute-offset") # => eax -21502 3d/compare-eax-and 0/imm32/false -21503 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21504 # if (name == "copy-object") return true -21505 (string-equal? %esi "copy-object") # => eax -21506 3d/compare-eax-and 0/imm32/false -21507 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21508 # if (name == "clear-object") return true -21509 (string-equal? %esi "clear-object") # => eax -21510 3d/compare-eax-and 0/imm32/false -21511 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21512 # if (name == "allocate") return true -21513 (string-equal? %esi "allocate") # => eax -21514 3d/compare-eax-and 0/imm32/false -21515 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21516 # if (name == "populate") return true -21517 (string-equal? %esi "populate") # => eax -21518 3d/compare-eax-and 0/imm32/false -21519 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21520 # if (name == "populate-stream") return true -21521 (string-equal? %esi "populate-stream") # => eax -21522 3d/compare-eax-and 0/imm32/false -21523 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21524 # if (name == "read-from-stream") return true -21525 (string-equal? %esi "read-from-stream") # => eax -21526 3d/compare-eax-and 0/imm32/false -21527 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21528 # if (name == "write-to-stream") return true -21529 (string-equal? %esi "write-to-stream") # => eax -21530 3d/compare-eax-and 0/imm32/false -21531 0f 85/jump-if-!= $has-primitive-name?:end/disp32 -21532 # var curr/ecx: (addr primitive) = Primitives -21533 b9/copy-to-ecx Primitives/imm32 -21534 { -21535 $has-primitive-name?:loop: -21536 # if (curr == null) break -21537 81 7/subop/compare %ecx 0/imm32 -21538 74/jump-if-= break/disp8 -21539 # if (primitive->name == name) return true -21540 (lookup *ecx *(ecx+4)) # Primitive-name Primitive-name => eax -21541 #? (write-buffered Stderr %eax) -21542 #? (write-buffered Stderr Newline) -21543 #? (flush Stderr) -21544 (string-equal? %esi %eax) # => eax -21545 3d/compare-eax-and 0/imm32/false -21546 75/jump-if-!= $has-primitive-name?:end/disp8 -21547 $has-primitive-name?:next-primitive: -21548 # curr = curr->next -21549 (lookup *(ecx+0x3c) *(ecx+0x40)) # Primitive-next Primitive-next => eax -21550 89/<- %ecx 0/r32/eax -21551 # -21552 e9/jump loop/disp32 -21553 } -21554 # return null -21555 b8/copy-to-eax 0/imm32 -21556 $has-primitive-name?:end: -21557 # . restore registers -21558 5e/pop-to-esi -21559 59/pop-to-ecx -21560 # . epilogue -21561 89/<- %esp 5/r32/ebp -21562 5d/pop-to-ebp -21563 c3/return -21564 -21565 check-mu-primitive: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21566 # . prologue -21567 55/push-ebp -21568 89/<- %ebp 4/r32/esp -21569 # . save registers -21570 50/push-eax -21571 51/push-ecx -21572 # var op/ecx: (addr array byte) = lookup(stmt->operation) -21573 8b/-> *(ebp+8) 0/r32/eax -21574 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -21575 89/<- %ecx 0/r32/eax -21576 # if (op == "copy") check-mu-copy-stmt -21577 { -21578 (string-equal? %ecx "copy") # => eax -21579 3d/compare-eax-and 0/imm32/false -21580 74/jump-if-= break/disp8 -21581 (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21582 e9/jump $check-mu-primitive:end/disp32 -21583 } -21584 # if (op == "copy-to") check-mu-copy-to-stmt -21585 { -21586 (string-equal? %ecx "copy-to") # => eax -21587 3d/compare-eax-and 0/imm32/false -21588 74/jump-if-= break/disp8 -21589 (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21590 e9/jump $check-mu-primitive:end/disp32 -21591 } -21592 # if (op == "copy-byte") check-mu-copy-byte-stmt -21593 { -21594 (string-equal? %ecx "copy-byte") # => eax -21595 3d/compare-eax-and 0/imm32/false -21596 74/jump-if-= break/disp8 -21597 (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21598 e9/jump $check-mu-primitive:end/disp32 -21599 } -21600 # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt -21601 { -21602 (string-equal? %ecx "copy-byte-to") # => eax -21603 3d/compare-eax-and 0/imm32/false -21604 74/jump-if-= break/disp8 -21605 (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21606 e9/jump $check-mu-primitive:end/disp32 -21607 } -21608 # if (op == "compare") check-mu-compare-stmt -21609 { -21610 (string-equal? %ecx "compare") # => eax -21611 3d/compare-eax-and 0/imm32/false -21612 74/jump-if-= break/disp8 -21613 (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21614 e9/jump $check-mu-primitive:end/disp32 -21615 } -21616 # if (op == "address") check-mu-address-stmt -21617 { -21618 (string-equal? %ecx "address") # => eax -21619 3d/compare-eax-and 0/imm32/false -21620 74/jump-if-= break/disp8 -21621 (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21622 e9/jump $check-mu-primitive:end/disp32 -21623 } -21624 # if (op == "return") check-mu-return-stmt -21625 { -21626 (string-equal? %ecx "return") # => eax -21627 3d/compare-eax-and 0/imm32/false -21628 74/jump-if-= break/disp8 -21629 (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21630 e9/jump $check-mu-primitive:end/disp32 -21631 } -21632 # if (op == "get") check-mu-get-stmt -21633 { -21634 (string-equal? %ecx "get") # => eax -21635 3d/compare-eax-and 0/imm32/false -21636 74/jump-if-= break/disp8 -21637 (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21638 e9/jump $check-mu-primitive:end/disp32 -21639 } -21640 # if (op == "index") check-mu-index-stmt -21641 { -21642 (string-equal? %ecx "index") # => eax -21643 3d/compare-eax-and 0/imm32/false -21644 74/jump-if-= break/disp8 -21645 (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21646 e9/jump $check-mu-primitive:end/disp32 -21647 } -21648 # if (op == "length") check-mu-length-stmt -21649 { -21650 (string-equal? %ecx "length") # => eax -21651 3d/compare-eax-and 0/imm32/false -21652 74/jump-if-= break/disp8 -21653 (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21654 e9/jump $check-mu-primitive:end/disp32 -21655 } -21656 # if (op == "compute-offset") check-mu-compute-offset-stmt -21657 { -21658 (string-equal? %ecx "compute-offset") # => eax -21659 3d/compare-eax-and 0/imm32/false -21660 74/jump-if-= break/disp8 -21661 (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21662 e9/jump $check-mu-primitive:end/disp32 -21663 } -21664 # if (op == "copy-object") check-mu-copy-object-stmt -21665 { -21666 (string-equal? %ecx "copy-object") # => eax -21667 3d/compare-eax-and 0/imm32/false -21668 74/jump-if-= break/disp8 -21669 (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21670 e9/jump $check-mu-primitive:end/disp32 -21671 } -21672 # if (op == "clear-object") check-mu-clear-object-stmt -21673 { -21674 (string-equal? %ecx "clear-object") # => eax -21675 3d/compare-eax-and 0/imm32/false -21676 74/jump-if-= break/disp8 -21677 (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21678 e9/jump $check-mu-primitive:end/disp32 -21679 } -21680 # if (op == "allocate") check-mu-allocate-stmt -21681 { -21682 (string-equal? %ecx "allocate") # => eax -21683 3d/compare-eax-and 0/imm32/false -21684 74/jump-if-= break/disp8 -21685 (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21686 e9/jump $check-mu-primitive:end/disp32 -21687 } -21688 # if (op == "populate") check-mu-populate-stmt -21689 { -21690 (string-equal? %ecx "populate") # => eax -21691 3d/compare-eax-and 0/imm32/false -21692 74/jump-if-= break/disp8 -21693 (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21694 e9/jump $check-mu-primitive:end/disp32 -21695 } -21696 # if (op == "populate-stream") check-mu-populate-stream-stmt -21697 { -21698 (string-equal? %ecx "populate-stream") # => eax -21699 3d/compare-eax-and 0/imm32/false -21700 74/jump-if-= break/disp8 -21701 (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21702 e9/jump $check-mu-primitive:end/disp32 -21703 } -21704 # if (op == "read-from-stream") check-mu-read-from-stream-stmt -21705 { -21706 (string-equal? %ecx "read-from-stream") # => eax -21707 3d/compare-eax-and 0/imm32/false -21708 74/jump-if-= break/disp8 -21709 (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21710 e9/jump $check-mu-primitive:end/disp32 -21711 } -21712 # if (op == "write-to-stream") check-mu-write-to-stream-stmt -21713 { -21714 (string-equal? %ecx "write-to-stream") # => eax -21715 3d/compare-eax-and 0/imm32/false -21716 74/jump-if-= break/disp8 -21717 (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21718 e9/jump $check-mu-primitive:end/disp32 -21719 } -21720 # if (op == "convert") check-mu-convert-stmt -21721 { -21722 (string-equal? %ecx "convert") # => eax -21723 3d/compare-eax-and 0/imm32/false -21724 74/jump-if-= break/disp8 -21725 (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21726 e9/jump $check-mu-primitive:end/disp32 -21727 } -21728 # otherwise check-numberlike-stmt -21729 (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21730 $check-mu-primitive:end: -21731 # . restore registers -21732 59/pop-to-ecx -21733 58/pop-to-eax -21734 # . epilogue -21735 89/<- %esp 5/r32/ebp -21736 5d/pop-to-ebp -21737 c3/return -21738 -21739 # by default, Mu primitives should only operate on 'number-like' types -21740 check-mu-numberlike-primitive: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21741 # . prologue -21742 55/push-ebp -21743 89/<- %ebp 4/r32/esp -21744 # . save registers -21745 50/push-eax -21746 51/push-ecx -21747 56/push-esi -21748 # esi = stmt -21749 8b/-> *(ebp+8) 6/r32/esi -21750 # var gas/ecx: int = 2 -21751 b9/copy-to-ecx 2/imm32 -21752 # - check at most 1 output -21753 # var output/eax: (addr stmt-var) = stmt->outputs -21754 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -21755 { -21756 3d/compare-eax-and 0/imm32 -21757 74/jump-if-= break/disp8 -21758 $check-mu-numberlike-primitive:output: -21759 (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21760 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -21761 3d/compare-eax-and 0/imm32 -21762 0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32 -21763 # check output is in a register -21764 # --gas -21765 49/decrement-ecx -21766 } -21767 # - check first inout -21768 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -21769 { -21770 3d/compare-eax-and 0/imm32 -21771 0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32 -21772 $check-mu-numberlike-primitive:first-inout: -21773 (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -21774 # --gas -21775 49/decrement-ecx -21776 } -21777 # - check second inout -21778 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -21779 { -21780 3d/compare-eax-and 0/imm32 -21781 74/jump-if-= $check-mu-numberlike-primitive:end/disp8 -21782 $check-mu-numberlike-primitive:second-inout: -21783 # is a second inout allowed? -21784 81 7/subop/compare %ecx 0/imm32 -21785 0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32 -21786 $check-mu-numberlike-primitive:second-inout-permitted: -21787 (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21262 (emit-indent Stderr *(ebp+8)) +21263 (write-buffered Stderr "stack offset: ") +21264 (write-int32-hex-buffered Stderr *(ebx+0x14)) # Var-offset +21265 (write-buffered Stderr Newline) +21266 (flush Stderr) +21267 (emit-indent Stderr *(ebp+8)) +21268 (write-buffered Stderr "reg: ") +21269 (write-int32-hex-buffered Stderr *(ebx+0x18)) # Var-register +21270 (write-buffered Stderr ",") +21271 (write-int32-hex-buffered Stderr *(ebx+0x1c)) # Var-register +21272 (write-buffered Stderr "->") +21273 (flush Stderr) +21274 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register +21275 (write-int32-hex-buffered Stderr %eax) +21276 { +21277 3d/compare-eax-and 0/imm32 +21278 74/jump-if-= break/disp8 +21279 (write-buffered Stderr Space) +21280 (write-buffered Stderr %eax) +21281 } +21282 (write-buffered Stderr Newline) +21283 (flush Stderr) +21284 } +21285 $dump-var:end: +21286 # . restore registers +21287 5b/pop-to-ebx +21288 58/pop-to-eax +21289 # . epilogue +21290 89/<- %esp 5/r32/ebp +21291 5d/pop-to-ebp +21292 c3/return +21293 +21294 ####################################################### +21295 # Type-checking +21296 ####################################################### +21297 +21298 check-mu-types: # err: (addr buffered-file), ed: (addr exit-descriptor) +21299 # . prologue +21300 55/push-ebp +21301 89/<- %ebp 4/r32/esp +21302 # . save registers +21303 50/push-eax +21304 # var curr/eax: (addr function) = lookup(Program->functions) +21305 (lookup *_Program-functions *_Program-functions->payload) # => eax +21306 { +21307 $check-mu-types:loop: +21308 # if (curr == null) break +21309 3d/compare-eax-and 0/imm32 +21310 0f 84/jump-if-= break/disp32 +21311 +-- 8 lines: #? # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------ +21319 (check-mu-function %eax *(ebp+8) *(ebp+0xc)) +21320 # curr = lookup(curr->next) +21321 (lookup *(eax+0x20) *(eax+0x24)) # Function-next Function-next => eax +21322 e9/jump loop/disp32 +21323 } +21324 $check-mu-types:end: +21325 # . restore registers +21326 58/pop-to-eax +21327 # . epilogue +21328 89/<- %esp 5/r32/ebp +21329 5d/pop-to-ebp +21330 c3/return +21331 +21332 check-mu-function: # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21333 # . prologue +21334 55/push-ebp +21335 89/<- %ebp 4/r32/esp +21336 # . save registers +21337 50/push-eax +21338 56/push-esi +21339 # esi = f +21340 8b/-> *(ebp+8) 6/r32/esi +21341 # outputs +21342 (lookup *(esi+0x10) *(esi+0x14)) # Function-outputs Function-outputs => eax +21343 (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10)) +21344 # body +21345 (lookup *(esi+0x18) *(esi+0x1c)) # Function-body Function-body => eax +21346 (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10)) +21347 # if function has no outputs, we're done +21348 81 7/subop/compare *(esi+0x10) 0/imm32 +21349 74/jump-if-= $check-mu-function:end/disp8 +21350 # some final checks on body +21351 (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10)) +21352 (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10)) +21353 $check-mu-function:end: +21354 # . restore registers +21355 5e/pop-to-esi +21356 58/pop-to-eax +21357 # . epilogue +21358 89/<- %esp 5/r32/ebp +21359 5d/pop-to-ebp +21360 c3/return +21361 +21362 check-mu-block: # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21363 # . prologue +21364 55/push-ebp +21365 89/<- %ebp 4/r32/esp +21366 # . save registers +21367 50/push-eax +21368 # eax = block +21369 8b/-> *(ebp+8) 0/r32/eax +21370 # var stmts/eax: (addr list stmt) = lookup(block->statements) +21371 (lookup *(eax+4) *(eax+8)) # Block-stmts Block-stmts => eax +21372 # +21373 { +21374 $check-mu-block:check-empty: +21375 3d/compare-eax-and 0/imm32 +21376 0f 84/jump-if-= break/disp32 +21377 # emit block->statements +21378 (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21379 } +21380 $check-mu-block:end: +21381 # . restore registers +21382 58/pop-to-eax +21383 # . epilogue +21384 89/<- %esp 5/r32/ebp +21385 5d/pop-to-ebp +21386 c3/return +21387 +21388 check-mu-stmt-list: # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21389 # . prologue +21390 55/push-ebp +21391 89/<- %ebp 4/r32/esp +21392 # . save registers +21393 50/push-eax +21394 56/push-esi +21395 # esi = stmts +21396 8b/-> *(ebp+8) 6/r32/esi +21397 { +21398 $check-mu-stmt-list:loop: +21399 81 7/subop/compare %esi 0/imm32 +21400 0f 84/jump-if-= break/disp32 +21401 # var curr-stmt/eax: (addr stmt) = lookup(stmts->value) +21402 (lookup *esi *(esi+4)) # List-value List-value => eax +21403 { +21404 $check-mu-stmt-list:check-for-block: +21405 81 7/subop/compare *eax 0/imm32/block # Stmt-tag +21406 75/jump-if-!= break/disp8 +21407 $check-mu-stmt-list:block: +21408 (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21409 eb/jump $check-mu-stmt-list:continue/disp8 +21410 } +21411 { +21412 $check-mu-stmt-list:check-for-stmt1: +21413 81 7/subop/compare *eax 1/imm32/stmt1 # Stmt-tag +21414 0f 85/jump-if-!= break/disp32 +21415 $check-mu-stmt-list:stmt1: +21416 (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21417 eb/jump $check-mu-stmt-list:continue/disp8 +21418 } +21419 { +21420 $check-mu-stmt-list:check-for-reg-var-def: +21421 81 7/subop/compare *eax 3/imm32/reg-var-def # Stmt-tag +21422 0f 85/jump-if-!= break/disp32 +21423 $check-mu-stmt-list:reg-var-def: +21424 (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21425 eb/jump $check-mu-stmt-list:continue/disp8 +21426 } +21427 $check-mu-stmt-list:continue: +21428 # TODO: raise an error on unrecognized Stmt-tag +21429 (lookup *(esi+8) *(esi+0xc)) # List-next List-next => eax +21430 89/<- %esi 0/r32/eax +21431 e9/jump loop/disp32 +21432 } +21433 $check-mu-stmt-list:end: +21434 # . restore registers +21435 5e/pop-to-esi +21436 58/pop-to-eax +21437 # . epilogue +21438 89/<- %esp 5/r32/ebp +21439 5d/pop-to-ebp +21440 c3/return +21441 +21442 check-mu-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21443 # . prologue +21444 55/push-ebp +21445 89/<- %ebp 4/r32/esp +21446 # . save registers +21447 50/push-eax +21448 # - if stmt's operation matches a primitive, check against it +21449 (has-primitive-name? *(ebp+8)) # => eax +21450 3d/compare-eax-and 0/imm32/false +21451 { +21452 74/jump-if-= break/disp8 +21453 (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21454 e9/jump $check-mu-stmt:end/disp32 +21455 } +21456 # - otherwise find a function to check against +21457 # var f/eax: (addr function) = lookup(*Program->functions) +21458 (lookup *_Program-functions *_Program-functions->payload) # => eax +21459 (find-matching-function %eax *(ebp+8)) # => eax +21460 3d/compare-eax-and 0/imm32 +21461 { +21462 74/jump-if-= break/disp8 +21463 (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21464 eb/jump $check-mu-stmt:end/disp8 +21465 } +21466 # var f/eax: (addr function) = lookup(*Program->signatures) +21467 (lookup *_Program-signatures *_Program-signatures->payload) # => eax +21468 (find-matching-function %eax *(ebp+8)) # => eax +21469 3d/compare-eax-and 0/imm32 +21470 { +21471 74/jump-if-= break/disp8 +21472 (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21473 eb/jump $check-mu-stmt:end/disp8 +21474 } +21475 # - otherwise abort +21476 e9/jump $check-mu-stmt:unknown-call/disp32 +21477 $check-mu-stmt:end: +21478 # . restore registers +21479 58/pop-to-eax +21480 # . epilogue +21481 89/<- %esp 5/r32/ebp +21482 5d/pop-to-ebp +21483 c3/return +21484 +21485 $check-mu-stmt:unknown-call: +21486 (write-buffered *(ebp+0x10) "unknown function '") +21487 8b/-> *(ebp+8) 0/r32/eax +21488 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +21489 (write-buffered *(ebp+0x10) %eax) +21490 (write-buffered *(ebp+0x10) "'\n") +21491 (flush *(ebp+0x10)) +21492 (stop *(ebp+0x14) 1) +21493 # never gets here +21494 +21495 has-primitive-name?: # stmt: (addr stmt) -> result/eax: boolean +21496 # . prologue +21497 55/push-ebp +21498 89/<- %ebp 4/r32/esp +21499 # . save registers +21500 51/push-ecx +21501 56/push-esi +21502 # var name/esi: (addr array byte) = lookup(stmt->operation) +21503 8b/-> *(ebp+8) 6/r32/esi +21504 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax +21505 89/<- %esi 0/r32/eax +21506 # if (name == "return") return true +21507 (string-equal? %esi "return") # => eax +21508 3d/compare-eax-and 0/imm32/false +21509 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21510 # if (name == "get") return true +21511 (string-equal? %esi "get") # => eax +21512 3d/compare-eax-and 0/imm32/false +21513 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21514 # if (name == "index") return true +21515 (string-equal? %esi "index") # => eax +21516 3d/compare-eax-and 0/imm32/false +21517 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21518 # if (name == "length") return true +21519 (string-equal? %esi "length") # => eax +21520 3d/compare-eax-and 0/imm32/false +21521 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21522 # if (name == "compute-offset") return true +21523 (string-equal? %esi "compute-offset") # => eax +21524 3d/compare-eax-and 0/imm32/false +21525 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21526 # if (name == "copy-object") return true +21527 (string-equal? %esi "copy-object") # => eax +21528 3d/compare-eax-and 0/imm32/false +21529 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21530 # if (name == "clear-object") return true +21531 (string-equal? %esi "clear-object") # => eax +21532 3d/compare-eax-and 0/imm32/false +21533 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21534 # if (name == "allocate") return true +21535 (string-equal? %esi "allocate") # => eax +21536 3d/compare-eax-and 0/imm32/false +21537 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21538 # if (name == "populate") return true +21539 (string-equal? %esi "populate") # => eax +21540 3d/compare-eax-and 0/imm32/false +21541 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21542 # if (name == "populate-stream") return true +21543 (string-equal? %esi "populate-stream") # => eax +21544 3d/compare-eax-and 0/imm32/false +21545 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21546 # if (name == "read-from-stream") return true +21547 (string-equal? %esi "read-from-stream") # => eax +21548 3d/compare-eax-and 0/imm32/false +21549 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21550 # if (name == "write-to-stream") return true +21551 (string-equal? %esi "write-to-stream") # => eax +21552 3d/compare-eax-and 0/imm32/false +21553 0f 85/jump-if-!= $has-primitive-name?:end/disp32 +21554 # var curr/ecx: (addr primitive) = Primitives +21555 b9/copy-to-ecx Primitives/imm32 +21556 { +21557 $has-primitive-name?:loop: +21558 # if (curr == null) break +21559 81 7/subop/compare %ecx 0/imm32 +21560 74/jump-if-= break/disp8 +21561 # if (primitive->name == name) return true +21562 (lookup *ecx *(ecx+4)) # Primitive-name Primitive-name => eax +21563 #? (write-buffered Stderr %eax) +21564 #? (write-buffered Stderr Newline) +21565 #? (flush Stderr) +21566 (string-equal? %esi %eax) # => eax +21567 3d/compare-eax-and 0/imm32/false +21568 75/jump-if-!= $has-primitive-name?:end/disp8 +21569 $has-primitive-name?:next-primitive: +21570 # curr = curr->next +21571 (lookup *(ecx+0x3c) *(ecx+0x40)) # Primitive-next Primitive-next => eax +21572 89/<- %ecx 0/r32/eax +21573 # +21574 e9/jump loop/disp32 +21575 } +21576 # return null +21577 b8/copy-to-eax 0/imm32 +21578 $has-primitive-name?:end: +21579 # . restore registers +21580 5e/pop-to-esi +21581 59/pop-to-ecx +21582 # . epilogue +21583 89/<- %esp 5/r32/ebp +21584 5d/pop-to-ebp +21585 c3/return +21586 +21587 check-mu-primitive: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21588 # . prologue +21589 55/push-ebp +21590 89/<- %ebp 4/r32/esp +21591 # . save registers +21592 50/push-eax +21593 51/push-ecx +21594 # var op/ecx: (addr array byte) = lookup(stmt->operation) +21595 8b/-> *(ebp+8) 0/r32/eax +21596 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +21597 89/<- %ecx 0/r32/eax +21598 # if (op == "copy") check-mu-copy-stmt +21599 { +21600 (string-equal? %ecx "copy") # => eax +21601 3d/compare-eax-and 0/imm32/false +21602 74/jump-if-= break/disp8 +21603 (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21604 e9/jump $check-mu-primitive:end/disp32 +21605 } +21606 # if (op == "copy-to") check-mu-copy-to-stmt +21607 { +21608 (string-equal? %ecx "copy-to") # => eax +21609 3d/compare-eax-and 0/imm32/false +21610 74/jump-if-= break/disp8 +21611 (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21612 e9/jump $check-mu-primitive:end/disp32 +21613 } +21614 # if (op == "copy-byte") check-mu-copy-byte-stmt +21615 { +21616 (string-equal? %ecx "copy-byte") # => eax +21617 3d/compare-eax-and 0/imm32/false +21618 74/jump-if-= break/disp8 +21619 (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21620 e9/jump $check-mu-primitive:end/disp32 +21621 } +21622 # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt +21623 { +21624 (string-equal? %ecx "copy-byte-to") # => eax +21625 3d/compare-eax-and 0/imm32/false +21626 74/jump-if-= break/disp8 +21627 (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21628 e9/jump $check-mu-primitive:end/disp32 +21629 } +21630 # if (op == "compare") check-mu-compare-stmt +21631 { +21632 (string-equal? %ecx "compare") # => eax +21633 3d/compare-eax-and 0/imm32/false +21634 74/jump-if-= break/disp8 +21635 (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21636 e9/jump $check-mu-primitive:end/disp32 +21637 } +21638 # if (op == "address") check-mu-address-stmt +21639 { +21640 (string-equal? %ecx "address") # => eax +21641 3d/compare-eax-and 0/imm32/false +21642 74/jump-if-= break/disp8 +21643 (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21644 e9/jump $check-mu-primitive:end/disp32 +21645 } +21646 # if (op == "return") check-mu-return-stmt +21647 { +21648 (string-equal? %ecx "return") # => eax +21649 3d/compare-eax-and 0/imm32/false +21650 74/jump-if-= break/disp8 +21651 (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21652 e9/jump $check-mu-primitive:end/disp32 +21653 } +21654 # if (op == "get") check-mu-get-stmt +21655 { +21656 (string-equal? %ecx "get") # => eax +21657 3d/compare-eax-and 0/imm32/false +21658 74/jump-if-= break/disp8 +21659 (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21660 e9/jump $check-mu-primitive:end/disp32 +21661 } +21662 # if (op == "index") check-mu-index-stmt +21663 { +21664 (string-equal? %ecx "index") # => eax +21665 3d/compare-eax-and 0/imm32/false +21666 74/jump-if-= break/disp8 +21667 (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21668 e9/jump $check-mu-primitive:end/disp32 +21669 } +21670 # if (op == "length") check-mu-length-stmt +21671 { +21672 (string-equal? %ecx "length") # => eax +21673 3d/compare-eax-and 0/imm32/false +21674 74/jump-if-= break/disp8 +21675 (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21676 e9/jump $check-mu-primitive:end/disp32 +21677 } +21678 # if (op == "compute-offset") check-mu-compute-offset-stmt +21679 { +21680 (string-equal? %ecx "compute-offset") # => eax +21681 3d/compare-eax-and 0/imm32/false +21682 74/jump-if-= break/disp8 +21683 (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21684 e9/jump $check-mu-primitive:end/disp32 +21685 } +21686 # if (op == "copy-object") check-mu-copy-object-stmt +21687 { +21688 (string-equal? %ecx "copy-object") # => eax +21689 3d/compare-eax-and 0/imm32/false +21690 74/jump-if-= break/disp8 +21691 (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21692 e9/jump $check-mu-primitive:end/disp32 +21693 } +21694 # if (op == "clear-object") check-mu-clear-object-stmt +21695 { +21696 (string-equal? %ecx "clear-object") # => eax +21697 3d/compare-eax-and 0/imm32/false +21698 74/jump-if-= break/disp8 +21699 (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21700 e9/jump $check-mu-primitive:end/disp32 +21701 } +21702 # if (op == "allocate") check-mu-allocate-stmt +21703 { +21704 (string-equal? %ecx "allocate") # => eax +21705 3d/compare-eax-and 0/imm32/false +21706 74/jump-if-= break/disp8 +21707 (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21708 e9/jump $check-mu-primitive:end/disp32 +21709 } +21710 # if (op == "populate") check-mu-populate-stmt +21711 { +21712 (string-equal? %ecx "populate") # => eax +21713 3d/compare-eax-and 0/imm32/false +21714 74/jump-if-= break/disp8 +21715 (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21716 e9/jump $check-mu-primitive:end/disp32 +21717 } +21718 # if (op == "populate-stream") check-mu-populate-stream-stmt +21719 { +21720 (string-equal? %ecx "populate-stream") # => eax +21721 3d/compare-eax-and 0/imm32/false +21722 74/jump-if-= break/disp8 +21723 (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21724 e9/jump $check-mu-primitive:end/disp32 +21725 } +21726 # if (op == "read-from-stream") check-mu-read-from-stream-stmt +21727 { +21728 (string-equal? %ecx "read-from-stream") # => eax +21729 3d/compare-eax-and 0/imm32/false +21730 74/jump-if-= break/disp8 +21731 (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21732 e9/jump $check-mu-primitive:end/disp32 +21733 } +21734 # if (op == "write-to-stream") check-mu-write-to-stream-stmt +21735 { +21736 (string-equal? %ecx "write-to-stream") # => eax +21737 3d/compare-eax-and 0/imm32/false +21738 74/jump-if-= break/disp8 +21739 (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21740 e9/jump $check-mu-primitive:end/disp32 +21741 } +21742 # if (op == "convert") check-mu-convert-stmt +21743 { +21744 (string-equal? %ecx "convert") # => eax +21745 3d/compare-eax-and 0/imm32/false +21746 74/jump-if-= break/disp8 +21747 (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21748 e9/jump $check-mu-primitive:end/disp32 +21749 } +21750 # otherwise check-numberlike-stmt +21751 (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21752 $check-mu-primitive:end: +21753 # . restore registers +21754 59/pop-to-ecx +21755 58/pop-to-eax +21756 # . epilogue +21757 89/<- %esp 5/r32/ebp +21758 5d/pop-to-ebp +21759 c3/return +21760 +21761 # by default, Mu primitives should only operate on 'number-like' types +21762 check-mu-numberlike-primitive: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21763 # . prologue +21764 55/push-ebp +21765 89/<- %ebp 4/r32/esp +21766 # . save registers +21767 50/push-eax +21768 51/push-ecx +21769 56/push-esi +21770 # esi = stmt +21771 8b/-> *(ebp+8) 6/r32/esi +21772 # var gas/ecx: int = 2 +21773 b9/copy-to-ecx 2/imm32 +21774 # - check at most 1 output +21775 # var output/eax: (addr stmt-var) = stmt->outputs +21776 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +21777 { +21778 3d/compare-eax-and 0/imm32 +21779 74/jump-if-= break/disp8 +21780 $check-mu-numberlike-primitive:output: +21781 (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21782 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +21783 3d/compare-eax-and 0/imm32 +21784 0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32 +21785 # check output is in a register +21786 # --gas +21787 49/decrement-ecx 21788 } -21789 $check-mu-numberlike-primitive:third-inout: -21790 # if there's a third arg, raise an error -21791 81 7/subop/compare *(eax+8) 0/imm32 # Stmt-var-next -21792 0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32 -21793 $check-mu-numberlike-primitive:end: -21794 # . restore registers -21795 5e/pop-to-esi -21796 59/pop-to-ecx -21797 58/pop-to-eax -21798 # . epilogue -21799 89/<- %esp 5/r32/ebp -21800 5d/pop-to-ebp -21801 c3/return -21802 -21803 $check-mu-numberlike-primitive:error-too-many-inouts: -21804 (write-buffered *(ebp+0x10) "fn ") -21805 8b/-> *(ebp+0xc) 0/r32/eax -21806 (lookup *eax *(eax+4)) # Function-name Function-name => eax -21807 (write-buffered *(ebp+0x10) %eax) -21808 (write-buffered *(ebp+0x10) ": stmt ") -21809 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax -21810 (write-buffered *(ebp+0x10) %eax) -21811 (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n") -21812 (flush *(ebp+0x10)) -21813 (stop *(ebp+0x14) 1) -21814 # never gets here -21815 -21816 $check-mu-numberlike-primitive:error-too-many-outputs: -21817 (write-buffered *(ebp+0x10) "fn ") -21818 8b/-> *(ebp+0xc) 0/r32/eax -21819 (lookup *eax *(eax+4)) # Function-name Function-name => eax -21820 (write-buffered *(ebp+0x10) %eax) -21821 (write-buffered *(ebp+0x10) ": stmt ") -21822 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax -21823 (write-buffered *(ebp+0x10) %eax) -21824 (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n") -21825 (flush *(ebp+0x10)) -21826 (stop *(ebp+0x14) 1) -21827 # never gets here -21828 -21829 check-mu-numberlike-arg: # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21830 # . prologue -21831 55/push-ebp -21832 89/<- %ebp 4/r32/esp -21833 # . save registers -21834 50/push-eax -21835 56/push-esi -21836 # var t/esi: (addr type-tree) = lookup(v->value->type) -21837 8b/-> *(ebp+8) 0/r32/eax -21838 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -21839 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -21840 89/<- %esi 0/r32/eax -21841 $check-mu-numberlike-arg:check-literal: -21842 # if t is an int, return -21843 (simple-mu-type? %esi 0) # literal => eax -21844 3d/compare-eax-and 0/imm32/false -21845 0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32 -21846 $check-mu-numberlike-arg:check-addr: -21847 # if t is an addr and v is dereferenced, return whether t->payload is an addr -21848 { -21849 (mu-addr-type? %esi) # => eax -21850 3d/compare-eax-and 0/imm32/false -21851 74/jump-if-= break/disp8 -21852 8b/-> *(ebp+8) 0/r32/eax -21853 8b/-> *(eax+0x10) 0/r32/eax # Stmt-var-is-deref -21854 3d/compare-eax-and 0/imm32/false -21855 { -21856 74/jump-if-= break/disp8 -21857 (lookup *(esi+0xc) *(esi+0x10)) # Type-tree-right Type-tree-right => eax -21858 # if t->right is null, t = t->left -21859 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -21860 { -21861 75/jump-if-!= break/disp8 -21862 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -21863 } -21864 (mu-addr-type? %eax) # => eax -21865 3d/compare-eax-and 0/imm32/false -21866 74/jump-if-= $check-mu-numberlike-arg:end/disp8 -21867 } -21868 } -21869 $check-mu-numberlike-arg:output-checks: -21870 (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) -21871 $check-mu-numberlike-arg:end: -21872 # . restore registers -21873 5e/pop-to-esi -21874 58/pop-to-eax -21875 # . epilogue -21876 89/<- %esp 5/r32/ebp -21877 5d/pop-to-ebp -21878 c3/return -21879 -21880 check-mu-numberlike-output: # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21881 # . prologue -21882 55/push-ebp -21883 89/<- %ebp 4/r32/esp -21884 # . save registers -21885 50/push-eax -21886 # -21887 (mu-numberlike-output-var? *(ebp+8)) # => eax -21888 3d/compare-eax-and 0/imm32/false -21889 0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32 -21890 $check-mu-numberlike-output:end: -21891 # . restore registers -21892 58/pop-to-eax -21893 # . epilogue -21894 89/<- %esp 5/r32/ebp -21895 5d/pop-to-ebp -21896 c3/return -21897 -21898 $check-mu-numberlike-output:fail: -21899 # otherwise raise an error -21900 (write-buffered *(ebp+0x14) "fn ") -21901 8b/-> *(ebp+0x10) 0/r32/eax -21902 (lookup *eax *(eax+4)) # Function-name Function-name => eax -21903 (write-buffered *(ebp+0x14) %eax) -21904 (write-buffered *(ebp+0x14) ": stmt ") -21905 8b/-> *(ebp+0xc) 0/r32/eax -21906 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -21907 (write-buffered *(ebp+0x14) %eax) -21908 (write-buffered *(ebp+0x14) ": '") -21909 8b/-> *(ebp+8) 0/r32/eax -21910 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -21911 (lookup *eax *(eax+4)) # Var-name Var-name => eax -21912 (write-buffered *(ebp+0x14) %eax) -21913 (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n") -21914 (flush *(ebp+0x14)) -21915 (stop *(ebp+0x18) 1) -21916 # never gets here -21917 -21918 mu-numberlike-output-var?: # v: (addr stmt-var) -> result/eax: boolean -21919 # . prologue -21920 55/push-ebp -21921 89/<- %ebp 4/r32/esp -21922 # -21923 8b/-> *(ebp+8) 0/r32/eax -21924 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -21925 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -21926 (mu-numberlike-output? %eax) # => eax -21927 $mu-numberlike-output-var?:end: -21928 # . epilogue -21929 89/<- %esp 5/r32/ebp -21930 5d/pop-to-ebp -21931 c3/return -21932 -21933 mu-numberlike-output?: # v: (addr type-tree) -> result/eax: boolean -21934 # . prologue -21935 55/push-ebp -21936 89/<- %ebp 4/r32/esp -21937 # . save registers -21938 56/push-esi -21939 # var t/esi: (addr type-tree) = lookup(v->value->type) -21940 8b/-> *(ebp+8) 6/r32/esi -21941 $mu-numberlike-output?:check-int: -21942 # if t is an int, return -21943 (simple-mu-type? %esi 1) # int => eax -21944 3d/compare-eax-and 0/imm32/false -21945 0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32 -21946 $mu-numberlike-output?:check-float: -21947 # if t is a float, return -21948 (simple-mu-type? %esi 0xf) # float => eax -21949 3d/compare-eax-and 0/imm32/false -21950 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 -21951 $mu-numberlike-output?:check-boolean: -21952 # if t is a boolean, return -21953 (simple-mu-type? %esi 5) # boolean => eax -21954 3d/compare-eax-and 0/imm32/false -21955 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 -21956 $mu-numberlike-output?:check-byte: -21957 # if t is a byte, return -21958 (simple-mu-type? %esi 8) # byte => eax -21959 3d/compare-eax-and 0/imm32/false -21960 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 -21961 $mu-numberlike-output?:check-code-point: -21962 # if t is a code-point, return -21963 (simple-mu-type? %esi 0xd) # code-point => eax -21964 3d/compare-eax-and 0/imm32/false -21965 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 -21966 $mu-numberlike-output?:check-grapheme: -21967 # if t is a grapheme, return -21968 (simple-mu-type? %esi 0xe) # grapheme => eax -21969 3d/compare-eax-and 0/imm32/false -21970 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 -21971 $mu-numberlike-output?:return-false: -21972 b8/copy-to-eax 0/imm32/false -21973 eb/jump $mu-numberlike-output?:end/disp8 -21974 $mu-numberlike-output?:return-true: -21975 b8/copy-to-eax 1/imm32/true -21976 $mu-numberlike-output?:end: -21977 # . restore registers -21978 5e/pop-to-esi -21979 # . epilogue -21980 89/<- %esp 5/r32/ebp -21981 5d/pop-to-ebp -21982 c3/return -21983 -21984 check-mu-copy-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -21985 # . prologue -21986 55/push-ebp -21987 89/<- %ebp 4/r32/esp -21988 # . save registers -21989 50/push-eax -21990 51/push-ecx -21991 52/push-edx -21992 56/push-esi -21993 57/push-edi -21994 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) -21995 81 5/subop/subtract %esp 0x60/imm32 -21996 68/push 0x60/imm32/size -21997 68/push 0/imm32/read -21998 68/push 0/imm32/write -21999 89/<- %edx 4/r32/esp -22000 $check-mu-copy-stmt:get-output: -22001 # esi = stmt -22002 8b/-> *(ebp+8) 6/r32/esi -22003 # var output/edi: (addr stmt-var) = stmt->outputs -22004 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -22005 89/<- %edi 0/r32/eax -22006 # zero outputs -22007 3d/compare-eax-and 0/imm32 -22008 0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32 -22009 # > 1 output -22010 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -22011 3d/compare-eax-and 0/imm32 -22012 0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32 -22013 $check-mu-copy-stmt:get-inout: -22014 # var inout/esi: (addr stmt-var) = stmt->inouts -22015 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -22016 89/<- %esi 0/r32/eax -22017 # zero inouts -22018 3d/compare-eax-and 0/imm32 -22019 0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32 -22020 # > 1 inout -22021 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -22022 3d/compare-eax-and 0/imm32 -22023 0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32 -22024 $check-mu-copy-stmt:types: -22025 # if inout is not a scalar, abort -22026 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22027 (size-of %eax) # => eax -22028 3d/compare-eax-and 4/imm32 -22029 0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32 -22030 # var inout-type/ecx: (addr type-tree) = inout->value->type -22031 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22032 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22033 89/<- %ecx 0/r32/eax -22034 # if (inout->is-deref?) inout-type = inout-type->payload -22035 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref -22036 3d/compare-eax-and 0/imm32/false -22037 { -22038 74/jump-if-= break/disp8 -22039 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -22040 # if inout-type->right is null, t = inout-type->left -22041 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -22042 { -22043 75/jump-if-!= break/disp8 -22044 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22045 } -22046 89/<- %ecx 0/r32/eax -22047 } -22048 # if output not in register, abort -22049 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22050 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22051 3d/compare-eax-and 0/imm32 -22052 0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32 -22053 # var output-type/eax: (addr type-tree) = output->value->type -22054 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22055 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22056 # if (inout-type == output-type) return -22057 (type-match? %eax %ecx %edx) # => eax -22058 3d/compare-eax-and 0/imm32 -22059 0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32 -22060 # if output is an addr and inout is 0, return -22061 { -22062 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22063 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22064 (mu-addr-type? %eax) # => eax -22065 3d/compare-eax-and 0/imm32/false -22066 74/jump-if-= break/disp8 -22067 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22068 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22069 (string-equal? %eax "0") # => eax -22070 3d/compare-eax-and 0/imm32/false -22071 74/jump-if-= break/disp8 -22072 e9/jump $check-mu-copy-stmt:end/disp32 -22073 } -22074 # if output is an offset and inout is 0, return -22075 { -22076 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22077 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22078 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -22079 75/jump-if-!= break/disp8 -22080 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22081 (simple-mu-type? %eax 7) # offset => eax -22082 3d/compare-eax-and 0/imm32/false -22083 74/jump-if-= break/disp8 -22084 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22085 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22086 (string-equal? %eax "0") # => eax +21789 # - check first inout +21790 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +21791 { +21792 3d/compare-eax-and 0/imm32 +21793 0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32 +21794 $check-mu-numberlike-primitive:first-inout: +21795 (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21796 # --gas +21797 49/decrement-ecx +21798 } +21799 # - check second inout +21800 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +21801 { +21802 3d/compare-eax-and 0/imm32 +21803 74/jump-if-= $check-mu-numberlike-primitive:end/disp8 +21804 $check-mu-numberlike-primitive:second-inout: +21805 # is a second inout allowed? +21806 81 7/subop/compare %ecx 0/imm32 +21807 0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32 +21808 $check-mu-numberlike-primitive:second-inout-permitted: +21809 (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +21810 } +21811 $check-mu-numberlike-primitive:third-inout: +21812 # if there's a third arg, raise an error +21813 81 7/subop/compare *(eax+8) 0/imm32 # Stmt-var-next +21814 0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32 +21815 $check-mu-numberlike-primitive:end: +21816 # . restore registers +21817 5e/pop-to-esi +21818 59/pop-to-ecx +21819 58/pop-to-eax +21820 # . epilogue +21821 89/<- %esp 5/r32/ebp +21822 5d/pop-to-ebp +21823 c3/return +21824 +21825 $check-mu-numberlike-primitive:error-too-many-inouts: +21826 (write-buffered *(ebp+0x10) "fn ") +21827 8b/-> *(ebp+0xc) 0/r32/eax +21828 (lookup *eax *(eax+4)) # Function-name Function-name => eax +21829 (write-buffered *(ebp+0x10) %eax) +21830 (write-buffered *(ebp+0x10) ": stmt ") +21831 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax +21832 (write-buffered *(ebp+0x10) %eax) +21833 (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n") +21834 (flush *(ebp+0x10)) +21835 (stop *(ebp+0x14) 1) +21836 # never gets here +21837 +21838 $check-mu-numberlike-primitive:error-too-many-outputs: +21839 (write-buffered *(ebp+0x10) "fn ") +21840 8b/-> *(ebp+0xc) 0/r32/eax +21841 (lookup *eax *(eax+4)) # Function-name Function-name => eax +21842 (write-buffered *(ebp+0x10) %eax) +21843 (write-buffered *(ebp+0x10) ": stmt ") +21844 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax +21845 (write-buffered *(ebp+0x10) %eax) +21846 (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n") +21847 (flush *(ebp+0x10)) +21848 (stop *(ebp+0x14) 1) +21849 # never gets here +21850 +21851 check-mu-numberlike-arg: # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21852 # . prologue +21853 55/push-ebp +21854 89/<- %ebp 4/r32/esp +21855 # . save registers +21856 50/push-eax +21857 56/push-esi +21858 # var t/esi: (addr type-tree) = lookup(v->value->type) +21859 8b/-> *(ebp+8) 0/r32/eax +21860 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +21861 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +21862 89/<- %esi 0/r32/eax +21863 $check-mu-numberlike-arg:check-literal: +21864 # if t is an int, return +21865 (simple-mu-type? %esi 0) # literal => eax +21866 3d/compare-eax-and 0/imm32/false +21867 0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32 +21868 $check-mu-numberlike-arg:check-addr: +21869 # if t is an addr and v is dereferenced, return whether t->payload is an addr +21870 { +21871 (mu-addr-type? %esi) # => eax +21872 3d/compare-eax-and 0/imm32/false +21873 74/jump-if-= break/disp8 +21874 8b/-> *(ebp+8) 0/r32/eax +21875 8b/-> *(eax+0x10) 0/r32/eax # Stmt-var-is-deref +21876 3d/compare-eax-and 0/imm32/false +21877 { +21878 74/jump-if-= break/disp8 +21879 (lookup *(esi+0xc) *(esi+0x10)) # Type-tree-right Type-tree-right => eax +21880 # if t->right is null, t = t->left +21881 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +21882 { +21883 75/jump-if-!= break/disp8 +21884 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +21885 } +21886 (mu-addr-type? %eax) # => eax +21887 3d/compare-eax-and 0/imm32/false +21888 74/jump-if-= $check-mu-numberlike-arg:end/disp8 +21889 } +21890 } +21891 $check-mu-numberlike-arg:output-checks: +21892 (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) +21893 $check-mu-numberlike-arg:end: +21894 # . restore registers +21895 5e/pop-to-esi +21896 58/pop-to-eax +21897 # . epilogue +21898 89/<- %esp 5/r32/ebp +21899 5d/pop-to-ebp +21900 c3/return +21901 +21902 check-mu-numberlike-output: # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +21903 # . prologue +21904 55/push-ebp +21905 89/<- %ebp 4/r32/esp +21906 # . save registers +21907 50/push-eax +21908 # +21909 (mu-numberlike-output-var? *(ebp+8)) # => eax +21910 3d/compare-eax-and 0/imm32/false +21911 0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32 +21912 $check-mu-numberlike-output:end: +21913 # . restore registers +21914 58/pop-to-eax +21915 # . epilogue +21916 89/<- %esp 5/r32/ebp +21917 5d/pop-to-ebp +21918 c3/return +21919 +21920 $check-mu-numberlike-output:fail: +21921 # otherwise raise an error +21922 (write-buffered *(ebp+0x14) "fn ") +21923 8b/-> *(ebp+0x10) 0/r32/eax +21924 (lookup *eax *(eax+4)) # Function-name Function-name => eax +21925 (write-buffered *(ebp+0x14) %eax) +21926 (write-buffered *(ebp+0x14) ": stmt ") +21927 8b/-> *(ebp+0xc) 0/r32/eax +21928 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +21929 (write-buffered *(ebp+0x14) %eax) +21930 (write-buffered *(ebp+0x14) ": '") +21931 8b/-> *(ebp+8) 0/r32/eax +21932 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +21933 (lookup *eax *(eax+4)) # Var-name Var-name => eax +21934 (write-buffered *(ebp+0x14) %eax) +21935 (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n") +21936 (flush *(ebp+0x14)) +21937 (stop *(ebp+0x18) 1) +21938 # never gets here +21939 +21940 mu-numberlike-output-var?: # v: (addr stmt-var) -> result/eax: boolean +21941 # . prologue +21942 55/push-ebp +21943 89/<- %ebp 4/r32/esp +21944 # +21945 8b/-> *(ebp+8) 0/r32/eax +21946 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +21947 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +21948 (mu-numberlike-output? %eax) # => eax +21949 $mu-numberlike-output-var?:end: +21950 # . epilogue +21951 89/<- %esp 5/r32/ebp +21952 5d/pop-to-ebp +21953 c3/return +21954 +21955 mu-numberlike-output?: # v: (addr type-tree) -> result/eax: boolean +21956 # . prologue +21957 55/push-ebp +21958 89/<- %ebp 4/r32/esp +21959 # . save registers +21960 56/push-esi +21961 # var t/esi: (addr type-tree) = lookup(v->value->type) +21962 8b/-> *(ebp+8) 6/r32/esi +21963 $mu-numberlike-output?:check-int: +21964 # if t is an int, return +21965 (simple-mu-type? %esi 1) # int => eax +21966 3d/compare-eax-and 0/imm32/false +21967 0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32 +21968 $mu-numberlike-output?:check-float: +21969 # if t is a float, return +21970 (simple-mu-type? %esi 0xf) # float => eax +21971 3d/compare-eax-and 0/imm32/false +21972 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 +21973 $mu-numberlike-output?:check-boolean: +21974 # if t is a boolean, return +21975 (simple-mu-type? %esi 5) # boolean => eax +21976 3d/compare-eax-and 0/imm32/false +21977 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 +21978 $mu-numberlike-output?:check-byte: +21979 # if t is a byte, return +21980 (simple-mu-type? %esi 8) # byte => eax +21981 3d/compare-eax-and 0/imm32/false +21982 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 +21983 $mu-numberlike-output?:check-code-point: +21984 # if t is a code-point, return +21985 (simple-mu-type? %esi 0xd) # code-point => eax +21986 3d/compare-eax-and 0/imm32/false +21987 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 +21988 $mu-numberlike-output?:check-grapheme: +21989 # if t is a grapheme, return +21990 (simple-mu-type? %esi 0xe) # grapheme => eax +21991 3d/compare-eax-and 0/imm32/false +21992 75/jump-if-!= $mu-numberlike-output?:return-true/disp8 +21993 $mu-numberlike-output?:return-false: +21994 b8/copy-to-eax 0/imm32/false +21995 eb/jump $mu-numberlike-output?:end/disp8 +21996 $mu-numberlike-output?:return-true: +21997 b8/copy-to-eax 1/imm32/true +21998 $mu-numberlike-output?:end: +21999 # . restore registers +22000 5e/pop-to-esi +22001 # . epilogue +22002 89/<- %esp 5/r32/ebp +22003 5d/pop-to-ebp +22004 c3/return +22005 +22006 check-mu-copy-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +22007 # . prologue +22008 55/push-ebp +22009 89/<- %ebp 4/r32/esp +22010 # . save registers +22011 50/push-eax +22012 51/push-ecx +22013 52/push-edx +22014 56/push-esi +22015 57/push-edi +22016 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) +22017 81 5/subop/subtract %esp 0x60/imm32 +22018 68/push 0x60/imm32/size +22019 68/push 0/imm32/read +22020 68/push 0/imm32/write +22021 89/<- %edx 4/r32/esp +22022 $check-mu-copy-stmt:get-output: +22023 # esi = stmt +22024 8b/-> *(ebp+8) 6/r32/esi +22025 # var output/edi: (addr stmt-var) = stmt->outputs +22026 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +22027 89/<- %edi 0/r32/eax +22028 # zero outputs +22029 3d/compare-eax-and 0/imm32 +22030 0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32 +22031 # > 1 output +22032 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +22033 3d/compare-eax-and 0/imm32 +22034 0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32 +22035 $check-mu-copy-stmt:get-inout: +22036 # var inout/esi: (addr stmt-var) = stmt->inouts +22037 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +22038 89/<- %esi 0/r32/eax +22039 # zero inouts +22040 3d/compare-eax-and 0/imm32 +22041 0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32 +22042 # > 1 inout +22043 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +22044 3d/compare-eax-and 0/imm32 +22045 0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32 +22046 $check-mu-copy-stmt:types: +22047 # if inout is not a scalar, abort +22048 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22049 (size-of %eax) # => eax +22050 3d/compare-eax-and 4/imm32 +22051 0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32 +22052 # var inout-type/ecx: (addr type-tree) = inout->value->type +22053 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22054 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22055 89/<- %ecx 0/r32/eax +22056 # if (inout->is-deref?) inout-type = inout-type->payload +22057 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref +22058 3d/compare-eax-and 0/imm32/false +22059 { +22060 74/jump-if-= break/disp8 +22061 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +22062 # if inout-type->right is null, t = inout-type->left +22063 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +22064 { +22065 75/jump-if-!= break/disp8 +22066 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22067 } +22068 89/<- %ecx 0/r32/eax +22069 } +22070 # if output not in register, abort +22071 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22072 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +22073 3d/compare-eax-and 0/imm32 +22074 0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32 +22075 # var output-type/eax: (addr type-tree) = output->value->type +22076 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22077 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22078 # if (inout-type == output-type) return +22079 (type-match? %eax %ecx %edx) # => eax +22080 3d/compare-eax-and 0/imm32 +22081 0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32 +22082 # if output is an addr and inout is 0, return +22083 { +22084 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22085 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22086 (mu-addr-type? %eax) # => eax 22087 3d/compare-eax-and 0/imm32/false 22088 74/jump-if-= break/disp8 -22089 e9/jump $check-mu-copy-stmt:end/disp32 -22090 } -22091 # if output is a byte, abort if inout is not a literal. Otherwise return. -22092 { -22093 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22094 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22095 (simple-mu-type? %eax 8) # byte => eax -22096 3d/compare-eax-and 0/imm32/false -22097 74/jump-if-= break/disp8 -22098 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22089 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22090 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22091 (string-equal? %eax "0") # => eax +22092 3d/compare-eax-and 0/imm32/false +22093 74/jump-if-= break/disp8 +22094 e9/jump $check-mu-copy-stmt:end/disp32 +22095 } +22096 # if output is an offset and inout is 0, return +22097 { +22098 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax 22099 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22100 (simple-mu-type? %eax 0) # literal => eax -22101 3d/compare-eax-and 0/imm32/false -22102 0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32 -22103 eb/jump $check-mu-copy-stmt:end/disp8 -22104 } -22105 # if output is not number-like, abort -22106 (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -22107 $check-mu-copy-stmt:end: -22108 # . reclaim locals -22109 81 0/subop/add %esp 0x6c/imm32 -22110 # . restore registers -22111 5f/pop-to-edi -22112 5e/pop-to-esi -22113 5a/pop-to-edx -22114 59/pop-to-ecx -22115 58/pop-to-eax -22116 # . epilogue -22117 89/<- %esp 5/r32/ebp -22118 5d/pop-to-ebp -22119 c3/return -22120 -22121 $check-mu-copy-stmt:error-no-inout: -22122 (write-buffered *(ebp+0x10) "fn ") -22123 8b/-> *(ebp+0xc) 0/r32/eax -22124 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22125 (write-buffered *(ebp+0x10) %eax) -22126 (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n") -22127 (flush *(ebp+0x10)) -22128 (stop *(ebp+0x14) 1) -22129 # never gets here -22130 -22131 $check-mu-copy-stmt:error-too-many-inouts: -22132 (write-buffered *(ebp+0x10) "fn ") -22133 8b/-> *(ebp+0xc) 0/r32/eax -22134 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22135 (write-buffered *(ebp+0x10) %eax) -22136 (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n") -22137 (flush *(ebp+0x10)) -22138 (stop *(ebp+0x14) 1) -22139 # never gets here -22140 -22141 $check-mu-copy-stmt:error-no-output: -22142 (write-buffered *(ebp+0x10) "fn ") -22143 8b/-> *(ebp+0xc) 0/r32/eax -22144 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22145 (write-buffered *(ebp+0x10) %eax) -22146 (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n") -22147 (flush *(ebp+0x10)) -22148 (stop *(ebp+0x14) 1) -22149 # never gets here -22150 -22151 $check-mu-copy-stmt:error-output-not-in-register: -22152 (write-buffered *(ebp+0x10) "fn ") -22153 8b/-> *(ebp+0xc) 0/r32/eax -22154 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22155 (write-buffered *(ebp+0x10) %eax) -22156 (write-buffered *(ebp+0x10) ": stmt copy: output '") -22157 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22158 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22159 (write-buffered *(ebp+0x10) %eax) -22160 (write-buffered *(ebp+0x10) "' not in a register\n") -22161 (flush *(ebp+0x10)) -22162 (stop *(ebp+0x14) 1) -22163 # never gets here -22164 -22165 $check-mu-copy-stmt:error-too-many-outputs: -22166 (write-buffered *(ebp+0x10) "fn ") -22167 8b/-> *(ebp+0xc) 0/r32/eax -22168 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22169 (write-buffered *(ebp+0x10) %eax) -22170 (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n") -22171 (flush *(ebp+0x10)) -22172 (stop *(ebp+0x14) 1) -22173 # never gets here -22174 -22175 $check-mu-copy-stmt:error-inout-too-large: -22176 (write-buffered *(ebp+0x10) "fn ") -22177 8b/-> *(ebp+0xc) 0/r32/eax -22178 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22179 (write-buffered *(ebp+0x10) %eax) -22180 (write-buffered *(ebp+0x10) ": stmt copy: '") -22181 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22182 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22183 (write-buffered *(ebp+0x10) %eax) -22184 (write-buffered *(ebp+0x10) "' is too large to fit in a register\n") -22185 (flush *(ebp+0x10)) -22186 (stop *(ebp+0x14) 1) -22187 # never gets here -22188 -22189 $check-mu-copy-stmt:error-non-literal-to-byte: -22190 (write-buffered *(ebp+0x10) "fn ") -22191 8b/-> *(ebp+0xc) 0/r32/eax -22192 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22193 (write-buffered *(ebp+0x10) %eax) -22194 (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '") -22195 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22196 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22197 (write-buffered *(ebp+0x10) %eax) -22198 (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n") -22199 (flush *(ebp+0x10)) -22200 (stop *(ebp+0x14) 1) -22201 # never gets here -22202 -22203 check-mu-copy-to-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -22204 # . prologue -22205 55/push-ebp -22206 89/<- %ebp 4/r32/esp -22207 # . save registers -22208 50/push-eax -22209 51/push-ecx -22210 52/push-edx -22211 53/push-ebx -22212 56/push-esi -22213 57/push-edi -22214 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) -22215 81 5/subop/subtract %esp 0x60/imm32 -22216 68/push 0x60/imm32/size -22217 68/push 0/imm32/read -22218 68/push 0/imm32/write -22219 89/<- %edx 4/r32/esp -22220 # esi = stmt -22221 8b/-> *(ebp+8) 6/r32/esi -22222 $check-mu-copy-to-stmt:check-for-output: -22223 # if stmt->outputs abort -22224 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -22225 3d/compare-eax-and 0/imm32 -22226 0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32 -22227 $check-mu-copy-to-stmt:get-dest: -22228 # var dest/edi: (addr stmt-var) = stmt->inouts -22229 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -22230 89/<- %edi 0/r32/eax -22231 # zero inouts -22232 3d/compare-eax-and 0/imm32 -22233 0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32 -22234 $check-mu-copy-to-stmt:get-src: -22235 # var src/esi: (addr stmt-var) = dest->next -22236 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -22237 89/<- %esi 0/r32/eax -22238 # 1 inout -22239 3d/compare-eax-and 0/imm32 -22240 0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32 -22241 # > 2 inouts -22242 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -22243 3d/compare-eax-and 0/imm32 -22244 0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32 -22245 $check-mu-copy-to-stmt:types: -22246 # if src is not a scalar, abort -22247 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22248 (size-of %eax) # => eax -22249 3d/compare-eax-and 4/imm32 -22250 0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32 -22251 # var src-type/ecx: (addr type-tree) = src->value->type -22252 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22253 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22254 89/<- %ecx 0/r32/eax -22255 # if src not in register or literal, abort -22256 # (we can't use stack-offset because it hasn't been computed yet) -22257 { -22258 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22259 (lookup *(eax+0x8) *(eax+0xc)) # Var-type Var-type => eax -22260 (simple-mu-type? %eax 0) # => eax -22261 3d/compare-eax-and 0/imm32 -22262 75/jump-if-!= break/disp8 -22263 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22264 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22265 3d/compare-eax-and 0/imm32 -22266 75/jump-if-!= break/disp8 -22267 e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32 -22268 } -22269 # var dest-type/ebx: (addr type-tree) = dest->value->type -22270 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22271 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22272 89/<- %ebx 0/r32/eax -22273 # if (dest->is-deref?) dest-type = dest-type->payload -22274 $check-mu-copy-to-stmt:check-dest-deref: -22275 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -22276 3d/compare-eax-and 0/imm32/false -22277 { -22278 74/jump-if-= break/disp8 -22279 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -22280 $check-mu-copy-to-stmt:dest-is-deref: -22281 # if dest-type->right is null, dest-type = dest-type->left -22282 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -22283 { -22284 75/jump-if-!= break/disp8 -22285 $check-mu-copy-to-stmt:dest-is-deref2: -22286 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22287 } -22288 89/<- %ebx 0/r32/eax -22289 } -22290 # if dest is a byte and src is not a literal, abort -22291 { -22292 $check-mu-copy-to-stmt:final-check-byte: -22293 (simple-mu-type? %ebx 8) # byte => eax -22294 3d/compare-eax-and 0/imm32/false -22295 74/jump-if-= break/disp8 -22296 (simple-mu-type? %ecx 0) # literal => eax -22297 3d/compare-eax-and 0/imm32/false -22298 0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32 -22299 } -22300 # if (src-type == dest-type) return -22301 (type-match? %ebx %ecx %edx) # => eax -22302 3d/compare-eax-and 0/imm32 -22303 0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32 -22304 # if dest is an addr and src is 0, return -22305 { -22306 $check-mu-copy-to-stmt:final-check-addr: -22307 (mu-addr-type? %ebx) # => eax -22308 3d/compare-eax-and 0/imm32/false -22309 74/jump-if-= break/disp8 -22310 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22311 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22312 (string-equal? %eax "0") # => eax -22313 3d/compare-eax-and 0/imm32/false -22314 74/jump-if-= break/disp8 -22315 e9/jump $check-mu-copy-to-stmt:end/disp32 -22316 } -22317 # if dest is an offset and src is 0, return -22318 { -22319 $check-mu-copy-to-stmt:final-check-offset: -22320 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -22321 75/jump-if-!= break/disp8 -22322 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -22323 (simple-mu-type? %eax 7) # offset => eax -22324 3d/compare-eax-and 0/imm32/false -22325 74/jump-if-= break/disp8 -22326 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22327 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22328 (string-equal? %eax "0") # => eax -22329 3d/compare-eax-and 0/imm32/false -22330 74/jump-if-= break/disp8 -22331 e9/jump $check-mu-copy-to-stmt:end/disp32 -22332 } -22333 # if dest is not number-like, abort -22334 (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -22335 $check-mu-copy-to-stmt:end: -22336 # . reclaim locals -22337 81 0/subop/add %esp 0x6c/imm32 -22338 # . restore registers -22339 5f/pop-to-edi -22340 5e/pop-to-esi -22341 5b/pop-to-ebx -22342 5a/pop-to-edx -22343 59/pop-to-ecx -22344 58/pop-to-eax -22345 # . epilogue -22346 89/<- %esp 5/r32/ebp -22347 5d/pop-to-ebp -22348 c3/return -22349 -22350 $check-mu-copy-to-stmt:error-incorrect-inouts: -22351 (write-buffered *(ebp+0x10) "fn ") -22352 8b/-> *(ebp+0xc) 0/r32/eax -22353 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22354 (write-buffered *(ebp+0x10) %eax) -22355 (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n") -22356 (flush *(ebp+0x10)) -22357 (stop *(ebp+0x14) 1) -22358 # never gets here -22359 -22360 $check-mu-copy-to-stmt:error-too-many-outputs: -22361 (write-buffered *(ebp+0x10) "fn ") -22362 8b/-> *(ebp+0xc) 0/r32/eax -22363 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22364 (write-buffered *(ebp+0x10) %eax) -22365 (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n") -22366 (flush *(ebp+0x10)) -22367 (stop *(ebp+0x14) 1) -22368 # never gets here -22369 -22370 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register: -22371 (write-buffered *(ebp+0x10) "fn ") -22372 8b/-> *(ebp+0xc) 0/r32/eax -22373 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22374 (write-buffered *(ebp+0x10) %eax) -22375 (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n") -22376 (flush *(ebp+0x10)) -22377 (stop *(ebp+0x14) 1) -22378 # never gets here -22379 -22380 $check-mu-copy-to-stmt:error-src-too-large: -22381 (write-buffered *(ebp+0x10) "fn ") -22382 8b/-> *(ebp+0xc) 0/r32/eax -22383 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22384 (write-buffered *(ebp+0x10) %eax) -22385 (write-buffered *(ebp+0x10) ": stmt copy-to: '") -22386 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22387 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22388 (write-buffered *(ebp+0x10) %eax) -22389 (write-buffered *(ebp+0x10) "' is too large to copy\n") -22390 (flush *(ebp+0x10)) -22391 (stop *(ebp+0x14) 1) -22392 # never gets here -22393 -22394 $check-mu-copy-to-stmt:error-non-literal-to-byte: -22395 (write-buffered *(ebp+0x10) "fn ") -22396 8b/-> *(ebp+0xc) 0/r32/eax -22397 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22398 (write-buffered *(ebp+0x10) %eax) -22399 (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n") -22400 (flush *(ebp+0x10)) -22401 (stop *(ebp+0x14) 1) -22402 # never gets here -22403 -22404 check-mu-copy-byte-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -22405 # . prologue -22406 55/push-ebp -22407 89/<- %ebp 4/r32/esp -22408 # . save registers -22409 50/push-eax -22410 51/push-ecx -22411 52/push-edx -22412 56/push-esi -22413 57/push-edi -22414 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) -22415 81 5/subop/subtract %esp 0x60/imm32 -22416 68/push 0x60/imm32/size -22417 68/push 0/imm32/read -22418 68/push 0/imm32/write -22419 89/<- %edx 4/r32/esp -22420 $check-mu-copy-byte-stmt:get-output: -22421 # esi = stmt -22422 8b/-> *(ebp+8) 6/r32/esi -22423 # var output/edi: (addr stmt-var) = stmt->outputs -22424 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -22425 89/<- %edi 0/r32/eax -22426 # zero outputs -22427 3d/compare-eax-and 0/imm32 -22428 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32 -22429 # > 1 output -22430 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -22431 3d/compare-eax-and 0/imm32 -22432 0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32 -22433 $check-mu-copy-byte-stmt:get-inout: -22434 # var inout/esi: (addr stmt-var) = stmt->inouts -22435 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -22436 89/<- %esi 0/r32/eax -22437 # zero inouts -22438 3d/compare-eax-and 0/imm32 -22439 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32 -22440 # > 1 inout -22441 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -22442 3d/compare-eax-and 0/imm32 -22443 0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32 -22444 $check-mu-copy-byte-stmt:types: -22445 # if inout is not a scalar, abort -22446 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22447 (size-of %eax) # => eax -22448 3d/compare-eax-and 4/imm32 -22449 0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32 -22450 # var inout-type/ecx: (addr type-tree) = inout->value->type -22451 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22452 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22453 89/<- %ecx 0/r32/eax -22454 $check-mu-copy-byte-stmt:check-inout-deref: -22455 # if (inout->is-deref?) inout-type = inout-type->payload -22456 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref -22457 3d/compare-eax-and 0/imm32/false -22458 { -22459 74/jump-if-= break/disp8 -22460 $check-mu-copy-byte-stmt:inout-is-deref: -22461 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -22462 # if inout-type->right is null, t = inout-type->left -22463 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -22464 { -22465 75/jump-if-!= break/disp8 -22466 $check-mu-copy-byte-stmt:inout-is-deref2: -22467 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22468 } -22469 89/<- %ecx 0/r32/eax -22470 } -22471 # if output not in register, abort -22472 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22473 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22474 3d/compare-eax-and 0/imm32 -22475 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32 -22476 # var output-type/eax: (addr type-tree) = output->value->type -22477 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22478 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22479 # if output is not of type byte, abort -22480 (simple-mu-type? %eax 8) # byte => eax -22481 3d/compare-eax-and 0/imm32 -22482 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32 -22483 $check-mu-copy-byte-stmt:end: -22484 # . reclaim locals -22485 81 0/subop/add %esp 0x6c/imm32 -22486 # . restore registers -22487 5f/pop-to-edi -22488 5e/pop-to-esi -22489 5a/pop-to-edx -22490 59/pop-to-ecx -22491 58/pop-to-eax -22492 # . epilogue -22493 89/<- %esp 5/r32/ebp -22494 5d/pop-to-ebp -22495 c3/return -22496 -22497 $check-mu-copy-byte-stmt:error-no-inout: -22498 (write-buffered *(ebp+0x10) "fn ") -22499 8b/-> *(ebp+0xc) 0/r32/eax -22500 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22501 (write-buffered *(ebp+0x10) %eax) -22502 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n") -22503 (flush *(ebp+0x10)) -22504 (stop *(ebp+0x14) 1) -22505 # never gets here -22506 -22507 $check-mu-copy-byte-stmt:error-too-many-inouts: -22508 (write-buffered *(ebp+0x10) "fn ") -22509 8b/-> *(ebp+0xc) 0/r32/eax -22510 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22511 (write-buffered *(ebp+0x10) %eax) -22512 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n") -22513 (flush *(ebp+0x10)) -22514 (stop *(ebp+0x14) 1) -22515 # never gets here -22516 -22517 $check-mu-copy-byte-stmt:error-no-output: -22518 (write-buffered *(ebp+0x10) "fn ") -22519 8b/-> *(ebp+0xc) 0/r32/eax -22520 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22521 (write-buffered *(ebp+0x10) %eax) -22522 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n") -22523 (flush *(ebp+0x10)) -22524 (stop *(ebp+0x14) 1) -22525 # never gets here -22526 -22527 $check-mu-copy-byte-stmt:error-output-not-in-register: -22528 (write-buffered *(ebp+0x10) "fn ") -22529 8b/-> *(ebp+0xc) 0/r32/eax -22530 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22531 (write-buffered *(ebp+0x10) %eax) -22532 (write-buffered *(ebp+0x10) ": stmt copy-byte: output '") -22533 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22534 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22535 (write-buffered *(ebp+0x10) %eax) -22536 (write-buffered *(ebp+0x10) "' not in a register\n") -22537 (flush *(ebp+0x10)) -22538 (stop *(ebp+0x14) 1) -22539 # never gets here -22540 -22541 $check-mu-copy-byte-stmt:error-too-many-outputs: -22542 (write-buffered *(ebp+0x10) "fn ") -22543 8b/-> *(ebp+0xc) 0/r32/eax -22544 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22545 (write-buffered *(ebp+0x10) %eax) -22546 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n") -22547 (flush *(ebp+0x10)) -22548 (stop *(ebp+0x14) 1) -22549 # never gets here -22550 -22551 $check-mu-copy-byte-stmt:error-invalid-output-type: -22552 (write-buffered *(ebp+0x10) "fn ") -22553 8b/-> *(ebp+0xc) 0/r32/eax -22554 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22555 (write-buffered *(ebp+0x10) %eax) -22556 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n") -22557 (flush *(ebp+0x10)) -22558 (stop *(ebp+0x14) 1) -22559 # never gets here -22560 -22561 $check-mu-copy-byte-stmt:error-inout-too-large: -22562 (write-buffered *(ebp+0x10) "fn ") -22563 8b/-> *(ebp+0xc) 0/r32/eax -22564 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22565 (write-buffered *(ebp+0x10) %eax) -22566 (write-buffered *(ebp+0x10) ": stmt copy-byte: '") -22567 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22568 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22569 (write-buffered *(ebp+0x10) %eax) -22570 (write-buffered *(ebp+0x10) "' is too large to fit in a register\n") -22571 (flush *(ebp+0x10)) -22572 (stop *(ebp+0x14) 1) -22573 # never gets here -22574 -22575 check-mu-copy-byte-to-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -22576 # . prologue -22577 55/push-ebp -22578 89/<- %ebp 4/r32/esp -22579 # . save registers -22580 50/push-eax -22581 52/push-edx -22582 53/push-ebx -22583 56/push-esi -22584 57/push-edi -22585 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) -22586 81 5/subop/subtract %esp 0x60/imm32 -22587 68/push 0x60/imm32/size -22588 68/push 0/imm32/read -22589 68/push 0/imm32/write -22590 89/<- %edx 4/r32/esp -22591 # esi = stmt -22592 8b/-> *(ebp+8) 6/r32/esi -22593 $check-mu-copy-byte-to-stmt:check-for-output: -22594 # if stmt->outputs abort -22595 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -22596 3d/compare-eax-and 0/imm32 -22597 0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32 -22598 $check-mu-copy-byte-to-stmt:get-dest: -22599 # var dest/edi: (addr stmt-var) = stmt->inouts -22600 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -22601 89/<- %edi 0/r32/eax -22602 # zero inouts -22603 3d/compare-eax-and 0/imm32 -22604 0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32 -22605 $check-mu-copy-byte-to-stmt:get-src: -22606 # var src/esi: (addr stmt-var) = dest->next -22607 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -22608 89/<- %esi 0/r32/eax -22609 # 1 inout -22610 3d/compare-eax-and 0/imm32 -22611 0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32 -22612 # > 2 inouts -22613 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -22614 3d/compare-eax-and 0/imm32 -22615 0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32 -22616 $check-mu-copy-byte-to-stmt:types: -22617 # if src is not a scalar, abort -22618 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22619 (size-of %eax) # => eax -22620 3d/compare-eax-and 4/imm32 -22621 0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32 -22622 # if src not in register, abort -22623 { -22624 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22625 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22626 3d/compare-eax-and 0/imm32 -22627 75/jump-if-!= break/disp8 -22628 e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32 -22629 } -22630 # var dest-type/ebx: (addr type-tree) = dest->value->type -22631 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22632 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22633 89/<- %ebx 0/r32/eax -22634 # if (dest->is-deref?) dest-type = dest-type->payload -22635 $check-mu-copy-byte-to-stmt:check-dest-deref: -22636 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -22637 3d/compare-eax-and 0/imm32/false -22638 { -22639 74/jump-if-= break/disp8 -22640 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -22641 $check-mu-copy-byte-to-stmt:dest-is-deref: -22642 # if dest-type->right is null, dest-type = dest-type->left -22643 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -22644 { -22645 75/jump-if-!= break/disp8 -22646 $check-mu-copy-byte-to-stmt:dest-is-deref2: -22647 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22648 } -22649 89/<- %ebx 0/r32/eax -22650 } -22651 # if dest is not a byte, abort -22652 (simple-mu-type? %ebx 8) # byte => eax -22653 3d/compare-eax-and 0/imm32/false -22654 0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32 -22655 $check-mu-copy-byte-to-stmt:end: -22656 # . reclaim locals -22657 81 0/subop/add %esp 0x6c/imm32 -22658 # . restore registers -22659 5f/pop-to-edi -22660 5e/pop-to-esi -22661 5b/pop-to-ebx -22662 5a/pop-to-edx -22663 58/pop-to-eax -22664 # . epilogue -22665 89/<- %esp 5/r32/ebp -22666 5d/pop-to-ebp -22667 c3/return -22668 -22669 $check-mu-copy-byte-to-stmt:error-incorrect-inouts: -22670 (write-buffered *(ebp+0x10) "fn ") -22671 8b/-> *(ebp+0xc) 0/r32/eax -22672 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22673 (write-buffered *(ebp+0x10) %eax) -22674 (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n") -22675 (flush *(ebp+0x10)) -22676 (stop *(ebp+0x14) 1) -22677 # never gets here -22678 -22679 $check-mu-copy-byte-to-stmt:error-too-many-outputs: -22680 (write-buffered *(ebp+0x10) "fn ") -22681 8b/-> *(ebp+0xc) 0/r32/eax -22682 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22683 (write-buffered *(ebp+0x10) %eax) -22684 (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n") -22685 (flush *(ebp+0x10)) -22686 (stop *(ebp+0x14) 1) -22687 # never gets here -22688 -22689 $check-mu-copy-byte-to-stmt:error-src-not-in-register: -22690 (write-buffered *(ebp+0x10) "fn ") -22691 8b/-> *(ebp+0xc) 0/r32/eax -22692 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22693 (write-buffered *(ebp+0x10) %eax) -22694 (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n") -22695 (flush *(ebp+0x10)) -22696 (stop *(ebp+0x14) 1) -22697 # never gets here -22698 -22699 $check-mu-copy-byte-to-stmt:error-invalid-dest-type: -22700 (write-buffered *(ebp+0x10) "fn ") -22701 8b/-> *(ebp+0xc) 0/r32/eax -22702 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22703 (write-buffered *(ebp+0x10) %eax) -22704 (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '") -22705 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22706 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22707 (write-buffered *(ebp+0x10) %eax) -22708 (write-buffered *(ebp+0x10) "' must be a byte\n") -22709 (flush *(ebp+0x10)) -22710 (stop *(ebp+0x14) 1) -22711 # never gets here -22712 -22713 $check-mu-copy-byte-to-stmt:error-src-too-large: -22714 (write-buffered *(ebp+0x10) "fn ") -22715 8b/-> *(ebp+0xc) 0/r32/eax -22716 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22717 (write-buffered *(ebp+0x10) %eax) -22718 (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '") -22719 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22720 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22721 (write-buffered *(ebp+0x10) %eax) -22722 (write-buffered *(ebp+0x10) "' is too large to copy\n") -22723 (flush *(ebp+0x10)) -22724 (stop *(ebp+0x14) 1) -22725 # never gets here -22726 -22727 check-mu-compare-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -22728 # . prologue -22729 55/push-ebp -22730 89/<- %ebp 4/r32/esp -22731 # . save registers -22732 50/push-eax -22733 51/push-ecx -22734 52/push-edx -22735 53/push-ebx -22736 56/push-esi -22737 57/push-edi -22738 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) -22739 81 5/subop/subtract %esp 0x60/imm32 -22740 68/push 0x60/imm32/size -22741 68/push 0/imm32/read -22742 68/push 0/imm32/write -22743 89/<- %edx 4/r32/esp -22744 # esi = stmt -22745 8b/-> *(ebp+8) 6/r32/esi -22746 $check-mu-compare-stmt:check-for-output: -22747 # if stmt->outputs abort -22748 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -22749 3d/compare-eax-and 0/imm32 -22750 0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32 -22751 $check-mu-compare-stmt:get-left: -22752 # var left/edi: (addr stmt-var) = stmt->inouts -22753 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -22754 89/<- %edi 0/r32/eax -22755 # zero inouts -22756 3d/compare-eax-and 0/imm32 -22757 0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32 -22758 $check-mu-compare-stmt:get-right: -22759 # var right/esi: (addr stmt-var) = left->next -22760 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -22761 89/<- %esi 0/r32/eax -22762 # 1 inout -22763 3d/compare-eax-and 0/imm32 -22764 0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32 -22765 # > 2 inouts -22766 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -22767 3d/compare-eax-and 0/imm32 -22768 0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32 -22769 # if both inouts are in memory, abort -22770 { -22771 $check-mu-compare-stmt:both-in-mem: -22772 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22773 (lookup *(eax+0x8) *(eax+0xc)) # Var-type Var-type => eax -22774 (simple-mu-type? %eax 0) # => eax -22775 3d/compare-eax-and 0/imm32 -22776 0f 85/jump-if-!= break/disp32 -22777 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22778 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22779 3d/compare-eax-and 0/imm32 -22780 75/jump-if-!= break/disp8 -22781 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22782 (lookup *(eax+0x8) *(eax+0xc)) # Var-type Var-type => eax -22783 (simple-mu-type? %eax 0) # => eax -22784 3d/compare-eax-and 0/imm32 -22785 75/jump-if-!= break/disp8 -22786 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22787 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22788 3d/compare-eax-and 0/imm32 -22789 75/jump-if-!= break/disp8 -22790 e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32 -22791 } -22792 $check-mu-compare-stmt:types: -22793 # var right-type/ecx: (addr type-tree) = right->value->type -22794 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22795 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22796 89/<- %ecx 0/r32/eax -22797 # if (right->is-deref?) right-type = right-type->payload -22798 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref -22799 3d/compare-eax-and 0/imm32/false -22800 { -22801 74/jump-if-= break/disp8 -22802 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -22803 # if right-type->right is null, right-type = right-type->left -22804 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -22805 { -22806 75/jump-if-!= break/disp8 -22807 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22808 } -22809 89/<- %ecx 0/r32/eax -22810 } -22811 # if right-type is a literal string, abort -22812 (simple-mu-type? %ecx 0x10) # string-literal => eax -22813 3d/compare-eax-and 0/imm32/false -22814 0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32 -22815 # if right is not a scalar, abort +22100 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +22101 75/jump-if-!= break/disp8 +22102 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22103 (simple-mu-type? %eax 7) # offset => eax +22104 3d/compare-eax-and 0/imm32/false +22105 74/jump-if-= break/disp8 +22106 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22107 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22108 (string-equal? %eax "0") # => eax +22109 3d/compare-eax-and 0/imm32/false +22110 74/jump-if-= break/disp8 +22111 e9/jump $check-mu-copy-stmt:end/disp32 +22112 } +22113 # if output is a byte, abort if inout is not a literal. Otherwise return. +22114 { +22115 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22116 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22117 (simple-mu-type? %eax 8) # byte => eax +22118 3d/compare-eax-and 0/imm32/false +22119 74/jump-if-= break/disp8 +22120 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22121 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22122 (simple-mu-type? %eax 0) # literal => eax +22123 3d/compare-eax-and 0/imm32/false +22124 0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32 +22125 eb/jump $check-mu-copy-stmt:end/disp8 +22126 } +22127 # if output is not number-like, abort +22128 (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +22129 $check-mu-copy-stmt:end: +22130 # . reclaim locals +22131 81 0/subop/add %esp 0x6c/imm32 +22132 # . restore registers +22133 5f/pop-to-edi +22134 5e/pop-to-esi +22135 5a/pop-to-edx +22136 59/pop-to-ecx +22137 58/pop-to-eax +22138 # . epilogue +22139 89/<- %esp 5/r32/ebp +22140 5d/pop-to-ebp +22141 c3/return +22142 +22143 $check-mu-copy-stmt:error-no-inout: +22144 (write-buffered *(ebp+0x10) "fn ") +22145 8b/-> *(ebp+0xc) 0/r32/eax +22146 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22147 (write-buffered *(ebp+0x10) %eax) +22148 (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n") +22149 (flush *(ebp+0x10)) +22150 (stop *(ebp+0x14) 1) +22151 # never gets here +22152 +22153 $check-mu-copy-stmt:error-too-many-inouts: +22154 (write-buffered *(ebp+0x10) "fn ") +22155 8b/-> *(ebp+0xc) 0/r32/eax +22156 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22157 (write-buffered *(ebp+0x10) %eax) +22158 (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n") +22159 (flush *(ebp+0x10)) +22160 (stop *(ebp+0x14) 1) +22161 # never gets here +22162 +22163 $check-mu-copy-stmt:error-no-output: +22164 (write-buffered *(ebp+0x10) "fn ") +22165 8b/-> *(ebp+0xc) 0/r32/eax +22166 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22167 (write-buffered *(ebp+0x10) %eax) +22168 (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n") +22169 (flush *(ebp+0x10)) +22170 (stop *(ebp+0x14) 1) +22171 # never gets here +22172 +22173 $check-mu-copy-stmt:error-output-not-in-register: +22174 (write-buffered *(ebp+0x10) "fn ") +22175 8b/-> *(ebp+0xc) 0/r32/eax +22176 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22177 (write-buffered *(ebp+0x10) %eax) +22178 (write-buffered *(ebp+0x10) ": stmt copy: output '") +22179 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22180 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22181 (write-buffered *(ebp+0x10) %eax) +22182 (write-buffered *(ebp+0x10) "' not in a register\n") +22183 (flush *(ebp+0x10)) +22184 (stop *(ebp+0x14) 1) +22185 # never gets here +22186 +22187 $check-mu-copy-stmt:error-too-many-outputs: +22188 (write-buffered *(ebp+0x10) "fn ") +22189 8b/-> *(ebp+0xc) 0/r32/eax +22190 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22191 (write-buffered *(ebp+0x10) %eax) +22192 (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n") +22193 (flush *(ebp+0x10)) +22194 (stop *(ebp+0x14) 1) +22195 # never gets here +22196 +22197 $check-mu-copy-stmt:error-inout-too-large: +22198 (write-buffered *(ebp+0x10) "fn ") +22199 8b/-> *(ebp+0xc) 0/r32/eax +22200 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22201 (write-buffered *(ebp+0x10) %eax) +22202 (write-buffered *(ebp+0x10) ": stmt copy: '") +22203 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22204 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22205 (write-buffered *(ebp+0x10) %eax) +22206 (write-buffered *(ebp+0x10) "' is too large to fit in a register\n") +22207 (flush *(ebp+0x10)) +22208 (stop *(ebp+0x14) 1) +22209 # never gets here +22210 +22211 $check-mu-copy-stmt:error-non-literal-to-byte: +22212 (write-buffered *(ebp+0x10) "fn ") +22213 8b/-> *(ebp+0xc) 0/r32/eax +22214 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22215 (write-buffered *(ebp+0x10) %eax) +22216 (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '") +22217 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22218 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22219 (write-buffered *(ebp+0x10) %eax) +22220 (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n") +22221 (flush *(ebp+0x10)) +22222 (stop *(ebp+0x14) 1) +22223 # never gets here +22224 +22225 check-mu-copy-to-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +22226 # . prologue +22227 55/push-ebp +22228 89/<- %ebp 4/r32/esp +22229 # . save registers +22230 50/push-eax +22231 51/push-ecx +22232 52/push-edx +22233 53/push-ebx +22234 56/push-esi +22235 57/push-edi +22236 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) +22237 81 5/subop/subtract %esp 0x60/imm32 +22238 68/push 0x60/imm32/size +22239 68/push 0/imm32/read +22240 68/push 0/imm32/write +22241 89/<- %edx 4/r32/esp +22242 # esi = stmt +22243 8b/-> *(ebp+8) 6/r32/esi +22244 $check-mu-copy-to-stmt:check-for-output: +22245 # if stmt->outputs abort +22246 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +22247 3d/compare-eax-and 0/imm32 +22248 0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32 +22249 $check-mu-copy-to-stmt:get-dest: +22250 # var dest/edi: (addr stmt-var) = stmt->inouts +22251 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +22252 89/<- %edi 0/r32/eax +22253 # zero inouts +22254 3d/compare-eax-and 0/imm32 +22255 0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32 +22256 $check-mu-copy-to-stmt:get-src: +22257 # var src/esi: (addr stmt-var) = dest->next +22258 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +22259 89/<- %esi 0/r32/eax +22260 # 1 inout +22261 3d/compare-eax-and 0/imm32 +22262 0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32 +22263 # > 2 inouts +22264 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +22265 3d/compare-eax-and 0/imm32 +22266 0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32 +22267 $check-mu-copy-to-stmt:types: +22268 # if src is not a scalar, abort +22269 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22270 (size-of %eax) # => eax +22271 3d/compare-eax-and 4/imm32 +22272 0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32 +22273 # var src-type/ecx: (addr type-tree) = src->value->type +22274 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22275 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22276 89/<- %ecx 0/r32/eax +22277 # if src not in register or literal, abort +22278 # (we can't use stack-offset because it hasn't been computed yet) +22279 { +22280 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22281 (lookup *(eax+0x8) *(eax+0xc)) # Var-type Var-type => eax +22282 (simple-mu-type? %eax 0) # => eax +22283 3d/compare-eax-and 0/imm32 +22284 75/jump-if-!= break/disp8 +22285 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22286 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +22287 3d/compare-eax-and 0/imm32 +22288 75/jump-if-!= break/disp8 +22289 e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32 +22290 } +22291 # var dest-type/ebx: (addr type-tree) = dest->value->type +22292 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22293 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22294 89/<- %ebx 0/r32/eax +22295 # if (dest->is-deref?) dest-type = dest-type->payload +22296 $check-mu-copy-to-stmt:check-dest-deref: +22297 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +22298 3d/compare-eax-and 0/imm32/false +22299 { +22300 74/jump-if-= break/disp8 +22301 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +22302 $check-mu-copy-to-stmt:dest-is-deref: +22303 # if dest-type->right is null, dest-type = dest-type->left +22304 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +22305 { +22306 75/jump-if-!= break/disp8 +22307 $check-mu-copy-to-stmt:dest-is-deref2: +22308 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22309 } +22310 89/<- %ebx 0/r32/eax +22311 } +22312 # if dest is a byte and src is not a literal, abort +22313 { +22314 $check-mu-copy-to-stmt:final-check-byte: +22315 (simple-mu-type? %ebx 8) # byte => eax +22316 3d/compare-eax-and 0/imm32/false +22317 74/jump-if-= break/disp8 +22318 (simple-mu-type? %ecx 0) # literal => eax +22319 3d/compare-eax-and 0/imm32/false +22320 0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32 +22321 } +22322 # if (src-type == dest-type) return +22323 (type-match? %ebx %ecx %edx) # => eax +22324 3d/compare-eax-and 0/imm32 +22325 0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32 +22326 # if dest is an addr and src is 0, return +22327 { +22328 $check-mu-copy-to-stmt:final-check-addr: +22329 (mu-addr-type? %ebx) # => eax +22330 3d/compare-eax-and 0/imm32/false +22331 74/jump-if-= break/disp8 +22332 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22333 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22334 (string-equal? %eax "0") # => eax +22335 3d/compare-eax-and 0/imm32/false +22336 74/jump-if-= break/disp8 +22337 e9/jump $check-mu-copy-to-stmt:end/disp32 +22338 } +22339 # if dest is an offset and src is 0, return +22340 { +22341 $check-mu-copy-to-stmt:final-check-offset: +22342 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +22343 75/jump-if-!= break/disp8 +22344 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +22345 (simple-mu-type? %eax 7) # offset => eax +22346 3d/compare-eax-and 0/imm32/false +22347 74/jump-if-= break/disp8 +22348 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22349 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22350 (string-equal? %eax "0") # => eax +22351 3d/compare-eax-and 0/imm32/false +22352 74/jump-if-= break/disp8 +22353 e9/jump $check-mu-copy-to-stmt:end/disp32 +22354 } +22355 # if dest is not number-like, abort +22356 (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +22357 $check-mu-copy-to-stmt:end: +22358 # . reclaim locals +22359 81 0/subop/add %esp 0x6c/imm32 +22360 # . restore registers +22361 5f/pop-to-edi +22362 5e/pop-to-esi +22363 5b/pop-to-ebx +22364 5a/pop-to-edx +22365 59/pop-to-ecx +22366 58/pop-to-eax +22367 # . epilogue +22368 89/<- %esp 5/r32/ebp +22369 5d/pop-to-ebp +22370 c3/return +22371 +22372 $check-mu-copy-to-stmt:error-incorrect-inouts: +22373 (write-buffered *(ebp+0x10) "fn ") +22374 8b/-> *(ebp+0xc) 0/r32/eax +22375 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22376 (write-buffered *(ebp+0x10) %eax) +22377 (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n") +22378 (flush *(ebp+0x10)) +22379 (stop *(ebp+0x14) 1) +22380 # never gets here +22381 +22382 $check-mu-copy-to-stmt:error-too-many-outputs: +22383 (write-buffered *(ebp+0x10) "fn ") +22384 8b/-> *(ebp+0xc) 0/r32/eax +22385 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22386 (write-buffered *(ebp+0x10) %eax) +22387 (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n") +22388 (flush *(ebp+0x10)) +22389 (stop *(ebp+0x14) 1) +22390 # never gets here +22391 +22392 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register: +22393 (write-buffered *(ebp+0x10) "fn ") +22394 8b/-> *(ebp+0xc) 0/r32/eax +22395 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22396 (write-buffered *(ebp+0x10) %eax) +22397 (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n") +22398 (flush *(ebp+0x10)) +22399 (stop *(ebp+0x14) 1) +22400 # never gets here +22401 +22402 $check-mu-copy-to-stmt:error-src-too-large: +22403 (write-buffered *(ebp+0x10) "fn ") +22404 8b/-> *(ebp+0xc) 0/r32/eax +22405 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22406 (write-buffered *(ebp+0x10) %eax) +22407 (write-buffered *(ebp+0x10) ": stmt copy-to: '") +22408 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22409 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22410 (write-buffered *(ebp+0x10) %eax) +22411 (write-buffered *(ebp+0x10) "' is too large to copy\n") +22412 (flush *(ebp+0x10)) +22413 (stop *(ebp+0x14) 1) +22414 # never gets here +22415 +22416 $check-mu-copy-to-stmt:error-non-literal-to-byte: +22417 (write-buffered *(ebp+0x10) "fn ") +22418 8b/-> *(ebp+0xc) 0/r32/eax +22419 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22420 (write-buffered *(ebp+0x10) %eax) +22421 (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n") +22422 (flush *(ebp+0x10)) +22423 (stop *(ebp+0x14) 1) +22424 # never gets here +22425 +22426 check-mu-copy-byte-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +22427 # . prologue +22428 55/push-ebp +22429 89/<- %ebp 4/r32/esp +22430 # . save registers +22431 50/push-eax +22432 51/push-ecx +22433 52/push-edx +22434 56/push-esi +22435 57/push-edi +22436 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) +22437 81 5/subop/subtract %esp 0x60/imm32 +22438 68/push 0x60/imm32/size +22439 68/push 0/imm32/read +22440 68/push 0/imm32/write +22441 89/<- %edx 4/r32/esp +22442 $check-mu-copy-byte-stmt:get-output: +22443 # esi = stmt +22444 8b/-> *(ebp+8) 6/r32/esi +22445 # var output/edi: (addr stmt-var) = stmt->outputs +22446 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +22447 89/<- %edi 0/r32/eax +22448 # zero outputs +22449 3d/compare-eax-and 0/imm32 +22450 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32 +22451 # > 1 output +22452 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +22453 3d/compare-eax-and 0/imm32 +22454 0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32 +22455 $check-mu-copy-byte-stmt:get-inout: +22456 # var inout/esi: (addr stmt-var) = stmt->inouts +22457 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +22458 89/<- %esi 0/r32/eax +22459 # zero inouts +22460 3d/compare-eax-and 0/imm32 +22461 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32 +22462 # > 1 inout +22463 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +22464 3d/compare-eax-and 0/imm32 +22465 0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32 +22466 $check-mu-copy-byte-stmt:types: +22467 # if inout is not a scalar, abort +22468 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22469 (size-of %eax) # => eax +22470 3d/compare-eax-and 4/imm32 +22471 0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32 +22472 # var inout-type/ecx: (addr type-tree) = inout->value->type +22473 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22474 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22475 89/<- %ecx 0/r32/eax +22476 $check-mu-copy-byte-stmt:check-inout-deref: +22477 # if (inout->is-deref?) inout-type = inout-type->payload +22478 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref +22479 3d/compare-eax-and 0/imm32/false +22480 { +22481 74/jump-if-= break/disp8 +22482 $check-mu-copy-byte-stmt:inout-is-deref: +22483 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +22484 # if inout-type->right is null, t = inout-type->left +22485 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +22486 { +22487 75/jump-if-!= break/disp8 +22488 $check-mu-copy-byte-stmt:inout-is-deref2: +22489 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22490 } +22491 89/<- %ecx 0/r32/eax +22492 } +22493 # if output not in register, abort +22494 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22495 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +22496 3d/compare-eax-and 0/imm32 +22497 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32 +22498 # var output-type/eax: (addr type-tree) = output->value->type +22499 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22500 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22501 # if output is not of type byte, abort +22502 (simple-mu-type? %eax 8) # byte => eax +22503 3d/compare-eax-and 0/imm32 +22504 0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32 +22505 $check-mu-copy-byte-stmt:end: +22506 # . reclaim locals +22507 81 0/subop/add %esp 0x6c/imm32 +22508 # . restore registers +22509 5f/pop-to-edi +22510 5e/pop-to-esi +22511 5a/pop-to-edx +22512 59/pop-to-ecx +22513 58/pop-to-eax +22514 # . epilogue +22515 89/<- %esp 5/r32/ebp +22516 5d/pop-to-ebp +22517 c3/return +22518 +22519 $check-mu-copy-byte-stmt:error-no-inout: +22520 (write-buffered *(ebp+0x10) "fn ") +22521 8b/-> *(ebp+0xc) 0/r32/eax +22522 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22523 (write-buffered *(ebp+0x10) %eax) +22524 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n") +22525 (flush *(ebp+0x10)) +22526 (stop *(ebp+0x14) 1) +22527 # never gets here +22528 +22529 $check-mu-copy-byte-stmt:error-too-many-inouts: +22530 (write-buffered *(ebp+0x10) "fn ") +22531 8b/-> *(ebp+0xc) 0/r32/eax +22532 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22533 (write-buffered *(ebp+0x10) %eax) +22534 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n") +22535 (flush *(ebp+0x10)) +22536 (stop *(ebp+0x14) 1) +22537 # never gets here +22538 +22539 $check-mu-copy-byte-stmt:error-no-output: +22540 (write-buffered *(ebp+0x10) "fn ") +22541 8b/-> *(ebp+0xc) 0/r32/eax +22542 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22543 (write-buffered *(ebp+0x10) %eax) +22544 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n") +22545 (flush *(ebp+0x10)) +22546 (stop *(ebp+0x14) 1) +22547 # never gets here +22548 +22549 $check-mu-copy-byte-stmt:error-output-not-in-register: +22550 (write-buffered *(ebp+0x10) "fn ") +22551 8b/-> *(ebp+0xc) 0/r32/eax +22552 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22553 (write-buffered *(ebp+0x10) %eax) +22554 (write-buffered *(ebp+0x10) ": stmt copy-byte: output '") +22555 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22556 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22557 (write-buffered *(ebp+0x10) %eax) +22558 (write-buffered *(ebp+0x10) "' not in a register\n") +22559 (flush *(ebp+0x10)) +22560 (stop *(ebp+0x14) 1) +22561 # never gets here +22562 +22563 $check-mu-copy-byte-stmt:error-too-many-outputs: +22564 (write-buffered *(ebp+0x10) "fn ") +22565 8b/-> *(ebp+0xc) 0/r32/eax +22566 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22567 (write-buffered *(ebp+0x10) %eax) +22568 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n") +22569 (flush *(ebp+0x10)) +22570 (stop *(ebp+0x14) 1) +22571 # never gets here +22572 +22573 $check-mu-copy-byte-stmt:error-invalid-output-type: +22574 (write-buffered *(ebp+0x10) "fn ") +22575 8b/-> *(ebp+0xc) 0/r32/eax +22576 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22577 (write-buffered *(ebp+0x10) %eax) +22578 (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n") +22579 (flush *(ebp+0x10)) +22580 (stop *(ebp+0x14) 1) +22581 # never gets here +22582 +22583 $check-mu-copy-byte-stmt:error-inout-too-large: +22584 (write-buffered *(ebp+0x10) "fn ") +22585 8b/-> *(ebp+0xc) 0/r32/eax +22586 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22587 (write-buffered *(ebp+0x10) %eax) +22588 (write-buffered *(ebp+0x10) ": stmt copy-byte: '") +22589 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22590 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22591 (write-buffered *(ebp+0x10) %eax) +22592 (write-buffered *(ebp+0x10) "' is too large to fit in a register\n") +22593 (flush *(ebp+0x10)) +22594 (stop *(ebp+0x14) 1) +22595 # never gets here +22596 +22597 check-mu-copy-byte-to-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +22598 # . prologue +22599 55/push-ebp +22600 89/<- %ebp 4/r32/esp +22601 # . save registers +22602 50/push-eax +22603 52/push-edx +22604 53/push-ebx +22605 56/push-esi +22606 57/push-edi +22607 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) +22608 81 5/subop/subtract %esp 0x60/imm32 +22609 68/push 0x60/imm32/size +22610 68/push 0/imm32/read +22611 68/push 0/imm32/write +22612 89/<- %edx 4/r32/esp +22613 # esi = stmt +22614 8b/-> *(ebp+8) 6/r32/esi +22615 $check-mu-copy-byte-to-stmt:check-for-output: +22616 # if stmt->outputs abort +22617 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +22618 3d/compare-eax-and 0/imm32 +22619 0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32 +22620 $check-mu-copy-byte-to-stmt:get-dest: +22621 # var dest/edi: (addr stmt-var) = stmt->inouts +22622 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +22623 89/<- %edi 0/r32/eax +22624 # zero inouts +22625 3d/compare-eax-and 0/imm32 +22626 0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32 +22627 $check-mu-copy-byte-to-stmt:get-src: +22628 # var src/esi: (addr stmt-var) = dest->next +22629 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +22630 89/<- %esi 0/r32/eax +22631 # 1 inout +22632 3d/compare-eax-and 0/imm32 +22633 0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32 +22634 # > 2 inouts +22635 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +22636 3d/compare-eax-and 0/imm32 +22637 0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32 +22638 $check-mu-copy-byte-to-stmt:types: +22639 # if src is not a scalar, abort +22640 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22641 (size-of %eax) # => eax +22642 3d/compare-eax-and 4/imm32 +22643 0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32 +22644 # if src not in register, abort +22645 { +22646 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22647 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +22648 3d/compare-eax-and 0/imm32 +22649 75/jump-if-!= break/disp8 +22650 e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32 +22651 } +22652 # var dest-type/ebx: (addr type-tree) = dest->value->type +22653 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22654 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22655 89/<- %ebx 0/r32/eax +22656 # if (dest->is-deref?) dest-type = dest-type->payload +22657 $check-mu-copy-byte-to-stmt:check-dest-deref: +22658 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +22659 3d/compare-eax-and 0/imm32/false +22660 { +22661 74/jump-if-= break/disp8 +22662 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +22663 $check-mu-copy-byte-to-stmt:dest-is-deref: +22664 # if dest-type->right is null, dest-type = dest-type->left +22665 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +22666 { +22667 75/jump-if-!= break/disp8 +22668 $check-mu-copy-byte-to-stmt:dest-is-deref2: +22669 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22670 } +22671 89/<- %ebx 0/r32/eax +22672 } +22673 # if dest is not a byte, abort +22674 (simple-mu-type? %ebx 8) # byte => eax +22675 3d/compare-eax-and 0/imm32/false +22676 0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32 +22677 $check-mu-copy-byte-to-stmt:end: +22678 # . reclaim locals +22679 81 0/subop/add %esp 0x6c/imm32 +22680 # . restore registers +22681 5f/pop-to-edi +22682 5e/pop-to-esi +22683 5b/pop-to-ebx +22684 5a/pop-to-edx +22685 58/pop-to-eax +22686 # . epilogue +22687 89/<- %esp 5/r32/ebp +22688 5d/pop-to-ebp +22689 c3/return +22690 +22691 $check-mu-copy-byte-to-stmt:error-incorrect-inouts: +22692 (write-buffered *(ebp+0x10) "fn ") +22693 8b/-> *(ebp+0xc) 0/r32/eax +22694 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22695 (write-buffered *(ebp+0x10) %eax) +22696 (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n") +22697 (flush *(ebp+0x10)) +22698 (stop *(ebp+0x14) 1) +22699 # never gets here +22700 +22701 $check-mu-copy-byte-to-stmt:error-too-many-outputs: +22702 (write-buffered *(ebp+0x10) "fn ") +22703 8b/-> *(ebp+0xc) 0/r32/eax +22704 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22705 (write-buffered *(ebp+0x10) %eax) +22706 (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n") +22707 (flush *(ebp+0x10)) +22708 (stop *(ebp+0x14) 1) +22709 # never gets here +22710 +22711 $check-mu-copy-byte-to-stmt:error-src-not-in-register: +22712 (write-buffered *(ebp+0x10) "fn ") +22713 8b/-> *(ebp+0xc) 0/r32/eax +22714 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22715 (write-buffered *(ebp+0x10) %eax) +22716 (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n") +22717 (flush *(ebp+0x10)) +22718 (stop *(ebp+0x14) 1) +22719 # never gets here +22720 +22721 $check-mu-copy-byte-to-stmt:error-invalid-dest-type: +22722 (write-buffered *(ebp+0x10) "fn ") +22723 8b/-> *(ebp+0xc) 0/r32/eax +22724 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22725 (write-buffered *(ebp+0x10) %eax) +22726 (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '") +22727 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22728 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22729 (write-buffered *(ebp+0x10) %eax) +22730 (write-buffered *(ebp+0x10) "' must be a byte\n") +22731 (flush *(ebp+0x10)) +22732 (stop *(ebp+0x14) 1) +22733 # never gets here +22734 +22735 $check-mu-copy-byte-to-stmt:error-src-too-large: +22736 (write-buffered *(ebp+0x10) "fn ") +22737 8b/-> *(ebp+0xc) 0/r32/eax +22738 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22739 (write-buffered *(ebp+0x10) %eax) +22740 (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '") +22741 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22742 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22743 (write-buffered *(ebp+0x10) %eax) +22744 (write-buffered *(ebp+0x10) "' is too large to copy\n") +22745 (flush *(ebp+0x10)) +22746 (stop *(ebp+0x14) 1) +22747 # never gets here +22748 +22749 check-mu-compare-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +22750 # . prologue +22751 55/push-ebp +22752 89/<- %ebp 4/r32/esp +22753 # . save registers +22754 50/push-eax +22755 51/push-ecx +22756 52/push-edx +22757 53/push-ebx +22758 56/push-esi +22759 57/push-edi +22760 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) +22761 81 5/subop/subtract %esp 0x60/imm32 +22762 68/push 0x60/imm32/size +22763 68/push 0/imm32/read +22764 68/push 0/imm32/write +22765 89/<- %edx 4/r32/esp +22766 # esi = stmt +22767 8b/-> *(ebp+8) 6/r32/esi +22768 $check-mu-compare-stmt:check-for-output: +22769 # if stmt->outputs abort +22770 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +22771 3d/compare-eax-and 0/imm32 +22772 0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32 +22773 $check-mu-compare-stmt:get-left: +22774 # var left/edi: (addr stmt-var) = stmt->inouts +22775 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +22776 89/<- %edi 0/r32/eax +22777 # zero inouts +22778 3d/compare-eax-and 0/imm32 +22779 0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32 +22780 $check-mu-compare-stmt:get-right: +22781 # var right/esi: (addr stmt-var) = left->next +22782 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +22783 89/<- %esi 0/r32/eax +22784 # 1 inout +22785 3d/compare-eax-and 0/imm32 +22786 0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32 +22787 # > 2 inouts +22788 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +22789 3d/compare-eax-and 0/imm32 +22790 0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32 +22791 # if both inouts are in memory, abort +22792 { +22793 $check-mu-compare-stmt:both-in-mem: +22794 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22795 (lookup *(eax+0x8) *(eax+0xc)) # Var-type Var-type => eax +22796 (simple-mu-type? %eax 0) # => eax +22797 3d/compare-eax-and 0/imm32 +22798 0f 85/jump-if-!= break/disp32 +22799 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22800 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +22801 3d/compare-eax-and 0/imm32 +22802 75/jump-if-!= break/disp8 +22803 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22804 (lookup *(eax+0x8) *(eax+0xc)) # Var-type Var-type => eax +22805 (simple-mu-type? %eax 0) # => eax +22806 3d/compare-eax-and 0/imm32 +22807 75/jump-if-!= break/disp8 +22808 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22809 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +22810 3d/compare-eax-and 0/imm32 +22811 75/jump-if-!= break/disp8 +22812 e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32 +22813 } +22814 $check-mu-compare-stmt:types: +22815 # var right-type/ecx: (addr type-tree) = right->value->type 22816 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22817 (size-of %eax) # => eax -22818 3d/compare-eax-and 4/imm32 -22819 0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32 -22820 # if left is not a scalar, abort -22821 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22822 (size-of %eax) # => eax -22823 3d/compare-eax-and 4/imm32 -22824 0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32 -22825 # var left-type/ebx: (addr type-tree) = left->value->type -22826 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22827 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22828 89/<- %ebx 0/r32/eax -22829 # if (left->is-deref?) left-type = left-type->payload -22830 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -22831 3d/compare-eax-and 0/imm32/false -22832 { -22833 74/jump-if-= break/disp8 -22834 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -22835 # if left-type->right is null, left-type = left-type->left -22836 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -22837 { -22838 75/jump-if-!= break/disp8 -22839 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -22840 } -22841 89/<- %ebx 0/r32/eax -22842 } -22843 # if (left-type == right-type) return -22844 (type-match? %ebx %ecx %edx) # => eax -22845 3d/compare-eax-and 0/imm32 -22846 0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32 -22847 # if left is an addr and right is 0, return -22848 { -22849 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22850 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22851 (mu-addr-type? %eax) # => eax -22852 3d/compare-eax-and 0/imm32/false -22853 74/jump-if-= break/disp8 -22854 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22855 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22856 (string-equal? %eax "0") # => eax -22857 3d/compare-eax-and 0/imm32/false -22858 74/jump-if-= break/disp8 -22859 eb/jump $check-mu-compare-stmt:end/disp8 -22860 } -22861 # if left is not number-like, abort -22862 (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -22863 $check-mu-compare-stmt:end: -22864 # . reclaim locals -22865 81 0/subop/add %esp 0x6c/imm32 -22866 # . restore registers -22867 5f/pop-to-edi -22868 5e/pop-to-esi -22869 5b/pop-to-ebx -22870 5a/pop-to-edx -22871 59/pop-to-ecx -22872 58/pop-to-eax -22873 # . epilogue -22874 89/<- %esp 5/r32/ebp -22875 5d/pop-to-ebp -22876 c3/return -22877 -22878 $check-mu-compare-stmt:error-incorrect-inouts: -22879 (write-buffered *(ebp+0x10) "fn ") -22880 8b/-> *(ebp+0xc) 0/r32/eax -22881 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22882 (write-buffered *(ebp+0x10) %eax) -22883 (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n") -22884 (flush *(ebp+0x10)) -22885 (stop *(ebp+0x14) 1) -22886 # never gets here -22887 -22888 $check-mu-compare-stmt:error-too-many-outputs: -22889 (write-buffered *(ebp+0x10) "fn ") -22890 8b/-> *(ebp+0xc) 0/r32/eax -22891 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22892 (write-buffered *(ebp+0x10) %eax) -22893 (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n") -22894 (flush *(ebp+0x10)) -22895 (stop *(ebp+0x14) 1) -22896 # never gets here -22897 -22898 $check-mu-compare-stmt:error-both-in-memory: -22899 (write-buffered *(ebp+0x10) "fn ") -22900 8b/-> *(ebp+0xc) 0/r32/eax -22901 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22902 (write-buffered *(ebp+0x10) %eax) -22903 (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n") -22904 (flush *(ebp+0x10)) -22905 (stop *(ebp+0x14) 1) -22906 # never gets here -22907 -22908 $check-mu-compare-stmt:error-left-too-large: -22909 (write-buffered *(ebp+0x10) "fn ") -22910 8b/-> *(ebp+0xc) 0/r32/eax -22911 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22912 (write-buffered *(ebp+0x10) %eax) -22913 (write-buffered *(ebp+0x10) ": stmt compare: '") -22914 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22915 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22916 (write-buffered *(ebp+0x10) %eax) -22917 (write-buffered *(ebp+0x10) "' is too large to compare\n") -22918 (flush *(ebp+0x10)) -22919 (stop *(ebp+0x14) 1) -22920 # never gets here -22921 -22922 $check-mu-compare-stmt:error-right-too-large: -22923 (write-buffered *(ebp+0x10) "fn ") -22924 8b/-> *(ebp+0xc) 0/r32/eax -22925 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22926 (write-buffered *(ebp+0x10) %eax) -22927 (write-buffered *(ebp+0x10) ": stmt compare: '") -22928 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22929 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22930 (write-buffered *(ebp+0x10) %eax) -22931 (write-buffered *(ebp+0x10) "' is too large to compare\n") -22932 (flush *(ebp+0x10)) -22933 (stop *(ebp+0x14) 1) -22934 # never gets here -22935 -22936 $check-mu-compare-stmt:error-right-string-literal: -22937 (write-buffered *(ebp+0x10) "fn ") -22938 8b/-> *(ebp+0xc) 0/r32/eax -22939 (lookup *eax *(eax+4)) # Function-name Function-name => eax -22940 (write-buffered *(ebp+0x10) %eax) -22941 (write-buffered *(ebp+0x10) ": stmt compare: string literal ") -22942 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -22943 (lookup *eax *(eax+4)) # Var-name Var-name => eax -22944 (write-buffered *(ebp+0x10) %eax) -22945 (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n") -22946 (flush *(ebp+0x10)) -22947 (stop *(ebp+0x14) 1) -22948 # never gets here -22949 -22950 check-mu-address-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -22951 # . prologue -22952 55/push-ebp -22953 89/<- %ebp 4/r32/esp -22954 # . save registers -22955 50/push-eax -22956 51/push-ecx -22957 52/push-edx -22958 56/push-esi -22959 57/push-edi -22960 $check-mu-address-stmt:get-output: -22961 # esi = stmt -22962 8b/-> *(ebp+8) 6/r32/esi -22963 # var output/edi: (addr stmt-var) = stmt->outputs -22964 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -22965 89/<- %edi 0/r32/eax -22966 # zero outputs -22967 3d/compare-eax-and 0/imm32 -22968 0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32 -22969 # > 1 output -22970 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -22971 3d/compare-eax-and 0/imm32 -22972 0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32 -22973 $check-mu-address-stmt:get-inout: -22974 # var inout/esi: (addr stmt-var) = stmt->inouts -22975 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -22976 89/<- %esi 0/r32/eax -22977 # zero inouts -22978 3d/compare-eax-and 0/imm32 -22979 0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32 -22980 # > 1 inout -22981 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -22982 3d/compare-eax-and 0/imm32 -22983 0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32 -22984 $check-mu-address-stmt:types: -22985 # if output not in register, abort -22986 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22987 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -22988 3d/compare-eax-and 0/imm32 -22989 0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32 -22990 # var output-type/edx: (addr type-tree) = output->value->type -22991 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -22992 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -22993 89/<- %edx 0/r32/eax -22994 # if output-type not an addr, abort -22995 (mu-addr-type? %edx) # => eax -22996 3d/compare-eax-and 0/imm32/false -22997 0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32 -22998 # output-type = output-type->right -22999 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax -23000 # if output-type->right is null, output-type = output-type->left -23001 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -23002 { -23003 75/jump-if-!= break/disp8 -23004 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23005 } -23006 89/<- %edx 0/r32/eax -23007 # var inout-type/ecx: (addr type-tree) = inout->value->type -23008 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -23009 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -23010 89/<- %ecx 0/r32/eax -23011 # if (inout->is-deref?) inout-type = inout-type->payload -23012 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref -23013 3d/compare-eax-and 0/imm32/false -23014 { -23015 74/jump-if-= break/disp8 -23016 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -23017 # if inout-type->right is null, t = inout-type->left -23018 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -23019 { -23020 75/jump-if-!= break/disp8 -23021 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23022 } -23023 89/<- %ecx 0/r32/eax -23024 } -23025 # if (inout-type != output-type) abort -23026 (type-equal-ignoring-capacity? %edx %ecx) # => eax -23027 3d/compare-eax-and 0/imm32 -23028 0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32 -23029 $check-mu-address-stmt:end: -23030 # . restore registers -23031 5f/pop-to-edi -23032 5e/pop-to-esi -23033 5a/pop-to-edx -23034 59/pop-to-ecx -23035 58/pop-to-eax -23036 # . epilogue -23037 89/<- %esp 5/r32/ebp -23038 5d/pop-to-ebp -23039 c3/return -23040 -23041 $check-mu-address-stmt:error-no-inout: -23042 (write-buffered *(ebp+0x10) "fn ") -23043 8b/-> *(ebp+0xc) 0/r32/eax -23044 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23045 (write-buffered *(ebp+0x10) %eax) -23046 (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n") -23047 (flush *(ebp+0x10)) -23048 (stop *(ebp+0x14) 1) -23049 # never gets here -23050 -23051 $check-mu-address-stmt:error-too-many-inouts: -23052 (write-buffered *(ebp+0x10) "fn ") -23053 8b/-> *(ebp+0xc) 0/r32/eax -23054 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23055 (write-buffered *(ebp+0x10) %eax) -23056 (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n") -23057 (flush *(ebp+0x10)) -23058 (stop *(ebp+0x14) 1) -23059 # never gets here -23060 -23061 $check-mu-address-stmt:error-no-output: -23062 (write-buffered *(ebp+0x10) "fn ") -23063 8b/-> *(ebp+0xc) 0/r32/eax -23064 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23065 (write-buffered *(ebp+0x10) %eax) -23066 (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n") -23067 (flush *(ebp+0x10)) -23068 (stop *(ebp+0x14) 1) -23069 # never gets here -23070 -23071 $check-mu-address-stmt:error-output-not-in-register: -23072 (write-buffered *(ebp+0x10) "fn ") -23073 8b/-> *(ebp+0xc) 0/r32/eax -23074 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23075 (write-buffered *(ebp+0x10) %eax) -23076 (write-buffered *(ebp+0x10) ": stmt address: output '") -23077 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23078 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23079 (write-buffered *(ebp+0x10) %eax) -23080 (write-buffered *(ebp+0x10) "' not in a register\n") -23081 (flush *(ebp+0x10)) -23082 (stop *(ebp+0x14) 1) -23083 # never gets here -23084 -23085 $check-mu-address-stmt:error-too-many-outputs: -23086 (write-buffered *(ebp+0x10) "fn ") -23087 8b/-> *(ebp+0xc) 0/r32/eax -23088 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23089 (write-buffered *(ebp+0x10) %eax) -23090 (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n") -23091 (flush *(ebp+0x10)) -23092 (stop *(ebp+0x14) 1) -23093 # never gets here -23094 -23095 $check-mu-address-stmt:error-output-not-address: -23096 (write-buffered *(ebp+0x10) "fn ") -23097 8b/-> *(ebp+0xc) 0/r32/eax -23098 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23099 (write-buffered *(ebp+0x10) %eax) -23100 (write-buffered *(ebp+0x10) ": stmt address: output '") -23101 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23102 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23103 (write-buffered *(ebp+0x10) %eax) -23104 (write-buffered *(ebp+0x10) "' is not an addr\n") -23105 (flush *(ebp+0x10)) -23106 (stop *(ebp+0x14) 1) -23107 # never gets here -23108 -23109 $check-mu-address-stmt:error-type-mismatch: -23110 (write-buffered *(ebp+0x10) "fn ") -23111 8b/-> *(ebp+0xc) 0/r32/eax -23112 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23113 (write-buffered *(ebp+0x10) %eax) -23114 (write-buffered *(ebp+0x10) ": stmt address: output '") -23115 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23116 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23117 (write-buffered *(ebp+0x10) %eax) -23118 (write-buffered *(ebp+0x10) "' cannot hold address of '") -23119 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -23120 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22817 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22818 89/<- %ecx 0/r32/eax +22819 # if (right->is-deref?) right-type = right-type->payload +22820 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref +22821 3d/compare-eax-and 0/imm32/false +22822 { +22823 74/jump-if-= break/disp8 +22824 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +22825 # if right-type->right is null, right-type = right-type->left +22826 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +22827 { +22828 75/jump-if-!= break/disp8 +22829 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22830 } +22831 89/<- %ecx 0/r32/eax +22832 } +22833 # if right-type is a literal string, abort +22834 (simple-mu-type? %ecx 0x10) # string-literal => eax +22835 3d/compare-eax-and 0/imm32/false +22836 0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32 +22837 # if right is not a scalar, abort +22838 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22839 (size-of %eax) # => eax +22840 3d/compare-eax-and 4/imm32 +22841 0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32 +22842 # if left is not a scalar, abort +22843 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22844 (size-of %eax) # => eax +22845 3d/compare-eax-and 4/imm32 +22846 0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32 +22847 # var left-type/ebx: (addr type-tree) = left->value->type +22848 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22849 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22850 89/<- %ebx 0/r32/eax +22851 # if (left->is-deref?) left-type = left-type->payload +22852 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +22853 3d/compare-eax-and 0/imm32/false +22854 { +22855 74/jump-if-= break/disp8 +22856 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +22857 # if left-type->right is null, left-type = left-type->left +22858 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +22859 { +22860 75/jump-if-!= break/disp8 +22861 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +22862 } +22863 89/<- %ebx 0/r32/eax +22864 } +22865 # if (left-type == right-type) return +22866 (type-match? %ebx %ecx %edx) # => eax +22867 3d/compare-eax-and 0/imm32 +22868 0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32 +22869 # if left is an addr and right is 0, return +22870 { +22871 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22872 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +22873 (mu-addr-type? %eax) # => eax +22874 3d/compare-eax-and 0/imm32/false +22875 74/jump-if-= break/disp8 +22876 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22877 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22878 (string-equal? %eax "0") # => eax +22879 3d/compare-eax-and 0/imm32/false +22880 74/jump-if-= break/disp8 +22881 eb/jump $check-mu-compare-stmt:end/disp8 +22882 } +22883 # if left is not number-like, abort +22884 (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +22885 $check-mu-compare-stmt:end: +22886 # . reclaim locals +22887 81 0/subop/add %esp 0x6c/imm32 +22888 # . restore registers +22889 5f/pop-to-edi +22890 5e/pop-to-esi +22891 5b/pop-to-ebx +22892 5a/pop-to-edx +22893 59/pop-to-ecx +22894 58/pop-to-eax +22895 # . epilogue +22896 89/<- %esp 5/r32/ebp +22897 5d/pop-to-ebp +22898 c3/return +22899 +22900 $check-mu-compare-stmt:error-incorrect-inouts: +22901 (write-buffered *(ebp+0x10) "fn ") +22902 8b/-> *(ebp+0xc) 0/r32/eax +22903 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22904 (write-buffered *(ebp+0x10) %eax) +22905 (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n") +22906 (flush *(ebp+0x10)) +22907 (stop *(ebp+0x14) 1) +22908 # never gets here +22909 +22910 $check-mu-compare-stmt:error-too-many-outputs: +22911 (write-buffered *(ebp+0x10) "fn ") +22912 8b/-> *(ebp+0xc) 0/r32/eax +22913 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22914 (write-buffered *(ebp+0x10) %eax) +22915 (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n") +22916 (flush *(ebp+0x10)) +22917 (stop *(ebp+0x14) 1) +22918 # never gets here +22919 +22920 $check-mu-compare-stmt:error-both-in-memory: +22921 (write-buffered *(ebp+0x10) "fn ") +22922 8b/-> *(ebp+0xc) 0/r32/eax +22923 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22924 (write-buffered *(ebp+0x10) %eax) +22925 (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n") +22926 (flush *(ebp+0x10)) +22927 (stop *(ebp+0x14) 1) +22928 # never gets here +22929 +22930 $check-mu-compare-stmt:error-left-too-large: +22931 (write-buffered *(ebp+0x10) "fn ") +22932 8b/-> *(ebp+0xc) 0/r32/eax +22933 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22934 (write-buffered *(ebp+0x10) %eax) +22935 (write-buffered *(ebp+0x10) ": stmt compare: '") +22936 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +22937 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22938 (write-buffered *(ebp+0x10) %eax) +22939 (write-buffered *(ebp+0x10) "' is too large to compare\n") +22940 (flush *(ebp+0x10)) +22941 (stop *(ebp+0x14) 1) +22942 # never gets here +22943 +22944 $check-mu-compare-stmt:error-right-too-large: +22945 (write-buffered *(ebp+0x10) "fn ") +22946 8b/-> *(ebp+0xc) 0/r32/eax +22947 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22948 (write-buffered *(ebp+0x10) %eax) +22949 (write-buffered *(ebp+0x10) ": stmt compare: '") +22950 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22951 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22952 (write-buffered *(ebp+0x10) %eax) +22953 (write-buffered *(ebp+0x10) "' is too large to compare\n") +22954 (flush *(ebp+0x10)) +22955 (stop *(ebp+0x14) 1) +22956 # never gets here +22957 +22958 $check-mu-compare-stmt:error-right-string-literal: +22959 (write-buffered *(ebp+0x10) "fn ") +22960 8b/-> *(ebp+0xc) 0/r32/eax +22961 (lookup *eax *(eax+4)) # Function-name Function-name => eax +22962 (write-buffered *(ebp+0x10) %eax) +22963 (write-buffered *(ebp+0x10) ": stmt compare: string literal ") +22964 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +22965 (lookup *eax *(eax+4)) # Var-name Var-name => eax +22966 (write-buffered *(ebp+0x10) %eax) +22967 (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n") +22968 (flush *(ebp+0x10)) +22969 (stop *(ebp+0x14) 1) +22970 # never gets here +22971 +22972 check-mu-address-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +22973 # . prologue +22974 55/push-ebp +22975 89/<- %ebp 4/r32/esp +22976 # . save registers +22977 50/push-eax +22978 51/push-ecx +22979 52/push-edx +22980 56/push-esi +22981 57/push-edi +22982 $check-mu-address-stmt:get-output: +22983 # esi = stmt +22984 8b/-> *(ebp+8) 6/r32/esi +22985 # var output/edi: (addr stmt-var) = stmt->outputs +22986 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +22987 89/<- %edi 0/r32/eax +22988 # zero outputs +22989 3d/compare-eax-and 0/imm32 +22990 0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32 +22991 # > 1 output +22992 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +22993 3d/compare-eax-and 0/imm32 +22994 0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32 +22995 $check-mu-address-stmt:get-inout: +22996 # var inout/esi: (addr stmt-var) = stmt->inouts +22997 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +22998 89/<- %esi 0/r32/eax +22999 # zero inouts +23000 3d/compare-eax-and 0/imm32 +23001 0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32 +23002 # > 1 inout +23003 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +23004 3d/compare-eax-and 0/imm32 +23005 0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32 +23006 $check-mu-address-stmt:types: +23007 # if output not in register, abort +23008 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23009 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23010 3d/compare-eax-and 0/imm32 +23011 0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32 +23012 # var output-type/edx: (addr type-tree) = output->value->type +23013 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23014 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +23015 89/<- %edx 0/r32/eax +23016 # if output-type not an addr, abort +23017 (mu-addr-type? %edx) # => eax +23018 3d/compare-eax-and 0/imm32/false +23019 0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32 +23020 # output-type = output-type->right +23021 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax +23022 # if output-type->right is null, output-type = output-type->left +23023 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +23024 { +23025 75/jump-if-!= break/disp8 +23026 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23027 } +23028 89/<- %edx 0/r32/eax +23029 # var inout-type/ecx: (addr type-tree) = inout->value->type +23030 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +23031 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +23032 89/<- %ecx 0/r32/eax +23033 # if (inout->is-deref?) inout-type = inout-type->payload +23034 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref +23035 3d/compare-eax-and 0/imm32/false +23036 { +23037 74/jump-if-= break/disp8 +23038 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +23039 # if inout-type->right is null, t = inout-type->left +23040 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +23041 { +23042 75/jump-if-!= break/disp8 +23043 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23044 } +23045 89/<- %ecx 0/r32/eax +23046 } +23047 # if (inout-type != output-type) abort +23048 (type-equal-ignoring-capacity? %edx %ecx) # => eax +23049 3d/compare-eax-and 0/imm32 +23050 0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32 +23051 $check-mu-address-stmt:end: +23052 # . restore registers +23053 5f/pop-to-edi +23054 5e/pop-to-esi +23055 5a/pop-to-edx +23056 59/pop-to-ecx +23057 58/pop-to-eax +23058 # . epilogue +23059 89/<- %esp 5/r32/ebp +23060 5d/pop-to-ebp +23061 c3/return +23062 +23063 $check-mu-address-stmt:error-no-inout: +23064 (write-buffered *(ebp+0x10) "fn ") +23065 8b/-> *(ebp+0xc) 0/r32/eax +23066 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23067 (write-buffered *(ebp+0x10) %eax) +23068 (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n") +23069 (flush *(ebp+0x10)) +23070 (stop *(ebp+0x14) 1) +23071 # never gets here +23072 +23073 $check-mu-address-stmt:error-too-many-inouts: +23074 (write-buffered *(ebp+0x10) "fn ") +23075 8b/-> *(ebp+0xc) 0/r32/eax +23076 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23077 (write-buffered *(ebp+0x10) %eax) +23078 (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n") +23079 (flush *(ebp+0x10)) +23080 (stop *(ebp+0x14) 1) +23081 # never gets here +23082 +23083 $check-mu-address-stmt:error-no-output: +23084 (write-buffered *(ebp+0x10) "fn ") +23085 8b/-> *(ebp+0xc) 0/r32/eax +23086 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23087 (write-buffered *(ebp+0x10) %eax) +23088 (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n") +23089 (flush *(ebp+0x10)) +23090 (stop *(ebp+0x14) 1) +23091 # never gets here +23092 +23093 $check-mu-address-stmt:error-output-not-in-register: +23094 (write-buffered *(ebp+0x10) "fn ") +23095 8b/-> *(ebp+0xc) 0/r32/eax +23096 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23097 (write-buffered *(ebp+0x10) %eax) +23098 (write-buffered *(ebp+0x10) ": stmt address: output '") +23099 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23100 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23101 (write-buffered *(ebp+0x10) %eax) +23102 (write-buffered *(ebp+0x10) "' not in a register\n") +23103 (flush *(ebp+0x10)) +23104 (stop *(ebp+0x14) 1) +23105 # never gets here +23106 +23107 $check-mu-address-stmt:error-too-many-outputs: +23108 (write-buffered *(ebp+0x10) "fn ") +23109 8b/-> *(ebp+0xc) 0/r32/eax +23110 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23111 (write-buffered *(ebp+0x10) %eax) +23112 (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n") +23113 (flush *(ebp+0x10)) +23114 (stop *(ebp+0x14) 1) +23115 # never gets here +23116 +23117 $check-mu-address-stmt:error-output-not-address: +23118 (write-buffered *(ebp+0x10) "fn ") +23119 8b/-> *(ebp+0xc) 0/r32/eax +23120 (lookup *eax *(eax+4)) # Function-name Function-name => eax 23121 (write-buffered *(ebp+0x10) %eax) -23122 (write-buffered *(ebp+0x10) "'\n") -23123 (flush *(ebp+0x10)) -23124 (stop *(ebp+0x14) 1) -23125 # never gets here -23126 -23127 type-equal-ignoring-capacity?: # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean -23128 # . prologue -23129 55/push-ebp -23130 89/<- %ebp 4/r32/esp -23131 # . save registers -23132 51/push-ecx -23133 52/push-edx -23134 53/push-ebx -23135 # var curr-a/ecx: (addr type-tree) = a -23136 8b/-> *(ebp+8) 1/r32/ecx -23137 # var curr-b/ebx: (addr type-tree) = b -23138 8b/-> *(ebp+0xc) 3/r32/ebx -23139 # if (curr-a->is-atom?) fall back to regular equality -23140 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -23141 0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32 -23142 # if (curr-a->left != curr-b->left) return false -23143 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -23144 89/<- %edx 0/r32/eax -23145 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -23146 (type-equal? %edx %eax) # => eax -23147 3d/compare-eax-and 0/imm32/false -23148 0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32 # eax switches meaning -23149 # if (curr-a->left == "array") curr-a = curr-a->element-type -23150 { -23151 (mu-array? %edx) # => eax -23152 3d/compare-eax-and 0/imm32/false -23153 75/jump-if-!= break/disp8 -23154 $type-equal-ignoring-capacity?:array: -23155 # curr-a = curr-a->right->left -23156 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -23157 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23158 89/<- %ecx 0/r32/eax -23159 # curr-b = curr-b->right->left -23160 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -23161 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23162 89/<- %ebx 0/r32/eax -23163 eb/jump $type-equal-ignoring-capacity?:base-case/disp8 -23164 } -23165 # if (curr-a->left == "stream") curr-a = curr-a->element-type -23166 { -23167 (mu-stream? %edx) # => eax -23168 3d/compare-eax-and 0/imm32/false -23169 75/jump-if-!= break/disp8 -23170 $type-equal-ignoring-capacity?:stream: -23171 # curr-a = curr-a->right->left -23172 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -23173 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23174 89/<- %ecx 0/r32/eax -23175 # curr-b = curr-b->right->left -23176 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -23177 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23178 89/<- %ebx 0/r32/eax -23179 eb/jump $type-equal-ignoring-capacity?:base-case/disp8 -23180 } -23181 $type-equal-ignoring-capacity?:base-case: -23182 # return type-equal?(curr-a, curr-b) -23183 (type-equal? %ecx %ebx) # => eax -23184 $type-equal-ignoring-capacity?:end: -23185 # . restore registers -23186 5b/pop-to-ebx -23187 5a/pop-to-edx -23188 59/pop-to-ecx -23189 # . epilogue -23190 89/<- %esp 5/r32/ebp -23191 5d/pop-to-ebp -23192 c3/return -23193 -23194 check-mu-return-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -23195 # . prologue -23196 55/push-ebp -23197 89/<- %ebp 4/r32/esp -23198 # . save registers -23199 50/push-eax -23200 51/push-ecx -23201 52/push-edx -23202 53/push-ebx -23203 56/push-esi -23204 57/push-edi -23205 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) -23206 81 5/subop/subtract %esp 0x60/imm32 -23207 68/push 0x60/imm32/size -23208 68/push 0/imm32/read -23209 68/push 0/imm32/write -23210 89/<- %edx 4/r32/esp -23211 # var template/esi: (addr list var) = fn->outputs -23212 8b/-> *(ebp+0xc) 0/r32/eax -23213 (lookup *(eax+0x10) *(eax+0x14)) # Function-outputs Function-outputs => eax -23214 89/<- %esi 0/r32/eax -23215 # var curr-template/ebx: (addr list var) = fn->outputs -23216 89/<- %ebx 0/r32/eax -23217 # var curr/edi: (addr stmt-var) = stmt->inouts -23218 8b/-> *(ebp+8) 0/r32/eax -23219 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23220 89/<- %edi 0/r32/eax -23221 { -23222 # if template is null, break -23223 81 7/subop/compare %ebx 0/imm32 -23224 0f 84/jump-if-= break/disp32 -23225 # if curr is null, abort -23226 81 7/subop/compare %edi 0/imm32 -23227 0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32 -23228 # var template-type/ecx: (addr type-tree) = template->value->type -23229 (lookup *ebx *(ebx+4)) # List-value List-value => eax -23230 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -23231 89/<- %ecx 0/r32/eax -23232 # var curr-type/eax: (addr type-tree) = curr->value->type -23233 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23234 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -23235 # if (curr->is-deref?) curr-type = payload of curr-type -23236 81 7/subop/compare *(edi+0x10) 0/imm32/false # Stmt-var-is-deref -23237 { -23238 74/jump-if-= break/disp8 -23239 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -23240 # if t->right is null, t = t->left -23241 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -23242 75/jump-if-!= break/disp8 -23243 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23244 } -23245 # if curr-type is literal and template-type is float, abort -23246 50/push-eax -23247 { -23248 (simple-mu-type? %eax 0) # literal => eax -23249 3d/compare-eax-and 0/imm32/false -23250 74/jump-if-= break/disp8 -23251 (simple-mu-type? %ecx 0xf) # float => eax -23252 3d/compare-eax-and 0/imm32/false -23253 0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32 -23254 } -23255 58/pop-to-eax -23256 # if (curr-type != template-type) abort -23257 (type-match? %ecx %eax %edx) # => eax -23258 3d/compare-eax-and 0/imm32/false -23259 0f 84/jump-if-= $check-mu-return-stmt:error1/disp32 -23260 # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort -23261 (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8)) # => eax -23262 3d/compare-eax-and 0/imm32/false -23263 0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32 -23264 # template = template->next -23265 (lookup *(ebx+8) *(ebx+0xc)) # List-next List-next => eax -23266 89/<- %ebx 0/r32/eax -23267 # curr = curr->next -23268 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -23269 89/<- %edi 0/r32/eax -23270 # -23271 e9/jump loop/disp32 -23272 } -23273 # if curr is not null, abort -23274 81 7/subop/compare %edi 0/imm32 -23275 0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32 -23276 $check-mu-return-stmt:end: -23277 # . reclaim locals -23278 81 0/subop/add %esp 0x6c/imm32 -23279 # . restore registers -23280 5f/pop-to-edi -23281 5e/pop-to-esi -23282 5b/pop-to-ebx -23283 5a/pop-to-edx -23284 59/pop-to-ecx -23285 58/pop-to-eax -23286 # . epilogue -23287 89/<- %esp 5/r32/ebp -23288 5d/pop-to-ebp -23289 c3/return -23290 -23291 $check-mu-return-stmt:error1: -23292 (write-buffered *(ebp+0x10) "fn ") -23293 8b/-> *(ebp+0xc) 0/r32/eax -23294 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23295 (write-buffered *(ebp+0x10) %eax) -23296 (write-buffered *(ebp+0x10) ": return: '") -23297 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23298 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23299 (write-buffered *(ebp+0x10) %eax) -23300 (write-buffered *(ebp+0x10) "' has the wrong type\n") -23301 (flush *(ebp+0x10)) -23302 (stop *(ebp+0x14) 1) -23303 # never gets here -23304 -23305 $check-mu-return-stmt:error2: -23306 (write-buffered *(ebp+0x10) "fn ") -23307 8b/-> *(ebp+0xc) 0/r32/eax -23308 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23309 (write-buffered *(ebp+0x10) %eax) -23310 (write-buffered *(ebp+0x10) ": return: '") -23311 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23312 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23313 (write-buffered *(ebp+0x10) %eax) -23314 (write-buffered *(ebp+0x10) "' is no longer available\n") -23315 (flush *(ebp+0x10)) -23316 (stop *(ebp+0x14) 1) -23317 # never gets here -23318 -23319 $check-mu-return-stmt:error-literal-to-float: -23320 (write-buffered *(ebp+0x10) "fn ") -23321 8b/-> *(ebp+0xc) 0/r32/eax -23322 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23323 (write-buffered *(ebp+0x10) %eax) -23324 (write-buffered *(ebp+0x10) ": return: cannot copy literal '") -23325 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -23326 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23327 (write-buffered *(ebp+0x10) %eax) -23328 (write-buffered *(ebp+0x10) "' to float\n") -23329 (flush *(ebp+0x10)) -23330 (stop *(ebp+0x14) 1) -23331 # never gets here -23332 -23333 $check-mu-return-stmt:error-too-few-inouts: -23334 (write-buffered *(ebp+0x10) "fn ") -23335 8b/-> *(ebp+0xc) 0/r32/eax -23336 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23337 (write-buffered *(ebp+0x10) %eax) -23338 (write-buffered *(ebp+0x10) ": return: too few inouts\n") -23339 (flush *(ebp+0x10)) -23340 (stop *(ebp+0x14) 1) -23341 # never gets here -23342 -23343 $check-mu-return-stmt:error-too-many-inouts: -23344 (write-buffered *(ebp+0x10) "fn ") -23345 8b/-> *(ebp+0xc) 0/r32/eax -23346 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23347 (write-buffered *(ebp+0x10) %eax) -23348 (write-buffered *(ebp+0x10) ": return: too many inouts\n") -23349 (flush *(ebp+0x10)) -23350 (stop *(ebp+0x14) 1) -23351 # never gets here -23352 -23353 check-all-unique-registers: # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -23354 # . prologue -23355 55/push-ebp -23356 89/<- %ebp 4/r32/esp -23357 # . save registers -23358 50/push-eax -23359 51/push-ecx -23360 56/push-esi -23361 # var table/esi: (addr table (handle array byte) int 8) -23362 81 5/subop/subtract %esp 0x60/imm32 -23363 68/push 0x60/imm32/size -23364 68/push 0/imm32/read -23365 68/push 0/imm32/write -23366 89/<- %esi 4/r32/esp -23367 # var curr/ecx: (addr list var) = outputs -23368 8b/-> *(ebp+8) 1/r32/ecx -23369 { -23370 # if (curr == 0) break -23371 81 7/subop/compare %ecx 0/imm32 -23372 0f 84/jump-if-= break/disp32 -23373 # var reg/eax: (addr array byte) = curr->value->register # guaranteed to exist -23374 (lookup *ecx *(ecx+4)) # List-value List-value => eax -23375 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -23376 # if reg exists in table, abort -23377 (maybe-get %esi %eax 0xc) # => eax -23378 3d/compare-eax-and 0/imm32 -23379 0f 85/jump-if-!= $check-all-unique-registers:abort/disp32 -23380 # insert reg in table -23381 (lookup *ecx *(ecx+4)) # List-value List-value => eax -23382 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -23383 (get-or-insert %esi %eax 0xc Heap) -23384 # curr = curr->next -23385 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -23386 89/<- %ecx 0/r32/eax -23387 e9/jump loop/disp32 -23388 } -23389 $check-all-unique-registers:end: -23390 # . reclaim locals -23391 81 0/subop/add %esp 0x6c/imm32 -23392 # . restore registers -23393 5e/pop-to-esi -23394 59/pop-to-ecx -23395 58/pop-to-eax -23396 # . epilogue -23397 89/<- %esp 5/r32/ebp -23398 5d/pop-to-ebp -23399 c3/return -23400 -23401 $check-all-unique-registers:abort: -23402 (write-buffered *(ebp+0x10) "fn ") -23403 8b/-> *(ebp+0xc) 0/r32/eax -23404 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23405 (write-buffered *(ebp+0x10) %eax) -23406 (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n") -23407 (flush *(ebp+0x10)) -23408 (stop *(ebp+0x14) 1) -23409 # never gets here -23410 -23411 # return false if s's register is not between start (inclusive) and end (exclusive) -23412 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register -23413 # otherwise return true -23414 register-within-list-with-conflict?: # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean -23415 # . prologue -23416 55/push-ebp -23417 89/<- %ebp 4/r32/esp -23418 # . save registers -23419 51/push-ecx -23420 52/push-edx -23421 53/push-ebx -23422 56/push-esi -23423 57/push-edi -23424 # var target/ebx: (addr array byte) = s->value->register -23425 8b/-> *(ebp+8) 0/r32/eax -23426 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -23427 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -23428 #? (write-buffered Stderr "AA: ") -23429 #? (write-buffered Stderr %eax) -23430 #? (write-buffered Stderr Newline) -23431 #? (flush Stderr) -23432 # if (var->register == 0) return false -23433 3d/compare-eax-and 0/imm32 -23434 0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32 # eax turns into result -23435 89/<- %ebx 0/r32/eax -23436 # var curr/ecx: (addr list var) = start -23437 8b/-> *(ebp+0xc) 1/r32/ecx -23438 # edx = end -23439 8b/-> *(ebp+0x10) 2/r32/edx -23440 { -23441 # if (curr == 0) break -23442 81 7/subop/compare %edi 0/imm32 -23443 0f 84/jump-if-= break/disp32 -23444 # if (curr == end) break -23445 39/compare %ecx 2/r32/edx -23446 0f 84/jump-if-= break/disp32 -23447 # var curr-reg/eax: (addr array byte) = curr->value->register -23448 (lookup *ecx *(ecx+4)) # List-value List-value => eax -23449 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -23450 # if (curr-reg == 0) continue -23451 3d/compare-eax-and 0/imm32 -23452 74/jump-if-= $register-within-list-with-conflict?:continue/disp8 -23453 # if (curr-reg == target) check for conflict -23454 (string-equal? %eax %ebx) # => eax -23455 3d/compare-eax-and 0/imm32/false -23456 { -23457 74/jump-if-= break/disp8 -23458 #? (write-buffered Stderr "conflict?\n") -23459 #? (flush Stderr) -23460 # var return-inouts/eax: (addr stmt-var) = stmt->inouts -23461 8b/-> *(ebp+0x14) 0/r32/eax -23462 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23463 (register-conflict? %ebx %eax *(ebp+0xc)) # => eax -23464 eb/jump $register-within-list-with-conflict?:end/disp8 -23465 } -23466 $register-within-list-with-conflict?:continue: -23467 # curr = curr->next -23468 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -23469 89/<- %ecx 0/r32/eax -23470 e9/jump loop/disp32 -23471 } -23472 # return false -23473 b8/copy-to-eax 0/imm32/false -23474 $register-within-list-with-conflict?:end: -23475 # . restore registers -23476 5f/pop-to-edi -23477 5e/pop-to-esi -23478 5b/pop-to-ebx -23479 5a/pop-to-edx -23480 59/pop-to-ecx -23481 # . epilogue -23482 89/<- %esp 5/r32/ebp -23483 5d/pop-to-ebp -23484 c3/return -23485 -23486 # At the first occurrence of register 'reg' in fn-outputs, -23487 # check if the corresponding element of return-inouts has a different register. -23488 # This hacky helper is intended to be called in one specific place. Don't -23489 # reuse it as is. -23490 register-conflict?: # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean -23491 # . prologue -23492 55/push-ebp -23493 89/<- %ebp 4/r32/esp -23494 # . save registers -23495 51/push-ecx -23496 52/push-edx -23497 53/push-ebx -23498 56/push-esi -23499 57/push-edi -23500 #? (write-buffered Stderr "BB: ") -23501 #? (write-buffered Stderr *(ebp+8)) -23502 #? (write-buffered Stderr Newline) -23503 #? (flush Stderr) -23504 # var curr-output/edi: (addr list var) = fn-outputs -23505 8b/-> *(ebp+0x10) 7/r32/edi -23506 # var curr-inout/esi: (addr stmt-var) = return-inouts -23507 8b/-> *(ebp+0xc) 6/r32/esi -23508 { -23509 # if (curr-output == 0) abort -23510 81 7/subop/compare %edi 0/imm32 -23511 0f 84/jump-if-= break/disp32 -23512 # if (curr-output->value->register != reg) continue -23513 (lookup *edi *(edi+4)) # List-value List-value => eax -23514 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -23515 (string-equal? %eax *(ebp+8)) # => eax -23516 3d/compare-eax-and 0/imm32/false -23517 0f 84/jump-if= $register-conflict?:continue/disp32 -23518 #? (write-buffered Stderr "rescan\n") -23519 #? (flush Stderr) -23520 # var curr-reg/eax: (addr array byte) = curr-inout->value->register -23521 (lookup *esi *(esi+4)) # List-value List-value => eax -23522 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -23523 # if (curr-reg == 0) return true -23524 3d/compare-eax-and 0/imm32 -23525 { -23526 75/jump-if-!= break/disp8 -23527 #? (write-buffered Stderr "no register\n") -23528 #? (flush Stderr) -23529 b8/copy-to-eax 1/imm32/true -23530 e9/jump $register-conflict?:end/disp32 -23531 } -23532 # return (curr-reg != reg) -23533 (string-equal? %eax *(ebp+8)) # => eax -23534 3d/compare-eax-and 0/imm32/false -23535 0f 94/set-if-= %al -23536 #? (write-buffered Stderr "final: ") -23537 #? (write-int32-hex-buffered Stderr %eax) -23538 #? (write-buffered Stderr Newline) -23539 #? (flush Stderr) -23540 eb/jump $register-conflict?:end/disp8 -23541 $register-conflict?:continue: -23542 # curr-output = curr-output->next -23543 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax -23544 89/<- %edi 0/r32/eax -23545 # curr-inout = curr-inout->next -23546 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -23547 89/<- %esi 0/r32/eax -23548 e9/jump loop/disp32 -23549 } -23550 # should never get here -23551 (write-buffered Stderr "register-conflict? misused\n") -23552 (flush Stderr) -23553 e8/call syscall_exit/disp32 -23554 $register-conflict?:end: -23555 # . restore registers -23556 5f/pop-to-edi -23557 5e/pop-to-esi -23558 5b/pop-to-ebx -23559 5a/pop-to-edx -23560 59/pop-to-ecx -23561 # . epilogue -23562 89/<- %esp 5/r32/ebp -23563 5d/pop-to-ebp -23564 c3/return -23565 -23566 check-final-stmt-is-return: # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -23567 # . prologue -23568 55/push-ebp -23569 89/<- %ebp 4/r32/esp -23570 # . save registers -23571 50/push-eax -23572 51/push-ecx -23573 # var curr/ecx: (addr list stmt) = block->stmts -23574 8b/-> *(ebp+8) 0/r32/eax -23575 (lookup *(eax+4) *(eax+8)) # Block-stmts Block-stmts => eax -23576 3d/compare-eax-and 0/imm32 -23577 74/jump-if-= $check-final-stmt-is-return:error/disp8 -23578 89/<- %ecx 0/r32/eax -23579 { -23580 # if curr->next == 0, break -23581 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -23582 3d/compare-eax-and 0/imm32 -23583 74/jump-if-= break/disp8 -23584 # curr = curr->next -23585 89/<- %ecx 0/r32/eax -23586 e9/jump loop/disp32 -23587 } -23588 $check-final-stmt-is-return:check-tag: -23589 # if curr->value->tag != Stmt1, abort -23590 (lookup *ecx *(ecx+4)) # List-value List-value => eax -23591 81 7/subop/compare *eax 1/imm32/stmt1 # Stmt-tag -23592 75/jump-if-!= $check-final-stmt-is-return:error/disp8 -23593 $check-final-stmt-is-return:check-operation: -23594 # if curr->operation != "return", abort -23595 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -23596 (string-equal? %eax "return") -23597 3d/compare-eax-and 0/imm32/false -23598 74/jump-if-= $check-final-stmt-is-return:error/disp8 -23599 $check-final-stmt-is-return:end: -23600 # . restore registers -23601 59/pop-to-ecx -23602 58/pop-to-eax -23603 # . epilogue -23604 89/<- %esp 5/r32/ebp -23605 5d/pop-to-ebp -23606 c3/return -23607 -23608 $check-final-stmt-is-return:error: -23609 (write-buffered *(ebp+0x10) "fn ") -23610 8b/-> *(ebp+0xc) 0/r32/eax -23611 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23612 (write-buffered *(ebp+0x10) %eax) -23613 (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n") -23614 (flush *(ebp+0x10)) -23615 (stop *(ebp+0x14) 1) -23616 # never gets here -23617 -23618 check-no-breaks: # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -23619 # . prologue -23620 55/push-ebp -23621 89/<- %ebp 4/r32/esp -23622 # . save registers -23623 50/push-eax -23624 51/push-ecx -23625 # var curr/ecx: (addr list stmt) = block->stmts -23626 8b/-> *(ebp+8) 0/r32/eax -23627 (lookup *(eax+4) *(eax+8)) # Block-stmts Block-stmts => eax -23628 3d/compare-eax-and 0/imm32 -23629 0f 84/jump-if-= $check-no-breaks:end/disp32 -23630 89/<- %ecx 0/r32/eax -23631 { -23632 # if curr->next == 0, break -23633 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -23634 3d/compare-eax-and 0/imm32 -23635 74/jump-if-= break/disp8 -23636 # if curr->value->tag != Stmt1, continue -23637 (lookup *ecx *(ecx+4)) # List-value List-value => eax -23638 81 7/subop/compare *eax 1/imm32/stmt1 # Stmt-tag -23639 75/jump-if-!= $check-no-breaks:continue/disp8 -23640 # if curr->value->operation starts with "break", abort -23641 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -23642 (string-starts-with? %eax "break") # => eax -23643 3d/compare-eax-and 0/imm32/false -23644 75/jump-if-!= $check-no-breaks:error/disp8 -23645 $check-no-breaks:continue: -23646 # curr = curr->next -23647 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -23648 89/<- %ecx 0/r32/eax -23649 e9/jump loop/disp32 -23650 } -23651 $check-no-breaks:end: -23652 # . restore registers -23653 59/pop-to-ecx -23654 58/pop-to-eax -23655 # . epilogue -23656 89/<- %esp 5/r32/ebp -23657 5d/pop-to-ebp -23658 c3/return -23659 -23660 $check-no-breaks:error: -23661 (write-buffered *(ebp+0x10) "fn ") -23662 8b/-> *(ebp+0xc) 0/r32/eax -23663 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23664 (write-buffered *(ebp+0x10) %eax) -23665 (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n") -23666 (flush *(ebp+0x10)) -23667 (stop *(ebp+0x14) 1) -23668 # never gets here -23669 -23670 check-mu-get-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -23671 # . prologue -23672 55/push-ebp -23673 89/<- %ebp 4/r32/esp -23674 # . save registers -23675 50/push-eax -23676 51/push-ecx -23677 52/push-edx -23678 53/push-ebx -23679 56/push-esi -23680 57/push-edi -23681 # esi = stmt -23682 8b/-> *(ebp+8) 6/r32/esi -23683 # - check for 0 inouts -23684 # var base/ecx: (addr var) = stmt->inouts->value -23685 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23686 3d/compare-eax-and 0/imm32/false -23687 0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32 -23688 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -23689 89/<- %ecx 0/r32/eax -23690 $check-mu-get-stmt:check-base: -23691 # - check base type -23692 # if it's an 'addr', check that it's in a register -23693 # var base-type/ebx: (addr type-tree) = lookup(base->type) -23694 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -23695 89/<- %ebx 0/r32/eax -23696 { -23697 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -23698 0f 85/jump-if-!= break/disp32 -23699 $check-mu-get-stmt:base-is-compound: -23700 # if (type->left != addr) break -23701 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -23702 (simple-mu-type? %eax 2) # addr => eax -23703 3d/compare-eax-and 0/imm32/false -23704 74/jump-if-= break/disp8 -23705 $check-mu-get-stmt:base-is-addr: -23706 # now check for register -23707 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -23708 0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32 -23709 $check-mu-get-stmt:base-is-addr-in-register: -23710 # type->left is now an addr; skip it -23711 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -23712 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -23713 0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32 -23714 $check-mu-get-stmt:base-is-addr-to-atom-in-register: -23715 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23716 89/<- %ebx 0/r32/eax -23717 } -23718 $check-mu-get-stmt:check-base-typeinfo: -23719 # ensure type is a container -23720 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -23721 { -23722 75/jump-if-!= break/disp8 +23122 (write-buffered *(ebp+0x10) ": stmt address: output '") +23123 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23124 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23125 (write-buffered *(ebp+0x10) %eax) +23126 (write-buffered *(ebp+0x10) "' is not an addr\n") +23127 (flush *(ebp+0x10)) +23128 (stop *(ebp+0x14) 1) +23129 # never gets here +23130 +23131 $check-mu-address-stmt:error-type-mismatch: +23132 (write-buffered *(ebp+0x10) "fn ") +23133 8b/-> *(ebp+0xc) 0/r32/eax +23134 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23135 (write-buffered *(ebp+0x10) %eax) +23136 (write-buffered *(ebp+0x10) ": stmt address: output '") +23137 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23138 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23139 (write-buffered *(ebp+0x10) %eax) +23140 (write-buffered *(ebp+0x10) "' cannot hold address of '") +23141 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +23142 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23143 (write-buffered *(ebp+0x10) %eax) +23144 (write-buffered *(ebp+0x10) "'\n") +23145 (flush *(ebp+0x10)) +23146 (stop *(ebp+0x14) 1) +23147 # never gets here +23148 +23149 type-equal-ignoring-capacity?: # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean +23150 # . prologue +23151 55/push-ebp +23152 89/<- %ebp 4/r32/esp +23153 # . save registers +23154 51/push-ecx +23155 52/push-edx +23156 53/push-ebx +23157 # var curr-a/ecx: (addr type-tree) = a +23158 8b/-> *(ebp+8) 1/r32/ecx +23159 # var curr-b/ebx: (addr type-tree) = b +23160 8b/-> *(ebp+0xc) 3/r32/ebx +23161 # if (curr-a->is-atom?) fall back to regular equality +23162 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +23163 0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32 +23164 # if (curr-a->left != curr-b->left) return false +23165 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +23166 89/<- %edx 0/r32/eax +23167 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +23168 (type-equal? %edx %eax) # => eax +23169 3d/compare-eax-and 0/imm32/false +23170 0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32 # eax switches meaning +23171 # if (curr-a->left == "array") curr-a = curr-a->element-type +23172 { +23173 (mu-array? %edx) # => eax +23174 3d/compare-eax-and 0/imm32/false +23175 75/jump-if-!= break/disp8 +23176 $type-equal-ignoring-capacity?:array: +23177 # curr-a = curr-a->right->left +23178 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +23179 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23180 89/<- %ecx 0/r32/eax +23181 # curr-b = curr-b->right->left +23182 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +23183 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23184 89/<- %ebx 0/r32/eax +23185 eb/jump $type-equal-ignoring-capacity?:base-case/disp8 +23186 } +23187 # if (curr-a->left == "stream") curr-a = curr-a->element-type +23188 { +23189 (mu-stream? %edx) # => eax +23190 3d/compare-eax-and 0/imm32/false +23191 75/jump-if-!= break/disp8 +23192 $type-equal-ignoring-capacity?:stream: +23193 # curr-a = curr-a->right->left +23194 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +23195 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23196 89/<- %ecx 0/r32/eax +23197 # curr-b = curr-b->right->left +23198 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +23199 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23200 89/<- %ebx 0/r32/eax +23201 eb/jump $type-equal-ignoring-capacity?:base-case/disp8 +23202 } +23203 $type-equal-ignoring-capacity?:base-case: +23204 # return type-equal?(curr-a, curr-b) +23205 (type-equal? %ecx %ebx) # => eax +23206 $type-equal-ignoring-capacity?:end: +23207 # . restore registers +23208 5b/pop-to-ebx +23209 5a/pop-to-edx +23210 59/pop-to-ecx +23211 # . epilogue +23212 89/<- %esp 5/r32/ebp +23213 5d/pop-to-ebp +23214 c3/return +23215 +23216 check-mu-return-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +23217 # . prologue +23218 55/push-ebp +23219 89/<- %ebp 4/r32/esp +23220 # . save registers +23221 50/push-eax +23222 51/push-ecx +23223 52/push-edx +23224 53/push-ebx +23225 56/push-esi +23226 57/push-edi +23227 # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8) +23228 81 5/subop/subtract %esp 0x60/imm32 +23229 68/push 0x60/imm32/size +23230 68/push 0/imm32/read +23231 68/push 0/imm32/write +23232 89/<- %edx 4/r32/esp +23233 # var template/esi: (addr list var) = fn->outputs +23234 8b/-> *(ebp+0xc) 0/r32/eax +23235 (lookup *(eax+0x10) *(eax+0x14)) # Function-outputs Function-outputs => eax +23236 89/<- %esi 0/r32/eax +23237 # var curr-template/ebx: (addr list var) = fn->outputs +23238 89/<- %ebx 0/r32/eax +23239 # var curr/edi: (addr stmt-var) = stmt->inouts +23240 8b/-> *(ebp+8) 0/r32/eax +23241 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23242 89/<- %edi 0/r32/eax +23243 { +23244 # if template is null, break +23245 81 7/subop/compare %ebx 0/imm32 +23246 0f 84/jump-if-= break/disp32 +23247 # if curr is null, abort +23248 81 7/subop/compare %edi 0/imm32 +23249 0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32 +23250 # var template-type/ecx: (addr type-tree) = template->value->type +23251 (lookup *ebx *(ebx+4)) # List-value List-value => eax +23252 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +23253 89/<- %ecx 0/r32/eax +23254 # var curr-type/eax: (addr type-tree) = curr->value->type +23255 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23256 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +23257 # if (curr->is-deref?) curr-type = payload of curr-type +23258 81 7/subop/compare *(edi+0x10) 0/imm32/false # Stmt-var-is-deref +23259 { +23260 74/jump-if-= break/disp8 +23261 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +23262 # if t->right is null, t = t->left +23263 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +23264 75/jump-if-!= break/disp8 +23265 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23266 } +23267 # if curr-type is literal and template-type is float, abort +23268 50/push-eax +23269 { +23270 (simple-mu-type? %eax 0) # literal => eax +23271 3d/compare-eax-and 0/imm32/false +23272 74/jump-if-= break/disp8 +23273 (simple-mu-type? %ecx 0xf) # float => eax +23274 3d/compare-eax-and 0/imm32/false +23275 0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32 +23276 } +23277 58/pop-to-eax +23278 # if (curr-type != template-type) abort +23279 (type-match? %ecx %eax %edx) # => eax +23280 3d/compare-eax-and 0/imm32/false +23281 0f 84/jump-if-= $check-mu-return-stmt:error1/disp32 +23282 # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort +23283 (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8)) # => eax +23284 3d/compare-eax-and 0/imm32/false +23285 0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32 +23286 # template = template->next +23287 (lookup *(ebx+8) *(ebx+0xc)) # List-next List-next => eax +23288 89/<- %ebx 0/r32/eax +23289 # curr = curr->next +23290 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +23291 89/<- %edi 0/r32/eax +23292 # +23293 e9/jump loop/disp32 +23294 } +23295 # if curr is not null, abort +23296 81 7/subop/compare %edi 0/imm32 +23297 0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32 +23298 $check-mu-return-stmt:end: +23299 # . reclaim locals +23300 81 0/subop/add %esp 0x6c/imm32 +23301 # . restore registers +23302 5f/pop-to-edi +23303 5e/pop-to-esi +23304 5b/pop-to-ebx +23305 5a/pop-to-edx +23306 59/pop-to-ecx +23307 58/pop-to-eax +23308 # . epilogue +23309 89/<- %esp 5/r32/ebp +23310 5d/pop-to-ebp +23311 c3/return +23312 +23313 $check-mu-return-stmt:error1: +23314 (write-buffered *(ebp+0x10) "fn ") +23315 8b/-> *(ebp+0xc) 0/r32/eax +23316 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23317 (write-buffered *(ebp+0x10) %eax) +23318 (write-buffered *(ebp+0x10) ": return: '") +23319 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23320 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23321 (write-buffered *(ebp+0x10) %eax) +23322 (write-buffered *(ebp+0x10) "' has the wrong type\n") +23323 (flush *(ebp+0x10)) +23324 (stop *(ebp+0x14) 1) +23325 # never gets here +23326 +23327 $check-mu-return-stmt:error2: +23328 (write-buffered *(ebp+0x10) "fn ") +23329 8b/-> *(ebp+0xc) 0/r32/eax +23330 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23331 (write-buffered *(ebp+0x10) %eax) +23332 (write-buffered *(ebp+0x10) ": return: '") +23333 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23334 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23335 (write-buffered *(ebp+0x10) %eax) +23336 (write-buffered *(ebp+0x10) "' is no longer available\n") +23337 (flush *(ebp+0x10)) +23338 (stop *(ebp+0x14) 1) +23339 # never gets here +23340 +23341 $check-mu-return-stmt:error-literal-to-float: +23342 (write-buffered *(ebp+0x10) "fn ") +23343 8b/-> *(ebp+0xc) 0/r32/eax +23344 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23345 (write-buffered *(ebp+0x10) %eax) +23346 (write-buffered *(ebp+0x10) ": return: cannot copy literal '") +23347 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +23348 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23349 (write-buffered *(ebp+0x10) %eax) +23350 (write-buffered *(ebp+0x10) "' to float\n") +23351 (flush *(ebp+0x10)) +23352 (stop *(ebp+0x14) 1) +23353 # never gets here +23354 +23355 $check-mu-return-stmt:error-too-few-inouts: +23356 (write-buffered *(ebp+0x10) "fn ") +23357 8b/-> *(ebp+0xc) 0/r32/eax +23358 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23359 (write-buffered *(ebp+0x10) %eax) +23360 (write-buffered *(ebp+0x10) ": return: too few inouts\n") +23361 (flush *(ebp+0x10)) +23362 (stop *(ebp+0x14) 1) +23363 # never gets here +23364 +23365 $check-mu-return-stmt:error-too-many-inouts: +23366 (write-buffered *(ebp+0x10) "fn ") +23367 8b/-> *(ebp+0xc) 0/r32/eax +23368 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23369 (write-buffered *(ebp+0x10) %eax) +23370 (write-buffered *(ebp+0x10) ": return: too many inouts\n") +23371 (flush *(ebp+0x10)) +23372 (stop *(ebp+0x14) 1) +23373 # never gets here +23374 +23375 check-all-unique-registers: # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +23376 # . prologue +23377 55/push-ebp +23378 89/<- %ebp 4/r32/esp +23379 # . save registers +23380 50/push-eax +23381 51/push-ecx +23382 56/push-esi +23383 # var table/esi: (addr table (handle array byte) int 8) +23384 81 5/subop/subtract %esp 0x60/imm32 +23385 68/push 0x60/imm32/size +23386 68/push 0/imm32/read +23387 68/push 0/imm32/write +23388 89/<- %esi 4/r32/esp +23389 # var curr/ecx: (addr list var) = outputs +23390 8b/-> *(ebp+8) 1/r32/ecx +23391 { +23392 # if (curr == 0) break +23393 81 7/subop/compare %ecx 0/imm32 +23394 0f 84/jump-if-= break/disp32 +23395 # var reg/eax: (addr array byte) = curr->value->register # guaranteed to exist +23396 (lookup *ecx *(ecx+4)) # List-value List-value => eax +23397 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23398 # if reg exists in table, abort +23399 (maybe-get %esi %eax 0xc) # => eax +23400 3d/compare-eax-and 0/imm32 +23401 0f 85/jump-if-!= $check-all-unique-registers:abort/disp32 +23402 # insert reg in table +23403 (lookup *ecx *(ecx+4)) # List-value List-value => eax +23404 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23405 (get-or-insert %esi %eax 0xc Heap) +23406 # curr = curr->next +23407 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +23408 89/<- %ecx 0/r32/eax +23409 e9/jump loop/disp32 +23410 } +23411 $check-all-unique-registers:end: +23412 # . reclaim locals +23413 81 0/subop/add %esp 0x6c/imm32 +23414 # . restore registers +23415 5e/pop-to-esi +23416 59/pop-to-ecx +23417 58/pop-to-eax +23418 # . epilogue +23419 89/<- %esp 5/r32/ebp +23420 5d/pop-to-ebp +23421 c3/return +23422 +23423 $check-all-unique-registers:abort: +23424 (write-buffered *(ebp+0x10) "fn ") +23425 8b/-> *(ebp+0xc) 0/r32/eax +23426 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23427 (write-buffered *(ebp+0x10) %eax) +23428 (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n") +23429 (flush *(ebp+0x10)) +23430 (stop *(ebp+0x14) 1) +23431 # never gets here +23432 +23433 # return false if s's register is not between start (inclusive) and end (exclusive) +23434 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register +23435 # otherwise return true +23436 register-within-list-with-conflict?: # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean +23437 # . prologue +23438 55/push-ebp +23439 89/<- %ebp 4/r32/esp +23440 # . save registers +23441 51/push-ecx +23442 52/push-edx +23443 53/push-ebx +23444 56/push-esi +23445 57/push-edi +23446 # var target/ebx: (addr array byte) = s->value->register +23447 8b/-> *(ebp+8) 0/r32/eax +23448 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +23449 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23450 #? (write-buffered Stderr "AA: ") +23451 #? (write-buffered Stderr %eax) +23452 #? (write-buffered Stderr Newline) +23453 #? (flush Stderr) +23454 # if (var->register == 0) return false +23455 3d/compare-eax-and 0/imm32 +23456 0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32 # eax turns into result +23457 89/<- %ebx 0/r32/eax +23458 # var curr/ecx: (addr list var) = start +23459 8b/-> *(ebp+0xc) 1/r32/ecx +23460 # edx = end +23461 8b/-> *(ebp+0x10) 2/r32/edx +23462 { +23463 # if (curr == 0) break +23464 81 7/subop/compare %edi 0/imm32 +23465 0f 84/jump-if-= break/disp32 +23466 # if (curr == end) break +23467 39/compare %ecx 2/r32/edx +23468 0f 84/jump-if-= break/disp32 +23469 # var curr-reg/eax: (addr array byte) = curr->value->register +23470 (lookup *ecx *(ecx+4)) # List-value List-value => eax +23471 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23472 # if (curr-reg == 0) continue +23473 3d/compare-eax-and 0/imm32 +23474 74/jump-if-= $register-within-list-with-conflict?:continue/disp8 +23475 # if (curr-reg == target) check for conflict +23476 (string-equal? %eax %ebx) # => eax +23477 3d/compare-eax-and 0/imm32/false +23478 { +23479 74/jump-if-= break/disp8 +23480 #? (write-buffered Stderr "conflict?\n") +23481 #? (flush Stderr) +23482 # var return-inouts/eax: (addr stmt-var) = stmt->inouts +23483 8b/-> *(ebp+0x14) 0/r32/eax +23484 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23485 (register-conflict? %ebx %eax *(ebp+0xc)) # => eax +23486 eb/jump $register-within-list-with-conflict?:end/disp8 +23487 } +23488 $register-within-list-with-conflict?:continue: +23489 # curr = curr->next +23490 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +23491 89/<- %ecx 0/r32/eax +23492 e9/jump loop/disp32 +23493 } +23494 # return false +23495 b8/copy-to-eax 0/imm32/false +23496 $register-within-list-with-conflict?:end: +23497 # . restore registers +23498 5f/pop-to-edi +23499 5e/pop-to-esi +23500 5b/pop-to-ebx +23501 5a/pop-to-edx +23502 59/pop-to-ecx +23503 # . epilogue +23504 89/<- %esp 5/r32/ebp +23505 5d/pop-to-ebp +23506 c3/return +23507 +23508 # At the first occurrence of register 'reg' in fn-outputs, +23509 # check if the corresponding element of return-inouts has a different register. +23510 # This hacky helper is intended to be called in one specific place. Don't +23511 # reuse it as is. +23512 register-conflict?: # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean +23513 # . prologue +23514 55/push-ebp +23515 89/<- %ebp 4/r32/esp +23516 # . save registers +23517 51/push-ecx +23518 52/push-edx +23519 53/push-ebx +23520 56/push-esi +23521 57/push-edi +23522 #? (write-buffered Stderr "BB: ") +23523 #? (write-buffered Stderr *(ebp+8)) +23524 #? (write-buffered Stderr Newline) +23525 #? (flush Stderr) +23526 # var curr-output/edi: (addr list var) = fn-outputs +23527 8b/-> *(ebp+0x10) 7/r32/edi +23528 # var curr-inout/esi: (addr stmt-var) = return-inouts +23529 8b/-> *(ebp+0xc) 6/r32/esi +23530 { +23531 # if (curr-output == 0) abort +23532 81 7/subop/compare %edi 0/imm32 +23533 0f 84/jump-if-= break/disp32 +23534 # if (curr-output->value->register != reg) continue +23535 (lookup *edi *(edi+4)) # List-value List-value => eax +23536 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23537 (string-equal? %eax *(ebp+8)) # => eax +23538 3d/compare-eax-and 0/imm32/false +23539 0f 84/jump-if= $register-conflict?:continue/disp32 +23540 #? (write-buffered Stderr "rescan\n") +23541 #? (flush Stderr) +23542 # var curr-reg/eax: (addr array byte) = curr-inout->value->register +23543 (lookup *esi *(esi+4)) # List-value List-value => eax +23544 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +23545 # if (curr-reg == 0) return true +23546 3d/compare-eax-and 0/imm32 +23547 { +23548 75/jump-if-!= break/disp8 +23549 #? (write-buffered Stderr "no register\n") +23550 #? (flush Stderr) +23551 b8/copy-to-eax 1/imm32/true +23552 e9/jump $register-conflict?:end/disp32 +23553 } +23554 # return (curr-reg != reg) +23555 (string-equal? %eax *(ebp+8)) # => eax +23556 3d/compare-eax-and 0/imm32/false +23557 0f 94/set-if-= %al +23558 #? (write-buffered Stderr "final: ") +23559 #? (write-int32-hex-buffered Stderr %eax) +23560 #? (write-buffered Stderr Newline) +23561 #? (flush Stderr) +23562 eb/jump $register-conflict?:end/disp8 +23563 $register-conflict?:continue: +23564 # curr-output = curr-output->next +23565 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax +23566 89/<- %edi 0/r32/eax +23567 # curr-inout = curr-inout->next +23568 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +23569 89/<- %esi 0/r32/eax +23570 e9/jump loop/disp32 +23571 } +23572 # should never get here +23573 (write-buffered Stderr "register-conflict? misused\n") +23574 (flush Stderr) +23575 e8/call syscall_exit/disp32 +23576 $register-conflict?:end: +23577 # . restore registers +23578 5f/pop-to-edi +23579 5e/pop-to-esi +23580 5b/pop-to-ebx +23581 5a/pop-to-edx +23582 59/pop-to-ecx +23583 # . epilogue +23584 89/<- %esp 5/r32/ebp +23585 5d/pop-to-ebp +23586 c3/return +23587 +23588 check-final-stmt-is-return: # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +23589 # . prologue +23590 55/push-ebp +23591 89/<- %ebp 4/r32/esp +23592 # . save registers +23593 50/push-eax +23594 51/push-ecx +23595 # var curr/ecx: (addr list stmt) = block->stmts +23596 8b/-> *(ebp+8) 0/r32/eax +23597 (lookup *(eax+4) *(eax+8)) # Block-stmts Block-stmts => eax +23598 3d/compare-eax-and 0/imm32 +23599 74/jump-if-= $check-final-stmt-is-return:error/disp8 +23600 89/<- %ecx 0/r32/eax +23601 { +23602 # if curr->next == 0, break +23603 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +23604 3d/compare-eax-and 0/imm32 +23605 74/jump-if-= break/disp8 +23606 # curr = curr->next +23607 89/<- %ecx 0/r32/eax +23608 e9/jump loop/disp32 +23609 } +23610 $check-final-stmt-is-return:check-tag: +23611 # if curr->value->tag != Stmt1, abort +23612 (lookup *ecx *(ecx+4)) # List-value List-value => eax +23613 81 7/subop/compare *eax 1/imm32/stmt1 # Stmt-tag +23614 75/jump-if-!= $check-final-stmt-is-return:error/disp8 +23615 $check-final-stmt-is-return:check-operation: +23616 # if curr->operation != "return", abort +23617 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +23618 (string-equal? %eax "return") +23619 3d/compare-eax-and 0/imm32/false +23620 74/jump-if-= $check-final-stmt-is-return:error/disp8 +23621 $check-final-stmt-is-return:end: +23622 # . restore registers +23623 59/pop-to-ecx +23624 58/pop-to-eax +23625 # . epilogue +23626 89/<- %esp 5/r32/ebp +23627 5d/pop-to-ebp +23628 c3/return +23629 +23630 $check-final-stmt-is-return:error: +23631 (write-buffered *(ebp+0x10) "fn ") +23632 8b/-> *(ebp+0xc) 0/r32/eax +23633 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23634 (write-buffered *(ebp+0x10) %eax) +23635 (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n") +23636 (flush *(ebp+0x10)) +23637 (stop *(ebp+0x14) 1) +23638 # never gets here +23639 +23640 check-no-breaks: # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +23641 # . prologue +23642 55/push-ebp +23643 89/<- %ebp 4/r32/esp +23644 # . save registers +23645 50/push-eax +23646 51/push-ecx +23647 # var curr/ecx: (addr list stmt) = block->stmts +23648 8b/-> *(ebp+8) 0/r32/eax +23649 (lookup *(eax+4) *(eax+8)) # Block-stmts Block-stmts => eax +23650 3d/compare-eax-and 0/imm32 +23651 0f 84/jump-if-= $check-no-breaks:end/disp32 +23652 89/<- %ecx 0/r32/eax +23653 { +23654 # if curr->next == 0, break +23655 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +23656 3d/compare-eax-and 0/imm32 +23657 74/jump-if-= break/disp8 +23658 # if curr->value->tag != Stmt1, continue +23659 (lookup *ecx *(ecx+4)) # List-value List-value => eax +23660 81 7/subop/compare *eax 1/imm32/stmt1 # Stmt-tag +23661 75/jump-if-!= $check-no-breaks:continue/disp8 +23662 # if curr->value->operation starts with "break", abort +23663 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +23664 (string-starts-with? %eax "break") # => eax +23665 3d/compare-eax-and 0/imm32/false +23666 75/jump-if-!= $check-no-breaks:error/disp8 +23667 $check-no-breaks:continue: +23668 # curr = curr->next +23669 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +23670 89/<- %ecx 0/r32/eax +23671 e9/jump loop/disp32 +23672 } +23673 $check-no-breaks:end: +23674 # . restore registers +23675 59/pop-to-ecx +23676 58/pop-to-eax +23677 # . epilogue +23678 89/<- %esp 5/r32/ebp +23679 5d/pop-to-ebp +23680 c3/return +23681 +23682 $check-no-breaks:error: +23683 (write-buffered *(ebp+0x10) "fn ") +23684 8b/-> *(ebp+0xc) 0/r32/eax +23685 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23686 (write-buffered *(ebp+0x10) %eax) +23687 (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n") +23688 (flush *(ebp+0x10)) +23689 (stop *(ebp+0x14) 1) +23690 # never gets here +23691 +23692 check-mu-get-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +23693 # . prologue +23694 55/push-ebp +23695 89/<- %ebp 4/r32/esp +23696 # . save registers +23697 50/push-eax +23698 51/push-ecx +23699 52/push-edx +23700 53/push-ebx +23701 56/push-esi +23702 57/push-edi +23703 # esi = stmt +23704 8b/-> *(ebp+8) 6/r32/esi +23705 # - check for 0 inouts +23706 # var base/ecx: (addr var) = stmt->inouts->value +23707 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23708 3d/compare-eax-and 0/imm32/false +23709 0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32 +23710 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +23711 89/<- %ecx 0/r32/eax +23712 $check-mu-get-stmt:check-base: +23713 # - check base type +23714 # if it's an 'addr', check that it's in a register +23715 # var base-type/ebx: (addr type-tree) = lookup(base->type) +23716 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +23717 89/<- %ebx 0/r32/eax +23718 { +23719 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +23720 0f 85/jump-if-!= break/disp32 +23721 $check-mu-get-stmt:base-is-compound: +23722 # if (type->left != addr) break 23723 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -23724 89/<- %ebx 0/r32/eax -23725 } -23726 # var base-type-id/ebx: type-id = base-type->value -23727 8b/-> *(ebx+4) 3/r32/ebx # Type-tree-value -23728 (container? %ebx) # => eax -23729 3d/compare-eax-and 0/imm32/false -23730 0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32 -23731 # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id) -23732 # . var container/ecx: (handle typeinfo) -23733 68/push 0/imm32 -23734 68/push 0/imm32 -23735 89/<- %ecx 4/r32/esp -23736 # . -23737 (find-typeinfo %ebx %ecx) -23738 (lookup *ecx *(ecx+4)) # => eax -23739 # . reclaim container -23740 81 0/subop/add %esp 8/imm32 -23741 # . -23742 89/<- %edx 0/r32/eax -23743 # var offset/ecx: (addr stmt-var) = stmt->inouts->next -23744 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23745 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -23746 89/<- %ecx 0/r32/eax -23747 # - check for 1 inout -23748 3d/compare-eax-and 0/imm32/false -23749 0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32 -23750 # var offset/ecx: (addr var) = lookup(offset->value) -23751 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -23752 89/<- %ecx 0/r32/eax -23753 # - check for valid field -23754 81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized # Var-offset -23755 0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32 -23756 # - check for too many inouts -23757 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23758 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -23759 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -23760 3d/compare-eax-and 0/imm32/false -23761 0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32 -23762 # var output/edi: (addr var) = stmt->outputs->value -23763 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -23764 # - check for 0 outputs -23765 3d/compare-eax-and 0/imm32/false -23766 0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32 -23767 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -23768 89/<- %edi 0/r32/eax -23769 $check-mu-get-stmt:check-output-type: -23770 # - check output type -23771 # must be in register -23772 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax -23773 3d/compare-eax-and 0/imm32 -23774 0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32 -23775 # must have a non-atomic type -23776 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -23777 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -23778 0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32 -23779 # type must start with (addr ...) -23780 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23781 (simple-mu-type? %eax 2) # => eax +23724 (simple-mu-type? %eax 2) # addr => eax +23725 3d/compare-eax-and 0/imm32/false +23726 74/jump-if-= break/disp8 +23727 $check-mu-get-stmt:base-is-addr: +23728 # now check for register +23729 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +23730 0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32 +23731 $check-mu-get-stmt:base-is-addr-in-register: +23732 # type->left is now an addr; skip it +23733 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +23734 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +23735 0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32 +23736 $check-mu-get-stmt:base-is-addr-to-atom-in-register: +23737 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23738 89/<- %ebx 0/r32/eax +23739 } +23740 $check-mu-get-stmt:check-base-typeinfo: +23741 # ensure type is a container +23742 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +23743 { +23744 75/jump-if-!= break/disp8 +23745 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +23746 89/<- %ebx 0/r32/eax +23747 } +23748 # var base-type-id/ebx: type-id = base-type->value +23749 8b/-> *(ebx+4) 3/r32/ebx # Type-tree-value +23750 (container? %ebx) # => eax +23751 3d/compare-eax-and 0/imm32/false +23752 0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32 +23753 # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id) +23754 # . var container/ecx: (handle typeinfo) +23755 68/push 0/imm32 +23756 68/push 0/imm32 +23757 89/<- %ecx 4/r32/esp +23758 # . +23759 (find-typeinfo %ebx %ecx) +23760 (lookup *ecx *(ecx+4)) # => eax +23761 # . reclaim container +23762 81 0/subop/add %esp 8/imm32 +23763 # . +23764 89/<- %edx 0/r32/eax +23765 # var offset/ecx: (addr stmt-var) = stmt->inouts->next +23766 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23767 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +23768 89/<- %ecx 0/r32/eax +23769 # - check for 1 inout +23770 3d/compare-eax-and 0/imm32/false +23771 0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32 +23772 # var offset/ecx: (addr var) = lookup(offset->value) +23773 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +23774 89/<- %ecx 0/r32/eax +23775 # - check for valid field +23776 81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized # Var-offset +23777 0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32 +23778 # - check for too many inouts +23779 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23780 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +23781 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax 23782 3d/compare-eax-and 0/imm32/false -23783 0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32 -23784 $check-mu-get-stmt:check-output-type-match: -23785 # payload of addr type must match 'type' definition -23786 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -23787 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -23788 # if (payload->right == null) payload = payload->left -23789 81 7/subop/compare *(eax+0xc) 0/imm32/null # Type-tree-right -23790 { -23791 75/jump-if-!= break/disp8 -23792 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -23793 } -23794 89/<- %edi 0/r32/eax -23795 # . var output-name/ecx: (addr array byte) -23796 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -23797 89/<- %ecx 0/r32/eax -23798 # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry) -23799 (lookup *(edx+4) *(edx+8)) # Typeinfo-fields Typeinfo-fields => eax -23800 (get %eax %ecx 0x10) # => eax -23801 # . -23802 (lookup *eax *(eax+4)) # => eax -23803 (lookup *eax *(eax+4)) # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax -23804 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -23805 # . -23806 (type-equal? %edi %eax) # => eax -23807 3d/compare-eax-and 0/imm32/false -23808 0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32 -23809 # - check for too many outputs -23810 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -23811 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -23812 3d/compare-eax-and 0/imm32/false -23813 0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32 -23814 $check-mu-get-stmt:end: -23815 # . restore registers -23816 5f/pop-to-edi -23817 5e/pop-to-esi -23818 5b/pop-to-ebx -23819 5a/pop-to-edx -23820 59/pop-to-ecx -23821 58/pop-to-eax -23822 # . epilogue -23823 89/<- %esp 5/r32/ebp -23824 5d/pop-to-ebp -23825 c3/return -23826 -23827 $check-mu-get-stmt:error-too-few-inouts: -23828 (write-buffered *(ebp+0x10) "fn ") -23829 8b/-> *(ebp+0xc) 0/r32/eax -23830 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23831 (write-buffered *(ebp+0x10) %eax) -23832 (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n") -23833 (flush *(ebp+0x10)) -23834 (stop *(ebp+0x14) 1) -23835 # never gets here -23836 -23837 $check-mu-get-stmt:error-too-many-inouts: -23838 (write-buffered *(ebp+0x10) "fn ") -23839 8b/-> *(ebp+0xc) 0/r32/eax -23840 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23841 (write-buffered *(ebp+0x10) %eax) -23842 (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n") -23843 (flush *(ebp+0x10)) -23844 (stop *(ebp+0x14) 1) -23845 # never gets here -23846 -23847 $check-mu-get-stmt:error-too-few-outputs: -23848 (write-buffered *(ebp+0x10) "fn ") -23849 8b/-> *(ebp+0xc) 0/r32/eax -23850 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23851 (write-buffered *(ebp+0x10) %eax) -23852 (write-buffered *(ebp+0x10) ": stmt get: must have an output\n") -23853 (flush *(ebp+0x10)) -23854 (stop *(ebp+0x14) 1) -23855 # never gets here -23856 -23857 $check-mu-get-stmt:error-too-many-outputs: -23858 (write-buffered *(ebp+0x10) "fn ") -23859 8b/-> *(ebp+0xc) 0/r32/eax -23860 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23861 (write-buffered *(ebp+0x10) %eax) -23862 (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n") -23863 (flush *(ebp+0x10)) -23864 (stop *(ebp+0x14) 1) -23865 # never gets here -23866 -23867 $check-mu-get-stmt:error-bad-base: -23868 # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n") -23869 (write-buffered *(ebp+0x10) "fn ") -23870 8b/-> *(ebp+0xc) 0/r32/eax -23871 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23872 (write-buffered *(ebp+0x10) %eax) -23873 (write-buffered *(ebp+0x10) ": stmt get: var '") -23874 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23875 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -23876 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23877 (write-buffered *(ebp+0x10) %eax) -23878 (write-buffered *(ebp+0x10) "' must have a 'type' definition\n") -23879 (flush *(ebp+0x10)) -23880 (stop *(ebp+0x14) 1) -23881 # never gets here -23882 -23883 $check-mu-get-stmt:error-base-type-addr-but-not-register: -23884 (write-buffered *(ebp+0x10) "fn ") -23885 8b/-> *(ebp+0xc) 0/r32/eax -23886 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23887 (write-buffered *(ebp+0x10) %eax) -23888 (write-buffered *(ebp+0x10) ": stmt get: var '") -23889 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23890 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -23891 (lookup *eax *(eax+4)) # Var-name Var-name => eax -23892 (write-buffered *(ebp+0x10) %eax) -23893 (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n") -23894 (flush *(ebp+0x10)) -23895 (stop *(ebp+0x14) 1) -23896 # never gets here -23897 -23898 $check-mu-get-stmt:error-bad-field: -23899 # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n") -23900 (write-buffered *(ebp+0x10) "fn ") -23901 8b/-> *(ebp+0xc) 0/r32/eax -23902 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23903 (write-buffered *(ebp+0x10) %eax) -23904 (write-buffered *(ebp+0x10) ": stmt get: type '") -23905 # . write(Type-id->data[tmp]) -23906 bf/copy-to-edi Type-id/imm32 -23907 8b/-> *(edi+ebx<<2+0xc) 6/r32/esi -23908 { -23909 81 7/subop/compare %esi 0/imm32 -23910 74/jump-if-= break/disp8 -23911 (write-buffered *(ebp+0x10) %esi) -23912 } -23913 # . -23914 (write-buffered *(ebp+0x10) "' has no member called '") -23915 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -23916 (write-buffered *(ebp+0x10) %eax) -23917 (write-buffered *(ebp+0x10) "'\n") -23918 (flush *(ebp+0x10)) -23919 (stop *(ebp+0x14) 1) -23920 # never gets here -23921 -23922 $check-mu-get-stmt:error-output-not-in-register: -23923 (write-buffered *(ebp+0x10) "fn ") -23924 8b/-> *(ebp+0xc) 0/r32/eax -23925 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23926 (write-buffered *(ebp+0x10) %eax) -23927 (write-buffered *(ebp+0x10) ": stmt get: output '") -23928 (lookup *edi *(edi+4)) # Var-name Var-name => eax -23929 (write-buffered *(ebp+0x10) %eax) -23930 (write-buffered *(ebp+0x10) "' is not in a register\n") -23931 (flush *(ebp+0x10)) -23932 (stop *(ebp+0x14) 1) -23933 # never gets here -23934 -23935 $check-mu-get-stmt:error-output-type-not-address: -23936 (write-buffered *(ebp+0x10) "fn ") -23937 8b/-> *(ebp+0xc) 0/r32/eax -23938 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23939 (write-buffered *(ebp+0x10) %eax) -23940 (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n") -23941 (flush *(ebp+0x10)) -23942 (stop *(ebp+0x14) 1) -23943 # never gets here -23944 -23945 $check-mu-get-stmt:error-bad-output-type: -23946 (write-buffered *(ebp+0x10) "fn ") -23947 8b/-> *(ebp+0xc) 0/r32/eax -23948 (lookup *eax *(eax+4)) # Function-name Function-name => eax -23949 (write-buffered *(ebp+0x10) %eax) -23950 (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '") -23951 (write-buffered *(ebp+0x10) %ecx) -23952 (write-buffered *(ebp+0x10) "' of type '") -23953 bf/copy-to-edi Type-id/imm32 -23954 8b/-> *(edi+ebx<<2+0xc) 6/r32/esi -23955 { -23956 81 7/subop/compare %esi 0/imm32 -23957 74/jump-if-= break/disp8 -23958 (write-buffered *(ebp+0x10) %esi) -23959 } -23960 (write-buffered *(ebp+0x10) "'\n") -23961 (flush *(ebp+0x10)) -23962 (stop *(ebp+0x14) 1) -23963 # never gets here -23964 -23965 check-mu-index-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -23966 # . prologue -23967 55/push-ebp -23968 89/<- %ebp 4/r32/esp -23969 # . save registers -23970 50/push-eax -23971 51/push-ecx -23972 52/push-edx -23973 53/push-ebx -23974 56/push-esi -23975 57/push-edi -23976 # esi = stmt -23977 8b/-> *(ebp+8) 6/r32/esi -23978 # - check for 0 inouts -23979 # var base/ecx: (addr var) = stmt->inouts->value -23980 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -23981 $check-mu-index-stmt:check-no-inouts: -23982 3d/compare-eax-and 0/imm32 -23983 0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32 -23984 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -23985 89/<- %ecx 0/r32/eax -23986 # - check base type is either (addr array ...) in register or (array ...) on stack -23987 # var base-type/ebx: (addr type-tree) = lookup(base->type) -23988 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -23989 89/<- %ebx 0/r32/eax -23990 # if base-type is an atom, abort with a precise error -23991 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -23992 { -23993 74/jump-if-= break/disp8 -23994 (simple-mu-type? %ebx 3) # array => eax -23995 3d/compare-eax-and 0/imm32/false -23996 0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32 -23997 0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32 -23998 } -23999 $check-mu-index-stmt:base-is-compound: -24000 # if type->left not addr or array, abort -24001 { -24002 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24003 (simple-mu-type? %eax 2) # addr => eax -24004 3d/compare-eax-and 0/imm32/false -24005 75/jump-if-!= break/disp8 -24006 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24007 (simple-mu-type? %eax 3) # array => eax -24008 3d/compare-eax-and 0/imm32/false -24009 75/jump-if-!= break/disp8 -24010 e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32 -24011 } -24012 # if (type->left == addr) ensure type->right->left == array and type->register exists -24013 { -24014 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24015 (simple-mu-type? %eax 2) # addr => eax -24016 3d/compare-eax-and 0/imm32/false -24017 74/jump-if-= break/disp8 -24018 $check-mu-index-stmt:base-is-addr: -24019 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24020 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -24021 (simple-mu-type? %eax 3) # array => eax -24022 3d/compare-eax-and 0/imm32/false -24023 0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32 -24024 $check-mu-index-stmt:check-base-addr-is-register: -24025 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -24026 0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32 -24027 } -24028 # if (type->left == array) ensure type->register doesn't exist -24029 { -24030 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24031 (simple-mu-type? %eax 3) # array => eax -24032 3d/compare-eax-and 0/imm32/false -24033 74/jump-if-= break/disp8 -24034 $check-mu-index-stmt:base-is-array: -24035 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -24036 0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32 -24037 } -24038 # if (base-type->left == addr) base-type = base-type->right -24039 { -24040 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24041 (simple-mu-type? %eax 2) # addr => eax -24042 3d/compare-eax-and 0/imm32/false -24043 74/jump-if-= break/disp8 -24044 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24045 89/<- %ebx 0/r32/eax -24046 } -24047 # - check for 1 inout -24048 # var index/ecx: (addr stmt-var) = stmt->inouts->next->value -24049 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24050 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24051 $check-mu-index-stmt:check-single-inout: -24052 3d/compare-eax-and 0/imm32 -24053 0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32 -24054 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24055 89/<- %ecx 0/r32/eax -24056 # - check index is either a literal or register -24057 # var index-type/edx: (addr type-tree) -24058 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -24059 89/<- %edx 0/r32/eax -24060 # if index type is an atom, it must be a literal or int -24061 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom -24062 { -24063 74/jump-if-= break/disp8 -24064 $check-mu-index-stmt:index-type-is-atom: -24065 (simple-mu-type? %edx 0) # literal => eax -24066 3d/compare-eax-and 0/imm32/false -24067 75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8 -24068 (simple-mu-type? %edx 1) # int => eax -24069 3d/compare-eax-and 0/imm32/false -24070 75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8 -24071 (simple-mu-type? %edx 7) # offset => eax -24072 3d/compare-eax-and 0/imm32/false -24073 0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32 -24074 e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32 -24075 } -24076 # if index type is a non-atom: it must be an offset -24077 { -24078 75/jump-if-!= break/disp8 -24079 $check-mu-index-stmt:index-type-is-non-atom: -24080 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -24081 (simple-mu-type? %eax 7) # offset => eax -24082 3d/compare-eax-and 0/imm32/false -24083 0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32 -24084 } -24085 $check-mu-index-stmt:index-type-done: -24086 # check index is either a literal or in a register -24087 { -24088 (simple-mu-type? %edx 0) # literal => eax -24089 3d/compare-eax-and 0/imm32/false -24090 75/jump-if-!= break/disp8 -24091 $check-mu-index-stmt:check-index-in-register: -24092 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -24093 0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32 -24094 } -24095 # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes. -24096 { -24097 (simple-mu-type? %edx 1) # int => eax -24098 3d/compare-eax-and 0/imm32/false -24099 74/jump-if-= break/disp8 -24100 $check-mu-index-stmt:check-index-can-be-int: -24101 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24102 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24103 (array-element-size %eax) # => eax -24104 3d/compare-eax-and 1/imm32 -24105 74/jump-if-= break/disp8 -24106 3d/compare-eax-and 2/imm32 -24107 74/jump-if-= break/disp8 -24108 3d/compare-eax-and 4/imm32 -24109 74/jump-if-= break/disp8 -24110 3d/compare-eax-and 8/imm32 -24111 74/jump-if-= break/disp8 -24112 e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32 -24113 } -24114 # - check for too many inouts -24115 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24116 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24117 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24118 3d/compare-eax-and 0/imm32/false -24119 0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32 -24120 # - check for 0 outputs -24121 # var output/edi: (addr var) = stmt->outputs->value -24122 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24123 3d/compare-eax-and 0/imm32/false -24124 0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32 -24125 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24126 89/<- %edi 0/r32/eax -24127 # - check output type -24128 # must have a non-atomic type -24129 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -24130 89/<- %edx 0/r32/eax -24131 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom -24132 0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32 -24133 # type must start with (addr ...) -24134 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -24135 (simple-mu-type? %eax 2) # addr => eax -24136 3d/compare-eax-and 0/imm32/false -24137 0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32 -24138 # if tail(base-type) != tail(output-type) abort -24139 (type-tail %ebx) # => eax -24140 89/<- %ebx 0/r32/eax -24141 (type-tail %edx) # => eax -24142 (type-equal? %ebx %eax) # => eax -24143 3d/compare-eax-and 0/imm32/false -24144 0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32 -24145 # - check for too many outputs -24146 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24147 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24148 3d/compare-eax-and 0/imm32/false -24149 0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32 -24150 $check-mu-index-stmt:end: -24151 # . restore registers -24152 5f/pop-to-edi -24153 5e/pop-to-esi -24154 5b/pop-to-ebx -24155 5a/pop-to-edx -24156 59/pop-to-ecx -24157 58/pop-to-eax -24158 # . epilogue -24159 89/<- %esp 5/r32/ebp -24160 5d/pop-to-ebp -24161 c3/return -24162 -24163 $check-mu-index-stmt:error-base-non-array-type: -24164 (write-buffered *(ebp+0x10) "fn ") -24165 8b/-> *(ebp+0xc) 0/r32/eax -24166 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24167 (write-buffered *(ebp+0x10) %eax) -24168 (write-buffered *(ebp+0x10) ": stmt index: var '") -24169 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24170 (write-buffered *(ebp+0x10) %eax) -24171 (write-buffered *(ebp+0x10) "' is not an array\n") -24172 (flush *(ebp+0x10)) -24173 (stop *(ebp+0x14) 1) -24174 # never gets here -24175 -24176 $check-mu-index-stmt:error-base-array-atom-type: -24177 (write-buffered *(ebp+0x10) "fn ") -24178 8b/-> *(ebp+0xc) 0/r32/eax -24179 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24180 (write-buffered *(ebp+0x10) %eax) -24181 (write-buffered *(ebp+0x10) ": stmt index: array '") -24182 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24183 (write-buffered *(ebp+0x10) %eax) -24184 (write-buffered *(ebp+0x10) "' must specify the type of its elements\n") -24185 (flush *(ebp+0x10)) -24186 (stop *(ebp+0x14) 1) -24187 # never gets here -24188 -24189 $check-mu-index-stmt:error-base-address-array-type-on-stack: -24190 (write-buffered *(ebp+0x10) "fn ") -24191 8b/-> *(ebp+0xc) 0/r32/eax -24192 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24193 (write-buffered *(ebp+0x10) %eax) -24194 (write-buffered *(ebp+0x10) ": stmt index: var '") -24195 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24196 (write-buffered *(ebp+0x10) %eax) -24197 (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n") -24198 (flush *(ebp+0x10)) -24199 (stop *(ebp+0x14) 1) -24200 # never gets here -24201 -24202 $check-mu-index-stmt:error-base-array-type-in-register: -24203 (write-buffered *(ebp+0x10) "fn ") -24204 8b/-> *(ebp+0xc) 0/r32/eax -24205 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24206 (write-buffered *(ebp+0x10) %eax) -24207 (write-buffered *(ebp+0x10) ": stmt index: var '") -24208 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24209 (write-buffered *(ebp+0x10) %eax) -24210 (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n") -24211 (flush *(ebp+0x10)) -24212 (stop *(ebp+0x14) 1) -24213 # never gets here -24214 -24215 $check-mu-index-stmt:error-too-few-inouts: -24216 (write-buffered *(ebp+0x10) "fn ") -24217 8b/-> *(ebp+0xc) 0/r32/eax -24218 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24219 (write-buffered *(ebp+0x10) %eax) -24220 (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n") -24221 (flush *(ebp+0x10)) -24222 (stop *(ebp+0x14) 1) -24223 # never gets here -24224 -24225 $check-mu-index-stmt:error-invalid-index-type: -24226 (write-buffered *(ebp+0x10) "fn ") -24227 8b/-> *(ebp+0xc) 0/r32/eax -24228 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24229 (write-buffered *(ebp+0x10) %eax) -24230 (write-buffered *(ebp+0x10) ": stmt index: second argument '") -24231 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24232 (write-buffered *(ebp+0x10) %eax) -24233 (write-buffered *(ebp+0x10) "' must be an int or offset\n") -24234 (flush *(ebp+0x10)) -24235 (stop *(ebp+0x14) 1) -24236 # never gets here -24237 -24238 $check-mu-index-stmt:error-index-offset-atom-type: -24239 (write-buffered *(ebp+0x10) "fn ") -24240 8b/-> *(ebp+0xc) 0/r32/eax -24241 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24242 (write-buffered *(ebp+0x10) %eax) -24243 (write-buffered *(ebp+0x10) ": stmt index: offset '") -24244 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24245 (write-buffered *(ebp+0x10) %eax) -24246 (write-buffered *(ebp+0x10) "' must specify the type of array elements\n") -24247 (flush *(ebp+0x10)) -24248 (stop *(ebp+0x14) 1) -24249 # never gets here -24250 -24251 $check-mu-index-stmt:error-index-on-stack: -24252 (write-buffered *(ebp+0x10) "fn ") -24253 8b/-> *(ebp+0xc) 0/r32/eax -24254 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24255 (write-buffered *(ebp+0x10) %eax) -24256 (write-buffered *(ebp+0x10) ": stmt index: second argument '") -24257 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24258 (write-buffered *(ebp+0x10) %eax) -24259 (write-buffered *(ebp+0x10) "' must be in a register\n") -24260 (flush *(ebp+0x10)) -24261 (stop *(ebp+0x14) 1) -24262 # never gets here -24263 -24264 $check-mu-index-stmt:error-index-needs-offset: -24265 (write-buffered *(ebp+0x10) "fn ") -24266 8b/-> *(ebp+0xc) 0/r32/eax -24267 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24268 (write-buffered *(ebp+0x10) %eax) -24269 (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '") -24270 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24271 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24272 (lookup *eax *(eax+4)) # Var-name Var-name => eax -24273 (write-buffered *(ebp+0x10) %eax) -24274 (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n") -24275 (flush *(ebp+0x10)) -24276 (stop *(ebp+0x14) 1) -24277 # never gets here -24278 -24279 $check-mu-index-stmt:error-too-many-inouts: -24280 (write-buffered *(ebp+0x10) "fn ") -24281 8b/-> *(ebp+0xc) 0/r32/eax -24282 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24283 (write-buffered *(ebp+0x10) %eax) -24284 (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n") -24285 (flush *(ebp+0x10)) -24286 (stop *(ebp+0x14) 1) -24287 # never gets here -24288 -24289 $check-mu-index-stmt:error-too-few-outputs: -24290 (write-buffered *(ebp+0x10) "fn ") -24291 8b/-> *(ebp+0xc) 0/r32/eax -24292 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24293 (write-buffered *(ebp+0x10) %eax) -24294 (write-buffered *(ebp+0x10) ": stmt index: must have an output\n") -24295 (flush *(ebp+0x10)) -24296 (stop *(ebp+0x14) 1) -24297 # never gets here -24298 -24299 $check-mu-index-stmt:error-too-many-outputs: -24300 (write-buffered *(ebp+0x10) "fn ") -24301 8b/-> *(ebp+0xc) 0/r32/eax -24302 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24303 (write-buffered *(ebp+0x10) %eax) -24304 (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n") -24305 (flush *(ebp+0x10)) -24306 (stop *(ebp+0x14) 1) -24307 # never gets here -24308 -24309 $check-mu-index-stmt:error-output-not-in-register: -24310 (write-buffered *(ebp+0x10) "fn ") -24311 8b/-> *(ebp+0xc) 0/r32/eax -24312 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24313 (write-buffered *(ebp+0x10) %eax) -24314 (write-buffered *(ebp+0x10) ": stmt index: output '") -24315 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24316 (write-buffered *(ebp+0x10) %eax) -24317 (write-buffered *(ebp+0x10) "' is not in a register\n") -24318 (flush *(ebp+0x10)) -24319 (stop *(ebp+0x14) 1) -24320 # never gets here -24321 -24322 $check-mu-index-stmt:error-output-type-not-address: -24323 (write-buffered *(ebp+0x10) "fn ") -24324 8b/-> *(ebp+0xc) 0/r32/eax -24325 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24326 (write-buffered *(ebp+0x10) %eax) -24327 (write-buffered *(ebp+0x10) ": stmt index: output '") -24328 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24329 (write-buffered *(ebp+0x10) %eax) -24330 (write-buffered *(ebp+0x10) "' must be an addr\n") -24331 (flush *(ebp+0x10)) -24332 (stop *(ebp+0x14) 1) -24333 # never gets here -24334 -24335 $check-mu-index-stmt:error-bad-output-type: -24336 (write-buffered *(ebp+0x10) "fn ") -24337 8b/-> *(ebp+0xc) 0/r32/eax -24338 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24339 (write-buffered *(ebp+0x10) %eax) -24340 (write-buffered *(ebp+0x10) ": stmt index: output '") -24341 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24342 (write-buffered *(ebp+0x10) %eax) -24343 (write-buffered *(ebp+0x10) "' does not have the right type\n") -24344 (flush *(ebp+0x10)) -24345 (stop *(ebp+0x14) 1) -24346 # never gets here -24347 -24348 check-mu-length-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -24349 # . prologue -24350 55/push-ebp -24351 89/<- %ebp 4/r32/esp -24352 # . save registers -24353 50/push-eax -24354 51/push-ecx -24355 52/push-edx -24356 53/push-ebx -24357 56/push-esi -24358 57/push-edi -24359 # esi = stmt -24360 8b/-> *(ebp+8) 6/r32/esi -24361 # - check for 0 inouts -24362 # var base/ecx: (addr var) = stmt->inouts->value -24363 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24364 $check-mu-length-stmt:check-no-inouts: -24365 3d/compare-eax-and 0/imm32 -24366 0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32 -24367 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24368 89/<- %ecx 0/r32/eax -24369 # - check base type is either (addr array ...) in register or (array ...) on stack -24370 # var base-type/ebx: (addr type-tree) = lookup(base->type) -24371 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -24372 89/<- %ebx 0/r32/eax -24373 # if base-type is an atom, abort with a precise error -24374 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -24375 { -24376 74/jump-if-= break/disp8 -24377 (simple-mu-type? %ebx 3) # array => eax -24378 3d/compare-eax-and 0/imm32/false -24379 0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32 -24380 0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32 -24381 } -24382 $check-mu-length-stmt:base-is-compound: -24383 # if type->left not addr or array, abort -24384 { -24385 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24386 (simple-mu-type? %eax 2) # addr => eax -24387 3d/compare-eax-and 0/imm32/false -24388 75/jump-if-!= break/disp8 -24389 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24390 (simple-mu-type? %eax 3) # array => eax -24391 3d/compare-eax-and 0/imm32/false -24392 75/jump-if-!= break/disp8 -24393 e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32 -24394 } -24395 # if (type->left == addr) ensure type->right->left == array and type->register exists -24396 { -24397 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24398 (simple-mu-type? %eax 2) # addr => eax -24399 3d/compare-eax-and 0/imm32/false -24400 74/jump-if-= break/disp8 -24401 $check-mu-length-stmt:base-is-addr: -24402 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24403 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -24404 (simple-mu-type? %eax 3) # array => eax -24405 3d/compare-eax-and 0/imm32/false -24406 0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32 -24407 $check-mu-length-stmt:check-base-addr-is-register: -24408 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -24409 0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32 -24410 } -24411 # if (type->left == array) ensure type->register doesn't exist -24412 { -24413 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24414 (simple-mu-type? %eax 3) # array => eax -24415 3d/compare-eax-and 0/imm32/false -24416 74/jump-if-= break/disp8 -24417 $check-mu-length-stmt:base-is-array: -24418 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -24419 0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32 -24420 } -24421 # if (base-type->left == addr) base-type = base-type->right -24422 { -24423 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24424 (simple-mu-type? %eax 2) # addr => eax -24425 3d/compare-eax-and 0/imm32/false -24426 74/jump-if-= break/disp8 -24427 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24428 89/<- %ebx 0/r32/eax -24429 } -24430 # - check for too many inouts -24431 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24432 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24433 3d/compare-eax-and 0/imm32/false -24434 0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32 -24435 # - check for 0 outputs -24436 # var output/edi: (addr var) = stmt->outputs->value -24437 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24438 3d/compare-eax-and 0/imm32/false -24439 0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32 -24440 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24441 89/<- %edi 0/r32/eax -24442 # - check output type -24443 # must have a non-atomic type -24444 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -24445 (simple-mu-type? %eax 1) # int => eax -24446 3d/compare-eax-and 0/imm32/false -24447 0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32 -24448 # - check for too many outputs -24449 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24450 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24451 3d/compare-eax-and 0/imm32/false -24452 0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32 -24453 $check-mu-length-stmt:end: -24454 # . restore registers -24455 5f/pop-to-edi -24456 5e/pop-to-esi -24457 5b/pop-to-ebx -24458 5a/pop-to-edx -24459 59/pop-to-ecx -24460 58/pop-to-eax -24461 # . epilogue -24462 89/<- %esp 5/r32/ebp -24463 5d/pop-to-ebp -24464 c3/return -24465 -24466 $check-mu-length-stmt:error-base-non-array-type: -24467 (write-buffered *(ebp+0x10) "fn ") -24468 8b/-> *(ebp+0xc) 0/r32/eax -24469 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24470 (write-buffered *(ebp+0x10) %eax) -24471 (write-buffered *(ebp+0x10) ": stmt length: var '") -24472 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24473 (write-buffered *(ebp+0x10) %eax) -24474 (write-buffered *(ebp+0x10) "' is not an array\n") -24475 (flush *(ebp+0x10)) -24476 (stop *(ebp+0x14) 1) -24477 # never gets here -24478 -24479 $check-mu-length-stmt:error-base-array-atom-type: -24480 (write-buffered *(ebp+0x10) "fn ") -24481 8b/-> *(ebp+0xc) 0/r32/eax -24482 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24483 (write-buffered *(ebp+0x10) %eax) -24484 (write-buffered *(ebp+0x10) ": stmt length: array '") -24485 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24486 (write-buffered *(ebp+0x10) %eax) -24487 (write-buffered *(ebp+0x10) "' must specify the type of its elements\n") -24488 (flush *(ebp+0x10)) -24489 (stop *(ebp+0x14) 1) -24490 # never gets here -24491 -24492 $check-mu-length-stmt:error-base-address-array-type-on-stack: -24493 (write-buffered *(ebp+0x10) "fn ") -24494 8b/-> *(ebp+0xc) 0/r32/eax -24495 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24496 (write-buffered *(ebp+0x10) %eax) -24497 (write-buffered *(ebp+0x10) ": stmt length: var '") -24498 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24499 (write-buffered *(ebp+0x10) %eax) -24500 (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n") -24501 (flush *(ebp+0x10)) -24502 (stop *(ebp+0x14) 1) -24503 # never gets here -24504 -24505 $check-mu-length-stmt:error-base-array-type-in-register: -24506 (write-buffered *(ebp+0x10) "fn ") -24507 8b/-> *(ebp+0xc) 0/r32/eax -24508 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24509 (write-buffered *(ebp+0x10) %eax) -24510 (write-buffered *(ebp+0x10) ": stmt length: var '") -24511 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24512 (write-buffered *(ebp+0x10) %eax) -24513 (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n") -24514 (flush *(ebp+0x10)) -24515 (stop *(ebp+0x14) 1) -24516 # never gets here -24517 -24518 $check-mu-length-stmt:error-too-few-inouts: -24519 (write-buffered *(ebp+0x10) "fn ") -24520 8b/-> *(ebp+0xc) 0/r32/eax -24521 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24522 (write-buffered *(ebp+0x10) %eax) -24523 (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n") -24524 (flush *(ebp+0x10)) -24525 (stop *(ebp+0x14) 1) -24526 # never gets here -24527 -24528 $check-mu-length-stmt:error-invalid-index-type: -24529 (write-buffered *(ebp+0x10) "fn ") -24530 8b/-> *(ebp+0xc) 0/r32/eax -24531 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24532 (write-buffered *(ebp+0x10) %eax) -24533 (write-buffered *(ebp+0x10) ": stmt length: second argument '") -24534 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24535 (write-buffered *(ebp+0x10) %eax) -24536 (write-buffered *(ebp+0x10) "' must be an int or offset\n") -24537 (flush *(ebp+0x10)) -24538 (stop *(ebp+0x14) 1) -24539 # never gets here -24540 -24541 $check-mu-length-stmt:error-index-offset-atom-type: -24542 (write-buffered *(ebp+0x10) "fn ") -24543 8b/-> *(ebp+0xc) 0/r32/eax -24544 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24545 (write-buffered *(ebp+0x10) %eax) -24546 (write-buffered *(ebp+0x10) ": stmt length: offset '") -24547 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24548 (write-buffered *(ebp+0x10) %eax) -24549 (write-buffered *(ebp+0x10) "' must specify the type of array elements\n") -24550 (flush *(ebp+0x10)) -24551 (stop *(ebp+0x14) 1) -24552 # never gets here -24553 -24554 $check-mu-length-stmt:error-index-on-stack: -24555 (write-buffered *(ebp+0x10) "fn ") -24556 8b/-> *(ebp+0xc) 0/r32/eax -24557 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24558 (write-buffered *(ebp+0x10) %eax) -24559 (write-buffered *(ebp+0x10) ": stmt length: second argument '") -24560 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24561 (write-buffered *(ebp+0x10) %eax) -24562 (write-buffered *(ebp+0x10) "' must be in a register\n") -24563 (flush *(ebp+0x10)) -24564 (stop *(ebp+0x14) 1) -24565 # never gets here -24566 -24567 $check-mu-length-stmt:error-index-needs-offset: -24568 (write-buffered *(ebp+0x10) "fn ") -24569 8b/-> *(ebp+0xc) 0/r32/eax -24570 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24571 (write-buffered *(ebp+0x10) %eax) -24572 (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '") -24573 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24574 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24575 (lookup *eax *(eax+4)) # Var-name Var-name => eax -24576 (write-buffered *(ebp+0x10) %eax) -24577 (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n") -24578 (flush *(ebp+0x10)) -24579 (stop *(ebp+0x14) 1) -24580 # never gets here -24581 -24582 $check-mu-length-stmt:error-too-many-inouts: -24583 (write-buffered *(ebp+0x10) "fn ") -24584 8b/-> *(ebp+0xc) 0/r32/eax -24585 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24586 (write-buffered *(ebp+0x10) %eax) -24587 (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n") -24588 (flush *(ebp+0x10)) -24589 (stop *(ebp+0x14) 1) -24590 # never gets here -24591 -24592 $check-mu-length-stmt:error-too-few-outputs: -24593 (write-buffered *(ebp+0x10) "fn ") -24594 8b/-> *(ebp+0xc) 0/r32/eax -24595 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24596 (write-buffered *(ebp+0x10) %eax) -24597 (write-buffered *(ebp+0x10) ": stmt length: must have an output\n") -24598 (flush *(ebp+0x10)) -24599 (stop *(ebp+0x14) 1) -24600 # never gets here -24601 -24602 $check-mu-length-stmt:error-too-many-outputs: -24603 (write-buffered *(ebp+0x10) "fn ") -24604 8b/-> *(ebp+0xc) 0/r32/eax -24605 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24606 (write-buffered *(ebp+0x10) %eax) -24607 (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n") -24608 (flush *(ebp+0x10)) -24609 (stop *(ebp+0x14) 1) -24610 # never gets here -24611 -24612 $check-mu-length-stmt:error-output-not-in-register: -24613 (write-buffered *(ebp+0x10) "fn ") -24614 8b/-> *(ebp+0xc) 0/r32/eax -24615 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24616 (write-buffered *(ebp+0x10) %eax) -24617 (write-buffered *(ebp+0x10) ": stmt length: output '") -24618 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24619 (write-buffered *(ebp+0x10) %eax) -24620 (write-buffered *(ebp+0x10) "' is not in a register\n") -24621 (flush *(ebp+0x10)) -24622 (stop *(ebp+0x14) 1) -24623 # never gets here -24624 -24625 $check-mu-length-stmt:error-invalid-output-type: -24626 (write-buffered *(ebp+0x10) "fn ") -24627 8b/-> *(ebp+0xc) 0/r32/eax -24628 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24629 (write-buffered *(ebp+0x10) %eax) -24630 (write-buffered *(ebp+0x10) ": stmt length: output '") -24631 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24632 (write-buffered *(ebp+0x10) %eax) -24633 (write-buffered *(ebp+0x10) "' does not have the right type\n") -24634 (flush *(ebp+0x10)) -24635 (stop *(ebp+0x14) 1) -24636 # never gets here -24637 -24638 check-mu-compute-offset-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -24639 # . prologue -24640 55/push-ebp -24641 89/<- %ebp 4/r32/esp -24642 # . save registers -24643 50/push-eax -24644 51/push-ecx -24645 52/push-edx -24646 53/push-ebx -24647 56/push-esi -24648 57/push-edi -24649 # esi = stmt -24650 8b/-> *(ebp+8) 6/r32/esi -24651 # - check for 0 inouts -24652 # var base/ecx: (addr var) = stmt->inouts->value -24653 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24654 $check-mu-compute-offset-stmt:check-no-inouts: -24655 3d/compare-eax-and 0/imm32 -24656 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32 -24657 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24658 89/<- %ecx 0/r32/eax -24659 # - check base type is either (addr array ...) in register or (array ...) on stack -24660 # var base-type/ebx: (addr type-tree) = lookup(base->type) -24661 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -24662 89/<- %ebx 0/r32/eax -24663 # if base-type is an atom, abort with a precise error -24664 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -24665 { -24666 74/jump-if-= break/disp8 -24667 (simple-mu-type? %ebx 3) # array => eax -24668 3d/compare-eax-and 0/imm32/false -24669 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32 -24670 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32 -24671 } -24672 $check-mu-compute-offset-stmt:base-is-compound: -24673 # if type->left not addr or array, abort -24674 { -24675 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24676 (simple-mu-type? %eax 2) # addr => eax -24677 3d/compare-eax-and 0/imm32/false -24678 75/jump-if-!= break/disp8 -24679 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24680 (simple-mu-type? %eax 3) # array => eax -24681 3d/compare-eax-and 0/imm32/false -24682 75/jump-if-!= break/disp8 -24683 e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32 -24684 } -24685 # if (type->left == addr) ensure type->right->left == array and type->register exists -24686 { -24687 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24688 (simple-mu-type? %eax 2) # addr => eax -24689 3d/compare-eax-and 0/imm32/false -24690 74/jump-if-= break/disp8 -24691 $check-mu-compute-offset-stmt:base-is-addr: -24692 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24693 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -24694 (simple-mu-type? %eax 3) # array => eax -24695 3d/compare-eax-and 0/imm32/false -24696 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32 -24697 } -24698 # if (base-type->left == addr) base-type = base-type->right -24699 { -24700 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -24701 (simple-mu-type? %eax 2) # addr => eax -24702 3d/compare-eax-and 0/imm32/false -24703 74/jump-if-= break/disp8 -24704 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24705 89/<- %ebx 0/r32/eax +23783 0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32 +23784 # var output/edi: (addr var) = stmt->outputs->value +23785 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +23786 # - check for 0 outputs +23787 3d/compare-eax-and 0/imm32/false +23788 0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32 +23789 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +23790 89/<- %edi 0/r32/eax +23791 $check-mu-get-stmt:check-output-type: +23792 # - check output type +23793 # must be in register +23794 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax +23795 3d/compare-eax-and 0/imm32 +23796 0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32 +23797 # must have a non-atomic type +23798 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +23799 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +23800 0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32 +23801 # type must start with (addr ...) +23802 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23803 (simple-mu-type? %eax 2) # => eax +23804 3d/compare-eax-and 0/imm32/false +23805 0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32 +23806 $check-mu-get-stmt:check-output-type-match: +23807 # payload of addr type must match 'type' definition +23808 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +23809 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +23810 # if (payload->right == null) payload = payload->left +23811 81 7/subop/compare *(eax+0xc) 0/imm32/null # Type-tree-right +23812 { +23813 75/jump-if-!= break/disp8 +23814 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +23815 } +23816 89/<- %edi 0/r32/eax +23817 # . var output-name/ecx: (addr array byte) +23818 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +23819 89/<- %ecx 0/r32/eax +23820 # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry) +23821 (lookup *(edx+4) *(edx+8)) # Typeinfo-fields Typeinfo-fields => eax +23822 (get %eax %ecx 0x10) # => eax +23823 # . +23824 (lookup *eax *(eax+4)) # => eax +23825 (lookup *eax *(eax+4)) # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax +23826 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +23827 # . +23828 (type-equal? %edi %eax) # => eax +23829 3d/compare-eax-and 0/imm32/false +23830 0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32 +23831 # - check for too many outputs +23832 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +23833 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +23834 3d/compare-eax-and 0/imm32/false +23835 0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32 +23836 $check-mu-get-stmt:end: +23837 # . restore registers +23838 5f/pop-to-edi +23839 5e/pop-to-esi +23840 5b/pop-to-ebx +23841 5a/pop-to-edx +23842 59/pop-to-ecx +23843 58/pop-to-eax +23844 # . epilogue +23845 89/<- %esp 5/r32/ebp +23846 5d/pop-to-ebp +23847 c3/return +23848 +23849 $check-mu-get-stmt:error-too-few-inouts: +23850 (write-buffered *(ebp+0x10) "fn ") +23851 8b/-> *(ebp+0xc) 0/r32/eax +23852 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23853 (write-buffered *(ebp+0x10) %eax) +23854 (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n") +23855 (flush *(ebp+0x10)) +23856 (stop *(ebp+0x14) 1) +23857 # never gets here +23858 +23859 $check-mu-get-stmt:error-too-many-inouts: +23860 (write-buffered *(ebp+0x10) "fn ") +23861 8b/-> *(ebp+0xc) 0/r32/eax +23862 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23863 (write-buffered *(ebp+0x10) %eax) +23864 (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n") +23865 (flush *(ebp+0x10)) +23866 (stop *(ebp+0x14) 1) +23867 # never gets here +23868 +23869 $check-mu-get-stmt:error-too-few-outputs: +23870 (write-buffered *(ebp+0x10) "fn ") +23871 8b/-> *(ebp+0xc) 0/r32/eax +23872 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23873 (write-buffered *(ebp+0x10) %eax) +23874 (write-buffered *(ebp+0x10) ": stmt get: must have an output\n") +23875 (flush *(ebp+0x10)) +23876 (stop *(ebp+0x14) 1) +23877 # never gets here +23878 +23879 $check-mu-get-stmt:error-too-many-outputs: +23880 (write-buffered *(ebp+0x10) "fn ") +23881 8b/-> *(ebp+0xc) 0/r32/eax +23882 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23883 (write-buffered *(ebp+0x10) %eax) +23884 (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n") +23885 (flush *(ebp+0x10)) +23886 (stop *(ebp+0x14) 1) +23887 # never gets here +23888 +23889 $check-mu-get-stmt:error-bad-base: +23890 # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n") +23891 (write-buffered *(ebp+0x10) "fn ") +23892 8b/-> *(ebp+0xc) 0/r32/eax +23893 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23894 (write-buffered *(ebp+0x10) %eax) +23895 (write-buffered *(ebp+0x10) ": stmt get: var '") +23896 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23897 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +23898 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23899 (write-buffered *(ebp+0x10) %eax) +23900 (write-buffered *(ebp+0x10) "' must have a 'type' definition\n") +23901 (flush *(ebp+0x10)) +23902 (stop *(ebp+0x14) 1) +23903 # never gets here +23904 +23905 $check-mu-get-stmt:error-base-type-addr-but-not-register: +23906 (write-buffered *(ebp+0x10) "fn ") +23907 8b/-> *(ebp+0xc) 0/r32/eax +23908 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23909 (write-buffered *(ebp+0x10) %eax) +23910 (write-buffered *(ebp+0x10) ": stmt get: var '") +23911 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +23912 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +23913 (lookup *eax *(eax+4)) # Var-name Var-name => eax +23914 (write-buffered *(ebp+0x10) %eax) +23915 (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n") +23916 (flush *(ebp+0x10)) +23917 (stop *(ebp+0x14) 1) +23918 # never gets here +23919 +23920 $check-mu-get-stmt:error-bad-field: +23921 # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n") +23922 (write-buffered *(ebp+0x10) "fn ") +23923 8b/-> *(ebp+0xc) 0/r32/eax +23924 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23925 (write-buffered *(ebp+0x10) %eax) +23926 (write-buffered *(ebp+0x10) ": stmt get: type '") +23927 # . write(Type-id->data[tmp]) +23928 bf/copy-to-edi Type-id/imm32 +23929 8b/-> *(edi+ebx<<2+0xc) 6/r32/esi +23930 { +23931 81 7/subop/compare %esi 0/imm32 +23932 74/jump-if-= break/disp8 +23933 (write-buffered *(ebp+0x10) %esi) +23934 } +23935 # . +23936 (write-buffered *(ebp+0x10) "' has no member called '") +23937 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +23938 (write-buffered *(ebp+0x10) %eax) +23939 (write-buffered *(ebp+0x10) "'\n") +23940 (flush *(ebp+0x10)) +23941 (stop *(ebp+0x14) 1) +23942 # never gets here +23943 +23944 $check-mu-get-stmt:error-output-not-in-register: +23945 (write-buffered *(ebp+0x10) "fn ") +23946 8b/-> *(ebp+0xc) 0/r32/eax +23947 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23948 (write-buffered *(ebp+0x10) %eax) +23949 (write-buffered *(ebp+0x10) ": stmt get: output '") +23950 (lookup *edi *(edi+4)) # Var-name Var-name => eax +23951 (write-buffered *(ebp+0x10) %eax) +23952 (write-buffered *(ebp+0x10) "' is not in a register\n") +23953 (flush *(ebp+0x10)) +23954 (stop *(ebp+0x14) 1) +23955 # never gets here +23956 +23957 $check-mu-get-stmt:error-output-type-not-address: +23958 (write-buffered *(ebp+0x10) "fn ") +23959 8b/-> *(ebp+0xc) 0/r32/eax +23960 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23961 (write-buffered *(ebp+0x10) %eax) +23962 (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n") +23963 (flush *(ebp+0x10)) +23964 (stop *(ebp+0x14) 1) +23965 # never gets here +23966 +23967 $check-mu-get-stmt:error-bad-output-type: +23968 (write-buffered *(ebp+0x10) "fn ") +23969 8b/-> *(ebp+0xc) 0/r32/eax +23970 (lookup *eax *(eax+4)) # Function-name Function-name => eax +23971 (write-buffered *(ebp+0x10) %eax) +23972 (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '") +23973 (write-buffered *(ebp+0x10) %ecx) +23974 (write-buffered *(ebp+0x10) "' of type '") +23975 bf/copy-to-edi Type-id/imm32 +23976 8b/-> *(edi+ebx<<2+0xc) 6/r32/esi +23977 { +23978 81 7/subop/compare %esi 0/imm32 +23979 74/jump-if-= break/disp8 +23980 (write-buffered *(ebp+0x10) %esi) +23981 } +23982 (write-buffered *(ebp+0x10) "'\n") +23983 (flush *(ebp+0x10)) +23984 (stop *(ebp+0x14) 1) +23985 # never gets here +23986 +23987 check-mu-index-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +23988 # . prologue +23989 55/push-ebp +23990 89/<- %ebp 4/r32/esp +23991 # . save registers +23992 50/push-eax +23993 51/push-ecx +23994 52/push-edx +23995 53/push-ebx +23996 56/push-esi +23997 57/push-edi +23998 # esi = stmt +23999 8b/-> *(ebp+8) 6/r32/esi +24000 # - check for 0 inouts +24001 # var base/ecx: (addr var) = stmt->inouts->value +24002 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24003 $check-mu-index-stmt:check-no-inouts: +24004 3d/compare-eax-and 0/imm32 +24005 0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32 +24006 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24007 89/<- %ecx 0/r32/eax +24008 # - check base type is either (addr array ...) in register or (array ...) on stack +24009 # var base-type/ebx: (addr type-tree) = lookup(base->type) +24010 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +24011 89/<- %ebx 0/r32/eax +24012 # if base-type is an atom, abort with a precise error +24013 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +24014 { +24015 74/jump-if-= break/disp8 +24016 (simple-mu-type? %ebx 3) # array => eax +24017 3d/compare-eax-and 0/imm32/false +24018 0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32 +24019 0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32 +24020 } +24021 $check-mu-index-stmt:base-is-compound: +24022 # if type->left not addr or array, abort +24023 { +24024 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24025 (simple-mu-type? %eax 2) # addr => eax +24026 3d/compare-eax-and 0/imm32/false +24027 75/jump-if-!= break/disp8 +24028 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24029 (simple-mu-type? %eax 3) # array => eax +24030 3d/compare-eax-and 0/imm32/false +24031 75/jump-if-!= break/disp8 +24032 e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32 +24033 } +24034 # if (type->left == addr) ensure type->right->left == array and type->register exists +24035 { +24036 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24037 (simple-mu-type? %eax 2) # addr => eax +24038 3d/compare-eax-and 0/imm32/false +24039 74/jump-if-= break/disp8 +24040 $check-mu-index-stmt:base-is-addr: +24041 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +24042 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +24043 (simple-mu-type? %eax 3) # array => eax +24044 3d/compare-eax-and 0/imm32/false +24045 0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32 +24046 $check-mu-index-stmt:check-base-addr-is-register: +24047 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +24048 0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32 +24049 } +24050 # if (type->left == array) ensure type->register doesn't exist +24051 { +24052 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24053 (simple-mu-type? %eax 3) # array => eax +24054 3d/compare-eax-and 0/imm32/false +24055 74/jump-if-= break/disp8 +24056 $check-mu-index-stmt:base-is-array: +24057 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +24058 0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32 +24059 } +24060 # if (base-type->left == addr) base-type = base-type->right +24061 { +24062 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24063 (simple-mu-type? %eax 2) # addr => eax +24064 3d/compare-eax-and 0/imm32/false +24065 74/jump-if-= break/disp8 +24066 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +24067 89/<- %ebx 0/r32/eax +24068 } +24069 # - check for 1 inout +24070 # var index/ecx: (addr stmt-var) = stmt->inouts->next->value +24071 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24072 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24073 $check-mu-index-stmt:check-single-inout: +24074 3d/compare-eax-and 0/imm32 +24075 0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32 +24076 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24077 89/<- %ecx 0/r32/eax +24078 # - check index is either a literal or register +24079 # var index-type/edx: (addr type-tree) +24080 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +24081 89/<- %edx 0/r32/eax +24082 # if index type is an atom, it must be a literal or int +24083 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom +24084 { +24085 74/jump-if-= break/disp8 +24086 $check-mu-index-stmt:index-type-is-atom: +24087 (simple-mu-type? %edx 0) # literal => eax +24088 3d/compare-eax-and 0/imm32/false +24089 75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8 +24090 (simple-mu-type? %edx 1) # int => eax +24091 3d/compare-eax-and 0/imm32/false +24092 75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8 +24093 (simple-mu-type? %edx 7) # offset => eax +24094 3d/compare-eax-and 0/imm32/false +24095 0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32 +24096 e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32 +24097 } +24098 # if index type is a non-atom: it must be an offset +24099 { +24100 75/jump-if-!= break/disp8 +24101 $check-mu-index-stmt:index-type-is-non-atom: +24102 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +24103 (simple-mu-type? %eax 7) # offset => eax +24104 3d/compare-eax-and 0/imm32/false +24105 0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32 +24106 } +24107 $check-mu-index-stmt:index-type-done: +24108 # check index is either a literal or in a register +24109 { +24110 (simple-mu-type? %edx 0) # literal => eax +24111 3d/compare-eax-and 0/imm32/false +24112 75/jump-if-!= break/disp8 +24113 $check-mu-index-stmt:check-index-in-register: +24114 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +24115 0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32 +24116 } +24117 # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes. +24118 { +24119 (simple-mu-type? %edx 1) # int => eax +24120 3d/compare-eax-and 0/imm32/false +24121 74/jump-if-= break/disp8 +24122 $check-mu-index-stmt:check-index-can-be-int: +24123 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24124 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24125 (array-element-size %eax) # => eax +24126 3d/compare-eax-and 1/imm32 +24127 74/jump-if-= break/disp8 +24128 3d/compare-eax-and 2/imm32 +24129 74/jump-if-= break/disp8 +24130 3d/compare-eax-and 4/imm32 +24131 74/jump-if-= break/disp8 +24132 3d/compare-eax-and 8/imm32 +24133 74/jump-if-= break/disp8 +24134 e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32 +24135 } +24136 # - check for too many inouts +24137 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24138 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24139 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24140 3d/compare-eax-and 0/imm32/false +24141 0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32 +24142 # - check for 0 outputs +24143 # var output/edi: (addr var) = stmt->outputs->value +24144 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24145 3d/compare-eax-and 0/imm32/false +24146 0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32 +24147 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24148 89/<- %edi 0/r32/eax +24149 # - check output type +24150 # must have a non-atomic type +24151 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +24152 89/<- %edx 0/r32/eax +24153 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom +24154 0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32 +24155 # type must start with (addr ...) +24156 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +24157 (simple-mu-type? %eax 2) # addr => eax +24158 3d/compare-eax-and 0/imm32/false +24159 0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32 +24160 # if tail(base-type) != tail(output-type) abort +24161 (type-tail %ebx) # => eax +24162 89/<- %ebx 0/r32/eax +24163 (type-tail %edx) # => eax +24164 (type-equal? %ebx %eax) # => eax +24165 3d/compare-eax-and 0/imm32/false +24166 0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32 +24167 # - check for too many outputs +24168 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24169 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24170 3d/compare-eax-and 0/imm32/false +24171 0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32 +24172 $check-mu-index-stmt:end: +24173 # . restore registers +24174 5f/pop-to-edi +24175 5e/pop-to-esi +24176 5b/pop-to-ebx +24177 5a/pop-to-edx +24178 59/pop-to-ecx +24179 58/pop-to-eax +24180 # . epilogue +24181 89/<- %esp 5/r32/ebp +24182 5d/pop-to-ebp +24183 c3/return +24184 +24185 $check-mu-index-stmt:error-base-non-array-type: +24186 (write-buffered *(ebp+0x10) "fn ") +24187 8b/-> *(ebp+0xc) 0/r32/eax +24188 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24189 (write-buffered *(ebp+0x10) %eax) +24190 (write-buffered *(ebp+0x10) ": stmt index: var '") +24191 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24192 (write-buffered *(ebp+0x10) %eax) +24193 (write-buffered *(ebp+0x10) "' is not an array\n") +24194 (flush *(ebp+0x10)) +24195 (stop *(ebp+0x14) 1) +24196 # never gets here +24197 +24198 $check-mu-index-stmt:error-base-array-atom-type: +24199 (write-buffered *(ebp+0x10) "fn ") +24200 8b/-> *(ebp+0xc) 0/r32/eax +24201 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24202 (write-buffered *(ebp+0x10) %eax) +24203 (write-buffered *(ebp+0x10) ": stmt index: array '") +24204 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24205 (write-buffered *(ebp+0x10) %eax) +24206 (write-buffered *(ebp+0x10) "' must specify the type of its elements\n") +24207 (flush *(ebp+0x10)) +24208 (stop *(ebp+0x14) 1) +24209 # never gets here +24210 +24211 $check-mu-index-stmt:error-base-address-array-type-on-stack: +24212 (write-buffered *(ebp+0x10) "fn ") +24213 8b/-> *(ebp+0xc) 0/r32/eax +24214 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24215 (write-buffered *(ebp+0x10) %eax) +24216 (write-buffered *(ebp+0x10) ": stmt index: var '") +24217 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24218 (write-buffered *(ebp+0x10) %eax) +24219 (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n") +24220 (flush *(ebp+0x10)) +24221 (stop *(ebp+0x14) 1) +24222 # never gets here +24223 +24224 $check-mu-index-stmt:error-base-array-type-in-register: +24225 (write-buffered *(ebp+0x10) "fn ") +24226 8b/-> *(ebp+0xc) 0/r32/eax +24227 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24228 (write-buffered *(ebp+0x10) %eax) +24229 (write-buffered *(ebp+0x10) ": stmt index: var '") +24230 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24231 (write-buffered *(ebp+0x10) %eax) +24232 (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n") +24233 (flush *(ebp+0x10)) +24234 (stop *(ebp+0x14) 1) +24235 # never gets here +24236 +24237 $check-mu-index-stmt:error-too-few-inouts: +24238 (write-buffered *(ebp+0x10) "fn ") +24239 8b/-> *(ebp+0xc) 0/r32/eax +24240 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24241 (write-buffered *(ebp+0x10) %eax) +24242 (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n") +24243 (flush *(ebp+0x10)) +24244 (stop *(ebp+0x14) 1) +24245 # never gets here +24246 +24247 $check-mu-index-stmt:error-invalid-index-type: +24248 (write-buffered *(ebp+0x10) "fn ") +24249 8b/-> *(ebp+0xc) 0/r32/eax +24250 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24251 (write-buffered *(ebp+0x10) %eax) +24252 (write-buffered *(ebp+0x10) ": stmt index: second argument '") +24253 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24254 (write-buffered *(ebp+0x10) %eax) +24255 (write-buffered *(ebp+0x10) "' must be an int or offset\n") +24256 (flush *(ebp+0x10)) +24257 (stop *(ebp+0x14) 1) +24258 # never gets here +24259 +24260 $check-mu-index-stmt:error-index-offset-atom-type: +24261 (write-buffered *(ebp+0x10) "fn ") +24262 8b/-> *(ebp+0xc) 0/r32/eax +24263 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24264 (write-buffered *(ebp+0x10) %eax) +24265 (write-buffered *(ebp+0x10) ": stmt index: offset '") +24266 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24267 (write-buffered *(ebp+0x10) %eax) +24268 (write-buffered *(ebp+0x10) "' must specify the type of array elements\n") +24269 (flush *(ebp+0x10)) +24270 (stop *(ebp+0x14) 1) +24271 # never gets here +24272 +24273 $check-mu-index-stmt:error-index-on-stack: +24274 (write-buffered *(ebp+0x10) "fn ") +24275 8b/-> *(ebp+0xc) 0/r32/eax +24276 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24277 (write-buffered *(ebp+0x10) %eax) +24278 (write-buffered *(ebp+0x10) ": stmt index: second argument '") +24279 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24280 (write-buffered *(ebp+0x10) %eax) +24281 (write-buffered *(ebp+0x10) "' must be in a register\n") +24282 (flush *(ebp+0x10)) +24283 (stop *(ebp+0x14) 1) +24284 # never gets here +24285 +24286 $check-mu-index-stmt:error-index-needs-offset: +24287 (write-buffered *(ebp+0x10) "fn ") +24288 8b/-> *(ebp+0xc) 0/r32/eax +24289 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24290 (write-buffered *(ebp+0x10) %eax) +24291 (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '") +24292 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24293 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24294 (lookup *eax *(eax+4)) # Var-name Var-name => eax +24295 (write-buffered *(ebp+0x10) %eax) +24296 (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n") +24297 (flush *(ebp+0x10)) +24298 (stop *(ebp+0x14) 1) +24299 # never gets here +24300 +24301 $check-mu-index-stmt:error-too-many-inouts: +24302 (write-buffered *(ebp+0x10) "fn ") +24303 8b/-> *(ebp+0xc) 0/r32/eax +24304 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24305 (write-buffered *(ebp+0x10) %eax) +24306 (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n") +24307 (flush *(ebp+0x10)) +24308 (stop *(ebp+0x14) 1) +24309 # never gets here +24310 +24311 $check-mu-index-stmt:error-too-few-outputs: +24312 (write-buffered *(ebp+0x10) "fn ") +24313 8b/-> *(ebp+0xc) 0/r32/eax +24314 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24315 (write-buffered *(ebp+0x10) %eax) +24316 (write-buffered *(ebp+0x10) ": stmt index: must have an output\n") +24317 (flush *(ebp+0x10)) +24318 (stop *(ebp+0x14) 1) +24319 # never gets here +24320 +24321 $check-mu-index-stmt:error-too-many-outputs: +24322 (write-buffered *(ebp+0x10) "fn ") +24323 8b/-> *(ebp+0xc) 0/r32/eax +24324 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24325 (write-buffered *(ebp+0x10) %eax) +24326 (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n") +24327 (flush *(ebp+0x10)) +24328 (stop *(ebp+0x14) 1) +24329 # never gets here +24330 +24331 $check-mu-index-stmt:error-output-not-in-register: +24332 (write-buffered *(ebp+0x10) "fn ") +24333 8b/-> *(ebp+0xc) 0/r32/eax +24334 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24335 (write-buffered *(ebp+0x10) %eax) +24336 (write-buffered *(ebp+0x10) ": stmt index: output '") +24337 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24338 (write-buffered *(ebp+0x10) %eax) +24339 (write-buffered *(ebp+0x10) "' is not in a register\n") +24340 (flush *(ebp+0x10)) +24341 (stop *(ebp+0x14) 1) +24342 # never gets here +24343 +24344 $check-mu-index-stmt:error-output-type-not-address: +24345 (write-buffered *(ebp+0x10) "fn ") +24346 8b/-> *(ebp+0xc) 0/r32/eax +24347 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24348 (write-buffered *(ebp+0x10) %eax) +24349 (write-buffered *(ebp+0x10) ": stmt index: output '") +24350 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24351 (write-buffered *(ebp+0x10) %eax) +24352 (write-buffered *(ebp+0x10) "' must be an addr\n") +24353 (flush *(ebp+0x10)) +24354 (stop *(ebp+0x14) 1) +24355 # never gets here +24356 +24357 $check-mu-index-stmt:error-bad-output-type: +24358 (write-buffered *(ebp+0x10) "fn ") +24359 8b/-> *(ebp+0xc) 0/r32/eax +24360 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24361 (write-buffered *(ebp+0x10) %eax) +24362 (write-buffered *(ebp+0x10) ": stmt index: output '") +24363 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24364 (write-buffered *(ebp+0x10) %eax) +24365 (write-buffered *(ebp+0x10) "' does not have the right type\n") +24366 (flush *(ebp+0x10)) +24367 (stop *(ebp+0x14) 1) +24368 # never gets here +24369 +24370 check-mu-length-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +24371 # . prologue +24372 55/push-ebp +24373 89/<- %ebp 4/r32/esp +24374 # . save registers +24375 50/push-eax +24376 51/push-ecx +24377 52/push-edx +24378 53/push-ebx +24379 56/push-esi +24380 57/push-edi +24381 # esi = stmt +24382 8b/-> *(ebp+8) 6/r32/esi +24383 # - check for 0 inouts +24384 # var base/ecx: (addr var) = stmt->inouts->value +24385 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24386 $check-mu-length-stmt:check-no-inouts: +24387 3d/compare-eax-and 0/imm32 +24388 0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32 +24389 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24390 89/<- %ecx 0/r32/eax +24391 # - check base type is either (addr array ...) in register or (array ...) on stack +24392 # var base-type/ebx: (addr type-tree) = lookup(base->type) +24393 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +24394 89/<- %ebx 0/r32/eax +24395 # if base-type is an atom, abort with a precise error +24396 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +24397 { +24398 74/jump-if-= break/disp8 +24399 (simple-mu-type? %ebx 3) # array => eax +24400 3d/compare-eax-and 0/imm32/false +24401 0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32 +24402 0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32 +24403 } +24404 $check-mu-length-stmt:base-is-compound: +24405 # if type->left not addr or array, abort +24406 { +24407 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24408 (simple-mu-type? %eax 2) # addr => eax +24409 3d/compare-eax-and 0/imm32/false +24410 75/jump-if-!= break/disp8 +24411 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24412 (simple-mu-type? %eax 3) # array => eax +24413 3d/compare-eax-and 0/imm32/false +24414 75/jump-if-!= break/disp8 +24415 e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32 +24416 } +24417 # if (type->left == addr) ensure type->right->left == array and type->register exists +24418 { +24419 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24420 (simple-mu-type? %eax 2) # addr => eax +24421 3d/compare-eax-and 0/imm32/false +24422 74/jump-if-= break/disp8 +24423 $check-mu-length-stmt:base-is-addr: +24424 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +24425 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +24426 (simple-mu-type? %eax 3) # array => eax +24427 3d/compare-eax-and 0/imm32/false +24428 0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32 +24429 $check-mu-length-stmt:check-base-addr-is-register: +24430 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +24431 0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32 +24432 } +24433 # if (type->left == array) ensure type->register doesn't exist +24434 { +24435 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24436 (simple-mu-type? %eax 3) # array => eax +24437 3d/compare-eax-and 0/imm32/false +24438 74/jump-if-= break/disp8 +24439 $check-mu-length-stmt:base-is-array: +24440 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +24441 0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32 +24442 } +24443 # if (base-type->left == addr) base-type = base-type->right +24444 { +24445 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24446 (simple-mu-type? %eax 2) # addr => eax +24447 3d/compare-eax-and 0/imm32/false +24448 74/jump-if-= break/disp8 +24449 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +24450 89/<- %ebx 0/r32/eax +24451 } +24452 # - check for too many inouts +24453 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24454 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24455 3d/compare-eax-and 0/imm32/false +24456 0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32 +24457 # - check for 0 outputs +24458 # var output/edi: (addr var) = stmt->outputs->value +24459 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24460 3d/compare-eax-and 0/imm32/false +24461 0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32 +24462 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24463 89/<- %edi 0/r32/eax +24464 # - check output type +24465 # must have a non-atomic type +24466 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +24467 (simple-mu-type? %eax 1) # int => eax +24468 3d/compare-eax-and 0/imm32/false +24469 0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32 +24470 # - check for too many outputs +24471 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24472 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24473 3d/compare-eax-and 0/imm32/false +24474 0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32 +24475 $check-mu-length-stmt:end: +24476 # . restore registers +24477 5f/pop-to-edi +24478 5e/pop-to-esi +24479 5b/pop-to-ebx +24480 5a/pop-to-edx +24481 59/pop-to-ecx +24482 58/pop-to-eax +24483 # . epilogue +24484 89/<- %esp 5/r32/ebp +24485 5d/pop-to-ebp +24486 c3/return +24487 +24488 $check-mu-length-stmt:error-base-non-array-type: +24489 (write-buffered *(ebp+0x10) "fn ") +24490 8b/-> *(ebp+0xc) 0/r32/eax +24491 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24492 (write-buffered *(ebp+0x10) %eax) +24493 (write-buffered *(ebp+0x10) ": stmt length: var '") +24494 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24495 (write-buffered *(ebp+0x10) %eax) +24496 (write-buffered *(ebp+0x10) "' is not an array\n") +24497 (flush *(ebp+0x10)) +24498 (stop *(ebp+0x14) 1) +24499 # never gets here +24500 +24501 $check-mu-length-stmt:error-base-array-atom-type: +24502 (write-buffered *(ebp+0x10) "fn ") +24503 8b/-> *(ebp+0xc) 0/r32/eax +24504 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24505 (write-buffered *(ebp+0x10) %eax) +24506 (write-buffered *(ebp+0x10) ": stmt length: array '") +24507 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24508 (write-buffered *(ebp+0x10) %eax) +24509 (write-buffered *(ebp+0x10) "' must specify the type of its elements\n") +24510 (flush *(ebp+0x10)) +24511 (stop *(ebp+0x14) 1) +24512 # never gets here +24513 +24514 $check-mu-length-stmt:error-base-address-array-type-on-stack: +24515 (write-buffered *(ebp+0x10) "fn ") +24516 8b/-> *(ebp+0xc) 0/r32/eax +24517 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24518 (write-buffered *(ebp+0x10) %eax) +24519 (write-buffered *(ebp+0x10) ": stmt length: var '") +24520 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24521 (write-buffered *(ebp+0x10) %eax) +24522 (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n") +24523 (flush *(ebp+0x10)) +24524 (stop *(ebp+0x14) 1) +24525 # never gets here +24526 +24527 $check-mu-length-stmt:error-base-array-type-in-register: +24528 (write-buffered *(ebp+0x10) "fn ") +24529 8b/-> *(ebp+0xc) 0/r32/eax +24530 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24531 (write-buffered *(ebp+0x10) %eax) +24532 (write-buffered *(ebp+0x10) ": stmt length: var '") +24533 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24534 (write-buffered *(ebp+0x10) %eax) +24535 (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n") +24536 (flush *(ebp+0x10)) +24537 (stop *(ebp+0x14) 1) +24538 # never gets here +24539 +24540 $check-mu-length-stmt:error-too-few-inouts: +24541 (write-buffered *(ebp+0x10) "fn ") +24542 8b/-> *(ebp+0xc) 0/r32/eax +24543 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24544 (write-buffered *(ebp+0x10) %eax) +24545 (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n") +24546 (flush *(ebp+0x10)) +24547 (stop *(ebp+0x14) 1) +24548 # never gets here +24549 +24550 $check-mu-length-stmt:error-invalid-index-type: +24551 (write-buffered *(ebp+0x10) "fn ") +24552 8b/-> *(ebp+0xc) 0/r32/eax +24553 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24554 (write-buffered *(ebp+0x10) %eax) +24555 (write-buffered *(ebp+0x10) ": stmt length: second argument '") +24556 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24557 (write-buffered *(ebp+0x10) %eax) +24558 (write-buffered *(ebp+0x10) "' must be an int or offset\n") +24559 (flush *(ebp+0x10)) +24560 (stop *(ebp+0x14) 1) +24561 # never gets here +24562 +24563 $check-mu-length-stmt:error-index-offset-atom-type: +24564 (write-buffered *(ebp+0x10) "fn ") +24565 8b/-> *(ebp+0xc) 0/r32/eax +24566 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24567 (write-buffered *(ebp+0x10) %eax) +24568 (write-buffered *(ebp+0x10) ": stmt length: offset '") +24569 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24570 (write-buffered *(ebp+0x10) %eax) +24571 (write-buffered *(ebp+0x10) "' must specify the type of array elements\n") +24572 (flush *(ebp+0x10)) +24573 (stop *(ebp+0x14) 1) +24574 # never gets here +24575 +24576 $check-mu-length-stmt:error-index-on-stack: +24577 (write-buffered *(ebp+0x10) "fn ") +24578 8b/-> *(ebp+0xc) 0/r32/eax +24579 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24580 (write-buffered *(ebp+0x10) %eax) +24581 (write-buffered *(ebp+0x10) ": stmt length: second argument '") +24582 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24583 (write-buffered *(ebp+0x10) %eax) +24584 (write-buffered *(ebp+0x10) "' must be in a register\n") +24585 (flush *(ebp+0x10)) +24586 (stop *(ebp+0x14) 1) +24587 # never gets here +24588 +24589 $check-mu-length-stmt:error-index-needs-offset: +24590 (write-buffered *(ebp+0x10) "fn ") +24591 8b/-> *(ebp+0xc) 0/r32/eax +24592 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24593 (write-buffered *(ebp+0x10) %eax) +24594 (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '") +24595 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24596 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24597 (lookup *eax *(eax+4)) # Var-name Var-name => eax +24598 (write-buffered *(ebp+0x10) %eax) +24599 (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n") +24600 (flush *(ebp+0x10)) +24601 (stop *(ebp+0x14) 1) +24602 # never gets here +24603 +24604 $check-mu-length-stmt:error-too-many-inouts: +24605 (write-buffered *(ebp+0x10) "fn ") +24606 8b/-> *(ebp+0xc) 0/r32/eax +24607 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24608 (write-buffered *(ebp+0x10) %eax) +24609 (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n") +24610 (flush *(ebp+0x10)) +24611 (stop *(ebp+0x14) 1) +24612 # never gets here +24613 +24614 $check-mu-length-stmt:error-too-few-outputs: +24615 (write-buffered *(ebp+0x10) "fn ") +24616 8b/-> *(ebp+0xc) 0/r32/eax +24617 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24618 (write-buffered *(ebp+0x10) %eax) +24619 (write-buffered *(ebp+0x10) ": stmt length: must have an output\n") +24620 (flush *(ebp+0x10)) +24621 (stop *(ebp+0x14) 1) +24622 # never gets here +24623 +24624 $check-mu-length-stmt:error-too-many-outputs: +24625 (write-buffered *(ebp+0x10) "fn ") +24626 8b/-> *(ebp+0xc) 0/r32/eax +24627 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24628 (write-buffered *(ebp+0x10) %eax) +24629 (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n") +24630 (flush *(ebp+0x10)) +24631 (stop *(ebp+0x14) 1) +24632 # never gets here +24633 +24634 $check-mu-length-stmt:error-output-not-in-register: +24635 (write-buffered *(ebp+0x10) "fn ") +24636 8b/-> *(ebp+0xc) 0/r32/eax +24637 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24638 (write-buffered *(ebp+0x10) %eax) +24639 (write-buffered *(ebp+0x10) ": stmt length: output '") +24640 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24641 (write-buffered *(ebp+0x10) %eax) +24642 (write-buffered *(ebp+0x10) "' is not in a register\n") +24643 (flush *(ebp+0x10)) +24644 (stop *(ebp+0x14) 1) +24645 # never gets here +24646 +24647 $check-mu-length-stmt:error-invalid-output-type: +24648 (write-buffered *(ebp+0x10) "fn ") +24649 8b/-> *(ebp+0xc) 0/r32/eax +24650 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24651 (write-buffered *(ebp+0x10) %eax) +24652 (write-buffered *(ebp+0x10) ": stmt length: output '") +24653 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24654 (write-buffered *(ebp+0x10) %eax) +24655 (write-buffered *(ebp+0x10) "' does not have the right type\n") +24656 (flush *(ebp+0x10)) +24657 (stop *(ebp+0x14) 1) +24658 # never gets here +24659 +24660 check-mu-compute-offset-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +24661 # . prologue +24662 55/push-ebp +24663 89/<- %ebp 4/r32/esp +24664 # . save registers +24665 50/push-eax +24666 51/push-ecx +24667 52/push-edx +24668 53/push-ebx +24669 56/push-esi +24670 57/push-edi +24671 # esi = stmt +24672 8b/-> *(ebp+8) 6/r32/esi +24673 # - check for 0 inouts +24674 # var base/ecx: (addr var) = stmt->inouts->value +24675 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24676 $check-mu-compute-offset-stmt:check-no-inouts: +24677 3d/compare-eax-and 0/imm32 +24678 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32 +24679 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24680 89/<- %ecx 0/r32/eax +24681 # - check base type is either (addr array ...) in register or (array ...) on stack +24682 # var base-type/ebx: (addr type-tree) = lookup(base->type) +24683 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +24684 89/<- %ebx 0/r32/eax +24685 # if base-type is an atom, abort with a precise error +24686 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +24687 { +24688 74/jump-if-= break/disp8 +24689 (simple-mu-type? %ebx 3) # array => eax +24690 3d/compare-eax-and 0/imm32/false +24691 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32 +24692 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32 +24693 } +24694 $check-mu-compute-offset-stmt:base-is-compound: +24695 # if type->left not addr or array, abort +24696 { +24697 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24698 (simple-mu-type? %eax 2) # addr => eax +24699 3d/compare-eax-and 0/imm32/false +24700 75/jump-if-!= break/disp8 +24701 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24702 (simple-mu-type? %eax 3) # array => eax +24703 3d/compare-eax-and 0/imm32/false +24704 75/jump-if-!= break/disp8 +24705 e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32 24706 } -24707 # - check for 1 inout -24708 # var index/ecx: (addr stmt-var) = stmt->inouts->next->value -24709 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24710 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24711 $check-mu-compute-offset-stmt:check-single-inout: -24712 3d/compare-eax-and 0/imm32 -24713 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32 -24714 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24715 89/<- %ecx 0/r32/eax -24716 # - check index is either a literal or register -24717 # var index-type/edx: (addr type-tree) -24718 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -24719 89/<- %edx 0/r32/eax -24720 # index type must be a literal or int -24721 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom -24722 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32 -24723 { -24724 $check-mu-compute-offset-stmt:index-type-is-atom: -24725 (simple-mu-type? %edx 0) # literal => eax -24726 3d/compare-eax-and 0/imm32/false -24727 75/jump-if-!= break/disp8 -24728 (simple-mu-type? %edx 1) # int => eax -24729 3d/compare-eax-and 0/imm32/false -24730 75/jump-if-!= break/disp8 -24731 e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32 -24732 } -24733 # - check for too many inouts -24734 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24735 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24736 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24737 3d/compare-eax-and 0/imm32/false -24738 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32 -24739 # - check for 0 outputs -24740 # var output/edi: (addr var) = stmt->outputs->value -24741 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24742 3d/compare-eax-and 0/imm32/false -24743 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32 -24744 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -24745 89/<- %edi 0/r32/eax -24746 # - check output type -24747 # must have a non-atomic type -24748 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -24749 89/<- %edx 0/r32/eax -24750 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom -24751 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32 -24752 # type must start with (offset ...) -24753 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -24754 (simple-mu-type? %eax 7) # offset => eax -24755 3d/compare-eax-and 0/imm32/false -24756 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32 -24757 # if tail(base-type) != tail(output-type) abort -24758 (type-tail %ebx) # => eax -24759 89/<- %ebx 0/r32/eax -24760 (type-tail %edx) # => eax -24761 (type-equal? %ebx %eax) # => eax -24762 3d/compare-eax-and 0/imm32/false -24763 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32 -24764 # - check for too many outputs -24765 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24766 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -24767 3d/compare-eax-and 0/imm32/false -24768 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32 -24769 $check-mu-compute-offset-stmt:end: -24770 # . restore registers -24771 5f/pop-to-edi -24772 5e/pop-to-esi -24773 5b/pop-to-ebx -24774 5a/pop-to-edx -24775 59/pop-to-ecx -24776 58/pop-to-eax -24777 # . epilogue -24778 89/<- %esp 5/r32/ebp -24779 5d/pop-to-ebp -24780 c3/return -24781 -24782 $check-mu-compute-offset-stmt:error-base-non-array-type: -24783 (write-buffered *(ebp+0x10) "fn ") -24784 8b/-> *(ebp+0xc) 0/r32/eax -24785 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24786 (write-buffered *(ebp+0x10) %eax) -24787 (write-buffered *(ebp+0x10) ": stmt compute-offset: var '") -24788 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24789 (write-buffered *(ebp+0x10) %eax) -24790 (write-buffered *(ebp+0x10) "' is not an array\n") -24791 (flush *(ebp+0x10)) -24792 (stop *(ebp+0x14) 1) -24793 # never gets here -24794 -24795 $check-mu-compute-offset-stmt:error-base-array-atom-type: -24796 (write-buffered *(ebp+0x10) "fn ") -24797 8b/-> *(ebp+0xc) 0/r32/eax -24798 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24799 (write-buffered *(ebp+0x10) %eax) -24800 (write-buffered *(ebp+0x10) ": stmt compute-offset: array '") -24801 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24802 (write-buffered *(ebp+0x10) %eax) -24803 (write-buffered *(ebp+0x10) "' must specify the type of its elements\n") -24804 (flush *(ebp+0x10)) -24805 (stop *(ebp+0x14) 1) -24806 # never gets here -24807 -24808 $check-mu-compute-offset-stmt:error-too-few-inouts: -24809 (write-buffered *(ebp+0x10) "fn ") -24810 8b/-> *(ebp+0xc) 0/r32/eax -24811 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24812 (write-buffered *(ebp+0x10) %eax) -24813 (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n") -24814 (flush *(ebp+0x10)) -24815 (stop *(ebp+0x14) 1) -24816 # never gets here -24817 -24818 $check-mu-compute-offset-stmt:error-invalid-index-type: -24819 (write-buffered *(ebp+0x10) "fn ") -24820 8b/-> *(ebp+0xc) 0/r32/eax -24821 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24822 (write-buffered *(ebp+0x10) %eax) -24823 (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '") -24824 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24825 (write-buffered *(ebp+0x10) %eax) -24826 (write-buffered *(ebp+0x10) "' must be an int\n") -24827 (flush *(ebp+0x10)) -24828 (stop *(ebp+0x14) 1) -24829 # never gets here -24830 -24831 $check-mu-compute-offset-stmt:error-index-offset-atom-type: -24832 (write-buffered *(ebp+0x10) "fn ") -24833 8b/-> *(ebp+0xc) 0/r32/eax -24834 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24835 (write-buffered *(ebp+0x10) %eax) -24836 (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '") -24837 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24838 (write-buffered *(ebp+0x10) %eax) -24839 (write-buffered *(ebp+0x10) "' must specify the type of array elements\n") -24840 (flush *(ebp+0x10)) -24841 (stop *(ebp+0x14) 1) -24842 # never gets here -24843 -24844 $check-mu-compute-offset-stmt:error-index-on-stack: -24845 (write-buffered *(ebp+0x10) "fn ") -24846 8b/-> *(ebp+0xc) 0/r32/eax -24847 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24848 (write-buffered *(ebp+0x10) %eax) -24849 (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '") -24850 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -24851 (write-buffered *(ebp+0x10) %eax) -24852 (write-buffered *(ebp+0x10) "' must be in a register\n") -24853 (flush *(ebp+0x10)) -24854 (stop *(ebp+0x14) 1) -24855 # never gets here -24856 -24857 $check-mu-compute-offset-stmt:error-too-many-inouts: -24858 (write-buffered *(ebp+0x10) "fn ") -24859 8b/-> *(ebp+0xc) 0/r32/eax -24860 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24861 (write-buffered *(ebp+0x10) %eax) -24862 (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n") -24863 (flush *(ebp+0x10)) -24864 (stop *(ebp+0x14) 1) -24865 # never gets here -24866 -24867 $check-mu-compute-offset-stmt:error-too-few-outputs: -24868 (write-buffered *(ebp+0x10) "fn ") -24869 8b/-> *(ebp+0xc) 0/r32/eax -24870 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24871 (write-buffered *(ebp+0x10) %eax) -24872 (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n") -24873 (flush *(ebp+0x10)) -24874 (stop *(ebp+0x14) 1) -24875 # never gets here -24876 -24877 $check-mu-compute-offset-stmt:error-too-many-outputs: -24878 (write-buffered *(ebp+0x10) "fn ") -24879 8b/-> *(ebp+0xc) 0/r32/eax -24880 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24881 (write-buffered *(ebp+0x10) %eax) -24882 (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n") -24883 (flush *(ebp+0x10)) -24884 (stop *(ebp+0x14) 1) -24885 # never gets here -24886 -24887 $check-mu-compute-offset-stmt:error-output-not-in-register: -24888 (write-buffered *(ebp+0x10) "fn ") -24889 8b/-> *(ebp+0xc) 0/r32/eax -24890 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24891 (write-buffered *(ebp+0x10) %eax) -24892 (write-buffered *(ebp+0x10) ": stmt compute-offset: output '") -24893 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24894 (write-buffered *(ebp+0x10) %eax) -24895 (write-buffered *(ebp+0x10) "' is not in a register\n") -24896 (flush *(ebp+0x10)) -24897 (stop *(ebp+0x14) 1) -24898 # never gets here -24899 -24900 $check-mu-compute-offset-stmt:error-output-type-not-offset: -24901 (write-buffered *(ebp+0x10) "fn ") -24902 8b/-> *(ebp+0xc) 0/r32/eax -24903 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24904 (write-buffered *(ebp+0x10) %eax) -24905 (write-buffered *(ebp+0x10) ": stmt compute-offset: output '") -24906 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24907 (write-buffered *(ebp+0x10) %eax) -24908 (write-buffered *(ebp+0x10) "' must be an offset\n") -24909 (flush *(ebp+0x10)) -24910 (stop *(ebp+0x14) 1) -24911 # never gets here -24912 -24913 $check-mu-compute-offset-stmt:error-bad-output-type: -24914 (write-buffered *(ebp+0x10) "fn ") -24915 8b/-> *(ebp+0xc) 0/r32/eax -24916 (lookup *eax *(eax+4)) # Function-name Function-name => eax -24917 (write-buffered *(ebp+0x10) %eax) -24918 (write-buffered *(ebp+0x10) ": stmt compute-offset: output '") -24919 (lookup *edi *(edi+4)) # Var-name Var-name => eax -24920 (write-buffered *(ebp+0x10) %eax) -24921 (write-buffered *(ebp+0x10) "' does not have the right type\n") -24922 (flush *(ebp+0x10)) -24923 (stop *(ebp+0x14) 1) -24924 # never gets here -24925 -24926 check-mu-copy-object-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -24927 # . prologue -24928 55/push-ebp -24929 89/<- %ebp 4/r32/esp -24930 # . save registers -24931 50/push-eax -24932 51/push-ecx -24933 53/push-ebx -24934 56/push-esi -24935 57/push-edi -24936 # esi = stmt -24937 8b/-> *(ebp+8) 6/r32/esi -24938 $check-mu-copy-object-stmt:check-for-output: -24939 # if stmt->outputs abort -24940 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -24941 3d/compare-eax-and 0/imm32 -24942 0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32 -24943 $check-mu-copy-object-stmt:get-left: -24944 # var dest/edi: (addr stmt-var) = stmt->inouts -24945 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -24946 89/<- %edi 0/r32/eax -24947 # zero inouts -24948 3d/compare-eax-and 0/imm32 -24949 0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32 -24950 $check-mu-copy-object-stmt:get-src: -24951 # var src/esi: (addr stmt-var) = dest->next -24952 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -24953 89/<- %esi 0/r32/eax -24954 # 1 inout -24955 3d/compare-eax-and 0/imm32 -24956 0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32 -24957 # > 2 inouts -24958 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -24959 3d/compare-eax-and 0/imm32 -24960 0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32 -24961 $check-mu-copy-object-stmt:types: -24962 # var src-type/ecx: (addr type-tree) = src->value->type -24963 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -24964 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -24965 89/<- %ecx 0/r32/eax -24966 # if (src->is-deref?) src-type = src-type->payload -24967 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref -24968 3d/compare-eax-and 0/imm32/false -24969 { -24970 74/jump-if-= break/disp8 -24971 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -24972 # if src-type->right is null, src-type = src-type->left -24973 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -24974 { -24975 75/jump-if-!= break/disp8 -24976 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -24977 } -24978 89/<- %ecx 0/r32/eax -24979 } -24980 # if src-type is not addr, abort -24981 (mu-addr-type? %ecx) # => eax -24982 3d/compare-eax-and 0/imm32/false -24983 0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32 -24984 # var dest-type/ebx: (addr type-tree) = dest->value->type -24985 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +24707 # if (type->left == addr) ensure type->right->left == array and type->register exists +24708 { +24709 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24710 (simple-mu-type? %eax 2) # addr => eax +24711 3d/compare-eax-and 0/imm32/false +24712 74/jump-if-= break/disp8 +24713 $check-mu-compute-offset-stmt:base-is-addr: +24714 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +24715 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +24716 (simple-mu-type? %eax 3) # array => eax +24717 3d/compare-eax-and 0/imm32/false +24718 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32 +24719 } +24720 # if (base-type->left == addr) base-type = base-type->right +24721 { +24722 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +24723 (simple-mu-type? %eax 2) # addr => eax +24724 3d/compare-eax-and 0/imm32/false +24725 74/jump-if-= break/disp8 +24726 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +24727 89/<- %ebx 0/r32/eax +24728 } +24729 # - check for 1 inout +24730 # var index/ecx: (addr stmt-var) = stmt->inouts->next->value +24731 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24732 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24733 $check-mu-compute-offset-stmt:check-single-inout: +24734 3d/compare-eax-and 0/imm32 +24735 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32 +24736 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24737 89/<- %ecx 0/r32/eax +24738 # - check index is either a literal or register +24739 # var index-type/edx: (addr type-tree) +24740 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +24741 89/<- %edx 0/r32/eax +24742 # index type must be a literal or int +24743 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom +24744 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32 +24745 { +24746 $check-mu-compute-offset-stmt:index-type-is-atom: +24747 (simple-mu-type? %edx 0) # literal => eax +24748 3d/compare-eax-and 0/imm32/false +24749 75/jump-if-!= break/disp8 +24750 (simple-mu-type? %edx 1) # int => eax +24751 3d/compare-eax-and 0/imm32/false +24752 75/jump-if-!= break/disp8 +24753 e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32 +24754 } +24755 # - check for too many inouts +24756 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24757 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24758 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24759 3d/compare-eax-and 0/imm32/false +24760 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32 +24761 # - check for 0 outputs +24762 # var output/edi: (addr var) = stmt->outputs->value +24763 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24764 3d/compare-eax-and 0/imm32/false +24765 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32 +24766 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +24767 89/<- %edi 0/r32/eax +24768 # - check output type +24769 # must have a non-atomic type +24770 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +24771 89/<- %edx 0/r32/eax +24772 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom +24773 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32 +24774 # type must start with (offset ...) +24775 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +24776 (simple-mu-type? %eax 7) # offset => eax +24777 3d/compare-eax-and 0/imm32/false +24778 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32 +24779 # if tail(base-type) != tail(output-type) abort +24780 (type-tail %ebx) # => eax +24781 89/<- %ebx 0/r32/eax +24782 (type-tail %edx) # => eax +24783 (type-equal? %ebx %eax) # => eax +24784 3d/compare-eax-and 0/imm32/false +24785 0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32 +24786 # - check for too many outputs +24787 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24788 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +24789 3d/compare-eax-and 0/imm32/false +24790 0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32 +24791 $check-mu-compute-offset-stmt:end: +24792 # . restore registers +24793 5f/pop-to-edi +24794 5e/pop-to-esi +24795 5b/pop-to-ebx +24796 5a/pop-to-edx +24797 59/pop-to-ecx +24798 58/pop-to-eax +24799 # . epilogue +24800 89/<- %esp 5/r32/ebp +24801 5d/pop-to-ebp +24802 c3/return +24803 +24804 $check-mu-compute-offset-stmt:error-base-non-array-type: +24805 (write-buffered *(ebp+0x10) "fn ") +24806 8b/-> *(ebp+0xc) 0/r32/eax +24807 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24808 (write-buffered *(ebp+0x10) %eax) +24809 (write-buffered *(ebp+0x10) ": stmt compute-offset: var '") +24810 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24811 (write-buffered *(ebp+0x10) %eax) +24812 (write-buffered *(ebp+0x10) "' is not an array\n") +24813 (flush *(ebp+0x10)) +24814 (stop *(ebp+0x14) 1) +24815 # never gets here +24816 +24817 $check-mu-compute-offset-stmt:error-base-array-atom-type: +24818 (write-buffered *(ebp+0x10) "fn ") +24819 8b/-> *(ebp+0xc) 0/r32/eax +24820 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24821 (write-buffered *(ebp+0x10) %eax) +24822 (write-buffered *(ebp+0x10) ": stmt compute-offset: array '") +24823 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24824 (write-buffered *(ebp+0x10) %eax) +24825 (write-buffered *(ebp+0x10) "' must specify the type of its elements\n") +24826 (flush *(ebp+0x10)) +24827 (stop *(ebp+0x14) 1) +24828 # never gets here +24829 +24830 $check-mu-compute-offset-stmt:error-too-few-inouts: +24831 (write-buffered *(ebp+0x10) "fn ") +24832 8b/-> *(ebp+0xc) 0/r32/eax +24833 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24834 (write-buffered *(ebp+0x10) %eax) +24835 (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n") +24836 (flush *(ebp+0x10)) +24837 (stop *(ebp+0x14) 1) +24838 # never gets here +24839 +24840 $check-mu-compute-offset-stmt:error-invalid-index-type: +24841 (write-buffered *(ebp+0x10) "fn ") +24842 8b/-> *(ebp+0xc) 0/r32/eax +24843 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24844 (write-buffered *(ebp+0x10) %eax) +24845 (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '") +24846 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24847 (write-buffered *(ebp+0x10) %eax) +24848 (write-buffered *(ebp+0x10) "' must be an int\n") +24849 (flush *(ebp+0x10)) +24850 (stop *(ebp+0x14) 1) +24851 # never gets here +24852 +24853 $check-mu-compute-offset-stmt:error-index-offset-atom-type: +24854 (write-buffered *(ebp+0x10) "fn ") +24855 8b/-> *(ebp+0xc) 0/r32/eax +24856 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24857 (write-buffered *(ebp+0x10) %eax) +24858 (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '") +24859 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24860 (write-buffered *(ebp+0x10) %eax) +24861 (write-buffered *(ebp+0x10) "' must specify the type of array elements\n") +24862 (flush *(ebp+0x10)) +24863 (stop *(ebp+0x14) 1) +24864 # never gets here +24865 +24866 $check-mu-compute-offset-stmt:error-index-on-stack: +24867 (write-buffered *(ebp+0x10) "fn ") +24868 8b/-> *(ebp+0xc) 0/r32/eax +24869 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24870 (write-buffered *(ebp+0x10) %eax) +24871 (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '") +24872 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +24873 (write-buffered *(ebp+0x10) %eax) +24874 (write-buffered *(ebp+0x10) "' must be in a register\n") +24875 (flush *(ebp+0x10)) +24876 (stop *(ebp+0x14) 1) +24877 # never gets here +24878 +24879 $check-mu-compute-offset-stmt:error-too-many-inouts: +24880 (write-buffered *(ebp+0x10) "fn ") +24881 8b/-> *(ebp+0xc) 0/r32/eax +24882 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24883 (write-buffered *(ebp+0x10) %eax) +24884 (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n") +24885 (flush *(ebp+0x10)) +24886 (stop *(ebp+0x14) 1) +24887 # never gets here +24888 +24889 $check-mu-compute-offset-stmt:error-too-few-outputs: +24890 (write-buffered *(ebp+0x10) "fn ") +24891 8b/-> *(ebp+0xc) 0/r32/eax +24892 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24893 (write-buffered *(ebp+0x10) %eax) +24894 (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n") +24895 (flush *(ebp+0x10)) +24896 (stop *(ebp+0x14) 1) +24897 # never gets here +24898 +24899 $check-mu-compute-offset-stmt:error-too-many-outputs: +24900 (write-buffered *(ebp+0x10) "fn ") +24901 8b/-> *(ebp+0xc) 0/r32/eax +24902 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24903 (write-buffered *(ebp+0x10) %eax) +24904 (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n") +24905 (flush *(ebp+0x10)) +24906 (stop *(ebp+0x14) 1) +24907 # never gets here +24908 +24909 $check-mu-compute-offset-stmt:error-output-not-in-register: +24910 (write-buffered *(ebp+0x10) "fn ") +24911 8b/-> *(ebp+0xc) 0/r32/eax +24912 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24913 (write-buffered *(ebp+0x10) %eax) +24914 (write-buffered *(ebp+0x10) ": stmt compute-offset: output '") +24915 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24916 (write-buffered *(ebp+0x10) %eax) +24917 (write-buffered *(ebp+0x10) "' is not in a register\n") +24918 (flush *(ebp+0x10)) +24919 (stop *(ebp+0x14) 1) +24920 # never gets here +24921 +24922 $check-mu-compute-offset-stmt:error-output-type-not-offset: +24923 (write-buffered *(ebp+0x10) "fn ") +24924 8b/-> *(ebp+0xc) 0/r32/eax +24925 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24926 (write-buffered *(ebp+0x10) %eax) +24927 (write-buffered *(ebp+0x10) ": stmt compute-offset: output '") +24928 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24929 (write-buffered *(ebp+0x10) %eax) +24930 (write-buffered *(ebp+0x10) "' must be an offset\n") +24931 (flush *(ebp+0x10)) +24932 (stop *(ebp+0x14) 1) +24933 # never gets here +24934 +24935 $check-mu-compute-offset-stmt:error-bad-output-type: +24936 (write-buffered *(ebp+0x10) "fn ") +24937 8b/-> *(ebp+0xc) 0/r32/eax +24938 (lookup *eax *(eax+4)) # Function-name Function-name => eax +24939 (write-buffered *(ebp+0x10) %eax) +24940 (write-buffered *(ebp+0x10) ": stmt compute-offset: output '") +24941 (lookup *edi *(edi+4)) # Var-name Var-name => eax +24942 (write-buffered *(ebp+0x10) %eax) +24943 (write-buffered *(ebp+0x10) "' does not have the right type\n") +24944 (flush *(ebp+0x10)) +24945 (stop *(ebp+0x14) 1) +24946 # never gets here +24947 +24948 check-mu-copy-object-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +24949 # . prologue +24950 55/push-ebp +24951 89/<- %ebp 4/r32/esp +24952 # . save registers +24953 50/push-eax +24954 51/push-ecx +24955 53/push-ebx +24956 56/push-esi +24957 57/push-edi +24958 # esi = stmt +24959 8b/-> *(ebp+8) 6/r32/esi +24960 $check-mu-copy-object-stmt:check-for-output: +24961 # if stmt->outputs abort +24962 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +24963 3d/compare-eax-and 0/imm32 +24964 0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32 +24965 $check-mu-copy-object-stmt:get-left: +24966 # var dest/edi: (addr stmt-var) = stmt->inouts +24967 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +24968 89/<- %edi 0/r32/eax +24969 # zero inouts +24970 3d/compare-eax-and 0/imm32 +24971 0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32 +24972 $check-mu-copy-object-stmt:get-src: +24973 # var src/esi: (addr stmt-var) = dest->next +24974 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +24975 89/<- %esi 0/r32/eax +24976 # 1 inout +24977 3d/compare-eax-and 0/imm32 +24978 0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32 +24979 # > 2 inouts +24980 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +24981 3d/compare-eax-and 0/imm32 +24982 0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32 +24983 $check-mu-copy-object-stmt:types: +24984 # var src-type/ecx: (addr type-tree) = src->value->type +24985 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax 24986 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -24987 89/<- %ebx 0/r32/eax -24988 # if (dest->is-deref?) dest-type = dest-type->payload -24989 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +24987 89/<- %ecx 0/r32/eax +24988 # if (src->is-deref?) src-type = src-type->payload +24989 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref 24990 3d/compare-eax-and 0/imm32/false 24991 { 24992 74/jump-if-= break/disp8 -24993 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -24994 # if dest-type->right is null, dest-type = dest-type->left +24993 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +24994 # if src-type->right is null, src-type = src-type->left 24995 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right 24996 { 24997 75/jump-if-!= break/disp8 24998 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax 24999 } -25000 89/<- %ebx 0/r32/eax +25000 89/<- %ecx 0/r32/eax 25001 } -25002 # if (dest-type != src-type) abort -25003 (type-equal? %ecx %ebx) # => eax -25004 3d/compare-eax-and 0/imm32 +25002 # if src-type is not addr, abort +25003 (mu-addr-type? %ecx) # => eax +25004 3d/compare-eax-and 0/imm32/false 25005 0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32 -25006 $check-mu-copy-object-stmt:end: -25007 # . restore registers -25008 5f/pop-to-edi -25009 5e/pop-to-esi -25010 5b/pop-to-ebx -25011 59/pop-to-ecx -25012 58/pop-to-eax -25013 # . epilogue -25014 89/<- %esp 5/r32/ebp -25015 5d/pop-to-ebp -25016 c3/return -25017 -25018 $check-mu-copy-object-stmt:error-incorrect-inouts: -25019 (write-buffered *(ebp+0x10) "fn ") -25020 8b/-> *(ebp+0xc) 0/r32/eax -25021 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25022 (write-buffered *(ebp+0x10) %eax) -25023 (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n") -25024 (flush *(ebp+0x10)) -25025 (stop *(ebp+0x14) 1) -25026 # never gets here -25027 -25028 $check-mu-copy-object-stmt:error-too-many-outputs: -25029 (write-buffered *(ebp+0x10) "fn ") -25030 8b/-> *(ebp+0xc) 0/r32/eax -25031 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25032 (write-buffered *(ebp+0x10) %eax) -25033 (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n") -25034 (flush *(ebp+0x10)) -25035 (stop *(ebp+0x14) 1) -25036 # never gets here -25037 -25038 $check-mu-copy-object-stmt:error-invalid-types: -25039 (write-buffered *(ebp+0x10) "fn ") -25040 8b/-> *(ebp+0xc) 0/r32/eax -25041 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25042 (write-buffered *(ebp+0x10) %eax) -25043 (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n") -25044 (flush *(ebp+0x10)) -25045 (stop *(ebp+0x14) 1) -25046 # never gets here -25047 -25048 check-mu-clear-object-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25049 # . prologue -25050 55/push-ebp -25051 89/<- %ebp 4/r32/esp -25052 # . save registers -25053 50/push-eax -25054 51/push-ecx -25055 53/push-ebx -25056 56/push-esi -25057 57/push-edi -25058 # esi = stmt -25059 8b/-> *(ebp+8) 6/r32/esi -25060 $check-mu-clear-object-stmt:check-for-output: -25061 # if stmt->outputs abort -25062 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25063 3d/compare-eax-and 0/imm32 -25064 0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32 -25065 $check-mu-clear-object-stmt:get-left: -25066 # var dest/edi: (addr stmt-var) = stmt->inouts -25067 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25068 89/<- %edi 0/r32/eax -25069 # zero inouts -25070 3d/compare-eax-and 0/imm32 -25071 0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32 -25072 $check-mu-clear-object-stmt:get-src: -25073 # > 1 inout -25074 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -25075 3d/compare-eax-and 0/imm32 -25076 0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32 -25077 $check-mu-clear-object-stmt:types: -25078 # var src-type/ecx: (addr type-tree) = src->value->type -25079 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25080 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25081 89/<- %ecx 0/r32/eax -25082 # if (src->is-deref?) src-type = src-type->payload -25083 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -25084 3d/compare-eax-and 0/imm32/false -25085 { -25086 74/jump-if-= break/disp8 -25087 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -25088 # if src-type->right is null, src-type = src-type->left -25089 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -25090 { -25091 75/jump-if-!= break/disp8 -25092 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25093 } -25094 89/<- %ecx 0/r32/eax -25095 } -25096 # if src-type is not addr, abort -25097 (mu-addr-type? %ecx) # => eax -25098 3d/compare-eax-and 0/imm32/false -25099 0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32 -25100 $check-mu-clear-object-stmt:end: -25101 # . restore registers -25102 5f/pop-to-edi -25103 5e/pop-to-esi -25104 5b/pop-to-ebx -25105 59/pop-to-ecx -25106 58/pop-to-eax -25107 # . epilogue -25108 89/<- %esp 5/r32/ebp -25109 5d/pop-to-ebp -25110 c3/return -25111 -25112 $check-mu-clear-object-stmt:error-incorrect-inouts: -25113 (write-buffered *(ebp+0x10) "fn ") -25114 8b/-> *(ebp+0xc) 0/r32/eax -25115 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25116 (write-buffered *(ebp+0x10) %eax) -25117 (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n") -25118 (flush *(ebp+0x10)) -25119 (stop *(ebp+0x14) 1) -25120 # never gets here -25121 -25122 $check-mu-clear-object-stmt:error-too-many-outputs: -25123 (write-buffered *(ebp+0x10) "fn ") -25124 8b/-> *(ebp+0xc) 0/r32/eax -25125 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25126 (write-buffered *(ebp+0x10) %eax) -25127 (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n") -25128 (flush *(ebp+0x10)) -25129 (stop *(ebp+0x14) 1) -25130 # never gets here -25131 -25132 $check-mu-clear-object-stmt:error-invalid-type: -25133 (write-buffered *(ebp+0x10) "fn ") -25134 8b/-> *(ebp+0xc) 0/r32/eax -25135 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25136 (write-buffered *(ebp+0x10) %eax) -25137 (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n") -25138 (flush *(ebp+0x10)) -25139 (stop *(ebp+0x14) 1) -25140 # never gets here -25141 -25142 check-mu-allocate-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25143 # . prologue -25144 55/push-ebp -25145 89/<- %ebp 4/r32/esp -25146 # . save registers -25147 50/push-eax -25148 53/push-ebx -25149 56/push-esi -25150 57/push-edi -25151 # esi = stmt -25152 8b/-> *(ebp+8) 6/r32/esi -25153 $check-mu-allocate-stmt:check-for-output: -25154 # if stmt->outputs abort -25155 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25156 3d/compare-eax-and 0/imm32 -25157 0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32 -25158 $check-mu-allocate-stmt:get-target: -25159 # var target/edi: (addr stmt-var) = stmt->inouts -25160 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25161 89/<- %edi 0/r32/eax -25162 # zero inouts -25163 3d/compare-eax-and 0/imm32 -25164 0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32 -25165 # > 1 inouts -25166 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -25167 3d/compare-eax-and 0/imm32 -25168 0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32 -25169 $check-mu-allocate-stmt:check-type: -25170 # var target-type/ebx: (addr type-tree) = target->value->type -25171 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25172 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25173 89/<- %ebx 0/r32/eax -25174 # if (target->is-deref?) target-type = target-type->payload -25175 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -25176 3d/compare-eax-and 0/imm32/false -25177 { -25178 74/jump-if-= break/disp8 -25179 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25180 # if target-type->right is null, target-type = target-type->left -25181 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -25182 { -25183 75/jump-if-!= break/disp8 -25184 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25185 } -25186 89/<- %ebx 0/r32/eax -25187 } -25188 # if target-type is not addr, abort -25189 (mu-addr-type? %ebx) # => eax -25190 3d/compare-eax-and 0/imm32/false -25191 0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32 -25192 # if target-type->right is an atom, abort -25193 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25194 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -25195 0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32 -25196 # if target-type->right->left is not handle, abort -25197 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25198 (simple-mu-type? %eax 4) # handle => eax -25199 3d/compare-eax-and 0/imm32/false -25200 0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32 -25201 $check-mu-allocate-stmt:end: -25202 # . restore registers -25203 5f/pop-to-edi -25204 5e/pop-to-esi -25205 5b/pop-to-ebx -25206 58/pop-to-eax -25207 # . epilogue -25208 89/<- %esp 5/r32/ebp -25209 5d/pop-to-ebp -25210 c3/return -25211 -25212 $check-mu-allocate-stmt:error-incorrect-inouts: -25213 (write-buffered *(ebp+0x10) "fn ") -25214 8b/-> *(ebp+0xc) 0/r32/eax -25215 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25216 (write-buffered *(ebp+0x10) %eax) -25217 (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n") -25218 (flush *(ebp+0x10)) -25219 (stop *(ebp+0x14) 1) -25220 # never gets here -25221 -25222 $check-mu-allocate-stmt:error-too-many-outputs: -25223 (write-buffered *(ebp+0x10) "fn ") -25224 8b/-> *(ebp+0xc) 0/r32/eax -25225 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25226 (write-buffered *(ebp+0x10) %eax) -25227 (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n") -25228 (flush *(ebp+0x10)) -25229 (stop *(ebp+0x14) 1) -25230 # never gets here -25231 -25232 $check-mu-allocate-stmt:error-invalid-type: -25233 (write-buffered *(ebp+0x10) "fn ") -25234 8b/-> *(ebp+0xc) 0/r32/eax -25235 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25236 (write-buffered *(ebp+0x10) %eax) -25237 (write-buffered *(ebp+0x10) ": stmt allocate: inout '") -25238 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25239 (lookup *eax *(eax+4)) # Var-name Var-name => eax -25240 (write-buffered *(ebp+0x10) %eax) -25241 (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n") -25242 (flush *(ebp+0x10)) -25243 (stop *(ebp+0x14) 1) -25244 # never gets here -25245 -25246 check-mu-populate-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25247 # . prologue -25248 55/push-ebp -25249 89/<- %ebp 4/r32/esp -25250 # . save registers -25251 50/push-eax -25252 53/push-ebx -25253 56/push-esi -25254 57/push-edi -25255 # esi = stmt -25256 8b/-> *(ebp+8) 6/r32/esi -25257 $check-mu-populate-stmt:check-for-output: -25258 # if stmt->outputs abort -25259 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25260 3d/compare-eax-and 0/imm32 -25261 0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32 -25262 $check-mu-populate-stmt:get-target: -25263 # var target/edi: (addr stmt-var) = stmt->inouts -25264 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25265 89/<- %edi 0/r32/eax -25266 # zero inouts -25267 3d/compare-eax-and 0/imm32 -25268 0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32 -25269 $check-mu-populate-stmt:get-length: -25270 # var length/esi: (addr stmt-var) = dest->next -25271 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -25272 89/<- %esi 0/r32/eax -25273 # 1 inout -25274 3d/compare-eax-and 0/imm32 -25275 0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32 -25276 # > 2 inouts -25277 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -25278 3d/compare-eax-and 0/imm32 -25279 0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32 -25280 $check-mu-populate-stmt:check-target-type: -25281 # var target-type/ebx: (addr type-tree) = target->value->type -25282 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25283 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25284 89/<- %ebx 0/r32/eax -25285 $check-mu-populate-stmt:check-target-type-deref: -25286 # if (target->is-deref?) target-type = target-type->payload -25287 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -25288 3d/compare-eax-and 0/imm32/false -25289 { -25290 74/jump-if-= break/disp8 -25291 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25292 # if target-type->right is null, target-type = target-type->left -25293 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -25294 { -25295 75/jump-if-!= break/disp8 -25296 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25297 } -25298 89/<- %ebx 0/r32/eax -25299 } -25300 $check-mu-populate-stmt:check-target-type-addr: -25301 # if target-type is not addr, abort -25302 (mu-addr-type? %ebx) # => eax -25303 3d/compare-eax-and 0/imm32/false -25304 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32 -25305 # if target-type->right is an atom, abort -25306 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25307 89/<- %ebx 0/r32/eax -25308 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -25309 0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32 -25310 $check-mu-populate-stmt:check-target-type-handle: -25311 # if target-type->right->left is not handle, abort -25312 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -25313 (simple-mu-type? %eax 4) # handle => eax -25314 3d/compare-eax-and 0/imm32/false -25315 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32 -25316 # if target-type->right->right is an atom, abort -25317 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25318 89/<- %ebx 0/r32/eax -25319 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -25320 0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32 -25321 $check-mu-populate-stmt:check-target-type-array: -25322 # if target-type->right->right->left is not array, abort -25323 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -25324 (simple-mu-type? %eax 3) # array => eax +25006 # var dest-type/ebx: (addr type-tree) = dest->value->type +25007 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25008 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25009 89/<- %ebx 0/r32/eax +25010 # if (dest->is-deref?) dest-type = dest-type->payload +25011 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +25012 3d/compare-eax-and 0/imm32/false +25013 { +25014 74/jump-if-= break/disp8 +25015 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25016 # if dest-type->right is null, dest-type = dest-type->left +25017 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +25018 { +25019 75/jump-if-!= break/disp8 +25020 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25021 } +25022 89/<- %ebx 0/r32/eax +25023 } +25024 # if (dest-type != src-type) abort +25025 (type-equal? %ecx %ebx) # => eax +25026 3d/compare-eax-and 0/imm32 +25027 0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32 +25028 $check-mu-copy-object-stmt:end: +25029 # . restore registers +25030 5f/pop-to-edi +25031 5e/pop-to-esi +25032 5b/pop-to-ebx +25033 59/pop-to-ecx +25034 58/pop-to-eax +25035 # . epilogue +25036 89/<- %esp 5/r32/ebp +25037 5d/pop-to-ebp +25038 c3/return +25039 +25040 $check-mu-copy-object-stmt:error-incorrect-inouts: +25041 (write-buffered *(ebp+0x10) "fn ") +25042 8b/-> *(ebp+0xc) 0/r32/eax +25043 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25044 (write-buffered *(ebp+0x10) %eax) +25045 (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n") +25046 (flush *(ebp+0x10)) +25047 (stop *(ebp+0x14) 1) +25048 # never gets here +25049 +25050 $check-mu-copy-object-stmt:error-too-many-outputs: +25051 (write-buffered *(ebp+0x10) "fn ") +25052 8b/-> *(ebp+0xc) 0/r32/eax +25053 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25054 (write-buffered *(ebp+0x10) %eax) +25055 (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n") +25056 (flush *(ebp+0x10)) +25057 (stop *(ebp+0x14) 1) +25058 # never gets here +25059 +25060 $check-mu-copy-object-stmt:error-invalid-types: +25061 (write-buffered *(ebp+0x10) "fn ") +25062 8b/-> *(ebp+0xc) 0/r32/eax +25063 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25064 (write-buffered *(ebp+0x10) %eax) +25065 (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n") +25066 (flush *(ebp+0x10)) +25067 (stop *(ebp+0x14) 1) +25068 # never gets here +25069 +25070 check-mu-clear-object-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25071 # . prologue +25072 55/push-ebp +25073 89/<- %ebp 4/r32/esp +25074 # . save registers +25075 50/push-eax +25076 51/push-ecx +25077 53/push-ebx +25078 56/push-esi +25079 57/push-edi +25080 # esi = stmt +25081 8b/-> *(ebp+8) 6/r32/esi +25082 $check-mu-clear-object-stmt:check-for-output: +25083 # if stmt->outputs abort +25084 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25085 3d/compare-eax-and 0/imm32 +25086 0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32 +25087 $check-mu-clear-object-stmt:get-left: +25088 # var dest/edi: (addr stmt-var) = stmt->inouts +25089 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25090 89/<- %edi 0/r32/eax +25091 # zero inouts +25092 3d/compare-eax-and 0/imm32 +25093 0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32 +25094 $check-mu-clear-object-stmt:get-src: +25095 # > 1 inout +25096 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +25097 3d/compare-eax-and 0/imm32 +25098 0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32 +25099 $check-mu-clear-object-stmt:types: +25100 # var src-type/ecx: (addr type-tree) = src->value->type +25101 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25102 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25103 89/<- %ecx 0/r32/eax +25104 # if (src->is-deref?) src-type = src-type->payload +25105 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +25106 3d/compare-eax-and 0/imm32/false +25107 { +25108 74/jump-if-= break/disp8 +25109 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +25110 # if src-type->right is null, src-type = src-type->left +25111 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +25112 { +25113 75/jump-if-!= break/disp8 +25114 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25115 } +25116 89/<- %ecx 0/r32/eax +25117 } +25118 # if src-type is not addr, abort +25119 (mu-addr-type? %ecx) # => eax +25120 3d/compare-eax-and 0/imm32/false +25121 0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32 +25122 $check-mu-clear-object-stmt:end: +25123 # . restore registers +25124 5f/pop-to-edi +25125 5e/pop-to-esi +25126 5b/pop-to-ebx +25127 59/pop-to-ecx +25128 58/pop-to-eax +25129 # . epilogue +25130 89/<- %esp 5/r32/ebp +25131 5d/pop-to-ebp +25132 c3/return +25133 +25134 $check-mu-clear-object-stmt:error-incorrect-inouts: +25135 (write-buffered *(ebp+0x10) "fn ") +25136 8b/-> *(ebp+0xc) 0/r32/eax +25137 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25138 (write-buffered *(ebp+0x10) %eax) +25139 (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n") +25140 (flush *(ebp+0x10)) +25141 (stop *(ebp+0x14) 1) +25142 # never gets here +25143 +25144 $check-mu-clear-object-stmt:error-too-many-outputs: +25145 (write-buffered *(ebp+0x10) "fn ") +25146 8b/-> *(ebp+0xc) 0/r32/eax +25147 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25148 (write-buffered *(ebp+0x10) %eax) +25149 (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n") +25150 (flush *(ebp+0x10)) +25151 (stop *(ebp+0x14) 1) +25152 # never gets here +25153 +25154 $check-mu-clear-object-stmt:error-invalid-type: +25155 (write-buffered *(ebp+0x10) "fn ") +25156 8b/-> *(ebp+0xc) 0/r32/eax +25157 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25158 (write-buffered *(ebp+0x10) %eax) +25159 (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n") +25160 (flush *(ebp+0x10)) +25161 (stop *(ebp+0x14) 1) +25162 # never gets here +25163 +25164 check-mu-allocate-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25165 # . prologue +25166 55/push-ebp +25167 89/<- %ebp 4/r32/esp +25168 # . save registers +25169 50/push-eax +25170 53/push-ebx +25171 56/push-esi +25172 57/push-edi +25173 # esi = stmt +25174 8b/-> *(ebp+8) 6/r32/esi +25175 $check-mu-allocate-stmt:check-for-output: +25176 # if stmt->outputs abort +25177 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25178 3d/compare-eax-and 0/imm32 +25179 0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32 +25180 $check-mu-allocate-stmt:get-target: +25181 # var target/edi: (addr stmt-var) = stmt->inouts +25182 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25183 89/<- %edi 0/r32/eax +25184 # zero inouts +25185 3d/compare-eax-and 0/imm32 +25186 0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32 +25187 # > 1 inouts +25188 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +25189 3d/compare-eax-and 0/imm32 +25190 0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32 +25191 $check-mu-allocate-stmt:check-type: +25192 # var target-type/ebx: (addr type-tree) = target->value->type +25193 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25194 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25195 89/<- %ebx 0/r32/eax +25196 # if (target->is-deref?) target-type = target-type->payload +25197 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +25198 3d/compare-eax-and 0/imm32/false +25199 { +25200 74/jump-if-= break/disp8 +25201 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25202 # if target-type->right is null, target-type = target-type->left +25203 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +25204 { +25205 75/jump-if-!= break/disp8 +25206 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25207 } +25208 89/<- %ebx 0/r32/eax +25209 } +25210 # if target-type is not addr, abort +25211 (mu-addr-type? %ebx) # => eax +25212 3d/compare-eax-and 0/imm32/false +25213 0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32 +25214 # if target-type->right is an atom, abort +25215 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25216 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +25217 0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32 +25218 # if target-type->right->left is not handle, abort +25219 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25220 (simple-mu-type? %eax 4) # handle => eax +25221 3d/compare-eax-and 0/imm32/false +25222 0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32 +25223 $check-mu-allocate-stmt:end: +25224 # . restore registers +25225 5f/pop-to-edi +25226 5e/pop-to-esi +25227 5b/pop-to-ebx +25228 58/pop-to-eax +25229 # . epilogue +25230 89/<- %esp 5/r32/ebp +25231 5d/pop-to-ebp +25232 c3/return +25233 +25234 $check-mu-allocate-stmt:error-incorrect-inouts: +25235 (write-buffered *(ebp+0x10) "fn ") +25236 8b/-> *(ebp+0xc) 0/r32/eax +25237 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25238 (write-buffered *(ebp+0x10) %eax) +25239 (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n") +25240 (flush *(ebp+0x10)) +25241 (stop *(ebp+0x14) 1) +25242 # never gets here +25243 +25244 $check-mu-allocate-stmt:error-too-many-outputs: +25245 (write-buffered *(ebp+0x10) "fn ") +25246 8b/-> *(ebp+0xc) 0/r32/eax +25247 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25248 (write-buffered *(ebp+0x10) %eax) +25249 (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n") +25250 (flush *(ebp+0x10)) +25251 (stop *(ebp+0x14) 1) +25252 # never gets here +25253 +25254 $check-mu-allocate-stmt:error-invalid-type: +25255 (write-buffered *(ebp+0x10) "fn ") +25256 8b/-> *(ebp+0xc) 0/r32/eax +25257 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25258 (write-buffered *(ebp+0x10) %eax) +25259 (write-buffered *(ebp+0x10) ": stmt allocate: inout '") +25260 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25261 (lookup *eax *(eax+4)) # Var-name Var-name => eax +25262 (write-buffered *(ebp+0x10) %eax) +25263 (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n") +25264 (flush *(ebp+0x10)) +25265 (stop *(ebp+0x14) 1) +25266 # never gets here +25267 +25268 check-mu-populate-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25269 # . prologue +25270 55/push-ebp +25271 89/<- %ebp 4/r32/esp +25272 # . save registers +25273 50/push-eax +25274 53/push-ebx +25275 56/push-esi +25276 57/push-edi +25277 # esi = stmt +25278 8b/-> *(ebp+8) 6/r32/esi +25279 $check-mu-populate-stmt:check-for-output: +25280 # if stmt->outputs abort +25281 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25282 3d/compare-eax-and 0/imm32 +25283 0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32 +25284 $check-mu-populate-stmt:get-target: +25285 # var target/edi: (addr stmt-var) = stmt->inouts +25286 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25287 89/<- %edi 0/r32/eax +25288 # zero inouts +25289 3d/compare-eax-and 0/imm32 +25290 0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32 +25291 $check-mu-populate-stmt:get-length: +25292 # var length/esi: (addr stmt-var) = dest->next +25293 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +25294 89/<- %esi 0/r32/eax +25295 # 1 inout +25296 3d/compare-eax-and 0/imm32 +25297 0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32 +25298 # > 2 inouts +25299 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +25300 3d/compare-eax-and 0/imm32 +25301 0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32 +25302 $check-mu-populate-stmt:check-target-type: +25303 # var target-type/ebx: (addr type-tree) = target->value->type +25304 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25305 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25306 89/<- %ebx 0/r32/eax +25307 $check-mu-populate-stmt:check-target-type-deref: +25308 # if (target->is-deref?) target-type = target-type->payload +25309 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +25310 3d/compare-eax-and 0/imm32/false +25311 { +25312 74/jump-if-= break/disp8 +25313 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25314 # if target-type->right is null, target-type = target-type->left +25315 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +25316 { +25317 75/jump-if-!= break/disp8 +25318 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25319 } +25320 89/<- %ebx 0/r32/eax +25321 } +25322 $check-mu-populate-stmt:check-target-type-addr: +25323 # if target-type is not addr, abort +25324 (mu-addr-type? %ebx) # => eax 25325 3d/compare-eax-and 0/imm32/false 25326 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32 -25327 $check-mu-populate-stmt:check-length-type: -25328 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -25329 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25330 89/<- %ebx 0/r32/eax -25331 (simple-mu-type? %ebx 0) # literal => eax -25332 3d/compare-eax-and 0/imm32/false -25333 75/jump-if-!= $check-mu-populate-stmt:end/disp8 -25334 (simple-mu-type? %ebx 1) # int => eax -25335 3d/compare-eax-and 0/imm32/false -25336 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32 -25337 $check-mu-populate-stmt:end: -25338 # . restore registers -25339 5f/pop-to-edi -25340 5e/pop-to-esi -25341 5b/pop-to-ebx -25342 58/pop-to-eax -25343 # . epilogue -25344 89/<- %esp 5/r32/ebp -25345 5d/pop-to-ebp -25346 c3/return -25347 -25348 $check-mu-populate-stmt:error-incorrect-inouts: -25349 (write-buffered *(ebp+0x10) "fn ") -25350 8b/-> *(ebp+0xc) 0/r32/eax -25351 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25352 (write-buffered *(ebp+0x10) %eax) -25353 (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n") -25354 (flush *(ebp+0x10)) -25355 (stop *(ebp+0x14) 1) -25356 # never gets here -25357 -25358 $check-mu-populate-stmt:error-too-many-outputs: -25359 (write-buffered *(ebp+0x10) "fn ") -25360 8b/-> *(ebp+0xc) 0/r32/eax -25361 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25362 (write-buffered *(ebp+0x10) %eax) -25363 (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n") -25364 (flush *(ebp+0x10)) -25365 (stop *(ebp+0x14) 1) -25366 # never gets here -25367 -25368 $check-mu-populate-stmt:error-invalid-target-type: -25369 (write-buffered *(ebp+0x10) "fn ") -25370 8b/-> *(ebp+0xc) 0/r32/eax -25371 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25372 (write-buffered *(ebp+0x10) %eax) -25373 (write-buffered *(ebp+0x10) ": stmt populate: first inout '") -25374 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25375 (lookup *eax *(eax+4)) # Var-name Var-name => eax -25376 (write-buffered *(ebp+0x10) %eax) -25377 (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n") -25378 (flush *(ebp+0x10)) -25379 (stop *(ebp+0x14) 1) -25380 # never gets here -25381 -25382 $check-mu-populate-stmt:error-invalid-length-type: -25383 (write-buffered *(ebp+0x10) "fn ") -25384 8b/-> *(ebp+0xc) 0/r32/eax -25385 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25386 (write-buffered *(ebp+0x10) %eax) -25387 (write-buffered *(ebp+0x10) ": stmt populate: second inout '") -25388 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -25389 (lookup *eax *(eax+4)) # Var-name Var-name => eax -25390 (write-buffered *(ebp+0x10) %eax) -25391 (write-buffered *(ebp+0x10) "' must be an int\n") -25392 (flush *(ebp+0x10)) -25393 (stop *(ebp+0x14) 1) -25394 # never gets here -25395 -25396 check-mu-populate-stream-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25397 # . prologue -25398 55/push-ebp -25399 89/<- %ebp 4/r32/esp -25400 # . save registers -25401 50/push-eax -25402 53/push-ebx -25403 56/push-esi -25404 57/push-edi -25405 # esi = stmt -25406 8b/-> *(ebp+8) 6/r32/esi -25407 $check-mu-populate-stream-stmt:check-for-output: -25408 # if stmt->outputs abort -25409 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25410 3d/compare-eax-and 0/imm32 -25411 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32 -25412 $check-mu-populate-stream-stmt:get-target: -25413 # var target/edi: (addr stmt-var) = stmt->inouts -25414 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25415 89/<- %edi 0/r32/eax -25416 # zero inouts -25417 3d/compare-eax-and 0/imm32 -25418 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32 -25419 $check-mu-populate-stream-stmt:get-length: -25420 # var length/esi: (addr stmt-var) = dest->next -25421 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -25422 89/<- %esi 0/r32/eax -25423 # 1 inout -25424 3d/compare-eax-and 0/imm32 -25425 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32 -25426 # > 2 inouts -25427 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -25428 3d/compare-eax-and 0/imm32 -25429 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32 -25430 $check-mu-populate-stream-stmt:check-target-type: -25431 # var target-type/ebx: (addr type-tree) = target->value->type -25432 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25433 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25434 89/<- %ebx 0/r32/eax -25435 $check-mu-populate-stream-stmt:check-target-type-deref: -25436 # if (target->is-deref?) target-type = target-type->payload -25437 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref -25438 3d/compare-eax-and 0/imm32/false -25439 { -25440 74/jump-if-= break/disp8 -25441 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25442 # if target-type->right is null, target-type = target-type->left -25443 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -25444 { -25445 75/jump-if-!= break/disp8 -25446 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25447 } -25448 89/<- %ebx 0/r32/eax -25449 } -25450 $check-mu-populate-stream-stmt:check-target-type-addr: -25451 # if target-type is not addr, abort -25452 (mu-addr-type? %ebx) # => eax -25453 3d/compare-eax-and 0/imm32/false -25454 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 -25455 # if target-type->right is an atom, abort -25456 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25457 89/<- %ebx 0/r32/eax -25458 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -25459 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 -25460 $check-mu-populate-stream-stmt:check-target-type-handle: -25461 # if target-type->right->left is not handle, abort -25462 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -25463 (simple-mu-type? %eax 4) # handle => eax -25464 3d/compare-eax-and 0/imm32/false -25465 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 -25466 # if target-type->right->right is an atom, abort -25467 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25468 89/<- %ebx 0/r32/eax -25469 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -25470 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 -25471 $check-mu-populate-stream-stmt:check-target-type-stream: -25472 # if target-type->right->right->left is not stream, abort -25473 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -25474 (simple-mu-type? %eax 0xb) # stream => eax +25327 # if target-type->right is an atom, abort +25328 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25329 89/<- %ebx 0/r32/eax +25330 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +25331 0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32 +25332 $check-mu-populate-stmt:check-target-type-handle: +25333 # if target-type->right->left is not handle, abort +25334 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +25335 (simple-mu-type? %eax 4) # handle => eax +25336 3d/compare-eax-and 0/imm32/false +25337 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32 +25338 # if target-type->right->right is an atom, abort +25339 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25340 89/<- %ebx 0/r32/eax +25341 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +25342 0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32 +25343 $check-mu-populate-stmt:check-target-type-array: +25344 # if target-type->right->right->left is not array, abort +25345 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +25346 (simple-mu-type? %eax 3) # array => eax +25347 3d/compare-eax-and 0/imm32/false +25348 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32 +25349 $check-mu-populate-stmt:check-length-type: +25350 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +25351 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25352 89/<- %ebx 0/r32/eax +25353 (simple-mu-type? %ebx 0) # literal => eax +25354 3d/compare-eax-and 0/imm32/false +25355 75/jump-if-!= $check-mu-populate-stmt:end/disp8 +25356 (simple-mu-type? %ebx 1) # int => eax +25357 3d/compare-eax-and 0/imm32/false +25358 0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32 +25359 $check-mu-populate-stmt:end: +25360 # . restore registers +25361 5f/pop-to-edi +25362 5e/pop-to-esi +25363 5b/pop-to-ebx +25364 58/pop-to-eax +25365 # . epilogue +25366 89/<- %esp 5/r32/ebp +25367 5d/pop-to-ebp +25368 c3/return +25369 +25370 $check-mu-populate-stmt:error-incorrect-inouts: +25371 (write-buffered *(ebp+0x10) "fn ") +25372 8b/-> *(ebp+0xc) 0/r32/eax +25373 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25374 (write-buffered *(ebp+0x10) %eax) +25375 (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n") +25376 (flush *(ebp+0x10)) +25377 (stop *(ebp+0x14) 1) +25378 # never gets here +25379 +25380 $check-mu-populate-stmt:error-too-many-outputs: +25381 (write-buffered *(ebp+0x10) "fn ") +25382 8b/-> *(ebp+0xc) 0/r32/eax +25383 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25384 (write-buffered *(ebp+0x10) %eax) +25385 (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n") +25386 (flush *(ebp+0x10)) +25387 (stop *(ebp+0x14) 1) +25388 # never gets here +25389 +25390 $check-mu-populate-stmt:error-invalid-target-type: +25391 (write-buffered *(ebp+0x10) "fn ") +25392 8b/-> *(ebp+0xc) 0/r32/eax +25393 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25394 (write-buffered *(ebp+0x10) %eax) +25395 (write-buffered *(ebp+0x10) ": stmt populate: first inout '") +25396 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25397 (lookup *eax *(eax+4)) # Var-name Var-name => eax +25398 (write-buffered *(ebp+0x10) %eax) +25399 (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n") +25400 (flush *(ebp+0x10)) +25401 (stop *(ebp+0x14) 1) +25402 # never gets here +25403 +25404 $check-mu-populate-stmt:error-invalid-length-type: +25405 (write-buffered *(ebp+0x10) "fn ") +25406 8b/-> *(ebp+0xc) 0/r32/eax +25407 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25408 (write-buffered *(ebp+0x10) %eax) +25409 (write-buffered *(ebp+0x10) ": stmt populate: second inout '") +25410 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +25411 (lookup *eax *(eax+4)) # Var-name Var-name => eax +25412 (write-buffered *(ebp+0x10) %eax) +25413 (write-buffered *(ebp+0x10) "' must be an int\n") +25414 (flush *(ebp+0x10)) +25415 (stop *(ebp+0x14) 1) +25416 # never gets here +25417 +25418 check-mu-populate-stream-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25419 # . prologue +25420 55/push-ebp +25421 89/<- %ebp 4/r32/esp +25422 # . save registers +25423 50/push-eax +25424 53/push-ebx +25425 56/push-esi +25426 57/push-edi +25427 # esi = stmt +25428 8b/-> *(ebp+8) 6/r32/esi +25429 $check-mu-populate-stream-stmt:check-for-output: +25430 # if stmt->outputs abort +25431 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25432 3d/compare-eax-and 0/imm32 +25433 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32 +25434 $check-mu-populate-stream-stmt:get-target: +25435 # var target/edi: (addr stmt-var) = stmt->inouts +25436 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25437 89/<- %edi 0/r32/eax +25438 # zero inouts +25439 3d/compare-eax-and 0/imm32 +25440 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32 +25441 $check-mu-populate-stream-stmt:get-length: +25442 # var length/esi: (addr stmt-var) = dest->next +25443 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +25444 89/<- %esi 0/r32/eax +25445 # 1 inout +25446 3d/compare-eax-and 0/imm32 +25447 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32 +25448 # > 2 inouts +25449 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +25450 3d/compare-eax-and 0/imm32 +25451 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32 +25452 $check-mu-populate-stream-stmt:check-target-type: +25453 # var target-type/ebx: (addr type-tree) = target->value->type +25454 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25455 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25456 89/<- %ebx 0/r32/eax +25457 $check-mu-populate-stream-stmt:check-target-type-deref: +25458 # if (target->is-deref?) target-type = target-type->payload +25459 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref +25460 3d/compare-eax-and 0/imm32/false +25461 { +25462 74/jump-if-= break/disp8 +25463 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25464 # if target-type->right is null, target-type = target-type->left +25465 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +25466 { +25467 75/jump-if-!= break/disp8 +25468 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25469 } +25470 89/<- %ebx 0/r32/eax +25471 } +25472 $check-mu-populate-stream-stmt:check-target-type-addr: +25473 # if target-type is not addr, abort +25474 (mu-addr-type? %ebx) # => eax 25475 3d/compare-eax-and 0/imm32/false 25476 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 -25477 $check-mu-populate-stream-stmt:check-length-type: -25478 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -25479 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25480 89/<- %ebx 0/r32/eax -25481 (simple-mu-type? %ebx 0) # literal => eax -25482 3d/compare-eax-and 0/imm32/false -25483 75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8 -25484 (simple-mu-type? %ebx 1) # int => eax -25485 3d/compare-eax-and 0/imm32/false -25486 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32 -25487 $check-mu-populate-stream-stmt:end: -25488 # . restore registers -25489 5f/pop-to-edi -25490 5e/pop-to-esi -25491 5b/pop-to-ebx -25492 58/pop-to-eax -25493 # . epilogue -25494 89/<- %esp 5/r32/ebp -25495 5d/pop-to-ebp -25496 c3/return -25497 -25498 $check-mu-populate-stream-stmt:error-incorrect-inouts: -25499 (write-buffered *(ebp+0x10) "fn ") -25500 8b/-> *(ebp+0xc) 0/r32/eax -25501 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25502 (write-buffered *(ebp+0x10) %eax) -25503 (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n") -25504 (flush *(ebp+0x10)) -25505 (stop *(ebp+0x14) 1) -25506 # never gets here -25507 -25508 $check-mu-populate-stream-stmt:error-too-many-outputs: -25509 (write-buffered *(ebp+0x10) "fn ") -25510 8b/-> *(ebp+0xc) 0/r32/eax -25511 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25512 (write-buffered *(ebp+0x10) %eax) -25513 (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n") -25514 (flush *(ebp+0x10)) -25515 (stop *(ebp+0x14) 1) -25516 # never gets here -25517 -25518 $check-mu-populate-stream-stmt:error-invalid-target-type: -25519 (write-buffered *(ebp+0x10) "fn ") -25520 8b/-> *(ebp+0xc) 0/r32/eax -25521 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25522 (write-buffered *(ebp+0x10) %eax) -25523 (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '") -25524 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25525 (lookup *eax *(eax+4)) # Var-name Var-name => eax -25526 (write-buffered *(ebp+0x10) %eax) -25527 (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n") -25528 (flush *(ebp+0x10)) -25529 (stop *(ebp+0x14) 1) -25530 # never gets here -25531 -25532 $check-mu-populate-stream-stmt:error-invalid-length-type: -25533 (write-buffered *(ebp+0x10) "fn ") -25534 8b/-> *(ebp+0xc) 0/r32/eax -25535 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25536 (write-buffered *(ebp+0x10) %eax) -25537 (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '") -25538 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -25539 (lookup *eax *(eax+4)) # Var-name Var-name => eax -25540 (write-buffered *(ebp+0x10) %eax) -25541 (write-buffered *(ebp+0x10) "' must be an int\n") -25542 (flush *(ebp+0x10)) -25543 (stop *(ebp+0x14) 1) -25544 # never gets here -25545 -25546 check-mu-read-from-stream-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25547 # . prologue -25548 55/push-ebp -25549 89/<- %ebp 4/r32/esp -25550 # . save registers -25551 50/push-eax -25552 51/push-ecx -25553 52/push-edx -25554 53/push-ebx -25555 56/push-esi -25556 57/push-edi -25557 # esi = stmt -25558 8b/-> *(ebp+8) 6/r32/esi -25559 # - check for 0 inouts -25560 # var base/ecx: (addr var) = stmt->inouts->value -25561 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25562 $check-mu-read-from-stream-stmt:check-no-inouts: -25563 3d/compare-eax-and 0/imm32 -25564 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32 -25565 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -25566 89/<- %ecx 0/r32/eax -25567 # - check base type is (addr stream T) -25568 # var base-type/ebx: (addr type-tree) = lookup(base->type) -25569 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -25570 89/<- %ebx 0/r32/eax -25571 $check-mu-read-from-stream-stmt:check-base-is-compound: -25572 # if base-type is an atom, abort -25573 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -25574 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32 -25575 $check-mu-read-from-stream-stmt:check-base-is-addr: -25576 # if type->left not addr, abort -25577 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -25578 (simple-mu-type? %eax 2) # addr => eax -25579 3d/compare-eax-and 0/imm32/false -25580 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32 -25581 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream: -25582 # base-type = base-type->right -25583 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25584 89/<- %ebx 0/r32/eax -25585 # ensure base-type->left == stream -25586 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25587 (simple-mu-type? %eax 0xb) # stream => eax -25588 3d/compare-eax-and 0/imm32/false -25589 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32 -25590 # - check target type is (addr T) -25591 # var target/ecx: (addr stmt-var) = stmt->inouts->next->value -25592 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25593 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -25594 $check-mu-read-from-stream-stmt:check-single-inout: -25595 3d/compare-eax-and 0/imm32 -25596 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32 -25597 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -25598 89/<- %ecx 0/r32/eax -25599 # var target-type/edx: (addr type-tree) -25600 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -25601 89/<- %edx 0/r32/eax -25602 # if target-type is an atom, it must be a literal or int -25603 $check-mu-read-from-stream-stmt:check-target-is-compound: -25604 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom -25605 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32 -25606 $check-mu-read-from-stream-stmt:check-target-type: -25607 # target type must start with (addr ...) -25608 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -25609 (simple-mu-type? %eax 2) # addr => eax +25477 # if target-type->right is an atom, abort +25478 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25479 89/<- %ebx 0/r32/eax +25480 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +25481 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 +25482 $check-mu-populate-stream-stmt:check-target-type-handle: +25483 # if target-type->right->left is not handle, abort +25484 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +25485 (simple-mu-type? %eax 4) # handle => eax +25486 3d/compare-eax-and 0/imm32/false +25487 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 +25488 # if target-type->right->right is an atom, abort +25489 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25490 89/<- %ebx 0/r32/eax +25491 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +25492 0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 +25493 $check-mu-populate-stream-stmt:check-target-type-stream: +25494 # if target-type->right->right->left is not stream, abort +25495 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +25496 (simple-mu-type? %eax 0xb) # stream => eax +25497 3d/compare-eax-and 0/imm32/false +25498 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32 +25499 $check-mu-populate-stream-stmt:check-length-type: +25500 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +25501 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25502 89/<- %ebx 0/r32/eax +25503 (simple-mu-type? %ebx 0) # literal => eax +25504 3d/compare-eax-and 0/imm32/false +25505 75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8 +25506 (simple-mu-type? %ebx 1) # int => eax +25507 3d/compare-eax-and 0/imm32/false +25508 0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32 +25509 $check-mu-populate-stream-stmt:end: +25510 # . restore registers +25511 5f/pop-to-edi +25512 5e/pop-to-esi +25513 5b/pop-to-ebx +25514 58/pop-to-eax +25515 # . epilogue +25516 89/<- %esp 5/r32/ebp +25517 5d/pop-to-ebp +25518 c3/return +25519 +25520 $check-mu-populate-stream-stmt:error-incorrect-inouts: +25521 (write-buffered *(ebp+0x10) "fn ") +25522 8b/-> *(ebp+0xc) 0/r32/eax +25523 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25524 (write-buffered *(ebp+0x10) %eax) +25525 (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n") +25526 (flush *(ebp+0x10)) +25527 (stop *(ebp+0x14) 1) +25528 # never gets here +25529 +25530 $check-mu-populate-stream-stmt:error-too-many-outputs: +25531 (write-buffered *(ebp+0x10) "fn ") +25532 8b/-> *(ebp+0xc) 0/r32/eax +25533 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25534 (write-buffered *(ebp+0x10) %eax) +25535 (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n") +25536 (flush *(ebp+0x10)) +25537 (stop *(ebp+0x14) 1) +25538 # never gets here +25539 +25540 $check-mu-populate-stream-stmt:error-invalid-target-type: +25541 (write-buffered *(ebp+0x10) "fn ") +25542 8b/-> *(ebp+0xc) 0/r32/eax +25543 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25544 (write-buffered *(ebp+0x10) %eax) +25545 (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '") +25546 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25547 (lookup *eax *(eax+4)) # Var-name Var-name => eax +25548 (write-buffered *(ebp+0x10) %eax) +25549 (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n") +25550 (flush *(ebp+0x10)) +25551 (stop *(ebp+0x14) 1) +25552 # never gets here +25553 +25554 $check-mu-populate-stream-stmt:error-invalid-length-type: +25555 (write-buffered *(ebp+0x10) "fn ") +25556 8b/-> *(ebp+0xc) 0/r32/eax +25557 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25558 (write-buffered *(ebp+0x10) %eax) +25559 (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '") +25560 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +25561 (lookup *eax *(eax+4)) # Var-name Var-name => eax +25562 (write-buffered *(ebp+0x10) %eax) +25563 (write-buffered *(ebp+0x10) "' must be an int\n") +25564 (flush *(ebp+0x10)) +25565 (stop *(ebp+0x14) 1) +25566 # never gets here +25567 +25568 check-mu-read-from-stream-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25569 # . prologue +25570 55/push-ebp +25571 89/<- %ebp 4/r32/esp +25572 # . save registers +25573 50/push-eax +25574 51/push-ecx +25575 52/push-edx +25576 53/push-ebx +25577 56/push-esi +25578 57/push-edi +25579 # esi = stmt +25580 8b/-> *(ebp+8) 6/r32/esi +25581 # - check for 0 inouts +25582 # var base/ecx: (addr var) = stmt->inouts->value +25583 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25584 $check-mu-read-from-stream-stmt:check-no-inouts: +25585 3d/compare-eax-and 0/imm32 +25586 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32 +25587 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +25588 89/<- %ecx 0/r32/eax +25589 # - check base type is (addr stream T) +25590 # var base-type/ebx: (addr type-tree) = lookup(base->type) +25591 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +25592 89/<- %ebx 0/r32/eax +25593 $check-mu-read-from-stream-stmt:check-base-is-compound: +25594 # if base-type is an atom, abort +25595 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +25596 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32 +25597 $check-mu-read-from-stream-stmt:check-base-is-addr: +25598 # if type->left not addr, abort +25599 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +25600 (simple-mu-type? %eax 2) # addr => eax +25601 3d/compare-eax-and 0/imm32/false +25602 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32 +25603 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream: +25604 # base-type = base-type->right +25605 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25606 89/<- %ebx 0/r32/eax +25607 # ensure base-type->left == stream +25608 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25609 (simple-mu-type? %eax 0xb) # stream => eax 25610 3d/compare-eax-and 0/imm32/false -25611 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32 -25612 # if tail(base-type) != tail(target-type) abort -25613 (type-tail %ebx) # => eax -25614 89/<- %ebx 0/r32/eax -25615 (type-tail %edx) # => eax -25616 (type-equal? %ebx %eax) # => eax -25617 3d/compare-eax-and 0/imm32/false -25618 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32 -25619 $check-mu-read-from-stream-stmt:check-too-many-inouts: -25620 # - check for too many inouts -25621 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25622 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -25623 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -25624 3d/compare-eax-and 0/imm32/false -25625 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32 -25626 $check-mu-read-from-stream-stmt:check-unexpected-output: -25627 # - check for any output -25628 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25629 3d/compare-eax-and 0/imm32/false -25630 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32 -25631 $check-mu-read-from-stream-stmt:end: -25632 # . restore registers -25633 5f/pop-to-edi -25634 5e/pop-to-esi -25635 5b/pop-to-ebx -25636 5a/pop-to-edx -25637 59/pop-to-ecx -25638 58/pop-to-eax -25639 # . epilogue -25640 89/<- %esp 5/r32/ebp -25641 5d/pop-to-ebp -25642 c3/return -25643 -25644 $check-mu-read-from-stream-stmt:error-invalid-base-type: -25645 (write-buffered *(ebp+0x10) "fn ") -25646 8b/-> *(ebp+0xc) 0/r32/eax -25647 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25648 (write-buffered *(ebp+0x10) %eax) -25649 (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '") -25650 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -25651 (write-buffered *(ebp+0x10) %eax) -25652 (write-buffered *(ebp+0x10) "' must be an addr to a stream\n") -25653 (flush *(ebp+0x10)) -25654 (stop *(ebp+0x14) 1) -25655 # never gets here -25656 -25657 $check-mu-read-from-stream-stmt:error-too-few-inouts: -25658 (write-buffered *(ebp+0x10) "fn ") -25659 8b/-> *(ebp+0xc) 0/r32/eax -25660 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25661 (write-buffered *(ebp+0x10) %eax) -25662 (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n") -25663 (flush *(ebp+0x10)) -25664 (stop *(ebp+0x14) 1) -25665 # never gets here -25666 -25667 $check-mu-read-from-stream-stmt:error-target-type-not-address: -25668 (write-buffered *(ebp+0x10) "fn ") -25669 8b/-> *(ebp+0xc) 0/r32/eax -25670 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25671 (write-buffered *(ebp+0x10) %eax) -25672 (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '") -25673 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -25674 (write-buffered *(ebp+0x10) %eax) -25675 (write-buffered *(ebp+0x10) "' must be an addr\n") -25676 (flush *(ebp+0x10)) -25677 (stop *(ebp+0x14) 1) -25678 # never gets here -25679 -25680 $check-mu-read-from-stream-stmt:error-invalid-target-type: -25681 (write-buffered *(ebp+0x10) "fn ") -25682 8b/-> *(ebp+0xc) 0/r32/eax -25683 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25684 (write-buffered *(ebp+0x10) %eax) -25685 (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '") -25686 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -25687 (write-buffered *(ebp+0x10) %eax) -25688 (write-buffered *(ebp+0x10) "' does not have the right type\n") -25689 (flush *(ebp+0x10)) -25690 (stop *(ebp+0x14) 1) -25691 # never gets here -25692 -25693 $check-mu-read-from-stream-stmt:error-too-many-inouts: -25694 (write-buffered *(ebp+0x10) "fn ") -25695 8b/-> *(ebp+0xc) 0/r32/eax -25696 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25697 (write-buffered *(ebp+0x10) %eax) -25698 (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n") -25699 (flush *(ebp+0x10)) -25700 (stop *(ebp+0x14) 1) -25701 # never gets here -25702 -25703 $check-mu-read-from-stream-stmt:error-unexpected-output: -25704 (write-buffered *(ebp+0x10) "fn ") -25705 8b/-> *(ebp+0xc) 0/r32/eax -25706 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25707 (write-buffered *(ebp+0x10) %eax) -25708 (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n") -25709 (flush *(ebp+0x10)) -25710 (stop *(ebp+0x14) 1) -25711 # never gets here -25712 -25713 check-mu-write-to-stream-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25714 # . prologue -25715 55/push-ebp -25716 89/<- %ebp 4/r32/esp -25717 # . save registers -25718 50/push-eax -25719 51/push-ecx -25720 52/push-edx -25721 53/push-ebx -25722 56/push-esi -25723 57/push-edi -25724 # esi = stmt -25725 8b/-> *(ebp+8) 6/r32/esi -25726 # - check for 0 inouts -25727 # var base/ecx: (addr var) = stmt->inouts->value -25728 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25729 $check-mu-write-to-stream-stmt:check-no-inouts: -25730 3d/compare-eax-and 0/imm32 -25731 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32 -25732 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -25733 89/<- %ecx 0/r32/eax -25734 # - check base type is (addr stream T) -25735 # var base-type/ebx: (addr type-tree) = lookup(base->type) -25736 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -25737 89/<- %ebx 0/r32/eax -25738 $check-mu-write-to-stream-stmt:check-base-is-compound: -25739 # if base-type is an atom, abort -25740 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom -25741 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32 -25742 $check-mu-write-to-stream-stmt:check-base-is-addr: -25743 # if type->left not addr, abort -25744 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -25745 (simple-mu-type? %eax 2) # addr => eax -25746 3d/compare-eax-and 0/imm32/false -25747 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32 -25748 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream: -25749 # base-type = base-type->right -25750 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -25751 89/<- %ebx 0/r32/eax -25752 # ensure base-type->left == stream -25753 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25754 (simple-mu-type? %eax 0xb) # stream => eax -25755 3d/compare-eax-and 0/imm32/false -25756 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32 -25757 # - check target type is (addr T) -25758 # var target/ecx: (addr stmt-var) = stmt->inouts->next->value -25759 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25760 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -25761 $check-mu-write-to-stream-stmt:check-single-inout: -25762 3d/compare-eax-and 0/imm32 -25763 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32 -25764 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -25765 89/<- %ecx 0/r32/eax -25766 # var target-type/edx: (addr type-tree) -25767 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -25768 89/<- %edx 0/r32/eax -25769 # if target-type is an atom, it must be a literal or int -25770 $check-mu-write-to-stream-stmt:check-target-is-compound: -25771 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom -25772 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32 -25773 $check-mu-write-to-stream-stmt:check-target-type: -25774 # target type must start with (addr ...) -25775 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -25776 (simple-mu-type? %eax 2) # addr => eax +25611 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32 +25612 # - check target type is (addr T) +25613 # var target/ecx: (addr stmt-var) = stmt->inouts->next->value +25614 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25615 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +25616 $check-mu-read-from-stream-stmt:check-single-inout: +25617 3d/compare-eax-and 0/imm32 +25618 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32 +25619 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +25620 89/<- %ecx 0/r32/eax +25621 # var target-type/edx: (addr type-tree) +25622 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +25623 89/<- %edx 0/r32/eax +25624 # if target-type is an atom, it must be a literal or int +25625 $check-mu-read-from-stream-stmt:check-target-is-compound: +25626 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom +25627 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32 +25628 $check-mu-read-from-stream-stmt:check-target-type: +25629 # target type must start with (addr ...) +25630 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +25631 (simple-mu-type? %eax 2) # addr => eax +25632 3d/compare-eax-and 0/imm32/false +25633 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32 +25634 # if tail(base-type) != tail(target-type) abort +25635 (type-tail %ebx) # => eax +25636 89/<- %ebx 0/r32/eax +25637 (type-tail %edx) # => eax +25638 (type-equal? %ebx %eax) # => eax +25639 3d/compare-eax-and 0/imm32/false +25640 0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32 +25641 $check-mu-read-from-stream-stmt:check-too-many-inouts: +25642 # - check for too many inouts +25643 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25644 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +25645 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +25646 3d/compare-eax-and 0/imm32/false +25647 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32 +25648 $check-mu-read-from-stream-stmt:check-unexpected-output: +25649 # - check for any output +25650 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25651 3d/compare-eax-and 0/imm32/false +25652 0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32 +25653 $check-mu-read-from-stream-stmt:end: +25654 # . restore registers +25655 5f/pop-to-edi +25656 5e/pop-to-esi +25657 5b/pop-to-ebx +25658 5a/pop-to-edx +25659 59/pop-to-ecx +25660 58/pop-to-eax +25661 # . epilogue +25662 89/<- %esp 5/r32/ebp +25663 5d/pop-to-ebp +25664 c3/return +25665 +25666 $check-mu-read-from-stream-stmt:error-invalid-base-type: +25667 (write-buffered *(ebp+0x10) "fn ") +25668 8b/-> *(ebp+0xc) 0/r32/eax +25669 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25670 (write-buffered *(ebp+0x10) %eax) +25671 (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '") +25672 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +25673 (write-buffered *(ebp+0x10) %eax) +25674 (write-buffered *(ebp+0x10) "' must be an addr to a stream\n") +25675 (flush *(ebp+0x10)) +25676 (stop *(ebp+0x14) 1) +25677 # never gets here +25678 +25679 $check-mu-read-from-stream-stmt:error-too-few-inouts: +25680 (write-buffered *(ebp+0x10) "fn ") +25681 8b/-> *(ebp+0xc) 0/r32/eax +25682 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25683 (write-buffered *(ebp+0x10) %eax) +25684 (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n") +25685 (flush *(ebp+0x10)) +25686 (stop *(ebp+0x14) 1) +25687 # never gets here +25688 +25689 $check-mu-read-from-stream-stmt:error-target-type-not-address: +25690 (write-buffered *(ebp+0x10) "fn ") +25691 8b/-> *(ebp+0xc) 0/r32/eax +25692 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25693 (write-buffered *(ebp+0x10) %eax) +25694 (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '") +25695 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +25696 (write-buffered *(ebp+0x10) %eax) +25697 (write-buffered *(ebp+0x10) "' must be an addr\n") +25698 (flush *(ebp+0x10)) +25699 (stop *(ebp+0x14) 1) +25700 # never gets here +25701 +25702 $check-mu-read-from-stream-stmt:error-invalid-target-type: +25703 (write-buffered *(ebp+0x10) "fn ") +25704 8b/-> *(ebp+0xc) 0/r32/eax +25705 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25706 (write-buffered *(ebp+0x10) %eax) +25707 (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '") +25708 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +25709 (write-buffered *(ebp+0x10) %eax) +25710 (write-buffered *(ebp+0x10) "' does not have the right type\n") +25711 (flush *(ebp+0x10)) +25712 (stop *(ebp+0x14) 1) +25713 # never gets here +25714 +25715 $check-mu-read-from-stream-stmt:error-too-many-inouts: +25716 (write-buffered *(ebp+0x10) "fn ") +25717 8b/-> *(ebp+0xc) 0/r32/eax +25718 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25719 (write-buffered *(ebp+0x10) %eax) +25720 (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n") +25721 (flush *(ebp+0x10)) +25722 (stop *(ebp+0x14) 1) +25723 # never gets here +25724 +25725 $check-mu-read-from-stream-stmt:error-unexpected-output: +25726 (write-buffered *(ebp+0x10) "fn ") +25727 8b/-> *(ebp+0xc) 0/r32/eax +25728 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25729 (write-buffered *(ebp+0x10) %eax) +25730 (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n") +25731 (flush *(ebp+0x10)) +25732 (stop *(ebp+0x14) 1) +25733 # never gets here +25734 +25735 check-mu-write-to-stream-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25736 # . prologue +25737 55/push-ebp +25738 89/<- %ebp 4/r32/esp +25739 # . save registers +25740 50/push-eax +25741 51/push-ecx +25742 52/push-edx +25743 53/push-ebx +25744 56/push-esi +25745 57/push-edi +25746 # esi = stmt +25747 8b/-> *(ebp+8) 6/r32/esi +25748 # - check for 0 inouts +25749 # var base/ecx: (addr var) = stmt->inouts->value +25750 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25751 $check-mu-write-to-stream-stmt:check-no-inouts: +25752 3d/compare-eax-and 0/imm32 +25753 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32 +25754 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +25755 89/<- %ecx 0/r32/eax +25756 # - check base type is (addr stream T) +25757 # var base-type/ebx: (addr type-tree) = lookup(base->type) +25758 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +25759 89/<- %ebx 0/r32/eax +25760 $check-mu-write-to-stream-stmt:check-base-is-compound: +25761 # if base-type is an atom, abort +25762 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom +25763 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32 +25764 $check-mu-write-to-stream-stmt:check-base-is-addr: +25765 # if type->left not addr, abort +25766 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +25767 (simple-mu-type? %eax 2) # addr => eax +25768 3d/compare-eax-and 0/imm32/false +25769 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32 +25770 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream: +25771 # base-type = base-type->right +25772 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +25773 89/<- %ebx 0/r32/eax +25774 # ensure base-type->left == stream +25775 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25776 (simple-mu-type? %eax 0xb) # stream => eax 25777 3d/compare-eax-and 0/imm32/false -25778 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32 -25779 # if tail(base-type) != tail(target-type) abort -25780 (type-tail %ebx) # => eax -25781 89/<- %ebx 0/r32/eax -25782 (type-tail %edx) # => eax -25783 (type-equal? %ebx %eax) # => eax -25784 3d/compare-eax-and 0/imm32/false -25785 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32 -25786 $check-mu-write-to-stream-stmt:check-too-many-inouts: -25787 # - check for too many inouts -25788 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25789 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -25790 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -25791 3d/compare-eax-and 0/imm32/false -25792 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32 -25793 $check-mu-write-to-stream-stmt:check-unexpected-output: -25794 # - check for any output -25795 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25796 3d/compare-eax-and 0/imm32/false -25797 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32 -25798 $check-mu-write-to-stream-stmt:end: -25799 # . restore registers -25800 5f/pop-to-edi -25801 5e/pop-to-esi -25802 5b/pop-to-ebx -25803 5a/pop-to-edx -25804 59/pop-to-ecx -25805 58/pop-to-eax -25806 # . epilogue -25807 89/<- %esp 5/r32/ebp -25808 5d/pop-to-ebp -25809 c3/return -25810 -25811 $check-mu-write-to-stream-stmt:error-invalid-base-type: -25812 (write-buffered *(ebp+0x10) "fn ") -25813 8b/-> *(ebp+0xc) 0/r32/eax -25814 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25815 (write-buffered *(ebp+0x10) %eax) -25816 (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '") -25817 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -25818 (write-buffered *(ebp+0x10) %eax) -25819 (write-buffered *(ebp+0x10) "' must be an addr to a stream\n") -25820 (flush *(ebp+0x10)) -25821 (stop *(ebp+0x14) 1) -25822 # never gets here -25823 -25824 $check-mu-write-to-stream-stmt:error-too-few-inouts: -25825 (write-buffered *(ebp+0x10) "fn ") -25826 8b/-> *(ebp+0xc) 0/r32/eax -25827 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25828 (write-buffered *(ebp+0x10) %eax) -25829 (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n") -25830 (flush *(ebp+0x10)) -25831 (stop *(ebp+0x14) 1) -25832 # never gets here -25833 -25834 $check-mu-write-to-stream-stmt:error-target-type-not-address: -25835 (write-buffered *(ebp+0x10) "fn ") -25836 8b/-> *(ebp+0xc) 0/r32/eax -25837 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25838 (write-buffered *(ebp+0x10) %eax) -25839 (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '") -25840 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -25841 (write-buffered *(ebp+0x10) %eax) -25842 (write-buffered *(ebp+0x10) "' must be an addr\n") -25843 (flush *(ebp+0x10)) -25844 (stop *(ebp+0x14) 1) -25845 # never gets here -25846 -25847 $check-mu-write-to-stream-stmt:error-invalid-target-type: -25848 (write-buffered *(ebp+0x10) "fn ") -25849 8b/-> *(ebp+0xc) 0/r32/eax -25850 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25851 (write-buffered *(ebp+0x10) %eax) -25852 (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '") -25853 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -25854 (write-buffered *(ebp+0x10) %eax) -25855 (write-buffered *(ebp+0x10) "' does not have the right type\n") -25856 (flush *(ebp+0x10)) -25857 (stop *(ebp+0x14) 1) -25858 # never gets here -25859 -25860 $check-mu-write-to-stream-stmt:error-too-many-inouts: -25861 (write-buffered *(ebp+0x10) "fn ") -25862 8b/-> *(ebp+0xc) 0/r32/eax -25863 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25864 (write-buffered *(ebp+0x10) %eax) -25865 (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n") -25866 (flush *(ebp+0x10)) -25867 (stop *(ebp+0x14) 1) -25868 # never gets here -25869 -25870 $check-mu-write-to-stream-stmt:error-unexpected-output: -25871 (write-buffered *(ebp+0x10) "fn ") -25872 8b/-> *(ebp+0xc) 0/r32/eax -25873 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25874 (write-buffered *(ebp+0x10) %eax) -25875 (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n") -25876 (flush *(ebp+0x10)) -25877 (stop *(ebp+0x14) 1) -25878 # never gets here -25879 -25880 check-mu-convert-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -25881 # . prologue -25882 55/push-ebp -25883 89/<- %ebp 4/r32/esp -25884 # . save registers -25885 50/push-eax -25886 51/push-ecx -25887 52/push-edx -25888 56/push-esi -25889 57/push-edi -25890 $check-mu-convert-stmt:get-output: -25891 # esi = stmt -25892 8b/-> *(ebp+8) 6/r32/esi -25893 # var output/edi: (addr stmt-var) = stmt->outputs -25894 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -25895 89/<- %edi 0/r32/eax -25896 # zero outputs -25897 3d/compare-eax-and 0/imm32 -25898 0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32 -25899 # > 1 output -25900 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -25901 3d/compare-eax-and 0/imm32 -25902 0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32 -25903 $check-mu-convert-stmt:get-inout: -25904 # var inout/esi: (addr stmt-var) = stmt->inouts -25905 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -25906 89/<- %esi 0/r32/eax -25907 # zero inouts -25908 3d/compare-eax-and 0/imm32 -25909 0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32 -25910 # > 1 inout -25911 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -25912 3d/compare-eax-and 0/imm32 -25913 0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32 -25914 $check-mu-convert-stmt:types: -25915 # var inout-type/ecx: (addr type-tree) = inout->value->type -25916 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -25917 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25918 89/<- %ecx 0/r32/eax -25919 # if (inout->is-deref?) inout-type = inout-type->payload -25920 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref -25921 3d/compare-eax-and 0/imm32/false -25922 { -25923 74/jump-if-= break/disp8 -25924 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -25925 # if inout-type->right is null, t = inout-type->left -25926 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right -25927 { -25928 75/jump-if-!= break/disp8 -25929 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -25930 } -25931 89/<- %ecx 0/r32/eax -25932 } -25933 # if input is not int or float, abort -25934 { -25935 (simple-mu-type? %ecx 1) # int => eax -25936 3d/compare-eax-and 0/imm32/false -25937 75/jump-if-!= break/disp8 -25938 (simple-mu-type? %ecx 0xf) # float => eax -25939 3d/compare-eax-and 0/imm32/false -25940 75/jump-if-!= break/disp8 -25941 e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32 -25942 } -25943 # if output not in register, abort -25944 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25945 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -25946 3d/compare-eax-and 0/imm32 -25947 0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32 -25948 # var output-type/edx: (addr type-tree) = output->value->type -25949 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -25950 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -25951 89/<- %edx 0/r32/eax -25952 # if output is not int or float, abort -25953 { -25954 (simple-mu-type? %edx 1) # int => eax -25955 3d/compare-eax-and 0/imm32/false -25956 75/jump-if-!= break/disp8 -25957 (simple-mu-type? %edx 0xf) # float => eax +25778 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32 +25779 # - check target type is (addr T) +25780 # var target/ecx: (addr stmt-var) = stmt->inouts->next->value +25781 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25782 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +25783 $check-mu-write-to-stream-stmt:check-single-inout: +25784 3d/compare-eax-and 0/imm32 +25785 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32 +25786 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +25787 89/<- %ecx 0/r32/eax +25788 # var target-type/edx: (addr type-tree) +25789 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +25790 89/<- %edx 0/r32/eax +25791 # if target-type is an atom, it must be a literal or int +25792 $check-mu-write-to-stream-stmt:check-target-is-compound: +25793 81 7/subop/compare *edx 0/imm32/false # Type-tree-is-atom +25794 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32 +25795 $check-mu-write-to-stream-stmt:check-target-type: +25796 # target type must start with (addr ...) +25797 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +25798 (simple-mu-type? %eax 2) # addr => eax +25799 3d/compare-eax-and 0/imm32/false +25800 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32 +25801 # if tail(base-type) != tail(target-type) abort +25802 (type-tail %ebx) # => eax +25803 89/<- %ebx 0/r32/eax +25804 (type-tail %edx) # => eax +25805 (type-equal? %ebx %eax) # => eax +25806 3d/compare-eax-and 0/imm32/false +25807 0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32 +25808 $check-mu-write-to-stream-stmt:check-too-many-inouts: +25809 # - check for too many inouts +25810 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25811 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +25812 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +25813 3d/compare-eax-and 0/imm32/false +25814 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32 +25815 $check-mu-write-to-stream-stmt:check-unexpected-output: +25816 # - check for any output +25817 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25818 3d/compare-eax-and 0/imm32/false +25819 0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32 +25820 $check-mu-write-to-stream-stmt:end: +25821 # . restore registers +25822 5f/pop-to-edi +25823 5e/pop-to-esi +25824 5b/pop-to-ebx +25825 5a/pop-to-edx +25826 59/pop-to-ecx +25827 58/pop-to-eax +25828 # . epilogue +25829 89/<- %esp 5/r32/ebp +25830 5d/pop-to-ebp +25831 c3/return +25832 +25833 $check-mu-write-to-stream-stmt:error-invalid-base-type: +25834 (write-buffered *(ebp+0x10) "fn ") +25835 8b/-> *(ebp+0xc) 0/r32/eax +25836 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25837 (write-buffered *(ebp+0x10) %eax) +25838 (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '") +25839 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +25840 (write-buffered *(ebp+0x10) %eax) +25841 (write-buffered *(ebp+0x10) "' must be an addr to a stream\n") +25842 (flush *(ebp+0x10)) +25843 (stop *(ebp+0x14) 1) +25844 # never gets here +25845 +25846 $check-mu-write-to-stream-stmt:error-too-few-inouts: +25847 (write-buffered *(ebp+0x10) "fn ") +25848 8b/-> *(ebp+0xc) 0/r32/eax +25849 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25850 (write-buffered *(ebp+0x10) %eax) +25851 (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n") +25852 (flush *(ebp+0x10)) +25853 (stop *(ebp+0x14) 1) +25854 # never gets here +25855 +25856 $check-mu-write-to-stream-stmt:error-target-type-not-address: +25857 (write-buffered *(ebp+0x10) "fn ") +25858 8b/-> *(ebp+0xc) 0/r32/eax +25859 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25860 (write-buffered *(ebp+0x10) %eax) +25861 (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '") +25862 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +25863 (write-buffered *(ebp+0x10) %eax) +25864 (write-buffered *(ebp+0x10) "' must be an addr\n") +25865 (flush *(ebp+0x10)) +25866 (stop *(ebp+0x14) 1) +25867 # never gets here +25868 +25869 $check-mu-write-to-stream-stmt:error-invalid-target-type: +25870 (write-buffered *(ebp+0x10) "fn ") +25871 8b/-> *(ebp+0xc) 0/r32/eax +25872 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25873 (write-buffered *(ebp+0x10) %eax) +25874 (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '") +25875 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +25876 (write-buffered *(ebp+0x10) %eax) +25877 (write-buffered *(ebp+0x10) "' does not have the right type\n") +25878 (flush *(ebp+0x10)) +25879 (stop *(ebp+0x14) 1) +25880 # never gets here +25881 +25882 $check-mu-write-to-stream-stmt:error-too-many-inouts: +25883 (write-buffered *(ebp+0x10) "fn ") +25884 8b/-> *(ebp+0xc) 0/r32/eax +25885 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25886 (write-buffered *(ebp+0x10) %eax) +25887 (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n") +25888 (flush *(ebp+0x10)) +25889 (stop *(ebp+0x14) 1) +25890 # never gets here +25891 +25892 $check-mu-write-to-stream-stmt:error-unexpected-output: +25893 (write-buffered *(ebp+0x10) "fn ") +25894 8b/-> *(ebp+0xc) 0/r32/eax +25895 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25896 (write-buffered *(ebp+0x10) %eax) +25897 (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n") +25898 (flush *(ebp+0x10)) +25899 (stop *(ebp+0x14) 1) +25900 # never gets here +25901 +25902 check-mu-convert-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +25903 # . prologue +25904 55/push-ebp +25905 89/<- %ebp 4/r32/esp +25906 # . save registers +25907 50/push-eax +25908 51/push-ecx +25909 52/push-edx +25910 56/push-esi +25911 57/push-edi +25912 $check-mu-convert-stmt:get-output: +25913 # esi = stmt +25914 8b/-> *(ebp+8) 6/r32/esi +25915 # var output/edi: (addr stmt-var) = stmt->outputs +25916 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +25917 89/<- %edi 0/r32/eax +25918 # zero outputs +25919 3d/compare-eax-and 0/imm32 +25920 0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32 +25921 # > 1 output +25922 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +25923 3d/compare-eax-and 0/imm32 +25924 0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32 +25925 $check-mu-convert-stmt:get-inout: +25926 # var inout/esi: (addr stmt-var) = stmt->inouts +25927 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +25928 89/<- %esi 0/r32/eax +25929 # zero inouts +25930 3d/compare-eax-and 0/imm32 +25931 0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32 +25932 # > 1 inout +25933 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +25934 3d/compare-eax-and 0/imm32 +25935 0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32 +25936 $check-mu-convert-stmt:types: +25937 # var inout-type/ecx: (addr type-tree) = inout->value->type +25938 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +25939 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25940 89/<- %ecx 0/r32/eax +25941 # if (inout->is-deref?) inout-type = inout-type->payload +25942 8b/-> *(esi+0x10) 0/r32/eax # Stmt-var-is-deref +25943 3d/compare-eax-and 0/imm32/false +25944 { +25945 74/jump-if-= break/disp8 +25946 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +25947 # if inout-type->right is null, t = inout-type->left +25948 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right +25949 { +25950 75/jump-if-!= break/disp8 +25951 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +25952 } +25953 89/<- %ecx 0/r32/eax +25954 } +25955 # if input is not int or float, abort +25956 { +25957 (simple-mu-type? %ecx 1) # int => eax 25958 3d/compare-eax-and 0/imm32/false 25959 75/jump-if-!= break/disp8 -25960 e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32 -25961 } -25962 # if both are ints, abort -25963 { -25964 (simple-mu-type? %edx 1) # int => eax -25965 3d/compare-eax-and 0/imm32/false -25966 74/jump-if-= break/disp8 -25967 (simple-mu-type? %ecx 1) # int => eax -25968 3d/compare-eax-and 0/imm32/false -25969 74/jump-if-= break/disp8 -25970 e9/jump $check-mu-convert-stmt:error-int-to-int/disp32 -25971 } -25972 # if both are floats, abort -25973 { -25974 (simple-mu-type? %edx 0xf) # float => eax -25975 3d/compare-eax-and 0/imm32/false -25976 74/jump-if-= break/disp8 -25977 (simple-mu-type? %ecx 0xf) # float => eax -25978 3d/compare-eax-and 0/imm32/false -25979 74/jump-if-= break/disp8 -25980 e9/jump $check-mu-convert-stmt:error-float-to-float/disp32 -25981 } -25982 $check-mu-convert-stmt:end: -25983 # . restore registers -25984 5f/pop-to-edi -25985 5e/pop-to-esi -25986 5a/pop-to-edx -25987 59/pop-to-ecx -25988 58/pop-to-eax -25989 # . epilogue -25990 89/<- %esp 5/r32/ebp -25991 5d/pop-to-ebp -25992 c3/return -25993 -25994 $check-mu-convert-stmt:error-no-inout: -25995 (write-buffered *(ebp+0x10) "fn ") -25996 8b/-> *(ebp+0xc) 0/r32/eax -25997 (lookup *eax *(eax+4)) # Function-name Function-name => eax -25998 (write-buffered *(ebp+0x10) %eax) -25999 (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n") -26000 (flush *(ebp+0x10)) -26001 (stop *(ebp+0x14) 1) -26002 # never gets here -26003 -26004 $check-mu-convert-stmt:error-too-many-inouts: -26005 (write-buffered *(ebp+0x10) "fn ") -26006 8b/-> *(ebp+0xc) 0/r32/eax -26007 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26008 (write-buffered *(ebp+0x10) %eax) -26009 (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n") -26010 (flush *(ebp+0x10)) -26011 (stop *(ebp+0x14) 1) -26012 # never gets here -26013 -26014 $check-mu-convert-stmt:error-no-output: -26015 (write-buffered *(ebp+0x10) "fn ") -26016 8b/-> *(ebp+0xc) 0/r32/eax -26017 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26018 (write-buffered *(ebp+0x10) %eax) -26019 (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n") -26020 (flush *(ebp+0x10)) -26021 (stop *(ebp+0x14) 1) -26022 # never gets here -26023 -26024 $check-mu-convert-stmt:error-output-not-in-register: -26025 (write-buffered *(ebp+0x10) "fn ") -26026 8b/-> *(ebp+0xc) 0/r32/eax -26027 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26028 (write-buffered *(ebp+0x10) %eax) -26029 (write-buffered *(ebp+0x10) ": stmt convert: output '") -26030 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -26031 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26032 (write-buffered *(ebp+0x10) %eax) -26033 (write-buffered *(ebp+0x10) "' not in a register\n") -26034 (flush *(ebp+0x10)) -26035 (stop *(ebp+0x14) 1) -26036 # never gets here -26037 -26038 $check-mu-convert-stmt:error-too-many-outputs: -26039 (write-buffered *(ebp+0x10) "fn ") -26040 8b/-> *(ebp+0xc) 0/r32/eax -26041 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26042 (write-buffered *(ebp+0x10) %eax) -26043 (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n") -26044 (flush *(ebp+0x10)) -26045 (stop *(ebp+0x14) 1) -26046 # never gets here -26047 -26048 $check-mu-convert-stmt:error-invalid-inout-type: -26049 (write-buffered *(ebp+0x10) "fn ") -26050 8b/-> *(ebp+0xc) 0/r32/eax -26051 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26052 (write-buffered *(ebp+0x10) %eax) -26053 (write-buffered *(ebp+0x10) ": stmt convert: inout '") -26054 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax -26055 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26056 (write-buffered *(ebp+0x10) %eax) -26057 (write-buffered *(ebp+0x10) "' must be an int or float\n") -26058 (flush *(ebp+0x10)) -26059 (stop *(ebp+0x14) 1) -26060 # never gets here -26061 -26062 $check-mu-convert-stmt:error-invalid-output-type: -26063 (write-buffered *(ebp+0x10) "fn ") -26064 8b/-> *(ebp+0xc) 0/r32/eax -26065 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26066 (write-buffered *(ebp+0x10) %eax) -26067 (write-buffered *(ebp+0x10) ": stmt convert: output '") -26068 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax -26069 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26070 (write-buffered *(ebp+0x10) %eax) -26071 (write-buffered *(ebp+0x10) "' must be an int or float\n") -26072 (flush *(ebp+0x10)) -26073 (stop *(ebp+0x14) 1) -26074 # never gets here -26075 -26076 $check-mu-convert-stmt:error-int-to-int: -26077 (write-buffered *(ebp+0x10) "fn ") -26078 8b/-> *(ebp+0xc) 0/r32/eax -26079 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26080 (write-buffered *(ebp+0x10) %eax) -26081 (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n") -26082 (flush *(ebp+0x10)) -26083 (stop *(ebp+0x14) 1) -26084 # never gets here -26085 -26086 $check-mu-convert-stmt:error-float-to-float: -26087 (write-buffered *(ebp+0x10) "fn ") -26088 8b/-> *(ebp+0xc) 0/r32/eax -26089 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26090 (write-buffered *(ebp+0x10) %eax) -26091 (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n") -26092 (flush *(ebp+0x10)) -26093 (stop *(ebp+0x14) 1) -26094 # never gets here -26095 -26096 check-mu-call: # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -26097 # . prologue -26098 55/push-ebp -26099 89/<- %ebp 4/r32/esp -26100 # var type-parameters: (addr table (handle array byte) (addr type-tree) 8) -26101 68/push 0/imm32 -26102 # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8) -26103 81 5/subop/subtract %esp 0x60/imm32 -26104 68/push 0x60/imm32/size -26105 68/push 0/imm32/read -26106 68/push 0/imm32/write -26107 # save a pointer to type-parameters-storage at type-parameters -26108 89/<- *(ebp-4) 4/r32/esp -26109 (clear-stream *(ebp-4)) -26110 # . save registers -26111 50/push-eax -26112 51/push-ecx -26113 52/push-edx -26114 53/push-ebx -26115 56/push-esi -26116 57/push-edi -26117 # esi = stmt -26118 8b/-> *(ebp+8) 6/r32/esi -26119 # edi = callee -26120 8b/-> *(ebp+0xc) 7/r32/edi -26121 # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts) -26122 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -26123 89/<- %ecx 0/r32/eax -26124 # var expected/edx: (addr list var) = lookup(f->inouts) -26125 (lookup *(edi+8) *(edi+0xc)) # Function-inouts Function-inouts => eax -26126 89/<- %edx 0/r32/eax -26127 { -26128 $check-mu-call:check-for-inouts: -26129 # if (inouts == 0) break -26130 81 7/subop/compare %ecx 0/imm32 -26131 0f 84/jump-if-= break/disp32 -26132 # if (expected == 0) error -26133 81 7/subop/compare %edx 0/imm32 -26134 0f 84/jump-if-= break/disp32 -26135 $check-mu-call:check-null-addr: -26136 # if (inouts->value->name == "0") continue -26137 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26138 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26139 (string-equal? %eax "0") # => eax -26140 3d/compare-eax-and 0/imm32/false -26141 0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32 -26142 $check-mu-call:check-inout-type: -26143 # var t/ebx: (addr type-tree) = inouts->value->type -26144 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26145 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -26146 89/<- %ebx 0/r32/eax -26147 # if (inouts->is-deref?) t = t->right -26148 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -26149 { -26150 74/jump-if-= break/disp8 -26151 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -26152 89/<- %ebx 0/r32/eax -26153 # if t->right is null, t = t->left -26154 81 7/subop/compare *(ebx+0xc) 0/imm32 # Type-tree-right -26155 75/jump-if-!= break/disp8 -26156 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax -26157 89/<- %ebx 0/r32/eax -26158 } -26159 # var v2/eax: (addr v) = lookup(expected->value) -26160 (lookup *edx *(edx+4)) # List-value List-value => eax -26161 # var t2/eax: (addr type-tree) = lookup(v2->type) -26162 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -26163 # if (t != t2) error -26164 (type-match? %eax %ebx *(ebp-4)) # => eax -26165 3d/compare-eax-and 0/imm32/false -26166 { -26167 0f 85/jump-if-!= break/disp32 -26168 (write-buffered *(ebp+0x14) "fn ") -26169 8b/-> *(ebp+0x10) 0/r32/eax -26170 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26171 (write-buffered *(ebp+0x14) %eax) -26172 (write-buffered *(ebp+0x14) ": call ") -26173 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26174 (write-buffered *(ebp+0x14) %eax) -26175 (write-buffered *(ebp+0x14) ": type for inout '") -26176 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26177 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26178 (write-buffered *(ebp+0x14) %eax) -26179 (write-buffered *(ebp+0x14) "' is not right\n") -26180 (flush *(ebp+0x14)) -26181 (stop *(ebp+0x18) 1) -26182 } -26183 $check-mu-call:continue-to-next-inout: -26184 # inouts = lookup(inouts->next) -26185 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax -26186 89/<- %ecx 0/r32/eax -26187 # expected = lookup(expected->next) -26188 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -26189 89/<- %edx 0/r32/eax -26190 # -26191 e9/jump loop/disp32 -26192 } -26193 $check-mu-call:check-inout-count: -26194 # if (inouts == expected) proceed -26195 39/compare %ecx 2/r32/edx -26196 { -26197 0f 84/jump-if-= break/disp32 -26198 # exactly one of the two is null -26199 # if (inouts == 0) error("too many inouts") -26200 { -26201 81 7/subop/compare %ecx 0/imm32 -26202 0f 84/jump-if-= break/disp32 -26203 (write-buffered *(ebp+0x14) "fn ") -26204 8b/-> *(ebp+0x10) 0/r32/eax -26205 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26206 (write-buffered *(ebp+0x14) %eax) -26207 (write-buffered *(ebp+0x14) ": call ") -26208 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26209 (write-buffered *(ebp+0x14) %eax) -26210 (write-buffered *(ebp+0x14) ": too many inouts\n") -26211 (flush *(ebp+0x14)) -26212 (stop *(ebp+0x18) 1) -26213 } -26214 # if (expected == 0) error("too few inouts") -26215 { -26216 81 7/subop/compare %edx 0/imm32 -26217 0f 84/jump-if-= break/disp32 -26218 (write-buffered *(ebp+0x14) "fn ") -26219 8b/-> *(ebp+0x10) 0/r32/eax -26220 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26221 (write-buffered *(ebp+0x14) %eax) -26222 (write-buffered *(ebp+0x14) ": call ") -26223 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26224 (write-buffered *(ebp+0x14) %eax) -26225 (write-buffered *(ebp+0x14) ": too few inouts\n") -26226 (flush *(ebp+0x14)) -26227 (stop *(ebp+0x18) 1) -26228 } -26229 } -26230 $check-mu-call:check-outputs: -26231 # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs) -26232 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -26233 89/<- %ecx 0/r32/eax -26234 # var expected/edx: (addr list var) = lookup(f->outputs) -26235 (lookup *(edi+0x10) *(edi+0x14)) # Function-outputs Function-outputs => eax -26236 89/<- %edx 0/r32/eax -26237 { -26238 $check-mu-call:check-for-outputs: -26239 # if (outputs == 0) break -26240 81 7/subop/compare %ecx 0/imm32 -26241 0f 84/jump-if-= break/disp32 -26242 # if (expected == 0) error -26243 81 7/subop/compare %edx 0/imm32 -26244 0f 84/jump-if-= break/disp32 -26245 $check-mu-call:check-output-type: -26246 # var v/eax: (addr v) = lookup(outputs->value) -26247 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26248 # var t/ebx: (addr type-tree) = lookup(v->type) -26249 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -26250 89/<- %ebx 0/r32/eax -26251 # if (outputs->is-deref?) t = t->right # TODO: check that t->left is an addr -26252 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -26253 { -26254 74/jump-if-= break/disp8 -26255 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -26256 89/<- %ebx 0/r32/eax -26257 } -26258 # var v2/eax: (addr v) = lookup(expected->value) -26259 (lookup *edx *(edx+4)) # List-value List-value => eax -26260 # var t2/eax: (addr type-tree) = lookup(v2->type) -26261 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -26262 # if (t != t2) error -26263 (type-match? %eax %ebx *(ebp-4)) # => eax -26264 3d/compare-eax-and 0/imm32/false -26265 { -26266 0f 85/jump-if-!= break/disp32 -26267 (write-buffered *(ebp+0x14) "fn ") -26268 8b/-> *(ebp+0x10) 0/r32/eax -26269 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26270 (write-buffered *(ebp+0x14) %eax) -26271 (write-buffered *(ebp+0x14) ": call ") -26272 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26273 (write-buffered *(ebp+0x14) %eax) -26274 (write-buffered *(ebp+0x14) ": type for output '") -26275 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26276 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26277 (write-buffered *(ebp+0x14) %eax) -26278 (write-buffered *(ebp+0x14) "' is not right\n") -26279 (flush *(ebp+0x14)) -26280 (stop *(ebp+0x18) 1) -26281 } -26282 $check-mu-call:check-output-register: -26283 # var v/eax: (addr v) = lookup(outputs->value) -26284 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26285 # var r/ebx: (addr array byte) = lookup(v->register) -26286 (lookup *(eax+18) *(eax+0x1c)) # Var-register Var-register => eax -26287 89/<- %ebx 0/r32/eax -26288 # if (r == 0) error -26289 3d/compare-eax-and 0/imm32 -26290 { -26291 0f 85/jump-if-!= break/disp32 -26292 (write-buffered *(ebp+0x14) "fn ") -26293 8b/-> *(ebp+0x10) 0/r32/eax -26294 (lookup *eax *(eax+4)) # Function-name Function-name => eax +25960 (simple-mu-type? %ecx 0xf) # float => eax +25961 3d/compare-eax-and 0/imm32/false +25962 75/jump-if-!= break/disp8 +25963 e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32 +25964 } +25965 # if output not in register, abort +25966 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25967 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +25968 3d/compare-eax-and 0/imm32 +25969 0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32 +25970 # var output-type/edx: (addr type-tree) = output->value->type +25971 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +25972 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +25973 89/<- %edx 0/r32/eax +25974 # if output is not int or float, abort +25975 { +25976 (simple-mu-type? %edx 1) # int => eax +25977 3d/compare-eax-and 0/imm32/false +25978 75/jump-if-!= break/disp8 +25979 (simple-mu-type? %edx 0xf) # float => eax +25980 3d/compare-eax-and 0/imm32/false +25981 75/jump-if-!= break/disp8 +25982 e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32 +25983 } +25984 # if both are ints, abort +25985 { +25986 (simple-mu-type? %edx 1) # int => eax +25987 3d/compare-eax-and 0/imm32/false +25988 74/jump-if-= break/disp8 +25989 (simple-mu-type? %ecx 1) # int => eax +25990 3d/compare-eax-and 0/imm32/false +25991 74/jump-if-= break/disp8 +25992 e9/jump $check-mu-convert-stmt:error-int-to-int/disp32 +25993 } +25994 # if both are floats, abort +25995 { +25996 (simple-mu-type? %edx 0xf) # float => eax +25997 3d/compare-eax-and 0/imm32/false +25998 74/jump-if-= break/disp8 +25999 (simple-mu-type? %ecx 0xf) # float => eax +26000 3d/compare-eax-and 0/imm32/false +26001 74/jump-if-= break/disp8 +26002 e9/jump $check-mu-convert-stmt:error-float-to-float/disp32 +26003 } +26004 $check-mu-convert-stmt:end: +26005 # . restore registers +26006 5f/pop-to-edi +26007 5e/pop-to-esi +26008 5a/pop-to-edx +26009 59/pop-to-ecx +26010 58/pop-to-eax +26011 # . epilogue +26012 89/<- %esp 5/r32/ebp +26013 5d/pop-to-ebp +26014 c3/return +26015 +26016 $check-mu-convert-stmt:error-no-inout: +26017 (write-buffered *(ebp+0x10) "fn ") +26018 8b/-> *(ebp+0xc) 0/r32/eax +26019 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26020 (write-buffered *(ebp+0x10) %eax) +26021 (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n") +26022 (flush *(ebp+0x10)) +26023 (stop *(ebp+0x14) 1) +26024 # never gets here +26025 +26026 $check-mu-convert-stmt:error-too-many-inouts: +26027 (write-buffered *(ebp+0x10) "fn ") +26028 8b/-> *(ebp+0xc) 0/r32/eax +26029 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26030 (write-buffered *(ebp+0x10) %eax) +26031 (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n") +26032 (flush *(ebp+0x10)) +26033 (stop *(ebp+0x14) 1) +26034 # never gets here +26035 +26036 $check-mu-convert-stmt:error-no-output: +26037 (write-buffered *(ebp+0x10) "fn ") +26038 8b/-> *(ebp+0xc) 0/r32/eax +26039 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26040 (write-buffered *(ebp+0x10) %eax) +26041 (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n") +26042 (flush *(ebp+0x10)) +26043 (stop *(ebp+0x14) 1) +26044 # never gets here +26045 +26046 $check-mu-convert-stmt:error-output-not-in-register: +26047 (write-buffered *(ebp+0x10) "fn ") +26048 8b/-> *(ebp+0xc) 0/r32/eax +26049 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26050 (write-buffered *(ebp+0x10) %eax) +26051 (write-buffered *(ebp+0x10) ": stmt convert: output '") +26052 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +26053 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26054 (write-buffered *(ebp+0x10) %eax) +26055 (write-buffered *(ebp+0x10) "' not in a register\n") +26056 (flush *(ebp+0x10)) +26057 (stop *(ebp+0x14) 1) +26058 # never gets here +26059 +26060 $check-mu-convert-stmt:error-too-many-outputs: +26061 (write-buffered *(ebp+0x10) "fn ") +26062 8b/-> *(ebp+0xc) 0/r32/eax +26063 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26064 (write-buffered *(ebp+0x10) %eax) +26065 (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n") +26066 (flush *(ebp+0x10)) +26067 (stop *(ebp+0x14) 1) +26068 # never gets here +26069 +26070 $check-mu-convert-stmt:error-invalid-inout-type: +26071 (write-buffered *(ebp+0x10) "fn ") +26072 8b/-> *(ebp+0xc) 0/r32/eax +26073 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26074 (write-buffered *(ebp+0x10) %eax) +26075 (write-buffered *(ebp+0x10) ": stmt convert: inout '") +26076 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax +26077 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26078 (write-buffered *(ebp+0x10) %eax) +26079 (write-buffered *(ebp+0x10) "' must be an int or float\n") +26080 (flush *(ebp+0x10)) +26081 (stop *(ebp+0x14) 1) +26082 # never gets here +26083 +26084 $check-mu-convert-stmt:error-invalid-output-type: +26085 (write-buffered *(ebp+0x10) "fn ") +26086 8b/-> *(ebp+0xc) 0/r32/eax +26087 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26088 (write-buffered *(ebp+0x10) %eax) +26089 (write-buffered *(ebp+0x10) ": stmt convert: output '") +26090 (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax +26091 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26092 (write-buffered *(ebp+0x10) %eax) +26093 (write-buffered *(ebp+0x10) "' must be an int or float\n") +26094 (flush *(ebp+0x10)) +26095 (stop *(ebp+0x14) 1) +26096 # never gets here +26097 +26098 $check-mu-convert-stmt:error-int-to-int: +26099 (write-buffered *(ebp+0x10) "fn ") +26100 8b/-> *(ebp+0xc) 0/r32/eax +26101 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26102 (write-buffered *(ebp+0x10) %eax) +26103 (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n") +26104 (flush *(ebp+0x10)) +26105 (stop *(ebp+0x14) 1) +26106 # never gets here +26107 +26108 $check-mu-convert-stmt:error-float-to-float: +26109 (write-buffered *(ebp+0x10) "fn ") +26110 8b/-> *(ebp+0xc) 0/r32/eax +26111 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26112 (write-buffered *(ebp+0x10) %eax) +26113 (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n") +26114 (flush *(ebp+0x10)) +26115 (stop *(ebp+0x14) 1) +26116 # never gets here +26117 +26118 check-mu-call: # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +26119 # . prologue +26120 55/push-ebp +26121 89/<- %ebp 4/r32/esp +26122 # var type-parameters: (addr table (handle array byte) (addr type-tree) 8) +26123 68/push 0/imm32 +26124 # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8) +26125 81 5/subop/subtract %esp 0x60/imm32 +26126 68/push 0x60/imm32/size +26127 68/push 0/imm32/read +26128 68/push 0/imm32/write +26129 # save a pointer to type-parameters-storage at type-parameters +26130 89/<- *(ebp-4) 4/r32/esp +26131 (clear-stream *(ebp-4)) +26132 # . save registers +26133 50/push-eax +26134 51/push-ecx +26135 52/push-edx +26136 53/push-ebx +26137 56/push-esi +26138 57/push-edi +26139 # esi = stmt +26140 8b/-> *(ebp+8) 6/r32/esi +26141 # edi = callee +26142 8b/-> *(ebp+0xc) 7/r32/edi +26143 # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts) +26144 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +26145 89/<- %ecx 0/r32/eax +26146 # var expected/edx: (addr list var) = lookup(f->inouts) +26147 (lookup *(edi+8) *(edi+0xc)) # Function-inouts Function-inouts => eax +26148 89/<- %edx 0/r32/eax +26149 { +26150 $check-mu-call:check-for-inouts: +26151 # if (inouts == 0) break +26152 81 7/subop/compare %ecx 0/imm32 +26153 0f 84/jump-if-= break/disp32 +26154 # if (expected == 0) error +26155 81 7/subop/compare %edx 0/imm32 +26156 0f 84/jump-if-= break/disp32 +26157 $check-mu-call:check-null-addr: +26158 # if (inouts->value->name == "0") continue +26159 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26160 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26161 (string-equal? %eax "0") # => eax +26162 3d/compare-eax-and 0/imm32/false +26163 0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32 +26164 $check-mu-call:check-inout-type: +26165 # var t/ebx: (addr type-tree) = inouts->value->type +26166 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26167 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +26168 89/<- %ebx 0/r32/eax +26169 # if (inouts->is-deref?) t = t->right +26170 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +26171 { +26172 74/jump-if-= break/disp8 +26173 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +26174 89/<- %ebx 0/r32/eax +26175 # if t->right is null, t = t->left +26176 81 7/subop/compare *(ebx+0xc) 0/imm32 # Type-tree-right +26177 75/jump-if-!= break/disp8 +26178 (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax +26179 89/<- %ebx 0/r32/eax +26180 } +26181 # var v2/eax: (addr v) = lookup(expected->value) +26182 (lookup *edx *(edx+4)) # List-value List-value => eax +26183 # var t2/eax: (addr type-tree) = lookup(v2->type) +26184 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +26185 # if (t != t2) error +26186 (type-match? %eax %ebx *(ebp-4)) # => eax +26187 3d/compare-eax-and 0/imm32/false +26188 { +26189 0f 85/jump-if-!= break/disp32 +26190 (write-buffered *(ebp+0x14) "fn ") +26191 8b/-> *(ebp+0x10) 0/r32/eax +26192 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26193 (write-buffered *(ebp+0x14) %eax) +26194 (write-buffered *(ebp+0x14) ": call ") +26195 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26196 (write-buffered *(ebp+0x14) %eax) +26197 (write-buffered *(ebp+0x14) ": type for inout '") +26198 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26199 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26200 (write-buffered *(ebp+0x14) %eax) +26201 (write-buffered *(ebp+0x14) "' is not right\n") +26202 (flush *(ebp+0x14)) +26203 (stop *(ebp+0x18) 1) +26204 } +26205 $check-mu-call:continue-to-next-inout: +26206 # inouts = lookup(inouts->next) +26207 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax +26208 89/<- %ecx 0/r32/eax +26209 # expected = lookup(expected->next) +26210 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +26211 89/<- %edx 0/r32/eax +26212 # +26213 e9/jump loop/disp32 +26214 } +26215 $check-mu-call:check-inout-count: +26216 # if (inouts == expected) proceed +26217 39/compare %ecx 2/r32/edx +26218 { +26219 0f 84/jump-if-= break/disp32 +26220 # exactly one of the two is null +26221 # if (inouts == 0) error("too many inouts") +26222 { +26223 81 7/subop/compare %ecx 0/imm32 +26224 0f 84/jump-if-= break/disp32 +26225 (write-buffered *(ebp+0x14) "fn ") +26226 8b/-> *(ebp+0x10) 0/r32/eax +26227 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26228 (write-buffered *(ebp+0x14) %eax) +26229 (write-buffered *(ebp+0x14) ": call ") +26230 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26231 (write-buffered *(ebp+0x14) %eax) +26232 (write-buffered *(ebp+0x14) ": too many inouts\n") +26233 (flush *(ebp+0x14)) +26234 (stop *(ebp+0x18) 1) +26235 } +26236 # if (expected == 0) error("too few inouts") +26237 { +26238 81 7/subop/compare %edx 0/imm32 +26239 0f 84/jump-if-= break/disp32 +26240 (write-buffered *(ebp+0x14) "fn ") +26241 8b/-> *(ebp+0x10) 0/r32/eax +26242 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26243 (write-buffered *(ebp+0x14) %eax) +26244 (write-buffered *(ebp+0x14) ": call ") +26245 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26246 (write-buffered *(ebp+0x14) %eax) +26247 (write-buffered *(ebp+0x14) ": too few inouts\n") +26248 (flush *(ebp+0x14)) +26249 (stop *(ebp+0x18) 1) +26250 } +26251 } +26252 $check-mu-call:check-outputs: +26253 # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs) +26254 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +26255 89/<- %ecx 0/r32/eax +26256 # var expected/edx: (addr list var) = lookup(f->outputs) +26257 (lookup *(edi+0x10) *(edi+0x14)) # Function-outputs Function-outputs => eax +26258 89/<- %edx 0/r32/eax +26259 { +26260 $check-mu-call:check-for-outputs: +26261 # if (outputs == 0) break +26262 81 7/subop/compare %ecx 0/imm32 +26263 0f 84/jump-if-= break/disp32 +26264 # if (expected == 0) error +26265 81 7/subop/compare %edx 0/imm32 +26266 0f 84/jump-if-= break/disp32 +26267 $check-mu-call:check-output-type: +26268 # var v/eax: (addr v) = lookup(outputs->value) +26269 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26270 # var t/ebx: (addr type-tree) = lookup(v->type) +26271 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +26272 89/<- %ebx 0/r32/eax +26273 # if (outputs->is-deref?) t = t->right # TODO: check that t->left is an addr +26274 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +26275 { +26276 74/jump-if-= break/disp8 +26277 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +26278 89/<- %ebx 0/r32/eax +26279 } +26280 # var v2/eax: (addr v) = lookup(expected->value) +26281 (lookup *edx *(edx+4)) # List-value List-value => eax +26282 # var t2/eax: (addr type-tree) = lookup(v2->type) +26283 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +26284 # if (t != t2) error +26285 (type-match? %eax %ebx *(ebp-4)) # => eax +26286 3d/compare-eax-and 0/imm32/false +26287 { +26288 0f 85/jump-if-!= break/disp32 +26289 (write-buffered *(ebp+0x14) "fn ") +26290 8b/-> *(ebp+0x10) 0/r32/eax +26291 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26292 (write-buffered *(ebp+0x14) %eax) +26293 (write-buffered *(ebp+0x14) ": call ") +26294 (lookup *edi *(edi+4)) # Function-name Function-name => eax 26295 (write-buffered *(ebp+0x14) %eax) -26296 (write-buffered *(ebp+0x14) ": call ") -26297 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26298 (write-buffered *(ebp+0x14) %eax) -26299 (write-buffered *(ebp+0x14) ": output '") -26300 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26301 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26302 (write-buffered *(ebp+0x14) %eax) -26303 (write-buffered *(ebp+0x14) "' is not in a register\n") -26304 (flush *(ebp+0x14)) -26305 (stop *(ebp+0x18) 1) -26306 } -26307 # var v2/eax: (addr v) = lookup(expected->value) -26308 (lookup *edx *(edx+4)) # Stmt-var-value Stmt-var-value => eax -26309 # var r2/eax: (addr array byte) = lookup(v2->register) -26310 (lookup *(eax+18) *(eax+0x1c)) # Var-register Var-register => eax -26311 # if (r != r2) error -26312 (string-equal? %eax %ebx) # => eax -26313 3d/compare-eax-and 0/imm32/false -26314 { -26315 0f 85/jump-if-!= break/disp32 -26316 (write-buffered *(ebp+0x14) "fn ") -26317 8b/-> *(ebp+0x10) 0/r32/eax -26318 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26319 (write-buffered *(ebp+0x14) %eax) -26320 (write-buffered *(ebp+0x14) ": call ") -26321 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26322 (write-buffered *(ebp+0x14) %eax) -26323 (write-buffered *(ebp+0x14) ": register for output '") -26324 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -26325 (lookup *eax *(eax+4)) # Var-name Var-name => eax -26326 (write-buffered *(ebp+0x14) %eax) -26327 (write-buffered *(ebp+0x14) "' is not right\n") -26328 (flush *(ebp+0x14)) -26329 (stop *(ebp+0x18) 1) -26330 } -26331 $check-mu-call:continue-to-next-output: -26332 # outputs = lookup(outputs->next) -26333 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax -26334 89/<- %ecx 0/r32/eax -26335 # expected = lookup(expected->next) -26336 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax -26337 89/<- %edx 0/r32/eax -26338 # -26339 e9/jump loop/disp32 -26340 } -26341 $check-mu-call:check-output-count: -26342 # if (outputs == expected) proceed -26343 39/compare %ecx 2/r32/edx -26344 { -26345 0f 84/jump-if-= break/disp32 -26346 # exactly one of the two is null -26347 # if (outputs == 0) error("too many outputs") -26348 { -26349 81 7/subop/compare %ecx 0/imm32 -26350 0f 84/jump-if-= break/disp32 -26351 (write-buffered *(ebp+0x14) "fn ") -26352 8b/-> *(ebp+0x10) 0/r32/eax -26353 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26354 (write-buffered *(ebp+0x14) %eax) -26355 (write-buffered *(ebp+0x14) ": call ") -26356 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26357 (write-buffered *(ebp+0x14) %eax) -26358 (write-buffered *(ebp+0x14) ": too many outputs\n") -26359 (flush *(ebp+0x14)) -26360 (stop *(ebp+0x18) 1) -26361 } -26362 # if (expected == 0) error("too few outputs") -26363 { -26364 81 7/subop/compare %edx 0/imm32 -26365 0f 84/jump-if-= break/disp32 -26366 (write-buffered *(ebp+0x14) "fn ") -26367 8b/-> *(ebp+0x10) 0/r32/eax -26368 (lookup *eax *(eax+4)) # Function-name Function-name => eax -26369 (write-buffered *(ebp+0x14) %eax) -26370 (write-buffered *(ebp+0x14) ": call ") -26371 (lookup *edi *(edi+4)) # Function-name Function-name => eax -26372 (write-buffered *(ebp+0x14) %eax) -26373 (write-buffered *(ebp+0x14) ": too few outputs\n") -26374 (flush *(ebp+0x14)) -26375 (stop *(ebp+0x18) 1) -26376 } -26377 } -26378 $check-mu-call:end: -26379 # . restore registers -26380 5f/pop-to-edi -26381 5e/pop-to-esi -26382 5b/pop-to-ebx -26383 5a/pop-to-edx -26384 59/pop-to-ecx -26385 58/pop-to-eax -26386 # . reclaim locals exclusively on the stack -26387 81 0/subop/add %esp 0x70/imm32 -26388 # . epilogue -26389 89/<- %esp 5/r32/ebp -26390 5d/pop-to-ebp -26391 c3/return -26392 -26393 # like type-equal? but takes literals type parameters into account -26394 type-match?: # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean -26395 # . prologue -26396 55/push-ebp -26397 89/<- %ebp 4/r32/esp -26398 # if (call is literal and def is numberlike) return true -26399 { -26400 $type-match?:check-literal-int: -26401 (simple-mu-type? *(ebp+0xc) 0) # literal => eax -26402 3d/compare-eax-and 0/imm32/false -26403 74/jump-if-= break/disp8 -26404 (mu-numberlike-output? *(ebp+8)) # => eax -26405 3d/compare-eax-and 0/imm32/false -26406 74/jump-if-= break/disp8 -26407 b8/copy-to-eax 1/imm32/true -26408 e9/jump $type-match?:end/disp32 -26409 } -26410 # if (call is literal-string and def is string) return true -26411 { -26412 $type-match?:check-literal-string: -26413 (simple-mu-type? *(ebp+0xc) 0x10) # literal-string => eax -26414 3d/compare-eax-and 0/imm32/false -26415 74/jump-if-= break/disp8 -26416 (mu-string-type? *(ebp+8)) # => eax -26417 3d/compare-eax-and 0/imm32/false -26418 74/jump-if-= break/disp8 -26419 b8/copy-to-eax 1/imm32/true -26420 e9/jump $type-match?:end/disp32 -26421 } -26422 $type-match?:baseline: -26423 # otherwise fall back -26424 (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -26425 $type-match?:end: -26426 # . epilogue -26427 89/<- %esp 5/r32/ebp -26428 5d/pop-to-ebp -26429 c3/return -26430 -26431 type-component-match?: # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean -26432 # . prologue -26433 55/push-ebp -26434 89/<- %ebp 4/r32/esp -26435 # . save registers -26436 51/push-ecx -26437 52/push-edx -26438 53/push-ebx -26439 # ecx = def -26440 8b/-> *(ebp+8) 1/r32/ecx -26441 # edx = call -26442 8b/-> *(ebp+0xc) 2/r32/edx -26443 $type-component-match?:compare-addr: -26444 # if (def == call) return true -26445 8b/-> %ecx 0/r32/eax # Var-type -26446 39/compare %edx 0/r32/eax # Var-type -26447 b8/copy-to-eax 1/imm32/true -26448 0f 84/jump-if-= $type-component-match?:end/disp32 -26449 # if (def == 0) return false -26450 b8/copy-to-eax 0/imm32/false -26451 81 7/subop/compare %ecx 0/imm32 # Type-tree-is-atom -26452 0f 84/jump-if-= $type-component-match?:end/disp32 -26453 # if (call == 0) return false -26454 81 7/subop/compare %edx 0/imm32 # Type-tree-is-atom -26455 0f 84/jump-if-= $type-component-match?:end/disp32 -26456 # if def is a type parameter, just check in type-parameters -26457 { -26458 $type-component-match?:check-type-parameter: -26459 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26460 74/jump-if-= break/disp8 -26461 81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter # Type-tree-value -26462 75/jump-if-!= break/disp8 -26463 $type-component-match?:type-parameter: -26464 (type-parameter-match? *(ecx+8) *(ecx+0xc) %edx *(ebp+0x10)) # => eax -26465 e9/jump $type-component-match?:end/disp32 -26466 } -26467 # if def is a list containing just a type parameter, just check in type-parameters -26468 { -26469 $type-component-match?:check-list-type-parameter: -26470 # if def is a list.. -26471 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26472 75/jump-if-!= break/disp8 -26473 # ..that's a singleton -26474 81 7/subop/compare *(ecx+0xc) 0/imm32 # Type-tree-left -26475 75/jump-if-!= break/disp8 -26476 # ..and whose head is a type parameter -26477 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26478 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -26479 74/jump-if-= break/disp8 -26480 81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter # Type-tree-value -26481 75/jump-if-!= break/disp8 -26482 $type-component-match?:list-type-parameter: -26483 (type-parameter-match? *(eax+8) *(eax+0xc) %edx *(ebp+0x10)) # => eax -26484 e9/jump $type-component-match?:end/disp32 -26485 } -26486 $type-component-match?:compare-atom-state: -26487 # if (def->is-atom? != call->is-atom?) return false -26488 8b/-> *ecx 3/r32/ebx # Type-tree-is-atom -26489 39/compare *edx 3/r32/ebx # Type-tree-is-atom -26490 b8/copy-to-eax 0/imm32/false -26491 0f 85/jump-if-!= $type-component-match?:end/disp32 -26492 # if def->is-atom? return (def->value == call->value) -26493 { -26494 $type-component-match?:check-atom: -26495 81 7/subop/compare %ebx 0/imm32/false -26496 74/jump-if-= break/disp8 -26497 $type-component-match?:is-atom: -26498 8b/-> *(ecx+4) 0/r32/eax # Type-tree-value -26499 39/compare *(edx+4) 0/r32/eax # Type-tree-value -26500 0f 94/set-if-= %al -26501 81 4/subop/and %eax 0xff/imm32 -26502 e9/jump $type-component-match?:end/disp32 -26503 } -26504 $type-component-match?:check-left: -26505 # if (!type-component-match?(def->left, call->left)) return false -26506 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26507 89/<- %ebx 0/r32/eax -26508 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -26509 (type-component-match? %ebx %eax *(ebp+0x10)) # => eax -26510 3d/compare-eax-and 0/imm32/false -26511 74/jump-if-= $type-component-match?:end/disp8 -26512 $type-component-match?:check-right: -26513 # return type-component-match?(def->right, call->right) -26514 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26515 89/<- %ebx 0/r32/eax -26516 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax -26517 (type-component-match? %ebx %eax *(ebp+0x10)) # => eax -26518 $type-component-match?:end: -26519 # . restore registers -26520 5b/pop-to-ebx -26521 5a/pop-to-edx -26522 59/pop-to-ecx -26523 # . epilogue -26524 89/<- %esp 5/r32/ebp -26525 5d/pop-to-ebp -26526 c3/return -26527 -26528 type-parameter-match?: # type-parameter-name: (handle array byte), type: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean -26529 # . prologue -26530 55/push-ebp -26531 89/<- %ebp 4/r32/esp -26532 # . save registers -26533 51/push-ecx -26534 # -26535 (get-or-insert-handle *(ebp+0x14) *(ebp+8) *(ebp+0xc) 0xc) # => eax -26536 # if parameter wasn't saved, save it -26537 { -26538 81 7/subop/compare *eax 0/imm32 -26539 75/jump-if-!= break/disp8 -26540 8b/-> *(ebp+0x10) 1/r32/ecx -26541 89/<- *eax 1/r32/ecx -26542 } -26543 # -26544 (type-equal? *(ebp+0x10) *eax) # => eax -26545 $type-parameter-match?:end: -26546 # . restore registers -26547 59/pop-to-ecx -26548 # . epilogue -26549 89/<- %esp 5/r32/ebp -26550 5d/pop-to-ebp -26551 c3/return -26552 -26553 size-of: # v: (addr var) -> result/eax: int -26554 # . prologue -26555 55/push-ebp -26556 89/<- %ebp 4/r32/esp -26557 # . save registers -26558 51/push-ecx -26559 # var t/ecx: (addr type-tree) = lookup(v->type) -26560 8b/-> *(ebp+8) 1/r32/ecx -26561 #? (write-buffered Stderr "size-of ") -26562 #? (write-int32-hex-buffered Stderr %ecx) -26563 #? (write-buffered Stderr Newline) -26564 #? (write-buffered Stderr "type allocid: ") -26565 #? (write-int32-hex-buffered Stderr *(ecx+8)) -26566 #? (write-buffered Stderr Newline) -26567 #? (flush Stderr) -26568 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -26569 89/<- %ecx 0/r32/eax -26570 # if mu-array?(t) return size-of-array(t) -26571 { -26572 (mu-array? %ecx) # => eax -26573 3d/compare-eax-and 0/imm32/false -26574 74/jump-if-= break/disp8 -26575 (size-of-array %ecx) # => eax -26576 eb/jump $size-of:end/disp8 -26577 } -26578 # if mu-stream?(t) return size-of-stream(t) -26579 { -26580 (mu-stream? %ecx) # => eax -26581 3d/compare-eax-and 0/imm32/false -26582 74/jump-if-= break/disp8 -26583 (size-of-stream %ecx) # => eax -26584 eb/jump $size-of:end/disp8 -26585 } -26586 # if (!t->is-atom?) t = lookup(t->left) -26587 { -26588 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26589 75/jump-if-!= break/disp8 -26590 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26591 89/<- %ecx 0/r32/eax -26592 } -26593 # TODO: assert t->is-atom? -26594 (size-of-type-id *(ecx+4)) # Type-tree-value => eax -26595 $size-of:end: -26596 # . restore registers -26597 59/pop-to-ecx -26598 # . epilogue -26599 89/<- %esp 5/r32/ebp -26600 5d/pop-to-ebp -26601 c3/return -26602 -26603 size-of-deref: # v: (addr var) -> result/eax: int -26604 # . prologue -26605 55/push-ebp -26606 89/<- %ebp 4/r32/esp -26607 # . save registers -26608 51/push-ecx -26609 # var t/ecx: (addr type-tree) = lookup(v->type) -26610 8b/-> *(ebp+8) 1/r32/ecx -26611 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -26612 89/<- %ecx 0/r32/eax -26613 # TODO: assert(t is an addr) -26614 # t = lookup(t->right) -26615 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26616 89/<- %ecx 0/r32/eax -26617 # if mu-array?(t) return size-of-array(t) -26618 { -26619 (mu-array? %ecx) # => eax -26620 3d/compare-eax-and 0/imm32/false -26621 74/jump-if-= break/disp8 -26622 (size-of-array %ecx) # => eax -26623 eb/jump $size-of-deref:end/disp8 -26624 } -26625 # if mu-stream?(t) return size-of-stream(t) -26626 { -26627 (mu-stream? %ecx) # => eax -26628 3d/compare-eax-and 0/imm32/false -26629 74/jump-if-= break/disp8 -26630 (size-of-stream %ecx) # => eax -26631 eb/jump $size-of-deref:end/disp8 -26632 } -26633 # if (!t->is-atom?) t = lookup(t->left) -26634 { -26635 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26636 75/jump-if-!= break/disp8 -26637 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26638 89/<- %ecx 0/r32/eax -26639 } -26640 # TODO: assert t->is-atom? -26641 (size-of-type-id *(ecx+4)) # Type-tree-value => eax -26642 $size-of-deref:end: -26643 # . restore registers -26644 59/pop-to-ecx -26645 # . epilogue -26646 89/<- %esp 5/r32/ebp -26647 5d/pop-to-ebp -26648 c3/return -26649 -26650 mu-array?: # t: (addr type-tree) -> result/eax: boolean -26651 # . prologue -26652 55/push-ebp -26653 89/<- %ebp 4/r32/esp -26654 # . save registers -26655 51/push-ecx -26656 # ecx = t -26657 8b/-> *(ebp+8) 1/r32/ecx -26658 # if t->is-atom?, return false -26659 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26660 75/jump-if-!= $mu-array?:return-false/disp8 -26661 # if !t->left->is-atom?, return false -26662 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26663 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -26664 74/jump-if-= $mu-array?:return-false/disp8 -26665 # return t->left->value == array -26666 81 7/subop/compare *(eax+4) 3/imm32/array-type-id # Type-tree-value -26667 0f 94/set-if-= %al -26668 81 4/subop/and %eax 0xff/imm32 -26669 eb/jump $mu-array?:end/disp8 -26670 $mu-array?:return-false: -26671 b8/copy-to-eax 0/imm32/false -26672 $mu-array?:end: -26673 # . restore registers -26674 59/pop-to-ecx -26675 # . epilogue -26676 89/<- %esp 5/r32/ebp -26677 5d/pop-to-ebp -26678 c3/return -26679 -26680 # size of a statically allocated array where the size is part of the type expression -26681 size-of-array: # a: (addr type-tree) -> result/eax: int -26682 # . prologue -26683 55/push-ebp -26684 89/<- %ebp 4/r32/esp -26685 # . save registers -26686 51/push-ecx -26687 52/push-edx -26688 # -26689 8b/-> *(ebp+8) 1/r32/ecx -26690 # TODO: assert that a->left is 'array' -26691 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26692 89/<- %ecx 0/r32/eax -26693 # var elem-type/edx: type-id = a->right->left->value -26694 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26695 8b/-> *(eax+4) 2/r32/edx # Type-tree-value -26696 # TODO: assert that a->right->right->left->value == size -26697 # var array-size/ecx: int = a->right->right->left->value-size -26698 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26699 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -26700 8b/-> *(eax+8) 1/r32/ecx # Type-tree-value-size -26701 # return 4 + array-size * size-of(elem-type) -26702 (size-of-type-id-as-array-element %edx) # => eax -26703 f7 4/subop/multiply-into-edx-eax %ecx -26704 05/add-to-eax 4/imm32 # for array size -26705 # TODO: check edx for overflow -26706 $size-of-array:end: -26707 # . restore registers -26708 5a/pop-to-edx -26709 59/pop-to-ecx -26710 # . epilogue -26711 89/<- %esp 5/r32/ebp -26712 5d/pop-to-ebp -26713 c3/return -26714 -26715 mu-stream?: # t: (addr type-tree) -> result/eax: boolean -26716 # . prologue -26717 55/push-ebp -26718 89/<- %ebp 4/r32/esp -26719 # . save registers -26720 51/push-ecx -26721 # ecx = t -26722 8b/-> *(ebp+8) 1/r32/ecx -26723 # if t->is-atom?, return false -26724 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26725 75/jump-if-!= $mu-stream?:return-false/disp8 -26726 # if !t->left->is-atom?, return false -26727 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26728 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -26729 74/jump-if-= $mu-stream?:return-false/disp8 -26730 # return t->left->value == stream -26731 81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id # Type-tree-value -26732 0f 94/set-if-= %al -26733 81 4/subop/and %eax 0xff/imm32 -26734 eb/jump $mu-stream?:end/disp8 -26735 $mu-stream?:return-false: -26736 b8/copy-to-eax 0/imm32/false -26737 $mu-stream?:end: -26738 # . restore registers -26739 59/pop-to-ecx -26740 # . epilogue -26741 89/<- %esp 5/r32/ebp -26742 5d/pop-to-ebp -26743 c3/return -26744 -26745 # size of a statically allocated stream where the size is part of the type expression -26746 size-of-stream: # a: (addr type-tree) -> result/eax: int -26747 # . prologue -26748 55/push-ebp -26749 89/<- %ebp 4/r32/esp -26750 # -26751 (size-of-array *(ebp+8)) # assumes we ignore the actual type name 'array' in the type -26752 05/add-to-eax 8/imm32 # for read/write pointers -26753 $size-of-stream:end: -26754 # . epilogue -26755 89/<- %esp 5/r32/ebp -26756 5d/pop-to-ebp -26757 c3/return -26758 -26759 size-of-type-id: # t: type-id -> result/eax: int -26760 # . prologue -26761 55/push-ebp -26762 89/<- %ebp 4/r32/esp -26763 # . save registers -26764 51/push-ecx -26765 # var out/ecx: (handle typeinfo) -26766 68/push 0/imm32 -26767 68/push 0/imm32 -26768 89/<- %ecx 4/r32/esp -26769 # eax = t -26770 8b/-> *(ebp+8) 0/r32/eax -26771 # if t is a literal, return 0 -26772 3d/compare-eax-and 0/imm32 -26773 0f 84/jump-if-= $size-of-type-id:end/disp32 # eax changes type from type-id to int -26774 # if t is a byte, return 4 (because we don't really support non-multiples of 4) -26775 3d/compare-eax-and 8/imm32/byte -26776 { -26777 75/jump-if-!= break/disp8 -26778 b8/copy-to-eax 4/imm32 -26779 eb/jump $size-of-type-id:end/disp8 -26780 } -26781 # if t is a handle, return 8 -26782 3d/compare-eax-and 4/imm32/handle -26783 { -26784 75/jump-if-!= break/disp8 -26785 b8/copy-to-eax 8/imm32 -26786 eb/jump $size-of-type-id:end/disp8 # eax changes type from type-id to int -26787 } -26788 # if t is a slice, return 8 -26789 3d/compare-eax-and 0xc/imm32/slice -26790 { -26791 75/jump-if-!= break/disp8 -26792 b8/copy-to-eax 8/imm32 -26793 eb/jump $size-of-type-id:end/disp8 # eax changes type from type-id to int -26794 } -26795 # if t is a user-defined type, return its size -26796 # TODO: support non-atom type -26797 (find-typeinfo %eax %ecx) +26296 (write-buffered *(ebp+0x14) ": type for output '") +26297 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26298 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26299 (write-buffered *(ebp+0x14) %eax) +26300 (write-buffered *(ebp+0x14) "' is not right\n") +26301 (flush *(ebp+0x14)) +26302 (stop *(ebp+0x18) 1) +26303 } +26304 $check-mu-call:check-output-register: +26305 # var v/eax: (addr v) = lookup(outputs->value) +26306 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26307 # var r/ebx: (addr array byte) = lookup(v->register) +26308 (lookup *(eax+18) *(eax+0x1c)) # Var-register Var-register => eax +26309 89/<- %ebx 0/r32/eax +26310 # if (r == 0) error +26311 3d/compare-eax-and 0/imm32 +26312 { +26313 0f 85/jump-if-!= break/disp32 +26314 (write-buffered *(ebp+0x14) "fn ") +26315 8b/-> *(ebp+0x10) 0/r32/eax +26316 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26317 (write-buffered *(ebp+0x14) %eax) +26318 (write-buffered *(ebp+0x14) ": call ") +26319 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26320 (write-buffered *(ebp+0x14) %eax) +26321 (write-buffered *(ebp+0x14) ": output '") +26322 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26323 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26324 (write-buffered *(ebp+0x14) %eax) +26325 (write-buffered *(ebp+0x14) "' is not in a register\n") +26326 (flush *(ebp+0x14)) +26327 (stop *(ebp+0x18) 1) +26328 } +26329 # var v2/eax: (addr v) = lookup(expected->value) +26330 (lookup *edx *(edx+4)) # Stmt-var-value Stmt-var-value => eax +26331 # var r2/eax: (addr array byte) = lookup(v2->register) +26332 (lookup *(eax+18) *(eax+0x1c)) # Var-register Var-register => eax +26333 # if (r != r2) error +26334 (string-equal? %eax %ebx) # => eax +26335 3d/compare-eax-and 0/imm32/false +26336 { +26337 0f 85/jump-if-!= break/disp32 +26338 (write-buffered *(ebp+0x14) "fn ") +26339 8b/-> *(ebp+0x10) 0/r32/eax +26340 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26341 (write-buffered *(ebp+0x14) %eax) +26342 (write-buffered *(ebp+0x14) ": call ") +26343 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26344 (write-buffered *(ebp+0x14) %eax) +26345 (write-buffered *(ebp+0x14) ": register for output '") +26346 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +26347 (lookup *eax *(eax+4)) # Var-name Var-name => eax +26348 (write-buffered *(ebp+0x14) %eax) +26349 (write-buffered *(ebp+0x14) "' is not right\n") +26350 (flush *(ebp+0x14)) +26351 (stop *(ebp+0x18) 1) +26352 } +26353 $check-mu-call:continue-to-next-output: +26354 # outputs = lookup(outputs->next) +26355 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax +26356 89/<- %ecx 0/r32/eax +26357 # expected = lookup(expected->next) +26358 (lookup *(edx+8) *(edx+0xc)) # List-next List-next => eax +26359 89/<- %edx 0/r32/eax +26360 # +26361 e9/jump loop/disp32 +26362 } +26363 $check-mu-call:check-output-count: +26364 # if (outputs == expected) proceed +26365 39/compare %ecx 2/r32/edx +26366 { +26367 0f 84/jump-if-= break/disp32 +26368 # exactly one of the two is null +26369 # if (outputs == 0) error("too many outputs") +26370 { +26371 81 7/subop/compare %ecx 0/imm32 +26372 0f 84/jump-if-= break/disp32 +26373 (write-buffered *(ebp+0x14) "fn ") +26374 8b/-> *(ebp+0x10) 0/r32/eax +26375 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26376 (write-buffered *(ebp+0x14) %eax) +26377 (write-buffered *(ebp+0x14) ": call ") +26378 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26379 (write-buffered *(ebp+0x14) %eax) +26380 (write-buffered *(ebp+0x14) ": too many outputs\n") +26381 (flush *(ebp+0x14)) +26382 (stop *(ebp+0x18) 1) +26383 } +26384 # if (expected == 0) error("too few outputs") +26385 { +26386 81 7/subop/compare %edx 0/imm32 +26387 0f 84/jump-if-= break/disp32 +26388 (write-buffered *(ebp+0x14) "fn ") +26389 8b/-> *(ebp+0x10) 0/r32/eax +26390 (lookup *eax *(eax+4)) # Function-name Function-name => eax +26391 (write-buffered *(ebp+0x14) %eax) +26392 (write-buffered *(ebp+0x14) ": call ") +26393 (lookup *edi *(edi+4)) # Function-name Function-name => eax +26394 (write-buffered *(ebp+0x14) %eax) +26395 (write-buffered *(ebp+0x14) ": too few outputs\n") +26396 (flush *(ebp+0x14)) +26397 (stop *(ebp+0x18) 1) +26398 } +26399 } +26400 $check-mu-call:end: +26401 # . restore registers +26402 5f/pop-to-edi +26403 5e/pop-to-esi +26404 5b/pop-to-ebx +26405 5a/pop-to-edx +26406 59/pop-to-ecx +26407 58/pop-to-eax +26408 # . reclaim locals exclusively on the stack +26409 81 0/subop/add %esp 0x70/imm32 +26410 # . epilogue +26411 89/<- %esp 5/r32/ebp +26412 5d/pop-to-ebp +26413 c3/return +26414 +26415 # like type-equal? but takes literals type parameters into account +26416 type-match?: # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean +26417 # . prologue +26418 55/push-ebp +26419 89/<- %ebp 4/r32/esp +26420 # if (call is literal and def is numberlike) return true +26421 { +26422 $type-match?:check-literal-int: +26423 (simple-mu-type? *(ebp+0xc) 0) # literal => eax +26424 3d/compare-eax-and 0/imm32/false +26425 74/jump-if-= break/disp8 +26426 (mu-numberlike-output? *(ebp+8)) # => eax +26427 3d/compare-eax-and 0/imm32/false +26428 74/jump-if-= break/disp8 +26429 b8/copy-to-eax 1/imm32/true +26430 e9/jump $type-match?:end/disp32 +26431 } +26432 # if (call is literal-string and def is string) return true +26433 { +26434 $type-match?:check-literal-string: +26435 (simple-mu-type? *(ebp+0xc) 0x10) # literal-string => eax +26436 3d/compare-eax-and 0/imm32/false +26437 74/jump-if-= break/disp8 +26438 (mu-string-type? *(ebp+8)) # => eax +26439 3d/compare-eax-and 0/imm32/false +26440 74/jump-if-= break/disp8 +26441 b8/copy-to-eax 1/imm32/true +26442 e9/jump $type-match?:end/disp32 +26443 } +26444 $type-match?:baseline: +26445 # otherwise fall back +26446 (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +26447 $type-match?:end: +26448 # . epilogue +26449 89/<- %esp 5/r32/ebp +26450 5d/pop-to-ebp +26451 c3/return +26452 +26453 type-component-match?: # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean +26454 # . prologue +26455 55/push-ebp +26456 89/<- %ebp 4/r32/esp +26457 # . save registers +26458 51/push-ecx +26459 52/push-edx +26460 53/push-ebx +26461 # ecx = def +26462 8b/-> *(ebp+8) 1/r32/ecx +26463 # edx = call +26464 8b/-> *(ebp+0xc) 2/r32/edx +26465 $type-component-match?:compare-addr: +26466 # if (def == call) return true +26467 8b/-> %ecx 0/r32/eax # Var-type +26468 39/compare %edx 0/r32/eax # Var-type +26469 b8/copy-to-eax 1/imm32/true +26470 0f 84/jump-if-= $type-component-match?:end/disp32 +26471 # if (def == 0) return false +26472 b8/copy-to-eax 0/imm32/false +26473 81 7/subop/compare %ecx 0/imm32 # Type-tree-is-atom +26474 0f 84/jump-if-= $type-component-match?:end/disp32 +26475 # if (call == 0) return false +26476 81 7/subop/compare %edx 0/imm32 # Type-tree-is-atom +26477 0f 84/jump-if-= $type-component-match?:end/disp32 +26478 # if def is a type parameter, just check in type-parameters +26479 { +26480 $type-component-match?:check-type-parameter: +26481 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26482 74/jump-if-= break/disp8 +26483 81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter # Type-tree-value +26484 75/jump-if-!= break/disp8 +26485 $type-component-match?:type-parameter: +26486 (type-parameter-match? *(ecx+8) *(ecx+0xc) %edx *(ebp+0x10)) # => eax +26487 e9/jump $type-component-match?:end/disp32 +26488 } +26489 # if def is a list containing just a type parameter, just check in type-parameters +26490 { +26491 $type-component-match?:check-list-type-parameter: +26492 # if def is a list.. +26493 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26494 75/jump-if-!= break/disp8 +26495 # ..that's a singleton +26496 81 7/subop/compare *(ecx+0xc) 0/imm32 # Type-tree-left +26497 75/jump-if-!= break/disp8 +26498 # ..and whose head is a type parameter +26499 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26500 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +26501 74/jump-if-= break/disp8 +26502 81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter # Type-tree-value +26503 75/jump-if-!= break/disp8 +26504 $type-component-match?:list-type-parameter: +26505 (type-parameter-match? *(eax+8) *(eax+0xc) %edx *(ebp+0x10)) # => eax +26506 e9/jump $type-component-match?:end/disp32 +26507 } +26508 $type-component-match?:compare-atom-state: +26509 # if (def->is-atom? != call->is-atom?) return false +26510 8b/-> *ecx 3/r32/ebx # Type-tree-is-atom +26511 39/compare *edx 3/r32/ebx # Type-tree-is-atom +26512 b8/copy-to-eax 0/imm32/false +26513 0f 85/jump-if-!= $type-component-match?:end/disp32 +26514 # if def->is-atom? return (def->value == call->value) +26515 { +26516 $type-component-match?:check-atom: +26517 81 7/subop/compare %ebx 0/imm32/false +26518 74/jump-if-= break/disp8 +26519 $type-component-match?:is-atom: +26520 8b/-> *(ecx+4) 0/r32/eax # Type-tree-value +26521 39/compare *(edx+4) 0/r32/eax # Type-tree-value +26522 0f 94/set-if-= %al +26523 25/and-eax-with 0xff/imm32 +26524 e9/jump $type-component-match?:end/disp32 +26525 } +26526 $type-component-match?:check-left: +26527 # if (!type-component-match?(def->left, call->left)) return false +26528 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26529 89/<- %ebx 0/r32/eax +26530 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +26531 (type-component-match? %ebx %eax *(ebp+0x10)) # => eax +26532 3d/compare-eax-and 0/imm32/false +26533 74/jump-if-= $type-component-match?:end/disp8 +26534 $type-component-match?:check-right: +26535 # return type-component-match?(def->right, call->right) +26536 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26537 89/<- %ebx 0/r32/eax +26538 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax +26539 (type-component-match? %ebx %eax *(ebp+0x10)) # => eax +26540 $type-component-match?:end: +26541 # . restore registers +26542 5b/pop-to-ebx +26543 5a/pop-to-edx +26544 59/pop-to-ecx +26545 # . epilogue +26546 89/<- %esp 5/r32/ebp +26547 5d/pop-to-ebp +26548 c3/return +26549 +26550 type-parameter-match?: # type-parameter-name: (handle array byte), type: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean +26551 # . prologue +26552 55/push-ebp +26553 89/<- %ebp 4/r32/esp +26554 # . save registers +26555 51/push-ecx +26556 # +26557 (get-or-insert-handle *(ebp+0x14) *(ebp+8) *(ebp+0xc) 0xc) # => eax +26558 # if parameter wasn't saved, save it +26559 { +26560 81 7/subop/compare *eax 0/imm32 +26561 75/jump-if-!= break/disp8 +26562 8b/-> *(ebp+0x10) 1/r32/ecx +26563 89/<- *eax 1/r32/ecx +26564 } +26565 # +26566 (type-equal? *(ebp+0x10) *eax) # => eax +26567 $type-parameter-match?:end: +26568 # . restore registers +26569 59/pop-to-ecx +26570 # . epilogue +26571 89/<- %esp 5/r32/ebp +26572 5d/pop-to-ebp +26573 c3/return +26574 +26575 size-of: # v: (addr var) -> result/eax: int +26576 # . prologue +26577 55/push-ebp +26578 89/<- %ebp 4/r32/esp +26579 # . save registers +26580 51/push-ecx +26581 # var t/ecx: (addr type-tree) = lookup(v->type) +26582 8b/-> *(ebp+8) 1/r32/ecx +26583 #? (write-buffered Stderr "size-of ") +26584 #? (write-int32-hex-buffered Stderr %ecx) +26585 #? (write-buffered Stderr Newline) +26586 #? (write-buffered Stderr "type allocid: ") +26587 #? (write-int32-hex-buffered Stderr *(ecx+8)) +26588 #? (write-buffered Stderr Newline) +26589 #? (flush Stderr) +26590 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +26591 89/<- %ecx 0/r32/eax +26592 # if mu-array?(t) return size-of-array(t) +26593 { +26594 (mu-array? %ecx) # => eax +26595 3d/compare-eax-and 0/imm32/false +26596 74/jump-if-= break/disp8 +26597 (size-of-array %ecx) # => eax +26598 eb/jump $size-of:end/disp8 +26599 } +26600 # if mu-stream?(t) return size-of-stream(t) +26601 { +26602 (mu-stream? %ecx) # => eax +26603 3d/compare-eax-and 0/imm32/false +26604 74/jump-if-= break/disp8 +26605 (size-of-stream %ecx) # => eax +26606 eb/jump $size-of:end/disp8 +26607 } +26608 # if (!t->is-atom?) t = lookup(t->left) +26609 { +26610 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26611 75/jump-if-!= break/disp8 +26612 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26613 89/<- %ecx 0/r32/eax +26614 } +26615 # TODO: assert t->is-atom? +26616 (size-of-type-id *(ecx+4)) # Type-tree-value => eax +26617 $size-of:end: +26618 # . restore registers +26619 59/pop-to-ecx +26620 # . epilogue +26621 89/<- %esp 5/r32/ebp +26622 5d/pop-to-ebp +26623 c3/return +26624 +26625 size-of-deref: # v: (addr var) -> result/eax: int +26626 # . prologue +26627 55/push-ebp +26628 89/<- %ebp 4/r32/esp +26629 # . save registers +26630 51/push-ecx +26631 # var t/ecx: (addr type-tree) = lookup(v->type) +26632 8b/-> *(ebp+8) 1/r32/ecx +26633 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +26634 89/<- %ecx 0/r32/eax +26635 # TODO: assert(t is an addr) +26636 # t = lookup(t->right) +26637 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26638 89/<- %ecx 0/r32/eax +26639 # if mu-array?(t) return size-of-array(t) +26640 { +26641 (mu-array? %ecx) # => eax +26642 3d/compare-eax-and 0/imm32/false +26643 74/jump-if-= break/disp8 +26644 (size-of-array %ecx) # => eax +26645 eb/jump $size-of-deref:end/disp8 +26646 } +26647 # if mu-stream?(t) return size-of-stream(t) +26648 { +26649 (mu-stream? %ecx) # => eax +26650 3d/compare-eax-and 0/imm32/false +26651 74/jump-if-= break/disp8 +26652 (size-of-stream %ecx) # => eax +26653 eb/jump $size-of-deref:end/disp8 +26654 } +26655 # if (!t->is-atom?) t = lookup(t->left) +26656 { +26657 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26658 75/jump-if-!= break/disp8 +26659 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26660 89/<- %ecx 0/r32/eax +26661 } +26662 # TODO: assert t->is-atom? +26663 (size-of-type-id *(ecx+4)) # Type-tree-value => eax +26664 $size-of-deref:end: +26665 # . restore registers +26666 59/pop-to-ecx +26667 # . epilogue +26668 89/<- %esp 5/r32/ebp +26669 5d/pop-to-ebp +26670 c3/return +26671 +26672 mu-array?: # t: (addr type-tree) -> result/eax: boolean +26673 # . prologue +26674 55/push-ebp +26675 89/<- %ebp 4/r32/esp +26676 # . save registers +26677 51/push-ecx +26678 # ecx = t +26679 8b/-> *(ebp+8) 1/r32/ecx +26680 # if t->is-atom?, return false +26681 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26682 75/jump-if-!= $mu-array?:return-false/disp8 +26683 # if !t->left->is-atom?, return false +26684 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26685 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +26686 74/jump-if-= $mu-array?:return-false/disp8 +26687 # return t->left->value == array +26688 81 7/subop/compare *(eax+4) 3/imm32/array-type-id # Type-tree-value +26689 0f 94/set-if-= %al +26690 25/and-eax-with 0xff/imm32 +26691 eb/jump $mu-array?:end/disp8 +26692 $mu-array?:return-false: +26693 b8/copy-to-eax 0/imm32/false +26694 $mu-array?:end: +26695 # . restore registers +26696 59/pop-to-ecx +26697 # . epilogue +26698 89/<- %esp 5/r32/ebp +26699 5d/pop-to-ebp +26700 c3/return +26701 +26702 # size of a statically allocated array where the size is part of the type expression +26703 size-of-array: # a: (addr type-tree) -> result/eax: int +26704 # . prologue +26705 55/push-ebp +26706 89/<- %ebp 4/r32/esp +26707 # . save registers +26708 51/push-ecx +26709 52/push-edx +26710 # +26711 8b/-> *(ebp+8) 1/r32/ecx +26712 # TODO: assert that a->left is 'array' +26713 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26714 89/<- %ecx 0/r32/eax +26715 # var elem-type/edx: type-id = a->right->left->value +26716 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26717 8b/-> *(eax+4) 2/r32/edx # Type-tree-value +26718 # TODO: assert that a->right->right->left->value == size +26719 # var array-size/ecx: int = a->right->right->left->value-size +26720 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26721 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +26722 8b/-> *(eax+8) 1/r32/ecx # Type-tree-value-size +26723 # return 4 + array-size * size-of(elem-type) +26724 (size-of-type-id-as-array-element %edx) # => eax +26725 f7 4/subop/multiply-into-edx-eax %ecx +26726 05/add-to-eax 4/imm32 # for array size +26727 # TODO: check edx for overflow +26728 $size-of-array:end: +26729 # . restore registers +26730 5a/pop-to-edx +26731 59/pop-to-ecx +26732 # . epilogue +26733 89/<- %esp 5/r32/ebp +26734 5d/pop-to-ebp +26735 c3/return +26736 +26737 mu-stream?: # t: (addr type-tree) -> result/eax: boolean +26738 # . prologue +26739 55/push-ebp +26740 89/<- %ebp 4/r32/esp +26741 # . save registers +26742 51/push-ecx +26743 # ecx = t +26744 8b/-> *(ebp+8) 1/r32/ecx +26745 # if t->is-atom?, return false +26746 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26747 75/jump-if-!= $mu-stream?:return-false/disp8 +26748 # if !t->left->is-atom?, return false +26749 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26750 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +26751 74/jump-if-= $mu-stream?:return-false/disp8 +26752 # return t->left->value == stream +26753 81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id # Type-tree-value +26754 0f 94/set-if-= %al +26755 25/and-eax-with 0xff/imm32 +26756 eb/jump $mu-stream?:end/disp8 +26757 $mu-stream?:return-false: +26758 b8/copy-to-eax 0/imm32/false +26759 $mu-stream?:end: +26760 # . restore registers +26761 59/pop-to-ecx +26762 # . epilogue +26763 89/<- %esp 5/r32/ebp +26764 5d/pop-to-ebp +26765 c3/return +26766 +26767 # size of a statically allocated stream where the size is part of the type expression +26768 size-of-stream: # a: (addr type-tree) -> result/eax: int +26769 # . prologue +26770 55/push-ebp +26771 89/<- %ebp 4/r32/esp +26772 # +26773 (size-of-array *(ebp+8)) # assumes we ignore the actual type name 'array' in the type +26774 05/add-to-eax 8/imm32 # for read/write pointers +26775 $size-of-stream:end: +26776 # . epilogue +26777 89/<- %esp 5/r32/ebp +26778 5d/pop-to-ebp +26779 c3/return +26780 +26781 size-of-type-id: # t: type-id -> result/eax: int +26782 # . prologue +26783 55/push-ebp +26784 89/<- %ebp 4/r32/esp +26785 # . save registers +26786 51/push-ecx +26787 # var out/ecx: (handle typeinfo) +26788 68/push 0/imm32 +26789 68/push 0/imm32 +26790 89/<- %ecx 4/r32/esp +26791 # eax = t +26792 8b/-> *(ebp+8) 0/r32/eax +26793 # if t is a literal, return 0 +26794 3d/compare-eax-and 0/imm32 +26795 0f 84/jump-if-= $size-of-type-id:end/disp32 # eax changes type from type-id to int +26796 # if t is a byte, return 4 (because we don't really support non-multiples of 4) +26797 3d/compare-eax-and 8/imm32/byte 26798 { -26799 81 7/subop/compare *ecx 0/imm32 -26800 74/jump-if-= break/disp8 -26801 $size-of-type-id:user-defined: -26802 (lookup *ecx *(ecx+4)) # => eax -26803 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-total-size-in-bytes -26804 eb/jump $size-of-type-id:end/disp8 -26805 } -26806 # otherwise return the word size -26807 b8/copy-to-eax 4/imm32 -26808 $size-of-type-id:end: -26809 # . reclaim locals -26810 81 0/subop/add %esp 8/imm32 -26811 # . restore registers -26812 59/pop-to-ecx -26813 # . epilogue -26814 89/<- %esp 5/r32/ebp -26815 5d/pop-to-ebp -26816 c3/return -26817 -26818 # Minor violation of our type system since it returns an addr. But we could -26819 # replace it with a handle some time. -26820 # Returns null if t is an atom. -26821 type-tail: # t: (addr type-tree) -> out/eax: (addr type-tree) -26822 # . prologue -26823 55/push-ebp -26824 89/<- %ebp 4/r32/esp -26825 # . save registers -26826 51/push-ecx -26827 # eax = 0 -26828 b8/copy-to-eax 0/imm32 -26829 # ecx = t -26830 8b/-> *(ebp+8) 1/r32/ecx -26831 $type-tail:check-atom: -26832 # if t->is-atom? return 0 -26833 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom -26834 0f 85/jump-if-!= $type-tail:end/disp32 -26835 # var tail = t->right -26836 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26837 89/<- %ecx 0/r32/eax -26838 $type-tail:check-singleton: -26839 # if (tail->right == 0) return tail->left -26840 { -26841 81 7/subop/compare *(ecx+0xc) 0/imm32 # Type-tree-right -26842 75/jump-if-!= break/disp8 -26843 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26844 e9/jump $type-tail:end/disp32 -26845 } -26846 # if tail->right->left is an array-capacity, return tail->left -26847 { -26848 $type-tail:check-array-capacity: -26849 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26850 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -26851 75/jump-if-!= break/disp8 -26852 $type-tail:check-array-capacity-1: -26853 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -26854 3d/compare-eax-and 0/imm32 -26855 74/jump-if-= break/disp8 -26856 $type-tail:check-array-capacity-2: -26857 (simple-mu-type? %eax 9) # array-capacity => eax -26858 3d/compare-eax-and 0/imm32/false -26859 74/jump-if-= break/disp8 -26860 $type-tail:array-capacity: -26861 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26862 eb/jump $type-tail:end/disp8 -26863 } -26864 $type-tail:check-compound-left: -26865 # if !tail->left->is-atom? return tail->left -26866 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26867 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -26868 74/jump-if-= $type-tail:end/disp8 -26869 $type-tail:return-tail: -26870 # return tail -26871 89/<- %eax 1/r32/ecx -26872 $type-tail:end: -26873 # . restore registers -26874 59/pop-to-ecx -26875 # . epilogue -26876 89/<- %esp 5/r32/ebp -26877 5d/pop-to-ebp -26878 c3/return -26879 -26880 type-equal?: # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean -26881 # . prologue -26882 55/push-ebp -26883 89/<- %ebp 4/r32/esp -26884 # . save registers -26885 51/push-ecx -26886 52/push-edx -26887 53/push-ebx -26888 # ecx = a -26889 8b/-> *(ebp+8) 1/r32/ecx -26890 # edx = b -26891 8b/-> *(ebp+0xc) 2/r32/edx -26892 $type-equal?:compare-addr: -26893 # if (a == b) return true -26894 8b/-> %ecx 0/r32/eax # Var-type -26895 39/compare %edx 0/r32/eax # Var-type -26896 b8/copy-to-eax 1/imm32/true -26897 0f 84/jump-if-= $type-equal?:end/disp32 -26898 $type-equal?:compare-null-a: -26899 # if (a == 0) return false -26900 b8/copy-to-eax 0/imm32/false -26901 81 7/subop/compare %ecx 0/imm32 -26902 0f 84/jump-if-= $type-equal?:end/disp32 -26903 $type-equal?:compare-null-b: -26904 # if (b == 0) return false -26905 81 7/subop/compare %edx 0/imm32 -26906 0f 84/jump-if-= $type-equal?:end/disp32 -26907 $type-equal?:compare-atom-state: -26908 # if (a->is-atom? != b->is-atom?) return false -26909 8b/-> *ecx 3/r32/ebx # Type-tree-is-atom -26910 39/compare *edx 3/r32/ebx # Type-tree-is-atom -26911 b8/copy-to-eax 0/imm32/false -26912 0f 85/jump-if-!= $type-equal?:end/disp32 -26913 # if a->is-atom? return (a->value == b->value) -26914 { -26915 $type-equal?:check-atom: -26916 81 7/subop/compare %ebx 0/imm32/false -26917 74/jump-if-= break/disp8 -26918 $type-equal?:is-atom: -26919 8b/-> *(ecx+4) 0/r32/eax # Type-tree-value -26920 39/compare *(edx+4) 0/r32/eax # Type-tree-value -26921 0f 94/set-if-= %al -26922 81 4/subop/and %eax 0xff/imm32 -26923 e9/jump $type-equal?:end/disp32 -26924 } -26925 $type-equal?:check-left: -26926 # if (!type-equal?(a->left, b->left)) return false -26927 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax -26928 89/<- %ebx 0/r32/eax -26929 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax -26930 (type-equal? %eax %ebx) # => eax -26931 3d/compare-eax-and 0/imm32/false -26932 74/jump-if-= $type-equal?:end/disp8 -26933 $type-equal?:check-right: -26934 # return type-equal?(a->right, b->right) -26935 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax -26936 89/<- %ebx 0/r32/eax -26937 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax -26938 (type-equal? %eax %ebx) # => eax -26939 $type-equal?:end: -26940 # . restore registers -26941 5b/pop-to-ebx -26942 5a/pop-to-edx -26943 59/pop-to-ecx -26944 # . epilogue -26945 89/<- %esp 5/r32/ebp -26946 5d/pop-to-ebp -26947 c3/return -26948 -26949 ####################################################### -26950 # Code-generation -26951 ####################################################### -26952 -26953 == data -26954 -26955 # Global state added to each var record when performing code-generation. -26956 Curr-local-stack-offset: # (addr int) -26957 0/imm32 -26958 -26959 == code -26960 -26961 # We may not need to pass err/ed everywhere here. I think they're relics of Mu -26962 # getting type checks later in life. -26963 # But we do need them for runtime checks, particularly array index bounds checks. -26964 # So perhaps it's not worth taking them out. They're a safety net. -26965 -26966 emit-subx: # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) -26967 # . prologue -26968 55/push-ebp -26969 89/<- %ebp 4/r32/esp -26970 # . save registers -26971 50/push-eax -26972 # var curr/eax: (addr function) = *Program->functions -26973 (lookup *_Program-functions *_Program-functions->payload) # => eax -26974 { -26975 # if (curr == null) break -26976 3d/compare-eax-and 0/imm32 -26977 0f 84/jump-if-= break/disp32 -26978 (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10)) -26979 # curr = lookup(curr->next) -26980 (lookup *(eax+0x20) *(eax+0x24)) # Function-next Function-next => eax -26981 e9/jump loop/disp32 -26982 } -26983 $emit-subx:end: -26984 # . restore registers -26985 58/pop-to-eax -26986 # . epilogue -26987 89/<- %esp 5/r32/ebp -26988 5d/pop-to-ebp -26989 c3/return -26990 -26991 emit-subx-function: # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -26992 # . prologue -26993 55/push-ebp -26994 89/<- %ebp 4/r32/esp -26995 # some preprocessing -26996 (populate-mu-type-offsets-in-inouts *(ebp+0xc)) -26997 # . save registers -26998 50/push-eax -26999 51/push-ecx -27000 52/push-edx -27001 # initialize some global state -27002 c7 0/subop/copy *Curr-block-depth 1/imm32 # Important: keep this in sync with the parse phase -27003 c7 0/subop/copy *Curr-local-stack-offset 0/imm32 -27004 # ecx = f -27005 8b/-> *(ebp+0xc) 1/r32/ecx -27006 # var vars/edx: (stack (addr var) 256) -27007 81 5/subop/subtract %esp 0xc00/imm32 -27008 68/push 0xc00/imm32/size -27009 68/push 0/imm32/top -27010 89/<- %edx 4/r32/esp -27011 # var name/eax: (addr array byte) = lookup(f->name) -27012 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax -27013 # -27014 (write-buffered *(ebp+8) %eax) -27015 (write-buffered *(ebp+8) ":\n") -27016 (emit-subx-prologue *(ebp+8)) -27017 # var body/eax: (addr block) = lookup(f->body) -27018 (lookup *(ecx+0x18) *(ecx+0x1c)) # Function-body Function-body => eax -27019 # -27020 (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) -27021 (emit-subx-epilogue *(ebp+8)) -27022 # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have -27023 # been cleaned up -27024 $emit-subx-function:end: -27025 # . reclaim locals -27026 81 0/subop/add %esp 0xc08/imm32 -27027 # . restore registers -27028 5a/pop-to-edx -27029 59/pop-to-ecx -27030 58/pop-to-eax -27031 # . epilogue -27032 89/<- %esp 5/r32/ebp -27033 5d/pop-to-ebp -27034 c3/return -27035 -27036 populate-mu-type-offsets-in-inouts: # f: (addr function) -27037 # . prologue -27038 55/push-ebp -27039 89/<- %ebp 4/r32/esp -27040 # . save registers -27041 50/push-eax -27042 51/push-ecx -27043 52/push-edx -27044 53/push-ebx -27045 57/push-edi -27046 # var next-offset/edx: int = 8 -27047 ba/copy-to-edx 8/imm32 -27048 # var curr/ecx: (addr list var) = lookup(f->inouts) -27049 8b/-> *(ebp+8) 1/r32/ecx -27050 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax -27051 89/<- %ecx 0/r32/eax -27052 { -27053 $populate-mu-type-offsets-in-inouts:loop: -27054 81 7/subop/compare %ecx 0/imm32 -27055 74/jump-if-= break/disp8 -27056 # var v/ebx: (addr var) = lookup(curr->value) -27057 (lookup *ecx *(ecx+4)) # List-value List-value => eax -27058 89/<- %ebx 0/r32/eax -27059 #? (lookup *ebx *(ebx+4)) -27060 #? (write-buffered Stderr "setting offset of fn inout ") -27061 #? (write-buffered Stderr %eax) -27062 #? (write-buffered Stderr "@") -27063 #? (write-int32-hex-buffered Stderr %ebx) -27064 #? (write-buffered Stderr " to ") -27065 #? (write-int32-hex-buffered Stderr %edx) -27066 #? (write-buffered Stderr Newline) -27067 #? (flush Stderr) -27068 # v->offset = next-offset -27069 89/<- *(ebx+0x14) 2/r32/edx # Var-offset -27070 # next-offset += size-of(v) -27071 (size-of %ebx) # => eax -27072 01/add-to %edx 0/r32/eax -27073 # curr = lookup(curr->next) -27074 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -27075 89/<- %ecx 0/r32/eax -27076 # -27077 eb/jump loop/disp8 -27078 } -27079 $populate-mu-type-offsets-in-inouts:end: -27080 # . restore registers -27081 5f/pop-to-edi -27082 5b/pop-to-ebx -27083 5a/pop-to-edx -27084 59/pop-to-ecx -27085 58/pop-to-eax -27086 # . epilogue -27087 89/<- %esp 5/r32/ebp -27088 5d/pop-to-ebp -27089 c3/return -27090 -27091 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -27092 # . prologue -27093 55/push-ebp -27094 89/<- %ebp 4/r32/esp -27095 # . save registers -27096 50/push-eax -27097 51/push-ecx -27098 53/push-ebx -27099 56/push-esi -27100 # esi = stmts -27101 8b/-> *(ebp+0xc) 6/r32/esi -27102 # -27103 { -27104 $emit-subx-stmt-list:loop: -27105 81 7/subop/compare %esi 0/imm32 -27106 0f 84/jump-if-= break/disp32 -27107 # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value) -27108 (lookup *esi *(esi+4)) # List-value List-value => eax -27109 89/<- %ecx 0/r32/eax -27110 { -27111 $emit-subx-stmt-list:check-for-block: -27112 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -27113 75/jump-if-!= break/disp8 -27114 $emit-subx-stmt-list:block: -27115 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -27116 } -27117 { -27118 $emit-subx-stmt-list:check-for-stmt: -27119 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -27120 0f 85/jump-if-!= break/disp32 -27121 $emit-subx-stmt-list:stmt1: -27122 { -27123 (mu-branch? %ecx) # => eax -27124 3d/compare-eax-and 0/imm32/false -27125 0f 84/jump-if-= break/disp32 -27126 $emit-subx-stmt-list:branch-stmt: -27127 +-- 25 lines: # unconditional return ---------------------------------------------------------------------------------------------------------------------------------------------------- -27152 +-- 27 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- -27179 +-- 16 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- -27195 +-- 38 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- -27233 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- -27252 } -27253 $emit-subx-stmt-list:1-to-1: -27254 (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -27255 e9/jump $emit-subx-stmt-list:continue/disp32 -27256 } -27257 { -27258 $emit-subx-stmt-list:check-for-var-def: -27259 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag -27260 75/jump-if-!= break/disp8 -27261 $emit-subx-stmt-list:var-def: -27262 (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c)) -27263 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -27264 (push *(ebp+0x10) *(ecx+8)) # Vardef-var -27265 (push *(ebp+0x10) 0) # Live-var-register-spilled = 0 for vars on the stack -27266 # -27267 eb/jump $emit-subx-stmt-list:continue/disp8 -27268 } -27269 { -27270 $emit-subx-stmt-list:check-for-reg-var-def: -27271 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag -27272 0f 85/jump-if-!= break/disp32 -27273 $emit-subx-stmt-list:reg-var-def: -27274 # TODO: ensure that there's exactly one output -27275 (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -27276 # emit the instruction as usual -27277 (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -27278 # -27279 eb/jump $emit-subx-stmt-list:continue/disp8 -27280 } -27281 $emit-subx-stmt-list:continue: -27282 # TODO: raise an error on unrecognized Stmt-tag -27283 (lookup *(esi+8) *(esi+0xc)) # List-next List-next => eax -27284 89/<- %esi 0/r32/eax -27285 e9/jump loop/disp32 -27286 } -27287 $emit-subx-stmt-list:emit-cleanup: -27288 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) -27289 $emit-subx-stmt-list:clean-up: -27290 (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth) -27291 (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14)) -27292 $emit-subx-stmt-list:end: -27293 # . restore registers -27294 5e/pop-to-esi -27295 5b/pop-to-ebx -27296 59/pop-to-ecx -27297 58/pop-to-eax -27298 # . epilogue -27299 89/<- %esp 5/r32/ebp -27300 5d/pop-to-ebp -27301 c3/return -27302 -27303 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs. -27304 push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -27305 # . prologue -27306 55/push-ebp -27307 89/<- %ebp 4/r32/esp -27308 # . save registers -27309 50/push-eax -27310 51/push-ecx -27311 52/push-edx -27312 # ecx = stmt -27313 8b/-> *(ebp+0xc) 1/r32/ecx -27314 # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs) -27315 (lookup *(ecx+0x14) *(ecx+0x18)) # Regvardef-outputs Regvardef-outputs => eax -27316 # TODO: assert !sv->is-deref? -27317 # var v/ecx: (addr var) = lookup(sv->value) -27318 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -27319 89/<- %ecx 0/r32/eax -27320 # v->block-depth = *Curr-block-depth -27321 8b/-> *Curr-block-depth 0/r32/eax -27322 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth -27323 #? (write-buffered Stderr "var ") -27324 #? (lookup *ecx *(ecx+4)) -27325 #? (write-buffered Stderr %eax) -27326 #? (write-buffered Stderr " at depth ") -27327 #? (write-int32-hex-buffered Stderr *(ecx+0x10)) -27328 #? (write-buffered Stderr Newline) -27329 #? (flush Stderr) -27330 # ensure that v is in a register -27331 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register -27332 0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32 -27333 # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn) -27334 (not-yet-spilled-this-block? %ecx *(ebp+0x10)) # => eax -27335 89/<- %edx 0/r32/eax -27336 3d/compare-eax-and 0/imm32/false -27337 0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32 -27338 (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18)) # => eax -27339 89/<- %edx 0/r32/eax -27340 # check emit-spill? -27341 3d/compare-eax-and 0/imm32/false -27342 0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32 -27343 # TODO: assert(size-of(output) == 4) -27344 # *Curr-local-stack-offset -= 4 -27345 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 -27346 # emit spill -27347 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax -27348 (emit-push-register *(ebp+8) %eax) -27349 $push-output-and-maybe-emit-spill:push: -27350 8b/-> *(ebp+0xc) 1/r32/ecx -27351 (lookup *(ecx+0x14) *(ecx+0x18)) # Regvardef-outputs Regvardef-outputs => eax -27352 # push(vars, {sv->value, emit-spill?}) -27353 (push *(ebp+0x10) *eax) # Stmt-var-value -27354 (push *(ebp+0x10) *(eax+4)) # Stmt-var-value -27355 (push *(ebp+0x10) %edx) -27356 $push-output-and-maybe-emit-spill:end: -27357 # . restore registers -27358 5a/pop-to-edx -27359 59/pop-to-ecx -27360 58/pop-to-eax -27361 # . epilogue -27362 89/<- %esp 5/r32/ebp -27363 5d/pop-to-ebp -27364 c3/return -27365 -27366 $push-output-and-maybe-emit-spill:abort: -27367 # error("var '" var->name "' initialized from an instruction must live in a register\n") -27368 (write-buffered *(ebp+0x1c) "var '") -27369 (write-buffered *(ebp+0x1c) *eax) # Var-name -27370 (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n") -27371 (flush *(ebp+0x1c)) -27372 (stop *(ebp+0x20) 1) -27373 # never gets here -27374 -27375 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var) -27376 # . prologue -27377 55/push-ebp -27378 89/<- %ebp 4/r32/esp -27379 # . save registers -27380 50/push-eax -27381 51/push-ecx -27382 # ecx = stmt -27383 8b/-> *(ebp+0xc) 1/r32/ecx -27384 # var target/eax: (addr array byte) = curr-stmt->inouts->value->name -27385 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -27386 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -27387 (lookup *eax *(eax+4)) # Var-name Var-name => eax -27388 # clean up until target block -27389 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax) -27390 # emit jump to target block -27391 (emit-indent *(ebp+8) *Curr-block-depth) -27392 (write-buffered *(ebp+8) "e9/jump ") -27393 (write-buffered *(ebp+8) %eax) -27394 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax -27395 (string-starts-with? %eax "break") -27396 3d/compare-eax-and 0/imm32/false -27397 { -27398 74/jump-if-= break/disp8 -27399 (write-buffered *(ebp+8) ":break/disp32\n") -27400 eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8 -27401 } -27402 (write-buffered *(ebp+8) ":loop/disp32\n") -27403 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: -27404 # . restore registers -27405 59/pop-to-ecx -27406 58/pop-to-eax -27407 # . epilogue -27408 89/<- %esp 5/r32/ebp -27409 5d/pop-to-ebp -27410 c3/return -27411 -27412 emit-outputs: # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function) -27413 # . prologue -27414 55/push-ebp -27415 89/<- %ebp 4/r32/esp -27416 # . save registers -27417 50/push-eax -27418 51/push-ecx -27419 56/push-esi -27420 57/push-edi -27421 # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts -27422 8b/-> *(ebp+0xc) 0/r32/eax -27423 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -27424 89/<- %esi 0/r32/eax -27425 # var curr-output/edi: (addr list var) = fn->outputs -27426 8b/-> *(ebp+0x10) 0/r32/eax -27427 (lookup *(eax+0x10) *(eax+0x14)) # Function-outputs Function-outputs => eax -27428 89/<- %edi 0/r32/eax -27429 { -27430 $emit-outputs:loop: -27431 81 7/subop/compare %esi 0/imm32 -27432 0f 84/jump-if-= break/disp32 -27433 # emit copy to output register -27434 # var curr-output-register/ecx: (addr array byte) = curr-output->value->register -27435 (lookup *edi *(edi+4)) # List-value List-value => eax -27436 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -27437 89/<- %ecx 0/r32/eax -27438 # if curr-output-register starts with "x", emit a floating-point copy -27439 8a/copy-byte *(ecx+4) 0/r32/AL -27440 81 4/subop/and %eax 0xff/imm32 -27441 3d/compare-eax-and 0x78/imm32/x -27442 { -27443 75/jump-if-!= break/disp8 -27444 (emit-float-output *(ebp+8) %esi %ecx) -27445 eb/jump $emit-outputs:continue/disp8 -27446 } -27447 # otherwise emit an int copy -27448 (emit-int-output *(ebp+8) %esi %ecx) -27449 $emit-outputs:continue: -27450 # curr-inout = curr-inout->next -27451 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -27452 89/<- %esi 0/r32/eax -27453 # curr-output = curr-output->next -27454 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax -27455 89/<- %edi 0/r32/eax -27456 # -27457 e9/jump loop/disp32 -27458 } -27459 $emit-outputs:end: -27460 # . restore registers -27461 5f/pop-to-edi -27462 5e/pop-to-esi -27463 59/pop-to-ecx -27464 58/pop-to-eax -27465 # . epilogue -27466 89/<- %esp 5/r32/ebp -27467 5d/pop-to-ebp -27468 c3/return -27469 -27470 emit-int-output: # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte) -27471 # . prologue -27472 55/push-ebp -27473 89/<- %ebp 4/r32/esp -27474 # . save registers -27475 50/push-eax -27476 51/push-ecx -27477 # ecx = return-var->value -27478 8b/-> *(ebp+0xc) 0/r32/eax -27479 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -27480 89/<- %ecx 0/r32/eax -27481 # if curr-var is a literal, emit copy of a literal to the output -27482 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -27483 (simple-mu-type? %eax 0) # literal => eax -27484 { -27485 3d/compare-eax-and 0/imm32/false -27486 0f 84/jump-if-= break/disp32 -27487 (emit-indent *(ebp+8) *Curr-block-depth) -27488 (write-buffered *(ebp+8) "c7 0/subop/copy %") -27489 (write-buffered *(ebp+8) *(ebp+0x10)) -27490 (write-buffered *(ebp+8) " ") -27491 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -27492 (write-buffered *(ebp+8) %eax) -27493 (write-buffered *(ebp+8) "/imm32\n") -27494 e9/jump $emit-int-output:end/disp32 -27495 } -27496 # otherwise emit an integer copy -27497 (emit-indent *(ebp+8) *Curr-block-depth) -27498 (write-buffered *(ebp+8) "8b/->") -27499 (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc)) -27500 (write-buffered *(ebp+8) " ") -27501 (get Mu-registers *(ebp+0x10) 0xc "Mu-registers") # => eax -27502 (write-int32-hex-buffered *(ebp+8) *eax) -27503 (write-buffered *(ebp+8) "/r32\n") -27504 $emit-int-output:end: -27505 # . restore registers -27506 59/pop-to-ecx -27507 58/pop-to-eax -27508 # . epilogue -27509 89/<- %esp 5/r32/ebp -27510 5d/pop-to-ebp -27511 c3/return -27512 -27513 emit-float-output: # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte) -27514 # . prologue -27515 55/push-ebp -27516 89/<- %ebp 4/r32/esp -27517 # . save registers -27518 50/push-eax -27519 # -27520 (emit-indent *(ebp+8) *Curr-block-depth) -27521 (write-buffered *(ebp+8) "f3 0f 10/->") -27522 (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc)) -27523 (write-buffered *(ebp+8) " ") -27524 (get Mu-registers *(ebp+0x10) 0xc "Mu-registers") # => eax -27525 (write-int32-hex-buffered *(ebp+8) *eax) -27526 (write-buffered *(ebp+8) "/x32\n") -27527 $emit-float-output:end: -27528 # . restore registers +26799 75/jump-if-!= break/disp8 +26800 b8/copy-to-eax 4/imm32 +26801 eb/jump $size-of-type-id:end/disp8 +26802 } +26803 # if t is a handle, return 8 +26804 3d/compare-eax-and 4/imm32/handle +26805 { +26806 75/jump-if-!= break/disp8 +26807 b8/copy-to-eax 8/imm32 +26808 eb/jump $size-of-type-id:end/disp8 # eax changes type from type-id to int +26809 } +26810 # if t is a slice, return 8 +26811 3d/compare-eax-and 0xc/imm32/slice +26812 { +26813 75/jump-if-!= break/disp8 +26814 b8/copy-to-eax 8/imm32 +26815 eb/jump $size-of-type-id:end/disp8 # eax changes type from type-id to int +26816 } +26817 # if t is a user-defined type, return its size +26818 # TODO: support non-atom type +26819 (find-typeinfo %eax %ecx) +26820 { +26821 81 7/subop/compare *ecx 0/imm32 +26822 74/jump-if-= break/disp8 +26823 $size-of-type-id:user-defined: +26824 (lookup *ecx *(ecx+4)) # => eax +26825 8b/-> *(eax+0xc) 0/r32/eax # Typeinfo-total-size-in-bytes +26826 eb/jump $size-of-type-id:end/disp8 +26827 } +26828 # otherwise return the word size +26829 b8/copy-to-eax 4/imm32 +26830 $size-of-type-id:end: +26831 # . reclaim locals +26832 81 0/subop/add %esp 8/imm32 +26833 # . restore registers +26834 59/pop-to-ecx +26835 # . epilogue +26836 89/<- %esp 5/r32/ebp +26837 5d/pop-to-ebp +26838 c3/return +26839 +26840 # Minor violation of our type system since it returns an addr. But we could +26841 # replace it with a handle some time. +26842 # Returns null if t is an atom. +26843 type-tail: # t: (addr type-tree) -> out/eax: (addr type-tree) +26844 # . prologue +26845 55/push-ebp +26846 89/<- %ebp 4/r32/esp +26847 # . save registers +26848 51/push-ecx +26849 # eax = 0 +26850 b8/copy-to-eax 0/imm32 +26851 # ecx = t +26852 8b/-> *(ebp+8) 1/r32/ecx +26853 $type-tail:check-atom: +26854 # if t->is-atom? return 0 +26855 81 7/subop/compare *ecx 0/imm32/false # Type-tree-is-atom +26856 0f 85/jump-if-!= $type-tail:end/disp32 +26857 # var tail = t->right +26858 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26859 89/<- %ecx 0/r32/eax +26860 $type-tail:check-singleton: +26861 # if (tail->right == 0) return tail->left +26862 { +26863 81 7/subop/compare *(ecx+0xc) 0/imm32 # Type-tree-right +26864 75/jump-if-!= break/disp8 +26865 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26866 e9/jump $type-tail:end/disp32 +26867 } +26868 # if tail->right->left is an array-capacity, return tail->left +26869 { +26870 $type-tail:check-array-capacity: +26871 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26872 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +26873 75/jump-if-!= break/disp8 +26874 $type-tail:check-array-capacity-1: +26875 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +26876 3d/compare-eax-and 0/imm32 +26877 74/jump-if-= break/disp8 +26878 $type-tail:check-array-capacity-2: +26879 (simple-mu-type? %eax 9) # array-capacity => eax +26880 3d/compare-eax-and 0/imm32/false +26881 74/jump-if-= break/disp8 +26882 $type-tail:array-capacity: +26883 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26884 eb/jump $type-tail:end/disp8 +26885 } +26886 $type-tail:check-compound-left: +26887 # if !tail->left->is-atom? return tail->left +26888 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26889 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +26890 74/jump-if-= $type-tail:end/disp8 +26891 $type-tail:return-tail: +26892 # return tail +26893 89/<- %eax 1/r32/ecx +26894 $type-tail:end: +26895 # . restore registers +26896 59/pop-to-ecx +26897 # . epilogue +26898 89/<- %esp 5/r32/ebp +26899 5d/pop-to-ebp +26900 c3/return +26901 +26902 type-equal?: # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean +26903 # . prologue +26904 55/push-ebp +26905 89/<- %ebp 4/r32/esp +26906 # . save registers +26907 51/push-ecx +26908 52/push-edx +26909 53/push-ebx +26910 # ecx = a +26911 8b/-> *(ebp+8) 1/r32/ecx +26912 # edx = b +26913 8b/-> *(ebp+0xc) 2/r32/edx +26914 $type-equal?:compare-addr: +26915 # if (a == b) return true +26916 8b/-> %ecx 0/r32/eax # Var-type +26917 39/compare %edx 0/r32/eax # Var-type +26918 b8/copy-to-eax 1/imm32/true +26919 0f 84/jump-if-= $type-equal?:end/disp32 +26920 $type-equal?:compare-null-a: +26921 # if (a == 0) return false +26922 b8/copy-to-eax 0/imm32/false +26923 81 7/subop/compare %ecx 0/imm32 +26924 0f 84/jump-if-= $type-equal?:end/disp32 +26925 $type-equal?:compare-null-b: +26926 # if (b == 0) return false +26927 81 7/subop/compare %edx 0/imm32 +26928 0f 84/jump-if-= $type-equal?:end/disp32 +26929 $type-equal?:compare-atom-state: +26930 # if (a->is-atom? != b->is-atom?) return false +26931 8b/-> *ecx 3/r32/ebx # Type-tree-is-atom +26932 39/compare *edx 3/r32/ebx # Type-tree-is-atom +26933 b8/copy-to-eax 0/imm32/false +26934 0f 85/jump-if-!= $type-equal?:end/disp32 +26935 # if a->is-atom? return (a->value == b->value) +26936 { +26937 $type-equal?:check-atom: +26938 81 7/subop/compare %ebx 0/imm32/false +26939 74/jump-if-= break/disp8 +26940 $type-equal?:is-atom: +26941 8b/-> *(ecx+4) 0/r32/eax # Type-tree-value +26942 39/compare *(edx+4) 0/r32/eax # Type-tree-value +26943 0f 94/set-if-= %al +26944 25/and-eax-with 0xff/imm32 +26945 e9/jump $type-equal?:end/disp32 +26946 } +26947 $type-equal?:check-left: +26948 # if (!type-equal?(a->left, b->left)) return false +26949 (lookup *(ecx+4) *(ecx+8)) # Type-tree-left Type-tree-left => eax +26950 89/<- %ebx 0/r32/eax +26951 (lookup *(edx+4) *(edx+8)) # Type-tree-left Type-tree-left => eax +26952 (type-equal? %eax %ebx) # => eax +26953 3d/compare-eax-and 0/imm32/false +26954 74/jump-if-= $type-equal?:end/disp8 +26955 $type-equal?:check-right: +26956 # return type-equal?(a->right, b->right) +26957 (lookup *(ecx+0xc) *(ecx+0x10)) # Type-tree-right Type-tree-right => eax +26958 89/<- %ebx 0/r32/eax +26959 (lookup *(edx+0xc) *(edx+0x10)) # Type-tree-right Type-tree-right => eax +26960 (type-equal? %eax %ebx) # => eax +26961 $type-equal?:end: +26962 # . restore registers +26963 5b/pop-to-ebx +26964 5a/pop-to-edx +26965 59/pop-to-ecx +26966 # . epilogue +26967 89/<- %esp 5/r32/ebp +26968 5d/pop-to-ebp +26969 c3/return +26970 +26971 ####################################################### +26972 # Code-generation +26973 ####################################################### +26974 +26975 == data +26976 +26977 # Global state added to each var record when performing code-generation. +26978 Curr-local-stack-offset: # (addr int) +26979 0/imm32 +26980 +26981 == code +26982 +26983 # We may not need to pass err/ed everywhere here. I think they're relics of Mu +26984 # getting type checks later in life. +26985 # But we do need them for runtime checks, particularly array index bounds checks. +26986 # So perhaps it's not worth taking them out. They're a safety net. +26987 +26988 emit-subx: # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) +26989 # . prologue +26990 55/push-ebp +26991 89/<- %ebp 4/r32/esp +26992 # . save registers +26993 50/push-eax +26994 # var curr/eax: (addr function) = *Program->functions +26995 (lookup *_Program-functions *_Program-functions->payload) # => eax +26996 { +26997 # if (curr == null) break +26998 3d/compare-eax-and 0/imm32 +26999 0f 84/jump-if-= break/disp32 +27000 (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10)) +27001 # curr = lookup(curr->next) +27002 (lookup *(eax+0x20) *(eax+0x24)) # Function-next Function-next => eax +27003 e9/jump loop/disp32 +27004 } +27005 $emit-subx:end: +27006 # . restore registers +27007 58/pop-to-eax +27008 # . epilogue +27009 89/<- %esp 5/r32/ebp +27010 5d/pop-to-ebp +27011 c3/return +27012 +27013 emit-subx-function: # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +27014 # . prologue +27015 55/push-ebp +27016 89/<- %ebp 4/r32/esp +27017 # some preprocessing +27018 (populate-mu-type-offsets-in-inouts *(ebp+0xc)) +27019 # . save registers +27020 50/push-eax +27021 51/push-ecx +27022 52/push-edx +27023 # initialize some global state +27024 c7 0/subop/copy *Curr-block-depth 1/imm32 # Important: keep this in sync with the parse phase +27025 c7 0/subop/copy *Curr-local-stack-offset 0/imm32 +27026 # ecx = f +27027 8b/-> *(ebp+0xc) 1/r32/ecx +27028 # var vars/edx: (stack (addr var) 256) +27029 81 5/subop/subtract %esp 0xc00/imm32 +27030 68/push 0xc00/imm32/size +27031 68/push 0/imm32/top +27032 89/<- %edx 4/r32/esp +27033 # var name/eax: (addr array byte) = lookup(f->name) +27034 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax +27035 # +27036 (write-buffered *(ebp+8) %eax) +27037 (write-buffered *(ebp+8) ":\n") +27038 (emit-subx-prologue *(ebp+8)) +27039 # var body/eax: (addr block) = lookup(f->body) +27040 (lookup *(ecx+0x18) *(ecx+0x1c)) # Function-body Function-body => eax +27041 # +27042 (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) +27043 (emit-subx-epilogue *(ebp+8)) +27044 # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have +27045 # been cleaned up +27046 $emit-subx-function:end: +27047 # . reclaim locals +27048 81 0/subop/add %esp 0xc08/imm32 +27049 # . restore registers +27050 5a/pop-to-edx +27051 59/pop-to-ecx +27052 58/pop-to-eax +27053 # . epilogue +27054 89/<- %esp 5/r32/ebp +27055 5d/pop-to-ebp +27056 c3/return +27057 +27058 populate-mu-type-offsets-in-inouts: # f: (addr function) +27059 # . prologue +27060 55/push-ebp +27061 89/<- %ebp 4/r32/esp +27062 # . save registers +27063 50/push-eax +27064 51/push-ecx +27065 52/push-edx +27066 53/push-ebx +27067 57/push-edi +27068 # var next-offset/edx: int = 8 +27069 ba/copy-to-edx 8/imm32 +27070 # var curr/ecx: (addr list var) = lookup(f->inouts) +27071 8b/-> *(ebp+8) 1/r32/ecx +27072 (lookup *(ecx+8) *(ecx+0xc)) # Function-inouts Function-inouts => eax +27073 89/<- %ecx 0/r32/eax +27074 { +27075 $populate-mu-type-offsets-in-inouts:loop: +27076 81 7/subop/compare %ecx 0/imm32 +27077 74/jump-if-= break/disp8 +27078 # var v/ebx: (addr var) = lookup(curr->value) +27079 (lookup *ecx *(ecx+4)) # List-value List-value => eax +27080 89/<- %ebx 0/r32/eax +27081 #? (lookup *ebx *(ebx+4)) +27082 #? (write-buffered Stderr "setting offset of fn inout ") +27083 #? (write-buffered Stderr %eax) +27084 #? (write-buffered Stderr "@") +27085 #? (write-int32-hex-buffered Stderr %ebx) +27086 #? (write-buffered Stderr " to ") +27087 #? (write-int32-hex-buffered Stderr %edx) +27088 #? (write-buffered Stderr Newline) +27089 #? (flush Stderr) +27090 # v->offset = next-offset +27091 89/<- *(ebx+0x14) 2/r32/edx # Var-offset +27092 # next-offset += size-of(v) +27093 (size-of %ebx) # => eax +27094 01/add-to %edx 0/r32/eax +27095 # curr = lookup(curr->next) +27096 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +27097 89/<- %ecx 0/r32/eax +27098 # +27099 eb/jump loop/disp8 +27100 } +27101 $populate-mu-type-offsets-in-inouts:end: +27102 # . restore registers +27103 5f/pop-to-edi +27104 5b/pop-to-ebx +27105 5a/pop-to-edx +27106 59/pop-to-ecx +27107 58/pop-to-eax +27108 # . epilogue +27109 89/<- %esp 5/r32/ebp +27110 5d/pop-to-ebp +27111 c3/return +27112 +27113 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +27114 # . prologue +27115 55/push-ebp +27116 89/<- %ebp 4/r32/esp +27117 # . save registers +27118 50/push-eax +27119 51/push-ecx +27120 53/push-ebx +27121 56/push-esi +27122 # esi = stmts +27123 8b/-> *(ebp+0xc) 6/r32/esi +27124 # +27125 { +27126 $emit-subx-stmt-list:loop: +27127 81 7/subop/compare %esi 0/imm32 +27128 0f 84/jump-if-= break/disp32 +27129 # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value) +27130 (lookup *esi *(esi+4)) # List-value List-value => eax +27131 89/<- %ecx 0/r32/eax +27132 { +27133 $emit-subx-stmt-list:check-for-block: +27134 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +27135 75/jump-if-!= break/disp8 +27136 $emit-subx-stmt-list:block: +27137 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +27138 } +27139 { +27140 $emit-subx-stmt-list:check-for-stmt: +27141 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +27142 0f 85/jump-if-!= break/disp32 +27143 $emit-subx-stmt-list:stmt1: +27144 { +27145 (mu-branch? %ecx) # => eax +27146 3d/compare-eax-and 0/imm32/false +27147 0f 84/jump-if-= break/disp32 +27148 $emit-subx-stmt-list:branch-stmt: +27149 +-- 25 lines: # unconditional return ---------------------------------------------------------------------------------------------------------------------------------------------------- +27174 +-- 27 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- +27201 +-- 16 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- +27217 +-- 38 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- +27255 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- +27274 } +27275 $emit-subx-stmt-list:1-to-1: +27276 (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +27277 e9/jump $emit-subx-stmt-list:continue/disp32 +27278 } +27279 { +27280 $emit-subx-stmt-list:check-for-var-def: +27281 81 7/subop/compare *ecx 2/imm32/var-def # Stmt-tag +27282 75/jump-if-!= break/disp8 +27283 $emit-subx-stmt-list:var-def: +27284 (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c)) +27285 (push *(ebp+0x10) *(ecx+4)) # Vardef-var +27286 (push *(ebp+0x10) *(ecx+8)) # Vardef-var +27287 (push *(ebp+0x10) 0) # Live-var-register-spilled = 0 for vars on the stack +27288 # +27289 eb/jump $emit-subx-stmt-list:continue/disp8 +27290 } +27291 { +27292 $emit-subx-stmt-list:check-for-reg-var-def: +27293 81 7/subop/compare *ecx 3/imm32/reg-var-def # Stmt-tag +27294 0f 85/jump-if-!= break/disp32 +27295 $emit-subx-stmt-list:reg-var-def: +27296 # TODO: ensure that there's exactly one output +27297 (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +27298 # emit the instruction as usual +27299 (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +27300 # +27301 eb/jump $emit-subx-stmt-list:continue/disp8 +27302 } +27303 $emit-subx-stmt-list:continue: +27304 # TODO: raise an error on unrecognized Stmt-tag +27305 (lookup *(esi+8) *(esi+0xc)) # List-next List-next => eax +27306 89/<- %esi 0/r32/eax +27307 e9/jump loop/disp32 +27308 } +27309 $emit-subx-stmt-list:emit-cleanup: +27310 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) +27311 $emit-subx-stmt-list:clean-up: +27312 (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth) +27313 (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14)) +27314 $emit-subx-stmt-list:end: +27315 # . restore registers +27316 5e/pop-to-esi +27317 5b/pop-to-ebx +27318 59/pop-to-ecx +27319 58/pop-to-eax +27320 # . epilogue +27321 89/<- %esp 5/r32/ebp +27322 5d/pop-to-ebp +27323 c3/return +27324 +27325 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs. +27326 push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +27327 # . prologue +27328 55/push-ebp +27329 89/<- %ebp 4/r32/esp +27330 # . save registers +27331 50/push-eax +27332 51/push-ecx +27333 52/push-edx +27334 # ecx = stmt +27335 8b/-> *(ebp+0xc) 1/r32/ecx +27336 # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs) +27337 (lookup *(ecx+0x14) *(ecx+0x18)) # Regvardef-outputs Regvardef-outputs => eax +27338 # TODO: assert !sv->is-deref? +27339 # var v/ecx: (addr var) = lookup(sv->value) +27340 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +27341 89/<- %ecx 0/r32/eax +27342 # v->block-depth = *Curr-block-depth +27343 8b/-> *Curr-block-depth 0/r32/eax +27344 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth +27345 #? (write-buffered Stderr "var ") +27346 #? (lookup *ecx *(ecx+4)) +27347 #? (write-buffered Stderr %eax) +27348 #? (write-buffered Stderr " at depth ") +27349 #? (write-int32-hex-buffered Stderr *(ecx+0x10)) +27350 #? (write-buffered Stderr Newline) +27351 #? (flush Stderr) +27352 # ensure that v is in a register +27353 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register +27354 0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32 +27355 # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn) +27356 (not-yet-spilled-this-block? %ecx *(ebp+0x10)) # => eax +27357 89/<- %edx 0/r32/eax +27358 3d/compare-eax-and 0/imm32/false +27359 0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32 +27360 (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18)) # => eax +27361 89/<- %edx 0/r32/eax +27362 # check emit-spill? +27363 3d/compare-eax-and 0/imm32/false +27364 0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32 +27365 # TODO: assert(size-of(output) == 4) +27366 # *Curr-local-stack-offset -= 4 +27367 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 +27368 # emit spill +27369 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax +27370 (emit-push-register *(ebp+8) %eax) +27371 $push-output-and-maybe-emit-spill:push: +27372 8b/-> *(ebp+0xc) 1/r32/ecx +27373 (lookup *(ecx+0x14) *(ecx+0x18)) # Regvardef-outputs Regvardef-outputs => eax +27374 # push(vars, {sv->value, emit-spill?}) +27375 (push *(ebp+0x10) *eax) # Stmt-var-value +27376 (push *(ebp+0x10) *(eax+4)) # Stmt-var-value +27377 (push *(ebp+0x10) %edx) +27378 $push-output-and-maybe-emit-spill:end: +27379 # . restore registers +27380 5a/pop-to-edx +27381 59/pop-to-ecx +27382 58/pop-to-eax +27383 # . epilogue +27384 89/<- %esp 5/r32/ebp +27385 5d/pop-to-ebp +27386 c3/return +27387 +27388 $push-output-and-maybe-emit-spill:abort: +27389 # error("var '" var->name "' initialized from an instruction must live in a register\n") +27390 (write-buffered *(ebp+0x1c) "var '") +27391 (write-buffered *(ebp+0x1c) *eax) # Var-name +27392 (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n") +27393 (flush *(ebp+0x1c)) +27394 (stop *(ebp+0x20) 1) +27395 # never gets here +27396 +27397 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var) +27398 # . prologue +27399 55/push-ebp +27400 89/<- %ebp 4/r32/esp +27401 # . save registers +27402 50/push-eax +27403 51/push-ecx +27404 # ecx = stmt +27405 8b/-> *(ebp+0xc) 1/r32/ecx +27406 # var target/eax: (addr array byte) = curr-stmt->inouts->value->name +27407 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +27408 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +27409 (lookup *eax *(eax+4)) # Var-name Var-name => eax +27410 # clean up until target block +27411 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax) +27412 # emit jump to target block +27413 (emit-indent *(ebp+8) *Curr-block-depth) +27414 (write-buffered *(ebp+8) "e9/jump ") +27415 (write-buffered *(ebp+8) %eax) +27416 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax +27417 (string-starts-with? %eax "break") +27418 3d/compare-eax-and 0/imm32/false +27419 { +27420 74/jump-if-= break/disp8 +27421 (write-buffered *(ebp+8) ":break/disp32\n") +27422 eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8 +27423 } +27424 (write-buffered *(ebp+8) ":loop/disp32\n") +27425 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: +27426 # . restore registers +27427 59/pop-to-ecx +27428 58/pop-to-eax +27429 # . epilogue +27430 89/<- %esp 5/r32/ebp +27431 5d/pop-to-ebp +27432 c3/return +27433 +27434 emit-outputs: # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function) +27435 # . prologue +27436 55/push-ebp +27437 89/<- %ebp 4/r32/esp +27438 # . save registers +27439 50/push-eax +27440 51/push-ecx +27441 56/push-esi +27442 57/push-edi +27443 # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts +27444 8b/-> *(ebp+0xc) 0/r32/eax +27445 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +27446 89/<- %esi 0/r32/eax +27447 # var curr-output/edi: (addr list var) = fn->outputs +27448 8b/-> *(ebp+0x10) 0/r32/eax +27449 (lookup *(eax+0x10) *(eax+0x14)) # Function-outputs Function-outputs => eax +27450 89/<- %edi 0/r32/eax +27451 { +27452 $emit-outputs:loop: +27453 81 7/subop/compare %esi 0/imm32 +27454 0f 84/jump-if-= break/disp32 +27455 # emit copy to output register +27456 # var curr-output-register/ecx: (addr array byte) = curr-output->value->register +27457 (lookup *edi *(edi+4)) # List-value List-value => eax +27458 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +27459 89/<- %ecx 0/r32/eax +27460 # if curr-output-register starts with "x", emit a floating-point copy +27461 8a/copy-byte *(ecx+4) 0/r32/AL +27462 25/and-eax-with 0xff/imm32 +27463 3d/compare-eax-and 0x78/imm32/x +27464 { +27465 75/jump-if-!= break/disp8 +27466 (emit-float-output *(ebp+8) %esi %ecx) +27467 eb/jump $emit-outputs:continue/disp8 +27468 } +27469 # otherwise emit an int copy +27470 (emit-int-output *(ebp+8) %esi %ecx) +27471 $emit-outputs:continue: +27472 # curr-inout = curr-inout->next +27473 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +27474 89/<- %esi 0/r32/eax +27475 # curr-output = curr-output->next +27476 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax +27477 89/<- %edi 0/r32/eax +27478 # +27479 e9/jump loop/disp32 +27480 } +27481 $emit-outputs:end: +27482 # . restore registers +27483 5f/pop-to-edi +27484 5e/pop-to-esi +27485 59/pop-to-ecx +27486 58/pop-to-eax +27487 # . epilogue +27488 89/<- %esp 5/r32/ebp +27489 5d/pop-to-ebp +27490 c3/return +27491 +27492 emit-int-output: # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte) +27493 # . prologue +27494 55/push-ebp +27495 89/<- %ebp 4/r32/esp +27496 # . save registers +27497 50/push-eax +27498 51/push-ecx +27499 # ecx = return-var->value +27500 8b/-> *(ebp+0xc) 0/r32/eax +27501 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +27502 89/<- %ecx 0/r32/eax +27503 # if curr-var is a literal, emit copy of a literal to the output +27504 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +27505 (simple-mu-type? %eax 0) # literal => eax +27506 { +27507 3d/compare-eax-and 0/imm32/false +27508 0f 84/jump-if-= break/disp32 +27509 (emit-indent *(ebp+8) *Curr-block-depth) +27510 (write-buffered *(ebp+8) "c7 0/subop/copy %") +27511 (write-buffered *(ebp+8) *(ebp+0x10)) +27512 (write-buffered *(ebp+8) " ") +27513 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +27514 (write-buffered *(ebp+8) %eax) +27515 (write-buffered *(ebp+8) "/imm32\n") +27516 e9/jump $emit-int-output:end/disp32 +27517 } +27518 # otherwise emit an integer copy +27519 (emit-indent *(ebp+8) *Curr-block-depth) +27520 (write-buffered *(ebp+8) "8b/->") +27521 (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc)) +27522 (write-buffered *(ebp+8) " ") +27523 (get Mu-registers *(ebp+0x10) 0xc "Mu-registers") # => eax +27524 (write-int32-hex-buffered *(ebp+8) *eax) +27525 (write-buffered *(ebp+8) "/r32\n") +27526 $emit-int-output:end: +27527 # . restore registers +27528 59/pop-to-ecx 27529 58/pop-to-eax 27530 # . epilogue 27531 89/<- %esp 5/r32/ebp 27532 5d/pop-to-ebp 27533 c3/return 27534 -27535 mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean +27535 emit-float-output: # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte) 27536 # . prologue 27537 55/push-ebp 27538 89/<- %ebp 4/r32/esp 27539 # . save registers -27540 51/push-ecx -27541 # ecx = lookup(stmt->operation) -27542 8b/-> *(ebp+8) 1/r32/ecx -27543 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax -27544 89/<- %ecx 0/r32/eax -27545 # if (stmt->operation starts with "loop") return true -27546 (string-starts-with? %ecx "loop") # => eax -27547 3d/compare-eax-and 0/imm32/false -27548 75/jump-if-not-equal $mu-branch?:end/disp8 -27549 # if (stmt->operation starts with "break") return true -27550 (string-starts-with? %ecx "break") # => eax -27551 3d/compare-eax-and 0/imm32/false -27552 75/jump-if-not-equal $mu-branch?:end/disp8 -27553 # otherwise return (stmt->operation starts with "return") -27554 (string-starts-with? %ecx "return") # => eax -27555 $mu-branch?:end: -27556 # . restore registers -27557 59/pop-to-ecx -27558 # . epilogue -27559 89/<- %esp 5/r32/ebp -27560 5d/pop-to-ebp -27561 c3/return -27562 -27563 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) -27564 # . prologue -27565 55/push-ebp -27566 89/<- %ebp 4/r32/esp -27567 # . save registers -27568 50/push-eax -27569 # eax = stmt -27570 8b/-> *(ebp+0xc) 0/r32/eax -27571 # -27572 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -27573 (get Reverse-branch %eax 0x10 "reverse-branch: ") # => eax: (addr handle array byte) -27574 (emit-indent *(ebp+8) *Curr-block-depth) -27575 (lookup *eax *(eax+4)) # => eax -27576 (write-buffered *(ebp+8) %eax) -27577 (write-buffered *(ebp+8) " break/disp32\n") -27578 $emit-reverse-break:end: -27579 # . restore registers -27580 58/pop-to-eax -27581 # . epilogue -27582 89/<- %esp 5/r32/ebp -27583 5d/pop-to-ebp -27584 c3/return -27585 -27586 == data -27587 -27588 # Table from Mu branch instructions to the reverse SubX opcodes for them. -27589 Reverse-branch: # (table (handle array byte) (handle array byte)) -27590 # a table is a stream -27591 0x1c0/imm32/write -27592 0/imm32/read -27593 0x1c0/imm32/size -27594 # data -27595 0x11/imm32/alloc-id _string-break-if-=/imm32 0x11/imm32/alloc-id _string_0f_85_jump_label/imm32 -27596 0x11/imm32/alloc-id _string-loop-if-=/imm32 0x11/imm32/alloc-id _string_0f_85_jump_label/imm32 -27597 0x11/imm32/alloc-id _string-break-if-!=/imm32 0x11/imm32/alloc-id _string_0f_84_jump_label/imm32 -27598 0x11/imm32/alloc-id _string-loop-if-!=/imm32 0x11/imm32/alloc-id _string_0f_84_jump_label/imm32 -27599 0x11/imm32/alloc-id _string-break-if-</imm32 0x11/imm32/alloc-id _string_0f_8d_jump_label/imm32 -27600 0x11/imm32/alloc-id _string-loop-if-</imm32 0x11/imm32/alloc-id _string_0f_8d_jump_label/imm32 -27601 0x11/imm32/alloc-id _string-break-if->/imm32 0x11/imm32/alloc-id _string_0f_8e_jump_label/imm32 -27602 0x11/imm32/alloc-id _string-loop-if->/imm32 0x11/imm32/alloc-id _string_0f_8e_jump_label/imm32 -27603 0x11/imm32/alloc-id _string-break-if-<=/imm32 0x11/imm32/alloc-id _string_0f_8f_jump_label/imm32 -27604 0x11/imm32/alloc-id _string-loop-if-<=/imm32 0x11/imm32/alloc-id _string_0f_8f_jump_label/imm32 -27605 0x11/imm32/alloc-id _string-break-if->=/imm32 0x11/imm32/alloc-id _string_0f_8c_jump_label/imm32 -27606 0x11/imm32/alloc-id _string-loop-if->=/imm32 0x11/imm32/alloc-id _string_0f_8c_jump_label/imm32 -27607 0x11/imm32/alloc-id _string-break-if-addr</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 -27608 0x11/imm32/alloc-id _string-loop-if-addr</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 -27609 0x11/imm32/alloc-id _string-break-if-addr>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 -27610 0x11/imm32/alloc-id _string-loop-if-addr>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 -27611 0x11/imm32/alloc-id _string-break-if-addr<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 -27612 0x11/imm32/alloc-id _string-loop-if-addr<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 -27613 0x11/imm32/alloc-id _string-break-if-addr>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 -27614 0x11/imm32/alloc-id _string-loop-if-addr>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 -27615 0x11/imm32/alloc-id _string-break-if-float</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 -27616 0x11/imm32/alloc-id _string-loop-if-float</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 -27617 0x11/imm32/alloc-id _string-break-if-float>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 -27618 0x11/imm32/alloc-id _string-loop-if-float>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 -27619 0x11/imm32/alloc-id _string-break-if-float<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 -27620 0x11/imm32/alloc-id _string-loop-if-float<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 -27621 0x11/imm32/alloc-id _string-break-if-float>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 -27622 0x11/imm32/alloc-id _string-loop-if-float>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 -27623 -27624 == code -27625 -27626 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte) -27627 # . prologue -27628 55/push-ebp -27629 89/<- %ebp 4/r32/esp -27630 # . save registers -27631 50/push-eax -27632 51/push-ecx -27633 52/push-edx -27634 53/push-ebx -27635 56/push-esi -27636 # ecx = vars -27637 8b/-> *(ebp+0xc) 1/r32/ecx -27638 # var eax: int = vars->top -27639 8b/-> *ecx 0/r32/eax -27640 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] -27641 8d/copy-address *(ecx+eax-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size -27642 # var min/ecx: (addr handle var) = vars->data -27643 8d/copy-address *(ecx+8) 1/r32/ecx -27644 # edx = depth -27645 8b/-> *(ebp+0x10) 2/r32/edx -27646 { -27647 $emit-unconditional-jump-to-depth:loop: -27648 # if (curr < min) break -27649 39/compare %esi 1/r32/ecx -27650 0f 82/jump-if-addr< break/disp32 -27651 # var v/ebx: (addr var) = lookup(*curr) -27652 (lookup *esi *(esi+4)) # => eax -27653 89/<- %ebx 0/r32/eax -27654 # if (v->block-depth < until-block-depth) break -27655 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth -27656 0f 8c/jump-if-< break/disp32 -27657 { -27658 $emit-unconditional-jump-to-depth:check: -27659 # if v->block-depth != until-block-depth, continue -27660 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth -27661 0f 85/jump-if-!= break/disp32 -27662 $emit-unconditional-jump-to-depth:depth-found: -27663 # if v is not a literal, continue -27664 (size-of %ebx) # => eax -27665 3d/compare-eax-and 0/imm32 -27666 0f 85/jump-if-!= break/disp32 -27667 $emit-unconditional-jump-to-depth:label-found: -27668 # emit unconditional jump, then return -27669 (emit-indent *(ebp+8) *Curr-block-depth) -27670 (write-buffered *(ebp+8) "e9/jump ") -27671 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -27672 (write-buffered *(ebp+8) %eax) -27673 (write-buffered *(ebp+8) ":") -27674 (write-buffered *(ebp+8) *(ebp+0x14)) -27675 (write-buffered *(ebp+8) "/disp32\n") -27676 eb/jump $emit-unconditional-jump-to-depth:end/disp8 -27677 } -27678 # curr -= 12 -27679 81 5/subop/subtract %esi 0xc/imm32 -27680 e9/jump loop/disp32 -27681 } -27682 # TODO: error if no label at 'depth' was found -27683 $emit-unconditional-jump-to-depth:end: -27684 # . restore registers -27685 5e/pop-to-esi -27686 5b/pop-to-ebx -27687 5a/pop-to-edx -27688 59/pop-to-ecx -27689 58/pop-to-eax -27690 # . epilogue -27691 89/<- %esp 5/r32/ebp -27692 5d/pop-to-ebp -27693 c3/return -27694 -27695 # emit clean-up code for 'vars' until some block depth -27696 # doesn't actually modify 'vars' so we need traverse manually inside the stack -27697 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int -27698 # . prologue -27699 55/push-ebp -27700 89/<- %ebp 4/r32/esp -27701 # . save registers -27702 50/push-eax -27703 51/push-ecx -27704 52/push-edx -27705 53/push-ebx -27706 56/push-esi -27707 #? (write-buffered Stderr "--- cleanup\n") -27708 #? (flush Stderr) -27709 # ecx = vars -27710 8b/-> *(ebp+0xc) 1/r32/ecx -27711 # var esi: int = vars->top -27712 8b/-> *ecx 6/r32/esi -27713 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] -27714 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size -27715 # var min/ecx: (addr handle var) = vars->data -27716 81 0/subop/add %ecx 8/imm32 -27717 # edx = until-block-depth -27718 8b/-> *(ebp+0x10) 2/r32/edx -27719 { -27720 $emit-cleanup-code-until-depth:loop: -27721 # if (curr < min) break -27722 39/compare %esi 1/r32/ecx -27723 0f 82/jump-if-addr< break/disp32 -27724 # var v/ebx: (addr var) = lookup(*curr) -27725 (lookup *esi *(esi+4)) # => eax -27726 89/<- %ebx 0/r32/eax -27727 #? (lookup *ebx *(ebx+4)) # Var-name -27728 #? (write-buffered Stderr "var ") -27729 #? (write-buffered Stderr %eax) -27730 #? (write-buffered Stderr Newline) -27731 #? (flush Stderr) -27732 # if (v->block-depth < until-block-depth) break -27733 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth -27734 0f 8c/jump-if-< break/disp32 -27735 # if v is in a register -27736 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register -27737 { -27738 0f 84/jump-if-= break/disp32 -27739 { -27740 $emit-cleanup-code-until-depth:check-for-previous-spill: -27741 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled -27742 3d/compare-eax-and 0/imm32/false -27743 74/jump-if-= break/disp8 -27744 $emit-cleanup-code-until-depth:reclaim-var-in-register: -27745 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -27746 (emit-pop-register *(ebp+8) %eax) -27747 } -27748 eb/jump $emit-cleanup-code-until-depth:continue/disp8 -27749 } -27750 # otherwise v is on the stack -27751 { -27752 75/jump-if-!= break/disp8 -27753 $emit-cleanup-code-until-depth:var-on-stack: -27754 (size-of %ebx) # => eax -27755 # don't emit code for labels -27756 3d/compare-eax-and 0/imm32 -27757 74/jump-if-= break/disp8 -27758 $emit-cleanup-code-until-depth:reclaim-var-on-stack: -27759 (emit-indent *(ebp+8) *Curr-block-depth) -27760 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -27761 (write-int32-hex-buffered *(ebp+8) %eax) -27762 (write-buffered *(ebp+8) "/imm32\n") -27763 } -27764 $emit-cleanup-code-until-depth:continue: -27765 # curr -= 12 -27766 81 5/subop/subtract %esi 0xc/imm32 -27767 e9/jump loop/disp32 -27768 } -27769 $emit-cleanup-code-until-depth:end: -27770 # . restore registers -27771 5e/pop-to-esi -27772 5b/pop-to-ebx -27773 5a/pop-to-edx -27774 59/pop-to-ecx -27775 58/pop-to-eax -27776 # . epilogue -27777 89/<- %esp 5/r32/ebp -27778 5d/pop-to-ebp -27779 c3/return -27780 -27781 # emit clean-up code for 'vars' that don't conflict with output registers -27782 # doesn't actually modify 'vars' so we need traverse manually inside the stack -27783 emit-cleanup-code-for-non-outputs: # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function) -27784 # . prologue -27785 55/push-ebp -27786 89/<- %ebp 4/r32/esp -27787 # . save registers -27788 50/push-eax -27789 51/push-ecx -27790 52/push-edx -27791 53/push-ebx -27792 56/push-esi -27793 57/push-edi -27794 # ecx = vars -27795 8b/-> *(ebp+0xc) 1/r32/ecx -27796 # var esi: int = vars->top -27797 8b/-> *ecx 6/r32/esi -27798 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] -27799 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size -27800 # var min/ecx: (addr handle var) = vars->data -27801 81 0/subop/add %ecx 8/imm32 -27802 { -27803 $emit-cleanup-code-for-non-outputs:loop: -27804 # if (curr < min) break -27805 39/compare %esi 1/r32/ecx -27806 0f 82/jump-if-addr< break/disp32 -27807 # var v/ebx: (addr var) = lookup(*curr) -27808 (lookup *esi *(esi+4)) # => eax -27809 89/<- %ebx 0/r32/eax -27810 # if v is in a register -27811 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register -27812 { -27813 0f 84/jump-if-= break/disp32 -27814 { -27815 $emit-cleanup-code-for-non-outputs:check-for-previous-spill: -27816 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled -27817 3d/compare-eax-and 0/imm32/false -27818 0f 84/jump-if-= break/disp32 -27819 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register: -27820 # var reg/edi: (addr array name) = v->register -27821 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -27822 89/<- %edi 0/r32/eax -27823 # if reg is not in function outputs, emit a pop -27824 (reg-in-function-outputs? *(ebp+0x10) %edi) # => eax -27825 3d/compare-eax-and 0/imm32/false -27826 { -27827 75/jump-if-!= break/disp8 -27828 (emit-pop-register *(ebp+8) %edi) -27829 eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8 -27830 } -27831 # otherwise just drop it from the stack -27832 (emit-indent *(ebp+8) *Curr-block-depth) -27833 (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n") -27834 } -27835 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done: -27836 eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8 -27837 } -27838 # otherwise v is on the stack -27839 { -27840 75/jump-if-!= break/disp8 -27841 $emit-cleanup-code-for-non-outputs:var-on-stack: -27842 (size-of %ebx) # => eax -27843 # don't emit code for labels -27844 3d/compare-eax-and 0/imm32 -27845 74/jump-if-= break/disp8 -27846 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack: -27847 (emit-indent *(ebp+8) *Curr-block-depth) -27848 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -27849 (write-int32-hex-buffered *(ebp+8) %eax) -27850 (write-buffered *(ebp+8) "/imm32\n") -27851 } -27852 $emit-cleanup-code-for-non-outputs:continue: -27853 # curr -= 12 -27854 81 5/subop/subtract %esi 0xc/imm32 -27855 e9/jump loop/disp32 -27856 } -27857 $emit-cleanup-code-for-non-outputs:end: -27858 # . restore registers -27859 5f/pop-to-edi -27860 5e/pop-to-esi -27861 5b/pop-to-ebx -27862 5a/pop-to-edx -27863 59/pop-to-ecx -27864 58/pop-to-eax -27865 # . epilogue -27866 89/<- %esp 5/r32/ebp -27867 5d/pop-to-ebp -27868 c3/return -27869 -27870 emit-push-register: # out: (addr buffered-file), reg: (addr array byte) -27871 # . prologue -27872 55/push-ebp -27873 89/<- %ebp 4/r32/esp -27874 # eax = reg -27875 8b/-> *(ebp+0xc) 0/r32/eax -27876 # var prefix/eax: byte = reg->data[0] -27877 8a/copy-byte *(eax+4) 0/r32/AL -27878 81 4/subop/and %eax 0xff/imm32 -27879 # if (prefix == 'x') push xmm register -27880 { -27881 3d/compare-eax-and 0x78/imm32/x -27882 0f 85/jump-if-!= break/disp32 -27883 # TODO validate register -27884 (emit-indent *(ebp+8) *Curr-block-depth) -27885 (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n") -27886 (emit-indent *(ebp+8) *Curr-block-depth) -27887 (write-buffered *(ebp+8) "f3 0f 11/<- *esp ") -27888 # var prefix/eax: byte = reg->data[3] -27889 8b/-> *(ebp+0xc) 0/r32/eax -27890 8a/copy-byte *(eax+7) 0/r32/AL -27891 81 4/subop/and %eax 0xff/imm32 -27892 (write-byte-buffered *(ebp+8) %eax) -27893 (write-buffered *(ebp+8) "/x32\n") -27894 e9/jump $emit-push-register:end/disp32 -27895 } -27896 # otherwise push gp register -27897 (emit-indent *(ebp+8) *Curr-block-depth) -27898 (write-buffered *(ebp+8) "ff 6/subop/push %") -27899 (write-buffered *(ebp+8) *(ebp+0xc)) -27900 (write-buffered *(ebp+8) Newline) -27901 $emit-push-register:end: -27902 # . epilogue -27903 89/<- %esp 5/r32/ebp -27904 5d/pop-to-ebp -27905 c3/return -27906 -27907 emit-pop-register: # out: (addr buffered-file), reg: (addr array byte) -27908 # . prologue -27909 55/push-ebp -27910 89/<- %ebp 4/r32/esp -27911 # . save registers -27912 50/push-eax -27913 # eax = reg -27914 8b/-> *(ebp+0xc) 0/r32/eax -27915 # var prefix/eax: byte = reg->data[0] -27916 8a/copy-byte *(eax+4) 0/r32/AL -27917 81 4/subop/and %eax 0xff/imm32 -27918 # if (prefix == 'x') pop to xmm register -27919 { -27920 3d/compare-eax-and 0x78/imm32/x -27921 0f 85/jump-if-!= break/disp32 -27922 # TODO validate register -27923 (emit-indent *(ebp+8) *Curr-block-depth) -27924 (write-buffered *(ebp+8) "f3 0f 10/-> *esp ") -27925 # var prefix/eax: byte = reg->data[3] -27926 8b/-> *(ebp+0xc) 0/r32/eax -27927 8a/copy-byte *(eax+7) 0/r32/AL -27928 81 4/subop/and %eax 0xff/imm32 -27929 (write-byte-buffered *(ebp+8) %eax) -27930 (write-buffered *(ebp+8) "/x32\n") -27931 (emit-indent *(ebp+8) *Curr-block-depth) -27932 (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n") -27933 e9/jump $emit-pop-register:end/disp32 -27934 } -27935 # otherwise pop to gp register -27936 (emit-indent *(ebp+8) *Curr-block-depth) -27937 (write-buffered *(ebp+8) "8f 0/subop/pop %") -27938 (write-buffered *(ebp+8) *(ebp+0xc)) -27939 (write-buffered *(ebp+8) Newline) -27940 $emit-pop-register:end: -27941 # . restore registers -27942 58/pop-to-eax -27943 # . epilogue -27944 89/<- %esp 5/r32/ebp -27945 5d/pop-to-ebp -27946 c3/return -27947 -27948 # emit clean-up code for 'vars' until a given label is encountered -27949 # doesn't actually modify 'vars' so we need traverse manually inside the stack -27950 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte) -27951 # . prologue -27952 55/push-ebp -27953 89/<- %ebp 4/r32/esp -27954 # . save registers -27955 50/push-eax -27956 51/push-ecx -27957 52/push-edx -27958 53/push-ebx -27959 # ecx = vars -27960 8b/-> *(ebp+0xc) 1/r32/ecx -27961 # var eax: int = vars->top -27962 8b/-> *ecx 0/r32/eax -27963 # var curr/edx: (addr handle var) = &vars->data[vars->top - 12] -27964 8d/copy-address *(ecx+eax-4) 2/r32/edx # vars + 8 + vars->top - 12/Live-var-size -27965 # var min/ecx: (addr handle var) = vars->data -27966 81 0/subop/add %ecx 8/imm32 -27967 { -27968 $emit-cleanup-code-until-target:loop: -27969 # if (curr < min) break -27970 39/compare %edx 1/r32/ecx -27971 0f 82/jump-if-addr< break/disp32 -27972 # var v/ebx: (handle var) = lookup(*curr) -27973 (lookup *edx *(edx+4)) # => eax -27974 89/<- %ebx 0/r32/eax -27975 # if (v->name == until-block-label) break -27976 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -27977 (string-equal? %eax *(ebp+0x10)) # => eax -27978 3d/compare-eax-and 0/imm32/false -27979 0f 85/jump-if-!= break/disp32 -27980 # if v is in a register -27981 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register -27982 { -27983 0f 84/jump-if-= break/disp32 -27984 { -27985 $emit-cleanup-code-until-target:check-for-previous-spill: -27986 8b/-> *(edx+8) 0/r32/eax # Live-var-register-spilled -27987 3d/compare-eax-and 0/imm32/false -27988 74/jump-if-= break/disp8 -27989 $emit-cleanup-code-until-target:reclaim-var-in-register: -27990 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -27991 (emit-pop-register *(ebp+8) %eax) -27992 } -27993 eb/jump $emit-cleanup-code-until-target:continue/disp8 -27994 } -27995 # otherwise v is on the stack -27996 { -27997 75/jump-if-!= break/disp8 -27998 $emit-cleanup-code-until-target:reclaim-var-on-stack: -27999 (size-of %ebx) # => eax -28000 # don't emit code for labels -28001 3d/compare-eax-and 0/imm32 -28002 74/jump-if-= break/disp8 -28003 # -28004 (emit-indent *(ebp+8) *Curr-block-depth) -28005 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -28006 (write-int32-hex-buffered *(ebp+8) %eax) -28007 (write-buffered *(ebp+8) "/imm32\n") -28008 } -28009 $emit-cleanup-code-until-target:continue: -28010 # curr -= 12 -28011 81 5/subop/subtract %edx 0xc/imm32 -28012 e9/jump loop/disp32 -28013 } -28014 $emit-cleanup-code-until-target:end: -28015 # . restore registers -28016 5b/pop-to-ebx -28017 5a/pop-to-edx -28018 59/pop-to-ecx -28019 58/pop-to-eax -28020 # . epilogue -28021 89/<- %esp 5/r32/ebp -28022 5d/pop-to-ebp -28023 c3/return -28024 -28025 # update Curr-local-stack-offset assuming vars until some block depth are popped -28026 # doesn't actually modify 'vars', so we need traverse manually inside the stack -28027 clean-up-stack-offset-state: # vars: (addr stack live-var), until-block-depth: int -28028 # . prologue -28029 55/push-ebp -28030 89/<- %ebp 4/r32/esp -28031 # . save registers -28032 50/push-eax -28033 51/push-ecx -28034 52/push-edx -28035 53/push-ebx -28036 56/push-esi -28037 # ecx = vars -28038 8b/-> *(ebp+8) 1/r32/ecx -28039 # var esi: int = vars->top -28040 8b/-> *ecx 6/r32/esi -28041 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] -28042 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size -28043 # var min/ecx: (addr handle var) = vars->data -28044 81 0/subop/add %ecx 8/imm32 -28045 # edx = until-block-depth -28046 8b/-> *(ebp+0xc) 2/r32/edx -28047 { -28048 $clean-up-stack-offset-state:loop: -28049 # if (curr < min) break -28050 39/compare %esi 1/r32/ecx -28051 0f 82/jump-if-addr< break/disp32 -28052 # var v/ebx: (addr var) = lookup(*curr) -28053 (lookup *esi *(esi+4)) # => eax -28054 89/<- %ebx 0/r32/eax -28055 # if (v->block-depth < until-block-depth) break -28056 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth -28057 0f 8c/jump-if-< break/disp32 -28058 # if v is in a register -28059 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register -28060 { -28061 0f 84/jump-if-= break/disp32 -28062 { -28063 $clean-up-stack-offset-state:check-for-previous-spill: -28064 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled -28065 3d/compare-eax-and 0/imm32/false -28066 74/jump-if-= break/disp8 -28067 $clean-up-stack-offset-state:reclaim-var-in-register: -28068 81 0/subop/add *Curr-local-stack-offset 4/imm32 -28069 } -28070 eb/jump $clean-up-stack-offset-state:continue/disp8 -28071 } -28072 # otherwise v is on the stack -28073 { -28074 75/jump-if-!= break/disp8 -28075 $clean-up-stack-offset-state:var-on-stack: -28076 (size-of %ebx) # => eax -28077 01/add-to *Curr-local-stack-offset 0/r32/eax -28078 } -28079 $clean-up-stack-offset-state:continue: -28080 # curr -= 12 -28081 81 5/subop/subtract %esi 0xc/imm32 -28082 e9/jump loop/disp32 -28083 } -28084 $clean-up-stack-offset-state:end: -28085 # . restore registers -28086 5e/pop-to-esi -28087 5b/pop-to-ebx -28088 5a/pop-to-edx -28089 59/pop-to-ecx -28090 58/pop-to-eax -28091 # . epilogue -28092 89/<- %esp 5/r32/ebp -28093 5d/pop-to-ebp -28094 c3/return -28095 -28096 # Return true if there isn't a variable in 'vars' with the same block-depth -28097 # and register as 'v'. -28098 # 'v' is guaranteed not to be within 'vars'. -28099 not-yet-spilled-this-block?: # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean -28100 # . prologue -28101 55/push-ebp -28102 89/<- %ebp 4/r32/esp -28103 # . save registers -28104 51/push-ecx -28105 52/push-edx -28106 53/push-ebx -28107 56/push-esi -28108 57/push-edi -28109 # ecx = vars -28110 8b/-> *(ebp+0xc) 1/r32/ecx -28111 # var eax: int = vars->top -28112 8b/-> *ecx 0/r32/eax -28113 # var curr/edx: (addr handle var) = &vars->data[vars->top - 12] -28114 8d/copy-address *(ecx+eax-4) 2/r32/edx # vars + 8 + vars->top - 12/Live-var-size -28115 # var min/ecx: (addr handle var) = vars->data -28116 8d/copy-address *(ecx+8) 1/r32/ecx -28117 # var depth/ebx: int = v->block-depth -28118 8b/-> *(ebp+8) 3/r32/ebx -28119 8b/-> *(ebx+0x10) 3/r32/ebx # Var-block-depth -28120 # var needle/esi: (addr array byte) = v->register -28121 8b/-> *(ebp+8) 6/r32/esi -28122 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax -28123 89/<- %esi 0/r32/eax -28124 { -28125 $not-yet-spilled-this-block?:loop: -28126 # if (curr < min) break -28127 39/compare %edx 1/r32/ecx -28128 0f 82/jump-if-addr< break/disp32 -28129 # var cand/edi: (addr var) = lookup(*curr) -28130 (lookup *edx *(edx+4)) # => eax -28131 89/<- %edi 0/r32/eax -28132 # if (cand->block-depth < depth) break -28133 39/compare *(edi+0x10) 3/r32/ebx # Var-block-depth -28134 0f 8c/jump-if-< break/disp32 -28135 # var cand-reg/edi: (array array byte) = cand->reg -28136 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax -28137 89/<- %edi 0/r32/eax -28138 # if (cand-reg == null) continue -28139 { -28140 $not-yet-spilled-this-block?:check-reg: -28141 81 7/subop/compare %edi 0/imm32 -28142 0f 84/jump-if-= break/disp32 -28143 # if (cand-reg == needle) return true -28144 (string-equal? %esi %edi) # => eax -28145 3d/compare-eax-and 0/imm32/false -28146 74/jump-if-= break/disp8 -28147 $not-yet-spilled-this-block?:return-false: -28148 b8/copy-to-eax 0/imm32/false -28149 eb/jump $not-yet-spilled-this-block?:end/disp8 -28150 } -28151 $not-yet-spilled-this-block?:continue: -28152 # curr -= 12 -28153 81 5/subop/subtract %edx 0xc/imm32 -28154 e9/jump loop/disp32 -28155 } -28156 $not-yet-spilled-this-block?:return-true: -28157 # return true -28158 b8/copy-to-eax 1/imm32/true -28159 $not-yet-spilled-this-block?:end: -28160 # . restore registers -28161 5f/pop-to-edi -28162 5e/pop-to-esi -28163 5b/pop-to-ebx -28164 5a/pop-to-edx -28165 59/pop-to-ecx -28166 # . epilogue -28167 89/<- %esp 5/r32/ebp -28168 5d/pop-to-ebp -28169 c3/return -28170 -28171 # could the register of 'v' ever be written to by one of the vars in fn-outputs? -28172 will-not-write-some-register?: # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean -28173 # . prologue -28174 55/push-ebp -28175 89/<- %ebp 4/r32/esp -28176 # eax = v -28177 8b/-> *(ebp+8) 0/r32/eax -28178 # var reg/eax: (addr array byte) = lookup(v->register) -28179 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28180 # var target/eax: (addr var) = find-register(fn-outputs, reg) -28181 (find-register *(ebp+0x10) %eax) # => eax -28182 # if (target == 0) return true -28183 { -28184 3d/compare-eax-and 0/imm32 -28185 75/jump-if-!= break/disp8 -28186 b8/copy-to-eax 1/imm32/true -28187 eb/jump $will-not-write-some-register?:end/disp8 -28188 } -28189 # return !assigns-in-stmts?(stmts, target) -28190 (assigns-in-stmts? *(ebp+0xc) %eax) # => eax -28191 3d/compare-eax-and 0/imm32/false -28192 # assume: true = 1, so no need to mask with 0x000000ff -28193 0f 94/set-if-= %al -28194 $will-not-write-some-register?:end: -28195 # . epilogue -28196 89/<- %esp 5/r32/ebp -28197 5d/pop-to-ebp -28198 c3/return -28199 -28200 # return fn output with matching register -28201 # always returns false if 'reg' is null -28202 find-register: # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var) +27540 50/push-eax +27541 # +27542 (emit-indent *(ebp+8) *Curr-block-depth) +27543 (write-buffered *(ebp+8) "f3 0f 10/->") +27544 (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc)) +27545 (write-buffered *(ebp+8) " ") +27546 (get Mu-registers *(ebp+0x10) 0xc "Mu-registers") # => eax +27547 (write-int32-hex-buffered *(ebp+8) *eax) +27548 (write-buffered *(ebp+8) "/x32\n") +27549 $emit-float-output:end: +27550 # . restore registers +27551 58/pop-to-eax +27552 # . epilogue +27553 89/<- %esp 5/r32/ebp +27554 5d/pop-to-ebp +27555 c3/return +27556 +27557 mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean +27558 # . prologue +27559 55/push-ebp +27560 89/<- %ebp 4/r32/esp +27561 # . save registers +27562 51/push-ecx +27563 # ecx = lookup(stmt->operation) +27564 8b/-> *(ebp+8) 1/r32/ecx +27565 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax +27566 89/<- %ecx 0/r32/eax +27567 # if (stmt->operation starts with "loop") return true +27568 (string-starts-with? %ecx "loop") # => eax +27569 3d/compare-eax-and 0/imm32/false +27570 75/jump-if-not-equal $mu-branch?:end/disp8 +27571 # if (stmt->operation starts with "break") return true +27572 (string-starts-with? %ecx "break") # => eax +27573 3d/compare-eax-and 0/imm32/false +27574 75/jump-if-not-equal $mu-branch?:end/disp8 +27575 # otherwise return (stmt->operation starts with "return") +27576 (string-starts-with? %ecx "return") # => eax +27577 $mu-branch?:end: +27578 # . restore registers +27579 59/pop-to-ecx +27580 # . epilogue +27581 89/<- %esp 5/r32/ebp +27582 5d/pop-to-ebp +27583 c3/return +27584 +27585 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) +27586 # . prologue +27587 55/push-ebp +27588 89/<- %ebp 4/r32/esp +27589 # . save registers +27590 50/push-eax +27591 # eax = stmt +27592 8b/-> *(ebp+0xc) 0/r32/eax +27593 # +27594 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +27595 (get Reverse-branch %eax 0x10 "reverse-branch: ") # => eax: (addr handle array byte) +27596 (emit-indent *(ebp+8) *Curr-block-depth) +27597 (lookup *eax *(eax+4)) # => eax +27598 (write-buffered *(ebp+8) %eax) +27599 (write-buffered *(ebp+8) " break/disp32\n") +27600 $emit-reverse-break:end: +27601 # . restore registers +27602 58/pop-to-eax +27603 # . epilogue +27604 89/<- %esp 5/r32/ebp +27605 5d/pop-to-ebp +27606 c3/return +27607 +27608 == data +27609 +27610 # Table from Mu branch instructions to the reverse SubX opcodes for them. +27611 Reverse-branch: # (table (handle array byte) (handle array byte)) +27612 # a table is a stream +27613 0x240/imm32/write +27614 0/imm32/read +27615 0x240/imm32/size +27616 # data +27617 0x11/imm32/alloc-id _string-break-if-=/imm32 0x11/imm32/alloc-id _string_0f_85_jump_label/imm32 +27618 0x11/imm32/alloc-id _string-loop-if-=/imm32 0x11/imm32/alloc-id _string_0f_85_jump_label/imm32 +27619 0x11/imm32/alloc-id _string-break-if-!=/imm32 0x11/imm32/alloc-id _string_0f_84_jump_label/imm32 +27620 0x11/imm32/alloc-id _string-loop-if-!=/imm32 0x11/imm32/alloc-id _string_0f_84_jump_label/imm32 +27621 0x11/imm32/alloc-id _string-break-if-</imm32 0x11/imm32/alloc-id _string_0f_8d_jump_label/imm32 +27622 0x11/imm32/alloc-id _string-loop-if-</imm32 0x11/imm32/alloc-id _string_0f_8d_jump_label/imm32 +27623 0x11/imm32/alloc-id _string-break-if->/imm32 0x11/imm32/alloc-id _string_0f_8e_jump_label/imm32 +27624 0x11/imm32/alloc-id _string-loop-if->/imm32 0x11/imm32/alloc-id _string_0f_8e_jump_label/imm32 +27625 0x11/imm32/alloc-id _string-break-if-<=/imm32 0x11/imm32/alloc-id _string_0f_8f_jump_label/imm32 +27626 0x11/imm32/alloc-id _string-loop-if-<=/imm32 0x11/imm32/alloc-id _string_0f_8f_jump_label/imm32 +27627 0x11/imm32/alloc-id _string-break-if->=/imm32 0x11/imm32/alloc-id _string_0f_8c_jump_label/imm32 +27628 0x11/imm32/alloc-id _string-loop-if->=/imm32 0x11/imm32/alloc-id _string_0f_8c_jump_label/imm32 +27629 0x11/imm32/alloc-id _string-break-if-addr</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 +27630 0x11/imm32/alloc-id _string-loop-if-addr</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 +27631 0x11/imm32/alloc-id _string-break-if-addr>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 +27632 0x11/imm32/alloc-id _string-loop-if-addr>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 +27633 0x11/imm32/alloc-id _string-break-if-addr<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 +27634 0x11/imm32/alloc-id _string-loop-if-addr<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 +27635 0x11/imm32/alloc-id _string-break-if-addr>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 +27636 0x11/imm32/alloc-id _string-loop-if-addr>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 +27637 0x11/imm32/alloc-id _string-break-if-float</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 +27638 0x11/imm32/alloc-id _string-loop-if-float</imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 +27639 0x11/imm32/alloc-id _string-break-if-float>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 +27640 0x11/imm32/alloc-id _string-loop-if-float>/imm32 0x11/imm32/alloc-id _string_0f_86_jump_label/imm32 +27641 0x11/imm32/alloc-id _string-break-if-float<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 +27642 0x11/imm32/alloc-id _string-loop-if-float<=/imm32 0x11/imm32/alloc-id _string_0f_87_jump_label/imm32 +27643 0x11/imm32/alloc-id _string-break-if-float>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 +27644 0x11/imm32/alloc-id _string-loop-if-float>=/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 +27645 0x11/imm32/alloc-id _string-break-if-carry/imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 +27646 0x11/imm32/alloc-id _string-loop-if-carry/imm32 0x11/imm32/alloc-id _string_0f_83_jump_label/imm32 +27647 0x11/imm32/alloc-id _string-break-if-not-carry/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 +27648 0x11/imm32/alloc-id _string-loop-if-not-carry/imm32 0x11/imm32/alloc-id _string_0f_82_jump_label/imm32 +27649 0x11/imm32/alloc-id _string-break-if-overflow/imm32 0x11/imm32/alloc-id _string_0f_81_jump_label/imm32 +27650 0x11/imm32/alloc-id _string-loop-if-overflow/imm32 0x11/imm32/alloc-id _string_0f_81_jump_label/imm32 +27651 0x11/imm32/alloc-id _string-break-if-not-overflow/imm32 0x11/imm32/alloc-id _string_0f_80_jump_label/imm32 +27652 0x11/imm32/alloc-id _string-loop-if-not-overflow/imm32 0x11/imm32/alloc-id _string_0f_80_jump_label/imm32 +27653 +27654 == code +27655 +27656 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte) +27657 # . prologue +27658 55/push-ebp +27659 89/<- %ebp 4/r32/esp +27660 # . save registers +27661 50/push-eax +27662 51/push-ecx +27663 52/push-edx +27664 53/push-ebx +27665 56/push-esi +27666 # ecx = vars +27667 8b/-> *(ebp+0xc) 1/r32/ecx +27668 # var eax: int = vars->top +27669 8b/-> *ecx 0/r32/eax +27670 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] +27671 8d/copy-address *(ecx+eax-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size +27672 # var min/ecx: (addr handle var) = vars->data +27673 8d/copy-address *(ecx+8) 1/r32/ecx +27674 # edx = depth +27675 8b/-> *(ebp+0x10) 2/r32/edx +27676 { +27677 $emit-unconditional-jump-to-depth:loop: +27678 # if (curr < min) break +27679 39/compare %esi 1/r32/ecx +27680 0f 82/jump-if-addr< break/disp32 +27681 # var v/ebx: (addr var) = lookup(*curr) +27682 (lookup *esi *(esi+4)) # => eax +27683 89/<- %ebx 0/r32/eax +27684 # if (v->block-depth < until-block-depth) break +27685 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth +27686 0f 8c/jump-if-< break/disp32 +27687 { +27688 $emit-unconditional-jump-to-depth:check: +27689 # if v->block-depth != until-block-depth, continue +27690 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth +27691 0f 85/jump-if-!= break/disp32 +27692 $emit-unconditional-jump-to-depth:depth-found: +27693 # if v is not a literal, continue +27694 (size-of %ebx) # => eax +27695 3d/compare-eax-and 0/imm32 +27696 0f 85/jump-if-!= break/disp32 +27697 $emit-unconditional-jump-to-depth:label-found: +27698 # emit unconditional jump, then return +27699 (emit-indent *(ebp+8) *Curr-block-depth) +27700 (write-buffered *(ebp+8) "e9/jump ") +27701 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +27702 (write-buffered *(ebp+8) %eax) +27703 (write-buffered *(ebp+8) ":") +27704 (write-buffered *(ebp+8) *(ebp+0x14)) +27705 (write-buffered *(ebp+8) "/disp32\n") +27706 eb/jump $emit-unconditional-jump-to-depth:end/disp8 +27707 } +27708 # curr -= 12 +27709 81 5/subop/subtract %esi 0xc/imm32 +27710 e9/jump loop/disp32 +27711 } +27712 # TODO: error if no label at 'depth' was found +27713 $emit-unconditional-jump-to-depth:end: +27714 # . restore registers +27715 5e/pop-to-esi +27716 5b/pop-to-ebx +27717 5a/pop-to-edx +27718 59/pop-to-ecx +27719 58/pop-to-eax +27720 # . epilogue +27721 89/<- %esp 5/r32/ebp +27722 5d/pop-to-ebp +27723 c3/return +27724 +27725 # emit clean-up code for 'vars' until some block depth +27726 # doesn't actually modify 'vars' so we need traverse manually inside the stack +27727 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int +27728 # . prologue +27729 55/push-ebp +27730 89/<- %ebp 4/r32/esp +27731 # . save registers +27732 50/push-eax +27733 51/push-ecx +27734 52/push-edx +27735 53/push-ebx +27736 56/push-esi +27737 #? (write-buffered Stderr "--- cleanup\n") +27738 #? (flush Stderr) +27739 # ecx = vars +27740 8b/-> *(ebp+0xc) 1/r32/ecx +27741 # var esi: int = vars->top +27742 8b/-> *ecx 6/r32/esi +27743 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] +27744 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size +27745 # var min/ecx: (addr handle var) = vars->data +27746 81 0/subop/add %ecx 8/imm32 +27747 # edx = until-block-depth +27748 8b/-> *(ebp+0x10) 2/r32/edx +27749 { +27750 $emit-cleanup-code-until-depth:loop: +27751 # if (curr < min) break +27752 39/compare %esi 1/r32/ecx +27753 0f 82/jump-if-addr< break/disp32 +27754 # var v/ebx: (addr var) = lookup(*curr) +27755 (lookup *esi *(esi+4)) # => eax +27756 89/<- %ebx 0/r32/eax +27757 #? (lookup *ebx *(ebx+4)) # Var-name +27758 #? (write-buffered Stderr "var ") +27759 #? (write-buffered Stderr %eax) +27760 #? (write-buffered Stderr Newline) +27761 #? (flush Stderr) +27762 # if (v->block-depth < until-block-depth) break +27763 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth +27764 0f 8c/jump-if-< break/disp32 +27765 # if v is in a register +27766 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register +27767 { +27768 0f 84/jump-if-= break/disp32 +27769 { +27770 $emit-cleanup-code-until-depth:check-for-previous-spill: +27771 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled +27772 3d/compare-eax-and 0/imm32/false +27773 74/jump-if-= break/disp8 +27774 $emit-cleanup-code-until-depth:reclaim-var-in-register: +27775 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +27776 (emit-pop-register *(ebp+8) %eax) +27777 } +27778 eb/jump $emit-cleanup-code-until-depth:continue/disp8 +27779 } +27780 # otherwise v is on the stack +27781 { +27782 75/jump-if-!= break/disp8 +27783 $emit-cleanup-code-until-depth:var-on-stack: +27784 (size-of %ebx) # => eax +27785 # don't emit code for labels +27786 3d/compare-eax-and 0/imm32 +27787 74/jump-if-= break/disp8 +27788 $emit-cleanup-code-until-depth:reclaim-var-on-stack: +27789 (emit-indent *(ebp+8) *Curr-block-depth) +27790 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +27791 (write-int32-hex-buffered *(ebp+8) %eax) +27792 (write-buffered *(ebp+8) "/imm32\n") +27793 } +27794 $emit-cleanup-code-until-depth:continue: +27795 # curr -= 12 +27796 81 5/subop/subtract %esi 0xc/imm32 +27797 e9/jump loop/disp32 +27798 } +27799 $emit-cleanup-code-until-depth:end: +27800 # . restore registers +27801 5e/pop-to-esi +27802 5b/pop-to-ebx +27803 5a/pop-to-edx +27804 59/pop-to-ecx +27805 58/pop-to-eax +27806 # . epilogue +27807 89/<- %esp 5/r32/ebp +27808 5d/pop-to-ebp +27809 c3/return +27810 +27811 # emit clean-up code for 'vars' that don't conflict with output registers +27812 # doesn't actually modify 'vars' so we need traverse manually inside the stack +27813 emit-cleanup-code-for-non-outputs: # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function) +27814 # . prologue +27815 55/push-ebp +27816 89/<- %ebp 4/r32/esp +27817 # . save registers +27818 50/push-eax +27819 51/push-ecx +27820 52/push-edx +27821 53/push-ebx +27822 56/push-esi +27823 57/push-edi +27824 # ecx = vars +27825 8b/-> *(ebp+0xc) 1/r32/ecx +27826 # var esi: int = vars->top +27827 8b/-> *ecx 6/r32/esi +27828 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] +27829 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size +27830 # var min/ecx: (addr handle var) = vars->data +27831 81 0/subop/add %ecx 8/imm32 +27832 { +27833 $emit-cleanup-code-for-non-outputs:loop: +27834 # if (curr < min) break +27835 39/compare %esi 1/r32/ecx +27836 0f 82/jump-if-addr< break/disp32 +27837 # var v/ebx: (addr var) = lookup(*curr) +27838 (lookup *esi *(esi+4)) # => eax +27839 89/<- %ebx 0/r32/eax +27840 # if v is in a register +27841 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register +27842 { +27843 0f 84/jump-if-= break/disp32 +27844 { +27845 $emit-cleanup-code-for-non-outputs:check-for-previous-spill: +27846 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled +27847 3d/compare-eax-and 0/imm32/false +27848 0f 84/jump-if-= break/disp32 +27849 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register: +27850 # var reg/edi: (addr array name) = v->register +27851 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +27852 89/<- %edi 0/r32/eax +27853 # if reg is not in function outputs, emit a pop +27854 (reg-in-function-outputs? *(ebp+0x10) %edi) # => eax +27855 3d/compare-eax-and 0/imm32/false +27856 { +27857 75/jump-if-!= break/disp8 +27858 (emit-pop-register *(ebp+8) %edi) +27859 eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8 +27860 } +27861 # otherwise just drop it from the stack +27862 (emit-indent *(ebp+8) *Curr-block-depth) +27863 (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n") +27864 } +27865 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done: +27866 eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8 +27867 } +27868 # otherwise v is on the stack +27869 { +27870 75/jump-if-!= break/disp8 +27871 $emit-cleanup-code-for-non-outputs:var-on-stack: +27872 (size-of %ebx) # => eax +27873 # don't emit code for labels +27874 3d/compare-eax-and 0/imm32 +27875 74/jump-if-= break/disp8 +27876 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack: +27877 (emit-indent *(ebp+8) *Curr-block-depth) +27878 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +27879 (write-int32-hex-buffered *(ebp+8) %eax) +27880 (write-buffered *(ebp+8) "/imm32\n") +27881 } +27882 $emit-cleanup-code-for-non-outputs:continue: +27883 # curr -= 12 +27884 81 5/subop/subtract %esi 0xc/imm32 +27885 e9/jump loop/disp32 +27886 } +27887 $emit-cleanup-code-for-non-outputs:end: +27888 # . restore registers +27889 5f/pop-to-edi +27890 5e/pop-to-esi +27891 5b/pop-to-ebx +27892 5a/pop-to-edx +27893 59/pop-to-ecx +27894 58/pop-to-eax +27895 # . epilogue +27896 89/<- %esp 5/r32/ebp +27897 5d/pop-to-ebp +27898 c3/return +27899 +27900 emit-push-register: # out: (addr buffered-file), reg: (addr array byte) +27901 # . prologue +27902 55/push-ebp +27903 89/<- %ebp 4/r32/esp +27904 # eax = reg +27905 8b/-> *(ebp+0xc) 0/r32/eax +27906 # var prefix/eax: byte = reg->data[0] +27907 8a/copy-byte *(eax+4) 0/r32/AL +27908 25/and-eax-with 0xff/imm32 +27909 # if (prefix == 'x') push xmm register +27910 { +27911 3d/compare-eax-and 0x78/imm32/x +27912 0f 85/jump-if-!= break/disp32 +27913 # TODO validate register +27914 (emit-indent *(ebp+8) *Curr-block-depth) +27915 (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n") +27916 (emit-indent *(ebp+8) *Curr-block-depth) +27917 (write-buffered *(ebp+8) "f3 0f 11/<- *esp ") +27918 # var prefix/eax: byte = reg->data[3] +27919 8b/-> *(ebp+0xc) 0/r32/eax +27920 8a/copy-byte *(eax+7) 0/r32/AL +27921 25/and-eax-with 0xff/imm32 +27922 (write-byte-buffered *(ebp+8) %eax) +27923 (write-buffered *(ebp+8) "/x32\n") +27924 e9/jump $emit-push-register:end/disp32 +27925 } +27926 # otherwise push gp register +27927 (emit-indent *(ebp+8) *Curr-block-depth) +27928 (write-buffered *(ebp+8) "ff 6/subop/push %") +27929 (write-buffered *(ebp+8) *(ebp+0xc)) +27930 (write-buffered *(ebp+8) Newline) +27931 $emit-push-register:end: +27932 # . epilogue +27933 89/<- %esp 5/r32/ebp +27934 5d/pop-to-ebp +27935 c3/return +27936 +27937 emit-pop-register: # out: (addr buffered-file), reg: (addr array byte) +27938 # . prologue +27939 55/push-ebp +27940 89/<- %ebp 4/r32/esp +27941 # . save registers +27942 50/push-eax +27943 # eax = reg +27944 8b/-> *(ebp+0xc) 0/r32/eax +27945 # var prefix/eax: byte = reg->data[0] +27946 8a/copy-byte *(eax+4) 0/r32/AL +27947 25/and-eax-with 0xff/imm32 +27948 # if (prefix == 'x') pop to xmm register +27949 { +27950 3d/compare-eax-and 0x78/imm32/x +27951 0f 85/jump-if-!= break/disp32 +27952 # TODO validate register +27953 (emit-indent *(ebp+8) *Curr-block-depth) +27954 (write-buffered *(ebp+8) "f3 0f 10/-> *esp ") +27955 # var prefix/eax: byte = reg->data[3] +27956 8b/-> *(ebp+0xc) 0/r32/eax +27957 8a/copy-byte *(eax+7) 0/r32/AL +27958 25/and-eax-with 0xff/imm32 +27959 (write-byte-buffered *(ebp+8) %eax) +27960 (write-buffered *(ebp+8) "/x32\n") +27961 (emit-indent *(ebp+8) *Curr-block-depth) +27962 (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n") +27963 e9/jump $emit-pop-register:end/disp32 +27964 } +27965 # otherwise pop to gp register +27966 (emit-indent *(ebp+8) *Curr-block-depth) +27967 (write-buffered *(ebp+8) "8f 0/subop/pop %") +27968 (write-buffered *(ebp+8) *(ebp+0xc)) +27969 (write-buffered *(ebp+8) Newline) +27970 $emit-pop-register:end: +27971 # . restore registers +27972 58/pop-to-eax +27973 # . epilogue +27974 89/<- %esp 5/r32/ebp +27975 5d/pop-to-ebp +27976 c3/return +27977 +27978 # emit clean-up code for 'vars' until a given label is encountered +27979 # doesn't actually modify 'vars' so we need traverse manually inside the stack +27980 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte) +27981 # . prologue +27982 55/push-ebp +27983 89/<- %ebp 4/r32/esp +27984 # . save registers +27985 50/push-eax +27986 51/push-ecx +27987 52/push-edx +27988 53/push-ebx +27989 # ecx = vars +27990 8b/-> *(ebp+0xc) 1/r32/ecx +27991 # var eax: int = vars->top +27992 8b/-> *ecx 0/r32/eax +27993 # var curr/edx: (addr handle var) = &vars->data[vars->top - 12] +27994 8d/copy-address *(ecx+eax-4) 2/r32/edx # vars + 8 + vars->top - 12/Live-var-size +27995 # var min/ecx: (addr handle var) = vars->data +27996 81 0/subop/add %ecx 8/imm32 +27997 { +27998 $emit-cleanup-code-until-target:loop: +27999 # if (curr < min) break +28000 39/compare %edx 1/r32/ecx +28001 0f 82/jump-if-addr< break/disp32 +28002 # var v/ebx: (handle var) = lookup(*curr) +28003 (lookup *edx *(edx+4)) # => eax +28004 89/<- %ebx 0/r32/eax +28005 # if (v->name == until-block-label) break +28006 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +28007 (string-equal? %eax *(ebp+0x10)) # => eax +28008 3d/compare-eax-and 0/imm32/false +28009 0f 85/jump-if-!= break/disp32 +28010 # if v is in a register +28011 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register +28012 { +28013 0f 84/jump-if-= break/disp32 +28014 { +28015 $emit-cleanup-code-until-target:check-for-previous-spill: +28016 8b/-> *(edx+8) 0/r32/eax # Live-var-register-spilled +28017 3d/compare-eax-and 0/imm32/false +28018 74/jump-if-= break/disp8 +28019 $emit-cleanup-code-until-target:reclaim-var-in-register: +28020 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +28021 (emit-pop-register *(ebp+8) %eax) +28022 } +28023 eb/jump $emit-cleanup-code-until-target:continue/disp8 +28024 } +28025 # otherwise v is on the stack +28026 { +28027 75/jump-if-!= break/disp8 +28028 $emit-cleanup-code-until-target:reclaim-var-on-stack: +28029 (size-of %ebx) # => eax +28030 # don't emit code for labels +28031 3d/compare-eax-and 0/imm32 +28032 74/jump-if-= break/disp8 +28033 # +28034 (emit-indent *(ebp+8) *Curr-block-depth) +28035 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +28036 (write-int32-hex-buffered *(ebp+8) %eax) +28037 (write-buffered *(ebp+8) "/imm32\n") +28038 } +28039 $emit-cleanup-code-until-target:continue: +28040 # curr -= 12 +28041 81 5/subop/subtract %edx 0xc/imm32 +28042 e9/jump loop/disp32 +28043 } +28044 $emit-cleanup-code-until-target:end: +28045 # . restore registers +28046 5b/pop-to-ebx +28047 5a/pop-to-edx +28048 59/pop-to-ecx +28049 58/pop-to-eax +28050 # . epilogue +28051 89/<- %esp 5/r32/ebp +28052 5d/pop-to-ebp +28053 c3/return +28054 +28055 # update Curr-local-stack-offset assuming vars until some block depth are popped +28056 # doesn't actually modify 'vars', so we need traverse manually inside the stack +28057 clean-up-stack-offset-state: # vars: (addr stack live-var), until-block-depth: int +28058 # . prologue +28059 55/push-ebp +28060 89/<- %ebp 4/r32/esp +28061 # . save registers +28062 50/push-eax +28063 51/push-ecx +28064 52/push-edx +28065 53/push-ebx +28066 56/push-esi +28067 # ecx = vars +28068 8b/-> *(ebp+8) 1/r32/ecx +28069 # var esi: int = vars->top +28070 8b/-> *ecx 6/r32/esi +28071 # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] +28072 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size +28073 # var min/ecx: (addr handle var) = vars->data +28074 81 0/subop/add %ecx 8/imm32 +28075 # edx = until-block-depth +28076 8b/-> *(ebp+0xc) 2/r32/edx +28077 { +28078 $clean-up-stack-offset-state:loop: +28079 # if (curr < min) break +28080 39/compare %esi 1/r32/ecx +28081 0f 82/jump-if-addr< break/disp32 +28082 # var v/ebx: (addr var) = lookup(*curr) +28083 (lookup *esi *(esi+4)) # => eax +28084 89/<- %ebx 0/r32/eax +28085 # if (v->block-depth < until-block-depth) break +28086 39/compare *(ebx+0x10) 2/r32/edx # Var-block-depth +28087 0f 8c/jump-if-< break/disp32 +28088 # if v is in a register +28089 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register +28090 { +28091 0f 84/jump-if-= break/disp32 +28092 { +28093 $clean-up-stack-offset-state:check-for-previous-spill: +28094 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled +28095 3d/compare-eax-and 0/imm32/false +28096 74/jump-if-= break/disp8 +28097 $clean-up-stack-offset-state:reclaim-var-in-register: +28098 81 0/subop/add *Curr-local-stack-offset 4/imm32 +28099 } +28100 eb/jump $clean-up-stack-offset-state:continue/disp8 +28101 } +28102 # otherwise v is on the stack +28103 { +28104 75/jump-if-!= break/disp8 +28105 $clean-up-stack-offset-state:var-on-stack: +28106 (size-of %ebx) # => eax +28107 01/add-to *Curr-local-stack-offset 0/r32/eax +28108 } +28109 $clean-up-stack-offset-state:continue: +28110 # curr -= 12 +28111 81 5/subop/subtract %esi 0xc/imm32 +28112 e9/jump loop/disp32 +28113 } +28114 $clean-up-stack-offset-state:end: +28115 # . restore registers +28116 5e/pop-to-esi +28117 5b/pop-to-ebx +28118 5a/pop-to-edx +28119 59/pop-to-ecx +28120 58/pop-to-eax +28121 # . epilogue +28122 89/<- %esp 5/r32/ebp +28123 5d/pop-to-ebp +28124 c3/return +28125 +28126 # Return true if there isn't a variable in 'vars' with the same block-depth +28127 # and register as 'v'. +28128 # 'v' is guaranteed not to be within 'vars'. +28129 not-yet-spilled-this-block?: # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean +28130 # . prologue +28131 55/push-ebp +28132 89/<- %ebp 4/r32/esp +28133 # . save registers +28134 51/push-ecx +28135 52/push-edx +28136 53/push-ebx +28137 56/push-esi +28138 57/push-edi +28139 # ecx = vars +28140 8b/-> *(ebp+0xc) 1/r32/ecx +28141 # var eax: int = vars->top +28142 8b/-> *ecx 0/r32/eax +28143 # var curr/edx: (addr handle var) = &vars->data[vars->top - 12] +28144 8d/copy-address *(ecx+eax-4) 2/r32/edx # vars + 8 + vars->top - 12/Live-var-size +28145 # var min/ecx: (addr handle var) = vars->data +28146 8d/copy-address *(ecx+8) 1/r32/ecx +28147 # var depth/ebx: int = v->block-depth +28148 8b/-> *(ebp+8) 3/r32/ebx +28149 8b/-> *(ebx+0x10) 3/r32/ebx # Var-block-depth +28150 # var needle/esi: (addr array byte) = v->register +28151 8b/-> *(ebp+8) 6/r32/esi +28152 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax +28153 89/<- %esi 0/r32/eax +28154 { +28155 $not-yet-spilled-this-block?:loop: +28156 # if (curr < min) break +28157 39/compare %edx 1/r32/ecx +28158 0f 82/jump-if-addr< break/disp32 +28159 # var cand/edi: (addr var) = lookup(*curr) +28160 (lookup *edx *(edx+4)) # => eax +28161 89/<- %edi 0/r32/eax +28162 # if (cand->block-depth < depth) break +28163 39/compare *(edi+0x10) 3/r32/ebx # Var-block-depth +28164 0f 8c/jump-if-< break/disp32 +28165 # var cand-reg/edi: (array array byte) = cand->reg +28166 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax +28167 89/<- %edi 0/r32/eax +28168 # if (cand-reg == null) continue +28169 { +28170 $not-yet-spilled-this-block?:check-reg: +28171 81 7/subop/compare %edi 0/imm32 +28172 0f 84/jump-if-= break/disp32 +28173 # if (cand-reg == needle) return true +28174 (string-equal? %esi %edi) # => eax +28175 3d/compare-eax-and 0/imm32/false +28176 74/jump-if-= break/disp8 +28177 $not-yet-spilled-this-block?:return-false: +28178 b8/copy-to-eax 0/imm32/false +28179 eb/jump $not-yet-spilled-this-block?:end/disp8 +28180 } +28181 $not-yet-spilled-this-block?:continue: +28182 # curr -= 12 +28183 81 5/subop/subtract %edx 0xc/imm32 +28184 e9/jump loop/disp32 +28185 } +28186 $not-yet-spilled-this-block?:return-true: +28187 # return true +28188 b8/copy-to-eax 1/imm32/true +28189 $not-yet-spilled-this-block?:end: +28190 # . restore registers +28191 5f/pop-to-edi +28192 5e/pop-to-esi +28193 5b/pop-to-ebx +28194 5a/pop-to-edx +28195 59/pop-to-ecx +28196 # . epilogue +28197 89/<- %esp 5/r32/ebp +28198 5d/pop-to-ebp +28199 c3/return +28200 +28201 # could the register of 'v' ever be written to by one of the vars in fn-outputs? +28202 will-not-write-some-register?: # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean 28203 # . prologue 28204 55/push-ebp 28205 89/<- %ebp 4/r32/esp -28206 # . save registers -28207 51/push-ecx -28208 # var curr/ecx: (addr list var) = lookup(fn->outputs) -28209 8b/-> *(ebp+8) 1/r32/ecx -28210 (lookup *(ecx+0x10) *(ecx+0x14)) # Function-outputs Function-outputs => eax -28211 89/<- %ecx 0/r32/eax -28212 { -28213 $find-register:loop: -28214 # if (curr == 0) break -28215 81 7/subop/compare %ecx 0/imm32 -28216 74/jump-if-= break/disp8 -28217 # eax = curr->value->register -28218 (lookup *ecx *(ecx+4)) # List-value List-value => eax -28219 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28220 # if (eax == reg) return curr->value -28221 $find-register:compare: -28222 (string-equal? *(ebp+0xc) %eax) # => eax -28223 { -28224 3d/compare-eax-and 0/imm32/false -28225 74/jump-if-= break/disp8 -28226 $find-register:found: -28227 (lookup *ecx *(ecx+4)) # List-value List-value => eax -28228 eb/jump $find-register:end/disp8 -28229 } -28230 # curr = lookup(curr->next) -28231 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -28232 89/<- %ecx 0/r32/eax -28233 # -28234 eb/jump loop/disp8 -28235 } -28236 $find-register:end: -28237 # . restore registers -28238 59/pop-to-ecx -28239 # . epilogue -28240 89/<- %esp 5/r32/ebp -28241 5d/pop-to-ebp -28242 c3/return -28243 -28244 assigns-in-stmts?: # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean -28245 # . prologue -28246 55/push-ebp -28247 89/<- %ebp 4/r32/esp -28248 # . save registers -28249 51/push-ecx -28250 # var curr/ecx: (addr list stmt) = stmts -28251 8b/-> *(ebp+8) 1/r32/ecx -28252 { -28253 # if (curr == 0) break -28254 81 7/subop/compare %ecx 0/imm32 -28255 74/jump-if-= break/disp8 -28256 # if assigns-in-stmt?(curr->value, v) return true -28257 (lookup *ecx *(ecx+4)) # List-value List-value => eax -28258 (assigns-in-stmt? %eax *(ebp+0xc)) # => eax -28259 3d/compare-eax-and 0/imm32/false -28260 75/jump-if-!= break/disp8 -28261 # curr = lookup(curr->next) -28262 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -28263 89/<- %ecx 0/r32/eax -28264 # -28265 eb/jump loop/disp8 -28266 } -28267 $assigns-in-stmts?:end: -28268 # . restore registers -28269 59/pop-to-ecx -28270 # . epilogue -28271 89/<- %esp 5/r32/ebp -28272 5d/pop-to-ebp -28273 c3/return -28274 -28275 assigns-in-stmt?: # stmt: (addr stmt), v: (addr var) -> result/eax: boolean -28276 # . prologue -28277 55/push-ebp -28278 89/<- %ebp 4/r32/esp -28279 # . save registers -28280 51/push-ecx -28281 # ecx = stmt -28282 8b/-> *(ebp+8) 1/r32/ecx -28283 # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v) -28284 { -28285 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -28286 75/jump-if-!= break/disp8 -28287 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax -28288 (assigns-in-stmt-vars? %eax *(ebp+0xc)) # => eax -28289 eb/jump $assigns-in-stmt?:end/disp8 -28290 } -28291 # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v) -28292 { -28293 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -28294 75/jump-if-!= break/disp8 -28295 (lookup *(ecx+4) *(ecx+8)) # Block-stmts Block-stmts => eax -28296 (assigns-in-stmts? %eax *(ebp+0xc)) # => eax -28297 eb/jump $assigns-in-stmt?:end/disp8 -28298 } -28299 # otherwise return false -28300 b8/copy 0/imm32/false -28301 $assigns-in-stmt?:end: -28302 # . restore registers -28303 59/pop-to-ecx -28304 # . epilogue -28305 89/<- %esp 5/r32/ebp -28306 5d/pop-to-ebp -28307 c3/return -28308 -28309 assigns-in-stmt-vars?: # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean -28310 # . prologue -28311 55/push-ebp -28312 89/<- %ebp 4/r32/esp -28313 # . save registers -28314 51/push-ecx -28315 # var curr/ecx: (addr stmt-var) = stmt-var -28316 8b/-> *(ebp+8) 1/r32/ecx -28317 { -28318 # if (curr == 0) break -28319 81 7/subop/compare %ecx 0/imm32 -28320 74/jump-if-= break/disp8 -28321 # eax = lookup(curr->value) -28322 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -28323 # if (eax == v && curr->is-deref? == false) return true -28324 { -28325 39/compare *(ebp+0xc) 0/r32/eax -28326 75/jump-if-!= break/disp8 -28327 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -28328 75/jump-if-!= break/disp8 -28329 b8/copy-to-eax 1/imm32/true -28330 eb/jump $assigns-in-stmt-vars?:end/disp8 -28331 } -28332 # curr = lookup(curr->next) -28333 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax -28334 89/<- %ecx 0/r32/eax -28335 # -28336 eb/jump loop/disp8 -28337 } -28338 $assigns-in-stmt-vars?:end: -28339 # . restore registers -28340 59/pop-to-ecx -28341 # . epilogue -28342 89/<- %esp 5/r32/ebp -28343 5d/pop-to-ebp -28344 c3/return -28345 -28346 # is there a var before 'v' with the same block-depth and register on the 'vars' stack? -28347 # v is guaranteed to be within vars -28348 # 'start' is provided as an optimization, a pointer within vars -28349 # *start == v -28350 same-register-spilled-before?: # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean -28351 # . prologue -28352 55/push-ebp -28353 89/<- %ebp 4/r32/esp -28354 # . save registers -28355 51/push-ecx -28356 52/push-edx -28357 53/push-ebx -28358 56/push-esi -28359 57/push-edi -28360 # ecx = v -28361 8b/-> *(ebp+8) 1/r32/ecx -28362 # var reg/edx: (addr array byte) = lookup(v->register) -28363 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax -28364 89/<- %edx 0/r32/eax -28365 # var depth/ebx: int = v->block-depth -28366 8b/-> *(ecx+0x10) 3/r32/ebx # Var-block-depth -28367 # var min/ecx: (addr handle var) = vars->data -28368 8b/-> *(ebp+0xc) 1/r32/ecx -28369 81 0/subop/add %ecx 8/imm32 -28370 # TODO: check that start >= min and start < &vars->data[top] -28371 # TODO: check that *start == v -28372 # var curr/esi: (addr handle var) = start -28373 8b/-> *(ebp+0x10) 6/r32/esi -28374 # curr -= 8 -28375 81 5/subop/subtract %esi 8/imm32 -28376 { -28377 $same-register-spilled-before?:loop: -28378 # if (curr < min) break -28379 39/compare %esi 1/r32/ecx -28380 0f 82/jump-if-addr< break/disp32 -28381 # var x/eax: (addr var) = lookup(*curr) -28382 (lookup *esi *(esi+4)) # => eax -28383 # if (x->block-depth < depth) break -28384 39/compare *(eax+0x10) 3/r32/ebx # Var-block-depth -28385 0f 8c/jump-if-< break/disp32 -28386 # if (x->register == 0) continue -28387 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -28388 74/jump-if-= $same-register-spilled-before?:continue/disp8 -28389 # if (x->register == reg) return true -28390 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28391 (string-equal? %eax %edx) # => eax -28392 3d/compare-eax-and 0/imm32/false -28393 b8/copy-to-eax 1/imm32/true -28394 75/jump-if-!= $same-register-spilled-before?:end/disp8 -28395 $same-register-spilled-before?:continue: -28396 # curr -= 8 -28397 81 5/subop/subtract %esi 8/imm32 -28398 e9/jump loop/disp32 -28399 } -28400 $same-register-spilled-before?:false: -28401 b8/copy-to-eax 0/imm32/false -28402 $same-register-spilled-before?:end: -28403 # . restore registers -28404 5f/pop-to-edi -28405 5e/pop-to-esi -28406 5b/pop-to-ebx -28407 5a/pop-to-edx -28408 59/pop-to-ecx -28409 # . epilogue -28410 89/<- %esp 5/r32/ebp -28411 5d/pop-to-ebp -28412 c3/return -28413 -28414 # clean up global state for 'vars' until some block depth (inclusive) -28415 clean-up-blocks: # vars: (addr stack live-var), until-block-depth: int, fn: (addr function) -28416 # . prologue -28417 55/push-ebp -28418 89/<- %ebp 4/r32/esp -28419 # . save registers -28420 50/push-eax -28421 51/push-ecx -28422 56/push-esi -28423 # esi = vars -28424 8b/-> *(ebp+8) 6/r32/esi -28425 # ecx = until-block-depth -28426 8b/-> *(ebp+0xc) 1/r32/ecx -28427 { -28428 $clean-up-blocks:reclaim-loop: -28429 # if (vars->top <= 0) break -28430 8b/-> *esi 0/r32/eax # Stack-top -28431 3d/compare-eax-and 0/imm32 -28432 0f 8e/jump-if-<= break/disp32 -28433 # var v/eax: (addr var) = lookup(vars[vars->top-12]) -28434 (lookup *(esi+eax-4) *(esi+eax)) # vars + 8 + vars->top - 12 => eax -28435 # if (v->block-depth < until-block-depth) break -28436 39/compare *(eax+0x10) 1/r32/ecx # Var-block-depth -28437 0f 8c/jump-if-< break/disp32 -28438 (pop %esi) # => eax -28439 (pop %esi) # => eax -28440 (pop %esi) # => eax -28441 e9/jump loop/disp32 -28442 } -28443 $clean-up-blocks:end: -28444 # . restore registers -28445 5e/pop-to-esi -28446 59/pop-to-ecx -28447 58/pop-to-eax -28448 # . epilogue -28449 89/<- %esp 5/r32/ebp -28450 5d/pop-to-ebp -28451 c3/return -28452 -28453 reg-in-function-outputs?: # fn: (addr function), target: (addr array byte) -> result/eax: boolean -28454 # . prologue -28455 55/push-ebp -28456 89/<- %ebp 4/r32/esp -28457 # . save registers -28458 51/push-ecx -28459 # var curr/ecx: (addr list var) = lookup(fn->outputs) -28460 8b/-> *(ebp+8) 0/r32/eax -28461 (lookup *(eax+0x10) *(eax+0x14)) # Function-outputs Function-outputs => eax -28462 89/<- %ecx 0/r32/eax -28463 # while curr != null -28464 { -28465 81 7/subop/compare %ecx 0/imm32 -28466 74/jump-if-= break/disp8 -28467 # var v/eax: (addr var) = lookup(curr->value) -28468 (lookup *ecx *(ecx+4)) # List-value List-value => eax -28469 # var reg/eax: (addr array byte) = lookup(v->register) -28470 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28471 # if (reg == target) return true -28472 (string-equal? %eax *(ebp+0xc)) # => eax -28473 3d/compare-eax-and 0/imm32/false -28474 75/jump-if-!= $reg-in-function-outputs?:end/disp8 -28475 # curr = curr->next -28476 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax -28477 89/<- %ecx 0/r32/eax -28478 # -28479 eb/jump loop/disp8 -28480 } -28481 # return false -28482 b8/copy-to-eax 0/imm32 -28483 $reg-in-function-outputs?:end: -28484 # . restore registers -28485 59/pop-to-ecx -28486 # . epilogue -28487 89/<- %esp 5/r32/ebp -28488 5d/pop-to-ebp -28489 c3/return -28490 -28491 emit-subx-var-def: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -28492 # . prologue -28493 55/push-ebp -28494 89/<- %ebp 4/r32/esp -28495 # . save registers -28496 50/push-eax -28497 51/push-ecx -28498 52/push-edx -28499 # eax = stmt -28500 8b/-> *(ebp+0xc) 0/r32/eax -28501 # var v/ecx: (addr var) -28502 (lookup *(eax+4) *(eax+8)) # Vardef-var Vardef-var => eax -28503 89/<- %ecx 0/r32/eax -28504 # v->block-depth = *Curr-block-depth -28505 8b/-> *Curr-block-depth 0/r32/eax -28506 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth -28507 # var n/edx: int = size-of(stmt->var) -28508 (size-of %ecx) # => eax -28509 89/<- %edx 0/r32/eax -28510 # *Curr-local-stack-offset -= n -28511 29/subtract-from *Curr-local-stack-offset 2/r32/edx -28512 # v->offset = *Curr-local-stack-offset -28513 8b/-> *Curr-local-stack-offset 0/r32/eax -28514 89/<- *(ecx+0x14) 0/r32/eax # Var-offset -28515 # if v is an array, do something special to initialize it -28516 { -28517 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -28518 (mu-array? %eax) # => eax -28519 3d/compare-eax-and 0/imm32/false -28520 0f 84/jump-if-= break/disp32 -28521 # var array-size-without-size/edx: int = n-4 -28522 81 5/subop/subtract %edx 4/imm32 -28523 # -28524 (emit-array-data-initialization *(ebp+8) %edx) -28525 e9/jump $emit-subx-var-def:end/disp32 -28526 } -28527 # another special-case for initializing streams -28528 # a stream is an array with 2 extra pointers -28529 { -28530 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -28531 (mu-stream? %eax) # => eax -28532 3d/compare-eax-and 0/imm32/false -28533 0f 84/jump-if-= break/disp32 -28534 # var array-size-without-size/edx: int = n-12 -28535 81 5/subop/subtract %edx 0xc/imm32 -28536 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax -28537 (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14)) -28538 # emit read and write pointers -28539 (emit-indent *(ebp+8) *Curr-block-depth) -28540 (write-buffered *(ebp+8) "68/push 0/imm32\n") -28541 (emit-indent *(ebp+8) *Curr-block-depth) -28542 (write-buffered *(ebp+8) "68/push 0/imm32\n") -28543 # -28544 eb/jump $emit-subx-var-def:end/disp8 -28545 } -28546 # while n > 0 -28547 { -28548 81 7/subop/compare %edx 0/imm32 -28549 7e/jump-if-<= break/disp8 -28550 (emit-indent *(ebp+8) *Curr-block-depth) -28551 (write-buffered *(ebp+8) "68/push 0/imm32\n") -28552 # n -= 4 -28553 81 5/subop/subtract %edx 4/imm32 -28554 # -28555 eb/jump loop/disp8 +28206 # eax = v +28207 8b/-> *(ebp+8) 0/r32/eax +28208 # var reg/eax: (addr array byte) = lookup(v->register) +28209 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28210 # var target/eax: (addr var) = find-register(fn-outputs, reg) +28211 (find-register *(ebp+0x10) %eax) # => eax +28212 # if (target == 0) return true +28213 { +28214 3d/compare-eax-and 0/imm32 +28215 75/jump-if-!= break/disp8 +28216 b8/copy-to-eax 1/imm32/true +28217 eb/jump $will-not-write-some-register?:end/disp8 +28218 } +28219 # return !assigns-in-stmts?(stmts, target) +28220 (assigns-in-stmts? *(ebp+0xc) %eax) # => eax +28221 3d/compare-eax-and 0/imm32/false +28222 # assume: true = 1, so no need to mask with 0x000000ff +28223 0f 94/set-if-= %al +28224 $will-not-write-some-register?:end: +28225 # . epilogue +28226 89/<- %esp 5/r32/ebp +28227 5d/pop-to-ebp +28228 c3/return +28229 +28230 # return fn output with matching register +28231 # always returns false if 'reg' is null +28232 find-register: # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var) +28233 # . prologue +28234 55/push-ebp +28235 89/<- %ebp 4/r32/esp +28236 # . save registers +28237 51/push-ecx +28238 # var curr/ecx: (addr list var) = lookup(fn->outputs) +28239 8b/-> *(ebp+8) 1/r32/ecx +28240 (lookup *(ecx+0x10) *(ecx+0x14)) # Function-outputs Function-outputs => eax +28241 89/<- %ecx 0/r32/eax +28242 { +28243 $find-register:loop: +28244 # if (curr == 0) break +28245 81 7/subop/compare %ecx 0/imm32 +28246 74/jump-if-= break/disp8 +28247 # eax = curr->value->register +28248 (lookup *ecx *(ecx+4)) # List-value List-value => eax +28249 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28250 # if (eax == reg) return curr->value +28251 $find-register:compare: +28252 (string-equal? *(ebp+0xc) %eax) # => eax +28253 { +28254 3d/compare-eax-and 0/imm32/false +28255 74/jump-if-= break/disp8 +28256 $find-register:found: +28257 (lookup *ecx *(ecx+4)) # List-value List-value => eax +28258 eb/jump $find-register:end/disp8 +28259 } +28260 # curr = lookup(curr->next) +28261 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +28262 89/<- %ecx 0/r32/eax +28263 # +28264 eb/jump loop/disp8 +28265 } +28266 $find-register:end: +28267 # . restore registers +28268 59/pop-to-ecx +28269 # . epilogue +28270 89/<- %esp 5/r32/ebp +28271 5d/pop-to-ebp +28272 c3/return +28273 +28274 assigns-in-stmts?: # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean +28275 # . prologue +28276 55/push-ebp +28277 89/<- %ebp 4/r32/esp +28278 # . save registers +28279 51/push-ecx +28280 # var curr/ecx: (addr list stmt) = stmts +28281 8b/-> *(ebp+8) 1/r32/ecx +28282 { +28283 # if (curr == 0) break +28284 81 7/subop/compare %ecx 0/imm32 +28285 74/jump-if-= break/disp8 +28286 # if assigns-in-stmt?(curr->value, v) return true +28287 (lookup *ecx *(ecx+4)) # List-value List-value => eax +28288 (assigns-in-stmt? %eax *(ebp+0xc)) # => eax +28289 3d/compare-eax-and 0/imm32/false +28290 75/jump-if-!= break/disp8 +28291 # curr = lookup(curr->next) +28292 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +28293 89/<- %ecx 0/r32/eax +28294 # +28295 eb/jump loop/disp8 +28296 } +28297 $assigns-in-stmts?:end: +28298 # . restore registers +28299 59/pop-to-ecx +28300 # . epilogue +28301 89/<- %esp 5/r32/ebp +28302 5d/pop-to-ebp +28303 c3/return +28304 +28305 assigns-in-stmt?: # stmt: (addr stmt), v: (addr var) -> result/eax: boolean +28306 # . prologue +28307 55/push-ebp +28308 89/<- %ebp 4/r32/esp +28309 # . save registers +28310 51/push-ecx +28311 # ecx = stmt +28312 8b/-> *(ebp+8) 1/r32/ecx +28313 # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v) +28314 { +28315 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +28316 75/jump-if-!= break/disp8 +28317 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax +28318 (assigns-in-stmt-vars? %eax *(ebp+0xc)) # => eax +28319 eb/jump $assigns-in-stmt?:end/disp8 +28320 } +28321 # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v) +28322 { +28323 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +28324 75/jump-if-!= break/disp8 +28325 (lookup *(ecx+4) *(ecx+8)) # Block-stmts Block-stmts => eax +28326 (assigns-in-stmts? %eax *(ebp+0xc)) # => eax +28327 eb/jump $assigns-in-stmt?:end/disp8 +28328 } +28329 # otherwise return false +28330 b8/copy 0/imm32/false +28331 $assigns-in-stmt?:end: +28332 # . restore registers +28333 59/pop-to-ecx +28334 # . epilogue +28335 89/<- %esp 5/r32/ebp +28336 5d/pop-to-ebp +28337 c3/return +28338 +28339 assigns-in-stmt-vars?: # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean +28340 # . prologue +28341 55/push-ebp +28342 89/<- %ebp 4/r32/esp +28343 # . save registers +28344 51/push-ecx +28345 # var curr/ecx: (addr stmt-var) = stmt-var +28346 8b/-> *(ebp+8) 1/r32/ecx +28347 { +28348 # if (curr == 0) break +28349 81 7/subop/compare %ecx 0/imm32 +28350 74/jump-if-= break/disp8 +28351 # eax = lookup(curr->value) +28352 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +28353 # if (eax == v && curr->is-deref? == false) return true +28354 { +28355 39/compare *(ebp+0xc) 0/r32/eax +28356 75/jump-if-!= break/disp8 +28357 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +28358 75/jump-if-!= break/disp8 +28359 b8/copy-to-eax 1/imm32/true +28360 eb/jump $assigns-in-stmt-vars?:end/disp8 +28361 } +28362 # curr = lookup(curr->next) +28363 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax +28364 89/<- %ecx 0/r32/eax +28365 # +28366 eb/jump loop/disp8 +28367 } +28368 $assigns-in-stmt-vars?:end: +28369 # . restore registers +28370 59/pop-to-ecx +28371 # . epilogue +28372 89/<- %esp 5/r32/ebp +28373 5d/pop-to-ebp +28374 c3/return +28375 +28376 # is there a var before 'v' with the same block-depth and register on the 'vars' stack? +28377 # v is guaranteed to be within vars +28378 # 'start' is provided as an optimization, a pointer within vars +28379 # *start == v +28380 same-register-spilled-before?: # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean +28381 # . prologue +28382 55/push-ebp +28383 89/<- %ebp 4/r32/esp +28384 # . save registers +28385 51/push-ecx +28386 52/push-edx +28387 53/push-ebx +28388 56/push-esi +28389 57/push-edi +28390 # ecx = v +28391 8b/-> *(ebp+8) 1/r32/ecx +28392 # var reg/edx: (addr array byte) = lookup(v->register) +28393 (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax +28394 89/<- %edx 0/r32/eax +28395 # var depth/ebx: int = v->block-depth +28396 8b/-> *(ecx+0x10) 3/r32/ebx # Var-block-depth +28397 # var min/ecx: (addr handle var) = vars->data +28398 8b/-> *(ebp+0xc) 1/r32/ecx +28399 81 0/subop/add %ecx 8/imm32 +28400 # TODO: check that start >= min and start < &vars->data[top] +28401 # TODO: check that *start == v +28402 # var curr/esi: (addr handle var) = start +28403 8b/-> *(ebp+0x10) 6/r32/esi +28404 # curr -= 8 +28405 81 5/subop/subtract %esi 8/imm32 +28406 { +28407 $same-register-spilled-before?:loop: +28408 # if (curr < min) break +28409 39/compare %esi 1/r32/ecx +28410 0f 82/jump-if-addr< break/disp32 +28411 # var x/eax: (addr var) = lookup(*curr) +28412 (lookup *esi *(esi+4)) # => eax +28413 # if (x->block-depth < depth) break +28414 39/compare *(eax+0x10) 3/r32/ebx # Var-block-depth +28415 0f 8c/jump-if-< break/disp32 +28416 # if (x->register == 0) continue +28417 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +28418 74/jump-if-= $same-register-spilled-before?:continue/disp8 +28419 # if (x->register == reg) return true +28420 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28421 (string-equal? %eax %edx) # => eax +28422 3d/compare-eax-and 0/imm32/false +28423 b8/copy-to-eax 1/imm32/true +28424 75/jump-if-!= $same-register-spilled-before?:end/disp8 +28425 $same-register-spilled-before?:continue: +28426 # curr -= 8 +28427 81 5/subop/subtract %esi 8/imm32 +28428 e9/jump loop/disp32 +28429 } +28430 $same-register-spilled-before?:false: +28431 b8/copy-to-eax 0/imm32/false +28432 $same-register-spilled-before?:end: +28433 # . restore registers +28434 5f/pop-to-edi +28435 5e/pop-to-esi +28436 5b/pop-to-ebx +28437 5a/pop-to-edx +28438 59/pop-to-ecx +28439 # . epilogue +28440 89/<- %esp 5/r32/ebp +28441 5d/pop-to-ebp +28442 c3/return +28443 +28444 # clean up global state for 'vars' until some block depth (inclusive) +28445 clean-up-blocks: # vars: (addr stack live-var), until-block-depth: int, fn: (addr function) +28446 # . prologue +28447 55/push-ebp +28448 89/<- %ebp 4/r32/esp +28449 # . save registers +28450 50/push-eax +28451 51/push-ecx +28452 56/push-esi +28453 # esi = vars +28454 8b/-> *(ebp+8) 6/r32/esi +28455 # ecx = until-block-depth +28456 8b/-> *(ebp+0xc) 1/r32/ecx +28457 { +28458 $clean-up-blocks:reclaim-loop: +28459 # if (vars->top <= 0) break +28460 8b/-> *esi 0/r32/eax # Stack-top +28461 3d/compare-eax-and 0/imm32 +28462 0f 8e/jump-if-<= break/disp32 +28463 # var v/eax: (addr var) = lookup(vars[vars->top-12]) +28464 (lookup *(esi+eax-4) *(esi+eax)) # vars + 8 + vars->top - 12 => eax +28465 # if (v->block-depth < until-block-depth) break +28466 39/compare *(eax+0x10) 1/r32/ecx # Var-block-depth +28467 0f 8c/jump-if-< break/disp32 +28468 (pop %esi) # => eax +28469 (pop %esi) # => eax +28470 (pop %esi) # => eax +28471 e9/jump loop/disp32 +28472 } +28473 $clean-up-blocks:end: +28474 # . restore registers +28475 5e/pop-to-esi +28476 59/pop-to-ecx +28477 58/pop-to-eax +28478 # . epilogue +28479 89/<- %esp 5/r32/ebp +28480 5d/pop-to-ebp +28481 c3/return +28482 +28483 reg-in-function-outputs?: # fn: (addr function), target: (addr array byte) -> result/eax: boolean +28484 # . prologue +28485 55/push-ebp +28486 89/<- %ebp 4/r32/esp +28487 # . save registers +28488 51/push-ecx +28489 # var curr/ecx: (addr list var) = lookup(fn->outputs) +28490 8b/-> *(ebp+8) 0/r32/eax +28491 (lookup *(eax+0x10) *(eax+0x14)) # Function-outputs Function-outputs => eax +28492 89/<- %ecx 0/r32/eax +28493 # while curr != null +28494 { +28495 81 7/subop/compare %ecx 0/imm32 +28496 74/jump-if-= break/disp8 +28497 # var v/eax: (addr var) = lookup(curr->value) +28498 (lookup *ecx *(ecx+4)) # List-value List-value => eax +28499 # var reg/eax: (addr array byte) = lookup(v->register) +28500 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28501 # if (reg == target) return true +28502 (string-equal? %eax *(ebp+0xc)) # => eax +28503 3d/compare-eax-and 0/imm32/false +28504 75/jump-if-!= $reg-in-function-outputs?:end/disp8 +28505 # curr = curr->next +28506 (lookup *(ecx+8) *(ecx+0xc)) # List-next List-next => eax +28507 89/<- %ecx 0/r32/eax +28508 # +28509 eb/jump loop/disp8 +28510 } +28511 # return false +28512 b8/copy-to-eax 0/imm32 +28513 $reg-in-function-outputs?:end: +28514 # . restore registers +28515 59/pop-to-ecx +28516 # . epilogue +28517 89/<- %esp 5/r32/ebp +28518 5d/pop-to-ebp +28519 c3/return +28520 +28521 emit-subx-var-def: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +28522 # . prologue +28523 55/push-ebp +28524 89/<- %ebp 4/r32/esp +28525 # . save registers +28526 50/push-eax +28527 51/push-ecx +28528 52/push-edx +28529 # eax = stmt +28530 8b/-> *(ebp+0xc) 0/r32/eax +28531 # var v/ecx: (addr var) +28532 (lookup *(eax+4) *(eax+8)) # Vardef-var Vardef-var => eax +28533 89/<- %ecx 0/r32/eax +28534 # v->block-depth = *Curr-block-depth +28535 8b/-> *Curr-block-depth 0/r32/eax +28536 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth +28537 # var n/edx: int = size-of(stmt->var) +28538 (size-of %ecx) # => eax +28539 89/<- %edx 0/r32/eax +28540 # *Curr-local-stack-offset -= n +28541 29/subtract-from *Curr-local-stack-offset 2/r32/edx +28542 # v->offset = *Curr-local-stack-offset +28543 8b/-> *Curr-local-stack-offset 0/r32/eax +28544 89/<- *(ecx+0x14) 0/r32/eax # Var-offset +28545 # if v is an array, do something special to initialize it +28546 { +28547 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +28548 (mu-array? %eax) # => eax +28549 3d/compare-eax-and 0/imm32/false +28550 0f 84/jump-if-= break/disp32 +28551 # var array-size-without-size/edx: int = n-4 +28552 81 5/subop/subtract %edx 4/imm32 +28553 # +28554 (emit-array-data-initialization *(ebp+8) %edx) +28555 e9/jump $emit-subx-var-def:end/disp32 28556 } -28557 $emit-subx-var-def:end: -28558 # . restore registers -28559 5a/pop-to-edx -28560 59/pop-to-ecx -28561 58/pop-to-eax -28562 # . epilogue -28563 89/<- %esp 5/r32/ebp -28564 5d/pop-to-ebp -28565 c3/return -28566 -28567 emit-array-data-initialization: # out: (addr buffered-file), n: int -28568 # . prologue -28569 55/push-ebp -28570 89/<- %ebp 4/r32/esp -28571 # -28572 (emit-indent *(ebp+8) *Curr-block-depth) -28573 (write-buffered *(ebp+8) "(push-n-zero-bytes ") -28574 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) -28575 (write-buffered *(ebp+8) ")\n") -28576 (emit-indent *(ebp+8) *Curr-block-depth) -28577 (write-buffered *(ebp+8) "68/push ") -28578 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) -28579 (write-buffered *(ebp+8) "/imm32\n") -28580 $emit-array-data-initialization:end: -28581 # . epilogue -28582 89/<- %esp 5/r32/ebp -28583 5d/pop-to-ebp -28584 c3/return -28585 -28586 emit-stream-data-initialization: # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -28587 # . prologue -28588 55/push-ebp -28589 89/<- %ebp 4/r32/esp -28590 # . save registers -28591 50/push-eax -28592 # Optimization: if it's a stream of bytes, don't initialize. -28593 # -28594 # We often construct large temporary streams on the stack for 'trace' -28595 # statements. Initializing such streams can significantly slow programs -28596 # down. -28597 # -28598 # Mu doesn't really depend on initializing stream contents for type- or -28599 # memory-safety; we're mostly doing so to make it easy to debug unsafe -28600 # SubX code that misuses stream objects by manipulating read/write -28601 # pointers. But you can't _really_ protect from unsafe SubX, so I think we -28602 # don't give up much safety or security here. -28603 { -28604 (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) # => eax -28605 3d/compare-eax-and 8/imm32/byte -28606 75/jump-if-!= break/disp8 -28607 (emit-indent *(ebp+8) *Curr-block-depth) -28608 (write-buffered *(ebp+8) "81 5/subop/subtract %esp ") -28609 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) -28610 (write-buffered *(ebp+8) "/imm32\n") -28611 eb/jump $emit-stream-data-initialization:emit-length/disp8 -28612 } -28613 (emit-indent *(ebp+8) *Curr-block-depth) -28614 (write-buffered *(ebp+8) "(push-n-zero-bytes ") -28615 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) -28616 (write-buffered *(ebp+8) ")\n") -28617 $emit-stream-data-initialization:emit-length: -28618 (emit-indent *(ebp+8) *Curr-block-depth) -28619 (write-buffered *(ebp+8) "68/push ") -28620 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) -28621 (write-buffered *(ebp+8) "/imm32\n") -28622 $emit-stream-data-initialization:end: -28623 # . restore registers -28624 58/pop-to-eax -28625 # . epilogue -28626 89/<- %esp 5/r32/ebp -28627 5d/pop-to-ebp -28628 c3/return -28629 -28630 emit-subx-stmt: # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -28631 # . prologue -28632 55/push-ebp -28633 89/<- %ebp 4/r32/esp -28634 # . save registers -28635 50/push-eax -28636 51/push-ecx -28637 # - some special-case primitives that don't actually use the 'primitives' data structure -28638 # var op/ecx: (addr array byte) = lookup(stmt->operation) -28639 8b/-> *(ebp+0xc) 1/r32/ecx -28640 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax -28641 89/<- %ecx 0/r32/eax -28642 # copy byte (can be a primitive except we need to emit a second instruction) -28643 { -28644 # if (!string-equal?(stmt->operation, "copy-byte")) break -28645 (string-equal? %ecx "copy-byte") # => eax -28646 3d/compare-eax-and 0/imm32/false -28647 0f 84/jump-if-= break/disp32 -28648 (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28649 e9/jump $emit-subx-stmt:end/disp32 -28650 } -28651 # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes -28652 # array size -28653 { -28654 # if (!string-equal?(stmt->operation, "length")) break -28655 (string-equal? %ecx "length") # => eax -28656 3d/compare-eax-and 0/imm32/false -28657 0f 84/jump-if-= break/disp32 -28658 (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28659 e9/jump $emit-subx-stmt:end/disp32 -28660 } -28661 # index into array -28662 { -28663 # if (!string-equal?(stmt->operation, "index")) break -28664 (string-equal? %ecx "index") # => eax -28665 3d/compare-eax-and 0/imm32/false -28666 0f 84/jump-if-= break/disp32 -28667 (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -28668 e9/jump $emit-subx-stmt:end/disp32 -28669 } -28670 # compute-offset for index into array -28671 { -28672 # if (!string-equal?(stmt->operation, "compute-offset")) break -28673 (string-equal? %ecx "compute-offset") # => eax -28674 3d/compare-eax-and 0/imm32/false -28675 0f 84/jump-if-= break/disp32 -28676 (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28677 e9/jump $emit-subx-stmt:end/disp32 -28678 } -28679 # get field from record -28680 { -28681 # if (!string-equal?(stmt->operation, "get")) break -28682 (string-equal? %ecx "get") # => eax -28683 3d/compare-eax-and 0/imm32/false -28684 0f 84/jump-if-= break/disp32 -28685 (translate-mu-get-stmt *(ebp+8) *(ebp+0xc)) -28686 e9/jump $emit-subx-stmt:end/disp32 -28687 } -28688 # allocate scalar -28689 { -28690 # if (!string-equal?(stmt->operation, "allocate")) break -28691 (string-equal? %ecx "allocate") # => eax -28692 3d/compare-eax-and 0/imm32/false -28693 0f 84/jump-if-= break/disp32 -28694 (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28695 e9/jump $emit-subx-stmt:end/disp32 -28696 } -28697 # copy-object -28698 { -28699 # if (!string-equal?(stmt->operation, "copy-object")) break -28700 (string-equal? %ecx "copy-object") # => eax -28701 3d/compare-eax-and 0/imm32/false -28702 0f 84/jump-if-= break/disp32 -28703 (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28704 e9/jump $emit-subx-stmt:end/disp32 -28705 } -28706 # clear-object -28707 { -28708 # if (!string-equal?(stmt->operation, "clear-object")) break -28709 (string-equal? %ecx "clear-object") # => eax -28710 3d/compare-eax-and 0/imm32/false -28711 0f 84/jump-if-= break/disp32 -28712 (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28713 e9/jump $emit-subx-stmt:end/disp32 -28714 } -28715 # allocate array -28716 { -28717 # if (!string-equal?(stmt->operation, "populate")) break -28718 (string-equal? %ecx "populate") # => eax -28719 3d/compare-eax-and 0/imm32/false -28720 0f 84/jump-if-= break/disp32 -28721 (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28722 e9/jump $emit-subx-stmt:end/disp32 -28723 } -28724 # allocate stream -28725 { -28726 # if (!string-equal?(stmt->operation, "populate-stream")) break -28727 (string-equal? %ecx "populate-stream") # => eax -28728 3d/compare-eax-and 0/imm32/false -28729 0f 84/jump-if-= break/disp32 -28730 (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28731 e9/jump $emit-subx-stmt:end/disp32 -28732 } -28733 # read from stream -28734 { -28735 # if (!string-equal?(stmt->operation, "read-from-stream")) break -28736 (string-equal? %ecx "read-from-stream") # => eax -28737 3d/compare-eax-and 0/imm32/false -28738 0f 84/jump-if-= break/disp32 -28739 (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28740 e9/jump $emit-subx-stmt:end/disp32 -28741 } -28742 # write to stream -28743 { -28744 # if (!string-equal?(stmt->operation, "write-to-stream")) break -28745 (string-equal? %ecx "write-to-stream") # => eax -28746 3d/compare-eax-and 0/imm32/false -28747 0f 84/jump-if-= break/disp32 -28748 (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) -28749 e9/jump $emit-subx-stmt:end/disp32 -28750 } -28751 # - optimizations -28752 # if copy instruction has same register in source and destination, emit nothing -28753 (redundant-copy? *(ebp+0xc)) # => eax -28754 3d/compare-eax-and 0/imm32/false -28755 75/jump-if-!= $emit-subx-stmt:end/disp8 -28756 # - if stmt matches a primitive, emit it -28757 { -28758 $emit-subx-stmt:check-for-primitive: -28759 # var curr/eax: (addr primitive) -28760 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => eax -28761 3d/compare-eax-and 0/imm32 -28762 74/jump-if-= break/disp8 -28763 $emit-subx-stmt:primitive: -28764 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -28765 e9/jump $emit-subx-stmt:end/disp32 -28766 } -28767 # - otherwise emit a call -28768 # TODO: type-checking -28769 $emit-subx-stmt:call: -28770 (emit-call *(ebp+8) *(ebp+0xc)) -28771 $emit-subx-stmt:end: -28772 # . restore registers -28773 59/pop-to-ecx -28774 58/pop-to-eax -28775 # . epilogue -28776 89/<- %esp 5/r32/ebp -28777 5d/pop-to-ebp -28778 c3/return -28779 -28780 redundant-copy?: # stmt: (addr stmt) -> result/eax: boolean -28781 # . prologue -28782 55/push-ebp -28783 89/<- %ebp 4/r32/esp -28784 # . save registers -28785 56/push-esi -28786 57/push-edi -28787 # esi = stmt -28788 8b/-> *(ebp+8) 6/r32/esi -28789 # if stmt->operation != "copy" return false -28790 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax -28791 (string-equal? %eax "copy") # => eax -28792 3d/compare-eax-and 0/imm32/false -28793 0f 84/jump-if-= $redundant-copy?:end/disp32 -28794 # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register -28795 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -28796 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -28797 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28798 # . if output-reg == null, return false -28799 3d/compare-eax-and 0/imm32 -28800 74/jump-if-= $redundant-copy?:end/disp8 -28801 89/<- %edi 0/r32/eax -28802 # return (inout->value->register == output->value->register) -28803 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -28804 # . if inout->is-deref return false -28805 81 7/subop/compare *(eax+0x10) 0/imm32/false # Stmt-var-is-deref -28806 { -28807 74/jump-if-= break/disp8 -28808 b8/copy-to-eax 0/imm32/false -28809 e9/jump $redundant-copy?:end/disp32 -28810 } -28811 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -28812 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28813 # . if inout-reg == null, return false -28814 3d/compare-eax-and 0/imm32 -28815 74/jump-if-= $redundant-copy?:end/disp8 -28816 (string-equal? %eax %edi) # => eax -28817 $redundant-copy?:end: -28818 # . restore registers -28819 5f/pop-to-edi -28820 5e/pop-to-esi -28821 # . epilogue -28822 89/<- %esp 5/r32/ebp -28823 5d/pop-to-ebp -28824 c3/return -28825 -28826 translate-mu-length-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -28827 # . prologue -28828 55/push-ebp -28829 89/<- %ebp 4/r32/esp -28830 # . save registers -28831 50/push-eax -28832 51/push-ecx -28833 52/push-edx -28834 53/push-ebx -28835 56/push-esi -28836 # esi = stmt -28837 8b/-> *(ebp+0xc) 6/r32/esi -28838 # var base/ebx: (addr var) = stmt->inouts[0]->value -28839 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -28840 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -28841 89/<- %ebx 0/r32/eax -28842 # var elemsize/ecx: int = array-element-size(base) -28843 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax -28844 89/<- %ecx 0/r32/eax -28845 # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register -28846 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -28847 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -28848 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -28849 89/<- %edx 0/r32/eax -28850 # if elemsize == 1 -28851 { -28852 81 7/subop/compare %ecx 1/imm32 -28853 75/jump-if-!= break/disp8 -28854 $translate-mu-length-stmt:size-1: -28855 (emit-save-size-to *(ebp+8) %ebx %edx) -28856 e9/jump $translate-mu-length-stmt:end/disp32 -28857 } -28858 # if elemsize is a power of 2 less than 256 -28859 { -28860 (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14)) # => eax -28861 3d/compare-eax-and 0/imm32/false -28862 74/jump-if-= break/disp8 -28863 81 7/subop/compare %ecx 0xff/imm32 -28864 7f/jump-if-> break/disp8 -28865 $translate-mu-length-stmt:size-power-of-2: -28866 (emit-save-size-to *(ebp+8) %ebx %edx) -28867 (emit-divide-by-shift-right *(ebp+8) %edx %ecx) -28868 e9/jump $translate-mu-length-stmt:end/disp32 -28869 } -28870 # otherwise, the complex case -28871 # . emit register spills -28872 { -28873 $translate-mu-length-stmt:complex: -28874 (string-equal? %edx "eax") # => eax -28875 3d/compare-eax-and 0/imm32/false -28876 75/break-if-!= break/disp8 -28877 (emit-indent *(ebp+8) *Curr-block-depth) -28878 (write-buffered *(ebp+8) "50/push-eax\n") -28879 } -28880 { -28881 (string-equal? %edx "ecx") # => eax -28882 3d/compare-eax-and 0/imm32/false -28883 75/break-if-!= break/disp8 -28884 (emit-indent *(ebp+8) *Curr-block-depth) -28885 (write-buffered *(ebp+8) "51/push-ecx\n") -28886 } -28887 { -28888 (string-equal? %edx "edx") # => eax -28889 3d/compare-eax-and 0/imm32/false -28890 75/break-if-!= break/disp8 -28891 (emit-indent *(ebp+8) *Curr-block-depth) -28892 (write-buffered *(ebp+8) "52/push-edx\n") -28893 } -28894 # . -28895 (emit-save-size-to *(ebp+8) %ebx "eax") -28896 (emit-indent *(ebp+8) *Curr-block-depth) -28897 (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n") -28898 (emit-indent *(ebp+8) *Curr-block-depth) -28899 (write-buffered *(ebp+8) "b9/copy-to-ecx ") -28900 (write-int32-hex-buffered *(ebp+8) %ecx) -28901 (write-buffered *(ebp+8) "/imm32\n") -28902 (emit-indent *(ebp+8) *Curr-block-depth) -28903 (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n") -28904 { -28905 (string-equal? %edx "eax") # => eax -28906 3d/compare-eax-and 0/imm32/false -28907 75/break-if-!= break/disp8 -28908 (emit-indent *(ebp+8) *Curr-block-depth) -28909 (write-buffered *(ebp+8) "89/<- %") -28910 (write-buffered *(ebp+8) %edx) -28911 (write-buffered *(ebp+8) " 0/r32/eax\n") -28912 } -28913 # . emit register restores -28914 { -28915 (string-equal? %edx "edx") # => eax -28916 3d/compare-eax-and 0/imm32/false -28917 75/break-if-!= break/disp8 -28918 (emit-indent *(ebp+8) *Curr-block-depth) -28919 (write-buffered *(ebp+8) "5a/pop-to-edx\n") -28920 } -28921 { -28922 (string-equal? %edx "ecx") # => eax -28923 3d/compare-eax-and 0/imm32/false -28924 75/break-if-!= break/disp8 -28925 (emit-indent *(ebp+8) *Curr-block-depth) -28926 (write-buffered *(ebp+8) "59/pop-to-ecx\n") -28927 } -28928 { -28929 (string-equal? %edx "eax") # => eax -28930 3d/compare-eax-and 0/imm32/false -28931 75/break-if-!= break/disp8 -28932 (emit-indent *(ebp+8) *Curr-block-depth) -28933 (write-buffered *(ebp+8) "58/pop-to-eax\n") -28934 } -28935 $translate-mu-length-stmt:end: -28936 # . restore registers -28937 5e/pop-to-esi -28938 5b/pop-to-ebx -28939 5a/pop-to-edx -28940 59/pop-to-ecx -28941 58/pop-to-eax -28942 # . epilogue -28943 89/<- %esp 5/r32/ebp -28944 5d/pop-to-ebp -28945 c3/return -28946 -28947 array-element-size: # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -28948 # . prologue -28949 55/push-ebp -28950 89/<- %ebp 4/r32/esp -28951 # -28952 (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -28953 (size-of-type-id-as-array-element %eax) # => eax -28954 $array-element-size:end: -28955 # . epilogue -28956 89/<- %esp 5/r32/ebp -28957 5d/pop-to-ebp -28958 c3/return -28959 -28960 array-element-type-id: # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id -28961 # precondition: n is positive -28962 # . prologue -28963 55/push-ebp -28964 89/<- %ebp 4/r32/esp -28965 # -28966 8b/-> *(ebp+8) 0/r32/eax -28967 # var t/eax: (addr type-tree) -28968 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -28969 # if t == 0 abort -28970 3d/compare-eax-with 0/imm32 -28971 0f 84/jump-if-== $array-element-type-id:error0/disp32 -28972 # if t->is-atom? abort -28973 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -28974 0f 85/jump-if-!= $array-element-type-id:error1/disp32 -28975 # if (t->left == addr) t = t->right -28976 { -28977 50/push-eax -28978 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -28979 (simple-mu-type? %eax 2) # addr => eax -28980 3d/compare-eax-with 0/imm32/false -28981 58/pop-to-eax -28982 74/jump-if-= break/disp8 -28983 $array-element-type-id:skip-addr: -28984 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -28985 } -28986 # if t == 0 abort -28987 3d/compare-eax-with 0/imm32 -28988 0f 84/jump-if-= $array-element-type-id:error2/disp32 -28989 # if t->is-atom? abort -28990 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -28991 0f 85/jump-if-!= $array-element-type-id:error2/disp32 -28992 # if t->left != array abort -28993 { -28994 50/push-eax -28995 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -28996 (simple-mu-type? %eax 3) # array => eax -28997 3d/compare-eax-with 0/imm32/false -28998 58/pop-to-eax -28999 $array-element-type-id:no-array: -29000 0f 84/jump-if-= $array-element-type-id:error2/disp32 -29001 } -29002 $array-element-type-id:skip-array: -29003 # t = t->right -29004 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -29005 # if t == 0 abort -29006 3d/compare-eax-with 0/imm32 -29007 0f 84/jump-if-= $array-element-type-id:error2/disp32 -29008 # if t->is-atom? abort -29009 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29010 0f 85/jump-if-!= $array-element-type-id:error2/disp32 -29011 # t = t->left -29012 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29013 # if (!t->is-atom?) t = t->left # TODO: assumes array element size can be determined from just first word of array element type -29014 # if (t->is-atom == false) t = lookup(t->left) -29015 { -29016 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29017 75/jump-if-!= break/disp8 -29018 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29019 } -29020 # return t->value -29021 8b/-> *(eax+4) 0/r32/eax # Type-tree-value -29022 $array-element-type-id:end: -29023 # . epilogue -29024 89/<- %esp 5/r32/ebp -29025 5d/pop-to-ebp -29026 c3/return -29027 -29028 $array-element-type-id:error0: -29029 (write-buffered *(ebp+0xc) "array-element-type-id: var '") -29030 50/push-eax -29031 8b/-> *(ebp+8) 0/r32/eax -29032 (lookup *eax *(eax+4)) # Var-name Var-name => eax -29033 (write-buffered *(ebp+0xc) %eax) -29034 58/pop-to-eax -29035 (write-buffered *(ebp+0xc) "' has no type\n") -29036 (flush *(ebp+0xc)) -29037 (stop *(ebp+0x10) 1) -29038 # never gets here -29039 -29040 $array-element-type-id:error1: -29041 (write-buffered *(ebp+0xc) "array-element-type-id: var '") -29042 50/push-eax -29043 8b/-> *(ebp+8) 0/r32/eax -29044 (lookup *eax *(eax+4)) # Var-name Var-name => eax -29045 (write-buffered *(ebp+0xc) %eax) -29046 58/pop-to-eax -29047 (write-buffered *(ebp+0xc) "' has atomic type ") -29048 (write-int32-hex-buffered *(ebp+0xc) *(eax+4)) # Type-tree-value -29049 (write-buffered *(ebp+0xc) Newline) -29050 (flush *(ebp+0xc)) -29051 (stop *(ebp+0x10) 1) -29052 # never gets here -29053 -29054 $array-element-type-id:error2: -29055 (write-buffered *(ebp+0xc) "array-element-type-id: var '") -29056 50/push-eax -29057 8b/-> *(ebp+8) 0/r32/eax -29058 (lookup *eax *(eax+4)) # Var-name Var-name => eax -29059 (write-buffered *(ebp+0xc) %eax) -29060 58/pop-to-eax -29061 (write-buffered *(ebp+0xc) "' has non-array type\n") -29062 (flush *(ebp+0xc)) -29063 (stop *(ebp+0x10) 1) -29064 # never gets here -29065 -29066 size-of-type-id-as-array-element: # t: type-id -> result/eax: int -29067 # . prologue -29068 55/push-ebp -29069 89/<- %ebp 4/r32/esp -29070 # eax = t -29071 8b/-> *(ebp+8) 0/r32/eax -29072 # if t is 'byte', size is 1 -29073 3d/compare-eax-and 8/imm32/byte -29074 { -29075 75/jump-if-!= break/disp8 -29076 b8/copy-to-eax 1/imm32 -29077 eb/jump $size-of-type-id-as-array-element:end/disp8 -29078 } -29079 # otherwise proceed as usual -29080 (size-of-type-id %eax) # => eax -29081 $size-of-type-id-as-array-element:end: -29082 # . epilogue -29083 89/<- %esp 5/r32/ebp -29084 5d/pop-to-ebp -29085 c3/return -29086 -29087 stream-element-type-id: # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id -29088 # precondition: n is positive -29089 # . prologue -29090 55/push-ebp -29091 89/<- %ebp 4/r32/esp -29092 # eax = type -29093 8b/-> *(ebp+8) 0/r32/eax -29094 # if type == 0 abort -29095 3d/compare-eax-with 0/imm32 -29096 0f 84/jump-if-== $stream-element-type-id:error0/disp32 -29097 # if type->is-atom? abort -29098 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29099 0f 85/jump-if-!= $stream-element-type-id:error1/disp32 -29100 # if (type->left == addr) type = type->right -29101 { -29102 50/push-eax -29103 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29104 (simple-mu-type? %eax 2) # addr => eax -29105 3d/compare-eax-with 0/imm32/false -29106 58/pop-to-eax -29107 74/jump-if-= break/disp8 -29108 $stream-element-type-id:skip-addr: -29109 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -29110 } -29111 # if type == 0 abort -29112 3d/compare-eax-with 0/imm32 -29113 0f 84/jump-if-= $stream-element-type-id:error2/disp32 -29114 # if type->is-atom? abort -29115 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29116 0f 85/jump-if-!= $stream-element-type-id:error2/disp32 -29117 # if type->left != stream abort -29118 { -29119 50/push-eax -29120 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29121 (simple-mu-type? %eax 0xb) # stream => eax -29122 3d/compare-eax-with 0/imm32/false -29123 58/pop-to-eax -29124 $stream-element-type-id:no-stream: -29125 0f 84/jump-if-= $stream-element-type-id:error2/disp32 -29126 } -29127 $stream-element-type-id:skip-stream: -29128 # type = type->right -29129 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -29130 # if type == 0 abort -29131 3d/compare-eax-with 0/imm32 -29132 0f 84/jump-if-= $stream-element-type-id:error2/disp32 -29133 # if type->is-atom? abort -29134 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29135 0f 85/jump-if-!= $stream-element-type-id:error2/disp32 -29136 # t = type->left -29137 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29138 # if (!type->is-atom?) type = type->left # TODO: assumes stream element size can be determined from just first word of stream element type -29139 { -29140 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29141 75/jump-if-!= break/disp8 -29142 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29143 } -29144 # return type->value -29145 8b/-> *(eax+4) 0/r32/eax # Type-tree-value -29146 $stream-element-type-id:end: -29147 # . epilogue -29148 89/<- %esp 5/r32/ebp -29149 5d/pop-to-ebp -29150 c3/return -29151 -29152 $stream-element-type-id:error0: -29153 (write-buffered *(ebp+0xc) "stream-element-type-id: var '") -29154 50/push-eax -29155 8b/-> *(ebp+8) 0/r32/eax -29156 (lookup *eax *(eax+4)) # Var-name Var-name => eax -29157 (write-buffered *(ebp+0xc) %eax) -29158 58/pop-to-eax -29159 (write-buffered *(ebp+0xc) "' has no type\n") -29160 (flush *(ebp+0xc)) -29161 (stop *(ebp+0x10) 1) -29162 # never gets here -29163 -29164 $stream-element-type-id:error1: -29165 (write-buffered *(ebp+0xc) "stream-element-type-id: var '") -29166 50/push-eax -29167 8b/-> *(ebp+8) 0/r32/eax -29168 (lookup *eax *(eax+4)) # Var-name Var-name => eax -29169 (write-buffered *(ebp+0xc) %eax) -29170 58/pop-to-eax -29171 (write-buffered *(ebp+0xc) "' has atomic type ") -29172 (write-int32-hex-buffered *(ebp+0xc) *(eax+4)) # Type-tree-value -29173 (write-buffered *(ebp+0xc) Newline) -29174 (flush *(ebp+0xc)) -29175 (stop *(ebp+0x10) 1) -29176 # never gets here -29177 -29178 $stream-element-type-id:error2: -29179 (write-buffered *(ebp+0xc) "stream-element-type-id: var '") -29180 50/push-eax -29181 8b/-> *(ebp+8) 0/r32/eax -29182 (lookup *eax *(eax+4)) # Var-name Var-name => eax -29183 (write-buffered *(ebp+0xc) %eax) -29184 58/pop-to-eax -29185 (write-buffered *(ebp+0xc) "' has non-stream type\n") -29186 (flush *(ebp+0xc)) -29187 (stop *(ebp+0x10) 1) -29188 # never gets here -29189 -29190 emit-save-size-to: # out: (addr buffered-file), base: (addr var), outreg: (addr array byte) -29191 # . prologue -29192 55/push-ebp -29193 89/<- %ebp 4/r32/esp -29194 # . save registers -29195 50/push-eax -29196 53/push-ebx -29197 # ebx = base -29198 8b/-> *(ebp+0xc) 3/r32/ebx -29199 (emit-indent *(ebp+8) *Curr-block-depth) -29200 (write-buffered *(ebp+8) "8b/-> *") -29201 # if base is an (addr array ...) in a register -29202 { -29203 81 7/subop/compare *(ebx+0x18)) 0/imm32 # Var-register -29204 74/jump-if-= break/disp8 -29205 $emit-save-size-to:emit-base-from-register: -29206 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -29207 (write-buffered *(ebp+8) %eax) -29208 eb/jump $emit-save-size-to:emit-output/disp8 -29209 } -29210 # otherwise if base is an (array ...) on the stack -29211 { -29212 81 7/subop/compare *(ebx+0x14)) 0/imm32 # Var-offset -29213 74/jump-if-= break/disp8 -29214 $emit-save-size-to:emit-base-from-stack: -29215 (write-buffered *(ebp+8) "(ebp+") -29216 (write-int32-hex-buffered *(ebp+8) *(ebx+0x14)) # Var-offset -29217 (write-buffered *(ebp+8) ")") -29218 } -29219 $emit-save-size-to:emit-output: -29220 (write-buffered *(ebp+8) " ") -29221 (get Mu-registers *(ebp+0x10) 0xc "Mu-registers") # => eax -29222 (write-int32-hex-buffered *(ebp+8) *eax) -29223 (write-buffered *(ebp+8) "/r32\n") -29224 $emit-save-size-to:end: -29225 # . restore registers -29226 5b/pop-to-ebx -29227 58/pop-to-eax -29228 # . epilogue -29229 89/<- %esp 5/r32/ebp -29230 5d/pop-to-ebp -29231 c3/return -29232 -29233 emit-divide-by-shift-right: # out: (addr buffered-file), reg: (addr array byte), size: int -29234 # . prologue -29235 55/push-ebp -29236 89/<- %ebp 4/r32/esp -29237 # . save registers -29238 50/push-eax -29239 # -29240 (emit-indent *(ebp+8) *Curr-block-depth) -29241 (write-buffered *(ebp+8) "c1/shift 5/subop/>> %") -29242 (write-buffered *(ebp+8) *(ebp+0xc)) -29243 (write-buffered *(ebp+8) Space) -29244 (num-shift-rights *(ebp+0x10)) # => eax -29245 (write-int32-hex-buffered *(ebp+8) %eax) -29246 (write-buffered *(ebp+8) "/imm8\n") -29247 $emit-divide-by-shift-right:end: -29248 # . restore registers -29249 58/pop-to-eax -29250 # . epilogue -29251 89/<- %esp 5/r32/ebp -29252 5d/pop-to-ebp -29253 c3/return -29254 -29255 translate-mu-copy-byte-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29256 # . prologue -29257 55/push-ebp -29258 89/<- %ebp 4/r32/esp -29259 # . save registers -29260 50/push-eax -29261 56/push-esi -29262 # esi = stmt -29263 8b/-> *(ebp+0xc) 6/r32/esi -29264 # -29265 (emit-indent *(ebp+8) *Curr-block-depth) -29266 (write-buffered *(ebp+8) "8a/byte->") -29267 # emit stmt->inouts[0] -29268 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29269 (emit-subx-var-as-rm32 *(ebp+8) %eax) -29270 # emit /r32 for stmt->outputs[0]->register -29271 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -29272 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29273 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29274 (maybe-get Mu-registers %eax 0xc) # => eax: (addr register-index) -29275 (write-buffered *(ebp+8) Space) -29276 (write-int32-hex-buffered *(ebp+8) *eax) -29277 (write-buffered *(ebp+8) "/r32\n") -29278 # clear rest of register -29279 (emit-indent *(ebp+8) *Curr-block-depth) -29280 (write-buffered *(ebp+8) "81 4/subop/and %") -29281 8b/-> *(ebp+0xc) 0/r32/eax -29282 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax -29283 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29284 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29285 (write-buffered *(ebp+8) %eax) -29286 (write-buffered *(ebp+8) " 0xff/imm32\n") -29287 $translate-mu-copy-byte-stmt:end: -29288 # . restore registers -29289 5e/pop-to-esi -29290 58/pop-to-eax -29291 # . epilogue -29292 89/<- %esp 5/r32/ebp -29293 5d/pop-to-ebp -29294 c3/return -29295 -29296 # a little different from other translate- functions; notice the extra 'fn' argument -29297 translate-mu-index-stmt: # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -29298 # . prologue -29299 55/push-ebp -29300 89/<- %ebp 4/r32/esp -29301 # . save registers -29302 53/push-ebx -29303 # ebx = stmt -29304 8b/-> *(ebp+0xc) 3/r32/ebx -29305 # var base/ebx: (addr var) = stmt->inouts[0] -29306 (lookup *(ebx+0xc) *(ebx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29307 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29308 89/<- %ebx 0/r32/eax -29309 # emit bounds-check -29310 (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) -29311 # if (var->register) do one thing -29312 { -29313 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register -29314 74/jump-if-= break/disp8 -29315 # TODO: ensure there's no dereference -29316 (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) -29317 eb/jump $translate-mu-index-stmt:end/disp8 -29318 } -29319 # if (var->offset) do a different thing -29320 { -29321 81 7/subop/compare *(ebx+0x14) 0/imm32 # Var-offset -29322 74/jump-if-= break/disp8 -29323 # TODO: ensure there's no dereference -29324 (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) -29325 eb/jump $translate-mu-index-stmt:end/disp8 -29326 } -29327 $translate-mu-index-stmt:end: -29328 # . restore registers -29329 5b/pop-to-ebx -29330 # . epilogue -29331 89/<- %esp 5/r32/ebp -29332 5d/pop-to-ebp -29333 c3/return -29334 -29335 $translate-mu-index-stmt:error1: -29336 (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n") -29337 (flush *(ebp+0x14)) -29338 (stop *(ebp+0x18) 1) -29339 # never gets here -29340 -29341 $translate-mu-index-stmt:error2: -29342 (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n") -29343 (flush *(ebp+0x14)) -29344 (stop *(ebp+0x18) 1) -29345 # never gets here -29346 -29347 emit-mu-index-bounds-check: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29348 # . prologue -29349 55/push-ebp -29350 89/<- %ebp 4/r32/esp -29351 # . save registers -29352 50/push-eax -29353 51/push-ecx -29354 52/push-edx -29355 53/push-ebx -29356 # ecx = stmt -29357 8b/-> *(ebp+0xc) 1/r32/ecx -29358 # -29359 (emit-indent *(ebp+8) *Curr-block-depth) -29360 (write-buffered *(ebp+8) "(__check-mu-array-bounds ") -29361 $emit-mu-index-bounds-check:compute-base: -29362 # var base/ebx: (addr var) = inouts[0] -29363 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29364 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29365 89/<- %ebx 0/r32/eax -29366 $emit-mu-index-bounds-check:emit-index: -29367 # var index/edx: (addr var) = inouts[1] -29368 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29369 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -29370 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29371 89/<- %edx 0/r32/eax -29372 # if index->register, print its code -29373 81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register -29374 { -29375 0f 84/jump-if-= break/disp32 -29376 $emit-mu-index-bounds-check:emit-register-index: -29377 (write-buffered *(ebp+8) "%") -29378 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -29379 (write-buffered *(ebp+8) %eax) -29380 eb/jump $emit-mu-index-bounds-check:index-done/disp8 -29381 } -29382 # otherwise if index is a literal, print it -29383 $emit-mu-index-bounds-check:emit-literal-index: -29384 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29385 (simple-mu-type? %eax 0) # => eax -29386 3d/compare-eax-and 0/imm32/false -29387 { -29388 0f 84/jump-if-= break/disp32 -29389 (lookup *edx *(edx+4)) # Var-name Var-name => eax -29390 (write-buffered *(ebp+8) %eax) -29391 } -29392 $emit-mu-index-bounds-check:index-done: -29393 (write-buffered *(ebp+8) " ") -29394 $emit-mu-index-bounds-check:emit-element-size: -29395 # if index is a literal or int, print size of array element -29396 { -29397 { -29398 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29399 (simple-mu-type? %eax 0) # literal => eax -29400 3d/compare-eax-and 0/imm32/false -29401 75/jump-if-!= break/disp8 -29402 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29403 (simple-mu-type? %eax 1) # int => eax -29404 3d/compare-eax-and 0/imm32/false -29405 75/jump-if-!= break/disp8 -29406 eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8 -29407 } -29408 $emit-mu-index-bounds-check:emit-int-register-index: -29409 (array-element-size %ebx *(ebp+0x14) *(ebp+0x18)) # => eax -29410 (write-int32-hex-buffered *(ebp+8) %eax) -29411 e9/jump $emit-mu-index-bounds-check:emit-base/disp32 -29412 } -29413 $emit-mu-index-bounds-check:emit-element-size-offset: -29414 # if index has type (offset ...), print "1" -29415 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29416 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +28557 # another special-case for initializing streams +28558 # a stream is an array with 2 extra pointers +28559 { +28560 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +28561 (mu-stream? %eax) # => eax +28562 3d/compare-eax-and 0/imm32/false +28563 0f 84/jump-if-= break/disp32 +28564 # var array-size-without-size/edx: int = n-12 +28565 81 5/subop/subtract %edx 0xc/imm32 +28566 (lookup *(ecx+8) *(ecx+0xc)) # Var-type Var-type => eax +28567 (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14)) +28568 # emit read and write pointers +28569 (emit-indent *(ebp+8) *Curr-block-depth) +28570 (write-buffered *(ebp+8) "68/push 0/imm32\n") +28571 (emit-indent *(ebp+8) *Curr-block-depth) +28572 (write-buffered *(ebp+8) "68/push 0/imm32\n") +28573 # +28574 eb/jump $emit-subx-var-def:end/disp8 +28575 } +28576 # while n > 0 +28577 { +28578 81 7/subop/compare %edx 0/imm32 +28579 7e/jump-if-<= break/disp8 +28580 (emit-indent *(ebp+8) *Curr-block-depth) +28581 (write-buffered *(ebp+8) "68/push 0/imm32\n") +28582 # n -= 4 +28583 81 5/subop/subtract %edx 4/imm32 +28584 # +28585 eb/jump loop/disp8 +28586 } +28587 $emit-subx-var-def:end: +28588 # . restore registers +28589 5a/pop-to-edx +28590 59/pop-to-ecx +28591 58/pop-to-eax +28592 # . epilogue +28593 89/<- %esp 5/r32/ebp +28594 5d/pop-to-ebp +28595 c3/return +28596 +28597 emit-array-data-initialization: # out: (addr buffered-file), n: int +28598 # . prologue +28599 55/push-ebp +28600 89/<- %ebp 4/r32/esp +28601 # +28602 (emit-indent *(ebp+8) *Curr-block-depth) +28603 (write-buffered *(ebp+8) "(push-n-zero-bytes ") +28604 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) +28605 (write-buffered *(ebp+8) ")\n") +28606 (emit-indent *(ebp+8) *Curr-block-depth) +28607 (write-buffered *(ebp+8) "68/push ") +28608 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) +28609 (write-buffered *(ebp+8) "/imm32\n") +28610 $emit-array-data-initialization:end: +28611 # . epilogue +28612 89/<- %esp 5/r32/ebp +28613 5d/pop-to-ebp +28614 c3/return +28615 +28616 emit-stream-data-initialization: # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) +28617 # . prologue +28618 55/push-ebp +28619 89/<- %ebp 4/r32/esp +28620 # . save registers +28621 50/push-eax +28622 # Optimization: if it's a stream of bytes, don't initialize. +28623 # +28624 # We often construct large temporary streams on the stack for 'trace' +28625 # statements. Initializing such streams can significantly slow programs +28626 # down. +28627 # +28628 # Mu doesn't really depend on initializing stream contents for type- or +28629 # memory-safety; we're mostly doing so to make it easy to debug unsafe +28630 # SubX code that misuses stream objects by manipulating read/write +28631 # pointers. But you can't _really_ protect from unsafe SubX, so I think we +28632 # don't give up much safety or security here. +28633 { +28634 (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) # => eax +28635 3d/compare-eax-and 8/imm32/byte +28636 75/jump-if-!= break/disp8 +28637 (emit-indent *(ebp+8) *Curr-block-depth) +28638 (write-buffered *(ebp+8) "81 5/subop/subtract %esp ") +28639 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) +28640 (write-buffered *(ebp+8) "/imm32\n") +28641 eb/jump $emit-stream-data-initialization:emit-length/disp8 +28642 } +28643 (emit-indent *(ebp+8) *Curr-block-depth) +28644 (write-buffered *(ebp+8) "(push-n-zero-bytes ") +28645 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) +28646 (write-buffered *(ebp+8) ")\n") +28647 $emit-stream-data-initialization:emit-length: +28648 (emit-indent *(ebp+8) *Curr-block-depth) +28649 (write-buffered *(ebp+8) "68/push ") +28650 (write-int32-hex-buffered *(ebp+8) *(ebp+0xc)) +28651 (write-buffered *(ebp+8) "/imm32\n") +28652 $emit-stream-data-initialization:end: +28653 # . restore registers +28654 58/pop-to-eax +28655 # . epilogue +28656 89/<- %esp 5/r32/ebp +28657 5d/pop-to-ebp +28658 c3/return +28659 +28660 emit-subx-stmt: # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +28661 # . prologue +28662 55/push-ebp +28663 89/<- %ebp 4/r32/esp +28664 # . save registers +28665 50/push-eax +28666 51/push-ecx +28667 # - some special-case primitives that don't actually use the 'primitives' data structure +28668 # var op/ecx: (addr array byte) = lookup(stmt->operation) +28669 8b/-> *(ebp+0xc) 1/r32/ecx +28670 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax +28671 89/<- %ecx 0/r32/eax +28672 # copy byte (can be a primitive except we need to emit a second instruction) +28673 { +28674 # if (!string-equal?(stmt->operation, "copy-byte")) break +28675 (string-equal? %ecx "copy-byte") # => eax +28676 3d/compare-eax-and 0/imm32/false +28677 0f 84/jump-if-= break/disp32 +28678 (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28679 e9/jump $emit-subx-stmt:end/disp32 +28680 } +28681 # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes +28682 # array size +28683 { +28684 # if (!string-equal?(stmt->operation, "length")) break +28685 (string-equal? %ecx "length") # => eax +28686 3d/compare-eax-and 0/imm32/false +28687 0f 84/jump-if-= break/disp32 +28688 (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28689 e9/jump $emit-subx-stmt:end/disp32 +28690 } +28691 # index into array +28692 { +28693 # if (!string-equal?(stmt->operation, "index")) break +28694 (string-equal? %ecx "index") # => eax +28695 3d/compare-eax-and 0/imm32/false +28696 0f 84/jump-if-= break/disp32 +28697 (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +28698 e9/jump $emit-subx-stmt:end/disp32 +28699 } +28700 # compute-offset for index into array +28701 { +28702 # if (!string-equal?(stmt->operation, "compute-offset")) break +28703 (string-equal? %ecx "compute-offset") # => eax +28704 3d/compare-eax-and 0/imm32/false +28705 0f 84/jump-if-= break/disp32 +28706 (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28707 e9/jump $emit-subx-stmt:end/disp32 +28708 } +28709 # get field from record +28710 { +28711 # if (!string-equal?(stmt->operation, "get")) break +28712 (string-equal? %ecx "get") # => eax +28713 3d/compare-eax-and 0/imm32/false +28714 0f 84/jump-if-= break/disp32 +28715 (translate-mu-get-stmt *(ebp+8) *(ebp+0xc)) +28716 e9/jump $emit-subx-stmt:end/disp32 +28717 } +28718 # allocate scalar +28719 { +28720 # if (!string-equal?(stmt->operation, "allocate")) break +28721 (string-equal? %ecx "allocate") # => eax +28722 3d/compare-eax-and 0/imm32/false +28723 0f 84/jump-if-= break/disp32 +28724 (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28725 e9/jump $emit-subx-stmt:end/disp32 +28726 } +28727 # copy-object +28728 { +28729 # if (!string-equal?(stmt->operation, "copy-object")) break +28730 (string-equal? %ecx "copy-object") # => eax +28731 3d/compare-eax-and 0/imm32/false +28732 0f 84/jump-if-= break/disp32 +28733 (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28734 e9/jump $emit-subx-stmt:end/disp32 +28735 } +28736 # clear-object +28737 { +28738 # if (!string-equal?(stmt->operation, "clear-object")) break +28739 (string-equal? %ecx "clear-object") # => eax +28740 3d/compare-eax-and 0/imm32/false +28741 0f 84/jump-if-= break/disp32 +28742 (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28743 e9/jump $emit-subx-stmt:end/disp32 +28744 } +28745 # allocate array +28746 { +28747 # if (!string-equal?(stmt->operation, "populate")) break +28748 (string-equal? %ecx "populate") # => eax +28749 3d/compare-eax-and 0/imm32/false +28750 0f 84/jump-if-= break/disp32 +28751 (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28752 e9/jump $emit-subx-stmt:end/disp32 +28753 } +28754 # allocate stream +28755 { +28756 # if (!string-equal?(stmt->operation, "populate-stream")) break +28757 (string-equal? %ecx "populate-stream") # => eax +28758 3d/compare-eax-and 0/imm32/false +28759 0f 84/jump-if-= break/disp32 +28760 (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28761 e9/jump $emit-subx-stmt:end/disp32 +28762 } +28763 # read from stream +28764 { +28765 # if (!string-equal?(stmt->operation, "read-from-stream")) break +28766 (string-equal? %ecx "read-from-stream") # => eax +28767 3d/compare-eax-and 0/imm32/false +28768 0f 84/jump-if-= break/disp32 +28769 (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28770 e9/jump $emit-subx-stmt:end/disp32 +28771 } +28772 # write to stream +28773 { +28774 # if (!string-equal?(stmt->operation, "write-to-stream")) break +28775 (string-equal? %ecx "write-to-stream") # => eax +28776 3d/compare-eax-and 0/imm32/false +28777 0f 84/jump-if-= break/disp32 +28778 (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c)) +28779 e9/jump $emit-subx-stmt:end/disp32 +28780 } +28781 # - optimizations +28782 # if copy instruction has same register in source and destination, emit nothing +28783 (redundant-copy? *(ebp+0xc)) # => eax +28784 3d/compare-eax-and 0/imm32/false +28785 75/jump-if-!= $emit-subx-stmt:end/disp8 +28786 # - if stmt matches a primitive, emit it +28787 { +28788 $emit-subx-stmt:check-for-primitive: +28789 # var curr/eax: (addr primitive) +28790 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => eax +28791 3d/compare-eax-and 0/imm32 +28792 74/jump-if-= break/disp8 +28793 $emit-subx-stmt:primitive: +28794 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +28795 e9/jump $emit-subx-stmt:end/disp32 +28796 } +28797 # - otherwise emit a call +28798 # TODO: type-checking +28799 $emit-subx-stmt:call: +28800 (emit-call *(ebp+8) *(ebp+0xc)) +28801 $emit-subx-stmt:end: +28802 # . restore registers +28803 59/pop-to-ecx +28804 58/pop-to-eax +28805 # . epilogue +28806 89/<- %esp 5/r32/ebp +28807 5d/pop-to-ebp +28808 c3/return +28809 +28810 redundant-copy?: # stmt: (addr stmt) -> result/eax: boolean +28811 # . prologue +28812 55/push-ebp +28813 89/<- %ebp 4/r32/esp +28814 # . save registers +28815 56/push-esi +28816 57/push-edi +28817 # esi = stmt +28818 8b/-> *(ebp+8) 6/r32/esi +28819 # if stmt->operation != "copy" return false +28820 (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax +28821 (string-equal? %eax "copy") # => eax +28822 3d/compare-eax-and 0/imm32/false +28823 0f 84/jump-if-= $redundant-copy?:end/disp32 +28824 # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register +28825 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +28826 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +28827 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28828 # . if output-reg == null, return false +28829 3d/compare-eax-and 0/imm32 +28830 74/jump-if-= $redundant-copy?:end/disp8 +28831 89/<- %edi 0/r32/eax +28832 # return (inout->value->register == output->value->register) +28833 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +28834 # . if inout->is-deref return false +28835 81 7/subop/compare *(eax+0x10) 0/imm32/false # Stmt-var-is-deref +28836 { +28837 74/jump-if-= break/disp8 +28838 b8/copy-to-eax 0/imm32/false +28839 e9/jump $redundant-copy?:end/disp32 +28840 } +28841 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +28842 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28843 # . if inout-reg == null, return false +28844 3d/compare-eax-and 0/imm32 +28845 74/jump-if-= $redundant-copy?:end/disp8 +28846 (string-equal? %eax %edi) # => eax +28847 $redundant-copy?:end: +28848 # . restore registers +28849 5f/pop-to-edi +28850 5e/pop-to-esi +28851 # . epilogue +28852 89/<- %esp 5/r32/ebp +28853 5d/pop-to-ebp +28854 c3/return +28855 +28856 translate-mu-length-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +28857 # . prologue +28858 55/push-ebp +28859 89/<- %ebp 4/r32/esp +28860 # . save registers +28861 50/push-eax +28862 51/push-ecx +28863 52/push-edx +28864 53/push-ebx +28865 56/push-esi +28866 # esi = stmt +28867 8b/-> *(ebp+0xc) 6/r32/esi +28868 # var base/ebx: (addr var) = stmt->inouts[0]->value +28869 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +28870 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +28871 89/<- %ebx 0/r32/eax +28872 # var elemsize/ecx: int = array-element-size(base) +28873 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax +28874 89/<- %ecx 0/r32/eax +28875 # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register +28876 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +28877 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +28878 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +28879 89/<- %edx 0/r32/eax +28880 # if elemsize == 1 +28881 { +28882 81 7/subop/compare %ecx 1/imm32 +28883 75/jump-if-!= break/disp8 +28884 $translate-mu-length-stmt:size-1: +28885 (emit-save-size-to *(ebp+8) %ebx %edx) +28886 e9/jump $translate-mu-length-stmt:end/disp32 +28887 } +28888 # if elemsize is a power of 2 less than 256 +28889 { +28890 (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14)) # => eax +28891 3d/compare-eax-and 0/imm32/false +28892 74/jump-if-= break/disp8 +28893 81 7/subop/compare %ecx 0xff/imm32 +28894 7f/jump-if-> break/disp8 +28895 $translate-mu-length-stmt:size-power-of-2: +28896 (emit-save-size-to *(ebp+8) %ebx %edx) +28897 (emit-divide-by-shift-right *(ebp+8) %edx %ecx) +28898 e9/jump $translate-mu-length-stmt:end/disp32 +28899 } +28900 # otherwise, the complex case +28901 # . emit register spills +28902 { +28903 $translate-mu-length-stmt:complex: +28904 (string-equal? %edx "eax") # => eax +28905 3d/compare-eax-and 0/imm32/false +28906 75/break-if-!= break/disp8 +28907 (emit-indent *(ebp+8) *Curr-block-depth) +28908 (write-buffered *(ebp+8) "50/push-eax\n") +28909 } +28910 { +28911 (string-equal? %edx "ecx") # => eax +28912 3d/compare-eax-and 0/imm32/false +28913 75/break-if-!= break/disp8 +28914 (emit-indent *(ebp+8) *Curr-block-depth) +28915 (write-buffered *(ebp+8) "51/push-ecx\n") +28916 } +28917 { +28918 (string-equal? %edx "edx") # => eax +28919 3d/compare-eax-and 0/imm32/false +28920 75/break-if-!= break/disp8 +28921 (emit-indent *(ebp+8) *Curr-block-depth) +28922 (write-buffered *(ebp+8) "52/push-edx\n") +28923 } +28924 # . +28925 (emit-save-size-to *(ebp+8) %ebx "eax") +28926 (emit-indent *(ebp+8) *Curr-block-depth) +28927 (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n") +28928 (emit-indent *(ebp+8) *Curr-block-depth) +28929 (write-buffered *(ebp+8) "b9/copy-to-ecx ") +28930 (write-int32-hex-buffered *(ebp+8) %ecx) +28931 (write-buffered *(ebp+8) "/imm32\n") +28932 (emit-indent *(ebp+8) *Curr-block-depth) +28933 (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n") +28934 { +28935 (string-equal? %edx "eax") # => eax +28936 3d/compare-eax-and 0/imm32/false +28937 75/break-if-!= break/disp8 +28938 (emit-indent *(ebp+8) *Curr-block-depth) +28939 (write-buffered *(ebp+8) "89/<- %") +28940 (write-buffered *(ebp+8) %edx) +28941 (write-buffered *(ebp+8) " 0/r32/eax\n") +28942 } +28943 # . emit register restores +28944 { +28945 (string-equal? %edx "edx") # => eax +28946 3d/compare-eax-and 0/imm32/false +28947 75/break-if-!= break/disp8 +28948 (emit-indent *(ebp+8) *Curr-block-depth) +28949 (write-buffered *(ebp+8) "5a/pop-to-edx\n") +28950 } +28951 { +28952 (string-equal? %edx "ecx") # => eax +28953 3d/compare-eax-and 0/imm32/false +28954 75/break-if-!= break/disp8 +28955 (emit-indent *(ebp+8) *Curr-block-depth) +28956 (write-buffered *(ebp+8) "59/pop-to-ecx\n") +28957 } +28958 { +28959 (string-equal? %edx "eax") # => eax +28960 3d/compare-eax-and 0/imm32/false +28961 75/break-if-!= break/disp8 +28962 (emit-indent *(ebp+8) *Curr-block-depth) +28963 (write-buffered *(ebp+8) "58/pop-to-eax\n") +28964 } +28965 $translate-mu-length-stmt:end: +28966 # . restore registers +28967 5e/pop-to-esi +28968 5b/pop-to-ebx +28969 5a/pop-to-edx +28970 59/pop-to-ecx +28971 58/pop-to-eax +28972 # . epilogue +28973 89/<- %esp 5/r32/ebp +28974 5d/pop-to-ebp +28975 c3/return +28976 +28977 array-element-size: # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +28978 # . prologue +28979 55/push-ebp +28980 89/<- %ebp 4/r32/esp +28981 # +28982 (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +28983 (size-of-type-id-as-array-element %eax) # => eax +28984 $array-element-size:end: +28985 # . epilogue +28986 89/<- %esp 5/r32/ebp +28987 5d/pop-to-ebp +28988 c3/return +28989 +28990 array-element-type-id: # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id +28991 # precondition: n is positive +28992 # . prologue +28993 55/push-ebp +28994 89/<- %ebp 4/r32/esp +28995 # +28996 8b/-> *(ebp+8) 0/r32/eax +28997 # var t/eax: (addr type-tree) +28998 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +28999 # if t == 0 abort +29000 3d/compare-eax-with 0/imm32 +29001 0f 84/jump-if-== $array-element-type-id:error0/disp32 +29002 # if t->is-atom? abort +29003 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29004 0f 85/jump-if-!= $array-element-type-id:error1/disp32 +29005 # if (t->left == addr) t = t->right +29006 { +29007 50/push-eax +29008 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29009 (simple-mu-type? %eax 2) # addr => eax +29010 3d/compare-eax-with 0/imm32/false +29011 58/pop-to-eax +29012 74/jump-if-= break/disp8 +29013 $array-element-type-id:skip-addr: +29014 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +29015 } +29016 # if t == 0 abort +29017 3d/compare-eax-with 0/imm32 +29018 0f 84/jump-if-= $array-element-type-id:error2/disp32 +29019 # if t->is-atom? abort +29020 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29021 0f 85/jump-if-!= $array-element-type-id:error2/disp32 +29022 # if t->left != array abort +29023 { +29024 50/push-eax +29025 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29026 (simple-mu-type? %eax 3) # array => eax +29027 3d/compare-eax-with 0/imm32/false +29028 58/pop-to-eax +29029 $array-element-type-id:no-array: +29030 0f 84/jump-if-= $array-element-type-id:error2/disp32 +29031 } +29032 $array-element-type-id:skip-array: +29033 # t = t->right +29034 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +29035 # if t == 0 abort +29036 3d/compare-eax-with 0/imm32 +29037 0f 84/jump-if-= $array-element-type-id:error2/disp32 +29038 # if t->is-atom? abort +29039 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29040 0f 85/jump-if-!= $array-element-type-id:error2/disp32 +29041 # t = t->left +29042 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29043 # if (!t->is-atom?) t = t->left # TODO: assumes array element size can be determined from just first word of array element type +29044 # if (t->is-atom == false) t = lookup(t->left) +29045 { +29046 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29047 75/jump-if-!= break/disp8 +29048 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29049 } +29050 # return t->value +29051 8b/-> *(eax+4) 0/r32/eax # Type-tree-value +29052 $array-element-type-id:end: +29053 # . epilogue +29054 89/<- %esp 5/r32/ebp +29055 5d/pop-to-ebp +29056 c3/return +29057 +29058 $array-element-type-id:error0: +29059 (write-buffered *(ebp+0xc) "array-element-type-id: var '") +29060 50/push-eax +29061 8b/-> *(ebp+8) 0/r32/eax +29062 (lookup *eax *(eax+4)) # Var-name Var-name => eax +29063 (write-buffered *(ebp+0xc) %eax) +29064 58/pop-to-eax +29065 (write-buffered *(ebp+0xc) "' has no type\n") +29066 (flush *(ebp+0xc)) +29067 (stop *(ebp+0x10) 1) +29068 # never gets here +29069 +29070 $array-element-type-id:error1: +29071 (write-buffered *(ebp+0xc) "array-element-type-id: var '") +29072 50/push-eax +29073 8b/-> *(ebp+8) 0/r32/eax +29074 (lookup *eax *(eax+4)) # Var-name Var-name => eax +29075 (write-buffered *(ebp+0xc) %eax) +29076 58/pop-to-eax +29077 (write-buffered *(ebp+0xc) "' has atomic type ") +29078 (write-int32-hex-buffered *(ebp+0xc) *(eax+4)) # Type-tree-value +29079 (write-buffered *(ebp+0xc) Newline) +29080 (flush *(ebp+0xc)) +29081 (stop *(ebp+0x10) 1) +29082 # never gets here +29083 +29084 $array-element-type-id:error2: +29085 (write-buffered *(ebp+0xc) "array-element-type-id: var '") +29086 50/push-eax +29087 8b/-> *(ebp+8) 0/r32/eax +29088 (lookup *eax *(eax+4)) # Var-name Var-name => eax +29089 (write-buffered *(ebp+0xc) %eax) +29090 58/pop-to-eax +29091 (write-buffered *(ebp+0xc) "' has non-array type\n") +29092 (flush *(ebp+0xc)) +29093 (stop *(ebp+0x10) 1) +29094 # never gets here +29095 +29096 size-of-type-id-as-array-element: # t: type-id -> result/eax: int +29097 # . prologue +29098 55/push-ebp +29099 89/<- %ebp 4/r32/esp +29100 # eax = t +29101 8b/-> *(ebp+8) 0/r32/eax +29102 # if t is 'byte', size is 1 +29103 3d/compare-eax-and 8/imm32/byte +29104 { +29105 75/jump-if-!= break/disp8 +29106 b8/copy-to-eax 1/imm32 +29107 eb/jump $size-of-type-id-as-array-element:end/disp8 +29108 } +29109 # otherwise proceed as usual +29110 (size-of-type-id %eax) # => eax +29111 $size-of-type-id-as-array-element:end: +29112 # . epilogue +29113 89/<- %esp 5/r32/ebp +29114 5d/pop-to-ebp +29115 c3/return +29116 +29117 stream-element-type-id: # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id +29118 # precondition: n is positive +29119 # . prologue +29120 55/push-ebp +29121 89/<- %ebp 4/r32/esp +29122 # eax = type +29123 8b/-> *(ebp+8) 0/r32/eax +29124 # if type == 0 abort +29125 3d/compare-eax-with 0/imm32 +29126 0f 84/jump-if-== $stream-element-type-id:error0/disp32 +29127 # if type->is-atom? abort +29128 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29129 0f 85/jump-if-!= $stream-element-type-id:error1/disp32 +29130 # if (type->left == addr) type = type->right +29131 { +29132 50/push-eax +29133 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29134 (simple-mu-type? %eax 2) # addr => eax +29135 3d/compare-eax-with 0/imm32/false +29136 58/pop-to-eax +29137 74/jump-if-= break/disp8 +29138 $stream-element-type-id:skip-addr: +29139 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +29140 } +29141 # if type == 0 abort +29142 3d/compare-eax-with 0/imm32 +29143 0f 84/jump-if-= $stream-element-type-id:error2/disp32 +29144 # if type->is-atom? abort +29145 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29146 0f 85/jump-if-!= $stream-element-type-id:error2/disp32 +29147 # if type->left != stream abort +29148 { +29149 50/push-eax +29150 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29151 (simple-mu-type? %eax 0xb) # stream => eax +29152 3d/compare-eax-with 0/imm32/false +29153 58/pop-to-eax +29154 $stream-element-type-id:no-stream: +29155 0f 84/jump-if-= $stream-element-type-id:error2/disp32 +29156 } +29157 $stream-element-type-id:skip-stream: +29158 # type = type->right +29159 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +29160 # if type == 0 abort +29161 3d/compare-eax-with 0/imm32 +29162 0f 84/jump-if-= $stream-element-type-id:error2/disp32 +29163 # if type->is-atom? abort +29164 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29165 0f 85/jump-if-!= $stream-element-type-id:error2/disp32 +29166 # t = type->left +29167 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29168 # if (!type->is-atom?) type = type->left # TODO: assumes stream element size can be determined from just first word of stream element type +29169 { +29170 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29171 75/jump-if-!= break/disp8 +29172 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29173 } +29174 # return type->value +29175 8b/-> *(eax+4) 0/r32/eax # Type-tree-value +29176 $stream-element-type-id:end: +29177 # . epilogue +29178 89/<- %esp 5/r32/ebp +29179 5d/pop-to-ebp +29180 c3/return +29181 +29182 $stream-element-type-id:error0: +29183 (write-buffered *(ebp+0xc) "stream-element-type-id: var '") +29184 50/push-eax +29185 8b/-> *(ebp+8) 0/r32/eax +29186 (lookup *eax *(eax+4)) # Var-name Var-name => eax +29187 (write-buffered *(ebp+0xc) %eax) +29188 58/pop-to-eax +29189 (write-buffered *(ebp+0xc) "' has no type\n") +29190 (flush *(ebp+0xc)) +29191 (stop *(ebp+0x10) 1) +29192 # never gets here +29193 +29194 $stream-element-type-id:error1: +29195 (write-buffered *(ebp+0xc) "stream-element-type-id: var '") +29196 50/push-eax +29197 8b/-> *(ebp+8) 0/r32/eax +29198 (lookup *eax *(eax+4)) # Var-name Var-name => eax +29199 (write-buffered *(ebp+0xc) %eax) +29200 58/pop-to-eax +29201 (write-buffered *(ebp+0xc) "' has atomic type ") +29202 (write-int32-hex-buffered *(ebp+0xc) *(eax+4)) # Type-tree-value +29203 (write-buffered *(ebp+0xc) Newline) +29204 (flush *(ebp+0xc)) +29205 (stop *(ebp+0x10) 1) +29206 # never gets here +29207 +29208 $stream-element-type-id:error2: +29209 (write-buffered *(ebp+0xc) "stream-element-type-id: var '") +29210 50/push-eax +29211 8b/-> *(ebp+8) 0/r32/eax +29212 (lookup *eax *(eax+4)) # Var-name Var-name => eax +29213 (write-buffered *(ebp+0xc) %eax) +29214 58/pop-to-eax +29215 (write-buffered *(ebp+0xc) "' has non-stream type\n") +29216 (flush *(ebp+0xc)) +29217 (stop *(ebp+0x10) 1) +29218 # never gets here +29219 +29220 emit-save-size-to: # out: (addr buffered-file), base: (addr var), outreg: (addr array byte) +29221 # . prologue +29222 55/push-ebp +29223 89/<- %ebp 4/r32/esp +29224 # . save registers +29225 50/push-eax +29226 53/push-ebx +29227 # ebx = base +29228 8b/-> *(ebp+0xc) 3/r32/ebx +29229 (emit-indent *(ebp+8) *Curr-block-depth) +29230 (write-buffered *(ebp+8) "8b/-> *") +29231 # if base is an (addr array ...) in a register +29232 { +29233 81 7/subop/compare *(ebx+0x18)) 0/imm32 # Var-register +29234 74/jump-if-= break/disp8 +29235 $emit-save-size-to:emit-base-from-register: +29236 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +29237 (write-buffered *(ebp+8) %eax) +29238 eb/jump $emit-save-size-to:emit-output/disp8 +29239 } +29240 # otherwise if base is an (array ...) on the stack +29241 { +29242 81 7/subop/compare *(ebx+0x14)) 0/imm32 # Var-offset +29243 74/jump-if-= break/disp8 +29244 $emit-save-size-to:emit-base-from-stack: +29245 (write-buffered *(ebp+8) "(ebp+") +29246 (write-int32-hex-buffered *(ebp+8) *(ebx+0x14)) # Var-offset +29247 (write-buffered *(ebp+8) ")") +29248 } +29249 $emit-save-size-to:emit-output: +29250 (write-buffered *(ebp+8) " ") +29251 (get Mu-registers *(ebp+0x10) 0xc "Mu-registers") # => eax +29252 (write-int32-hex-buffered *(ebp+8) *eax) +29253 (write-buffered *(ebp+8) "/r32\n") +29254 $emit-save-size-to:end: +29255 # . restore registers +29256 5b/pop-to-ebx +29257 58/pop-to-eax +29258 # . epilogue +29259 89/<- %esp 5/r32/ebp +29260 5d/pop-to-ebp +29261 c3/return +29262 +29263 emit-divide-by-shift-right: # out: (addr buffered-file), reg: (addr array byte), size: int +29264 # . prologue +29265 55/push-ebp +29266 89/<- %ebp 4/r32/esp +29267 # . save registers +29268 50/push-eax +29269 # +29270 (emit-indent *(ebp+8) *Curr-block-depth) +29271 (write-buffered *(ebp+8) "c1/shift 5/subop/>> %") +29272 (write-buffered *(ebp+8) *(ebp+0xc)) +29273 (write-buffered *(ebp+8) Space) +29274 (num-shift-rights *(ebp+0x10)) # => eax +29275 (write-int32-hex-buffered *(ebp+8) %eax) +29276 (write-buffered *(ebp+8) "/imm8\n") +29277 $emit-divide-by-shift-right:end: +29278 # . restore registers +29279 58/pop-to-eax +29280 # . epilogue +29281 89/<- %esp 5/r32/ebp +29282 5d/pop-to-ebp +29283 c3/return +29284 +29285 translate-mu-copy-byte-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29286 # . prologue +29287 55/push-ebp +29288 89/<- %ebp 4/r32/esp +29289 # . save registers +29290 50/push-eax +29291 56/push-esi +29292 # esi = stmt +29293 8b/-> *(ebp+0xc) 6/r32/esi +29294 # +29295 (emit-indent *(ebp+8) *Curr-block-depth) +29296 (write-buffered *(ebp+8) "8a/byte->") +29297 # emit stmt->inouts[0] +29298 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29299 (emit-subx-var-as-rm32 *(ebp+8) %eax) +29300 # emit /r32 for stmt->outputs[0]->register +29301 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +29302 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29303 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29304 (maybe-get Mu-registers %eax 0xc) # => eax: (addr register-index) +29305 (write-buffered *(ebp+8) Space) +29306 (write-int32-hex-buffered *(ebp+8) *eax) +29307 (write-buffered *(ebp+8) "/r32\n") +29308 # clear rest of register +29309 (emit-indent *(ebp+8) *Curr-block-depth) +29310 (write-buffered *(ebp+8) "81 4/subop/and %") +29311 8b/-> *(ebp+0xc) 0/r32/eax +29312 (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax +29313 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29314 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29315 (write-buffered *(ebp+8) %eax) +29316 (write-buffered *(ebp+8) " 0xff/imm32\n") +29317 $translate-mu-copy-byte-stmt:end: +29318 # . restore registers +29319 5e/pop-to-esi +29320 58/pop-to-eax +29321 # . epilogue +29322 89/<- %esp 5/r32/ebp +29323 5d/pop-to-ebp +29324 c3/return +29325 +29326 # a little different from other translate- functions; notice the extra 'fn' argument +29327 translate-mu-index-stmt: # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +29328 # . prologue +29329 55/push-ebp +29330 89/<- %ebp 4/r32/esp +29331 # . save registers +29332 53/push-ebx +29333 # ebx = stmt +29334 8b/-> *(ebp+0xc) 3/r32/ebx +29335 # var base/ebx: (addr var) = stmt->inouts[0] +29336 (lookup *(ebx+0xc) *(ebx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29337 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29338 89/<- %ebx 0/r32/eax +29339 # emit bounds-check +29340 (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) +29341 # if (var->register) do one thing +29342 { +29343 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register +29344 74/jump-if-= break/disp8 +29345 # TODO: ensure there's no dereference +29346 (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) +29347 eb/jump $translate-mu-index-stmt:end/disp8 +29348 } +29349 # if (var->offset) do a different thing +29350 { +29351 81 7/subop/compare *(ebx+0x14) 0/imm32 # Var-offset +29352 74/jump-if-= break/disp8 +29353 # TODO: ensure there's no dereference +29354 (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) +29355 eb/jump $translate-mu-index-stmt:end/disp8 +29356 } +29357 $translate-mu-index-stmt:end: +29358 # . restore registers +29359 5b/pop-to-ebx +29360 # . epilogue +29361 89/<- %esp 5/r32/ebp +29362 5d/pop-to-ebp +29363 c3/return +29364 +29365 $translate-mu-index-stmt:error1: +29366 (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n") +29367 (flush *(ebp+0x14)) +29368 (stop *(ebp+0x18) 1) +29369 # never gets here +29370 +29371 $translate-mu-index-stmt:error2: +29372 (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n") +29373 (flush *(ebp+0x14)) +29374 (stop *(ebp+0x18) 1) +29375 # never gets here +29376 +29377 emit-mu-index-bounds-check: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29378 # . prologue +29379 55/push-ebp +29380 89/<- %ebp 4/r32/esp +29381 # . save registers +29382 50/push-eax +29383 51/push-ecx +29384 52/push-edx +29385 53/push-ebx +29386 # ecx = stmt +29387 8b/-> *(ebp+0xc) 1/r32/ecx +29388 # +29389 (emit-indent *(ebp+8) *Curr-block-depth) +29390 (write-buffered *(ebp+8) "(__check-mu-array-bounds ") +29391 $emit-mu-index-bounds-check:compute-base: +29392 # var base/ebx: (addr var) = inouts[0] +29393 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29394 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29395 89/<- %ebx 0/r32/eax +29396 $emit-mu-index-bounds-check:emit-index: +29397 # var index/edx: (addr var) = inouts[1] +29398 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29399 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +29400 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29401 89/<- %edx 0/r32/eax +29402 # if index->register, print its code +29403 81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register +29404 { +29405 0f 84/jump-if-= break/disp32 +29406 $emit-mu-index-bounds-check:emit-register-index: +29407 (write-buffered *(ebp+8) "%") +29408 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +29409 (write-buffered *(ebp+8) %eax) +29410 eb/jump $emit-mu-index-bounds-check:index-done/disp8 +29411 } +29412 # otherwise if index is a literal, print it +29413 $emit-mu-index-bounds-check:emit-literal-index: +29414 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29415 (simple-mu-type? %eax 0) # => eax +29416 3d/compare-eax-and 0/imm32/false 29417 { -29418 75/jump-if-!= break/disp8 -29419 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29420 (simple-mu-type? %eax 7) # => eax -29421 3d/compare-eax-and 0/imm32/false -29422 { -29423 0f 84/jump-if-= break/disp32 -29424 $emit-mu-index-bounds-check:emit-offset-register-index: -29425 (write-buffered *(ebp+8) "1") -29426 } -29427 } -29428 $emit-mu-index-bounds-check:emit-base: -29429 # if base is in a register, print " *" base->register -29430 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register -29431 { -29432 74/jump-if-= break/disp8 -29433 (write-buffered *(ebp+8) " *") -29434 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -29435 (write-buffered *(ebp+8) %eax) -29436 e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32 -29437 } -29438 # otherwise print " *(ebp+" base->offset ")" -29439 (write-buffered *(ebp+8) " *(ebp+") -29440 (write-int32-hex-buffered *(ebp+8) *(ebx+0x14)) # Var-offset -29441 (write-buffered *(ebp+8) ")") -29442 $emit-mu-index-bounds-check:emit-function-name: -29443 # " \"" function-name "\"" -29444 (write-buffered *(ebp+8) " \"") -29445 8b/-> *(ebp+0x10) 1/r32/ecx -29446 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax -29447 (write-buffered *(ebp+8) %eax) -29448 (write-buffered *(ebp+8) "\"") -29449 $emit-mu-index-bounds-check:emit-array-name: -29450 # " \"" base->name "\"" -29451 (write-buffered *(ebp+8) " \"") -29452 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax -29453 (write-buffered *(ebp+8) %eax) -29454 (write-buffered *(ebp+8) "\")\n") -29455 $emit-mu-index-bounds-check:end: -29456 # . restore registers -29457 5b/pop-to-ebx -29458 5a/pop-to-edx -29459 59/pop-to-ecx -29460 58/pop-to-eax -29461 # . epilogue -29462 89/<- %esp 5/r32/ebp -29463 5d/pop-to-ebp -29464 c3/return -29465 -29466 translate-mu-index-stmt-with-array-in-register: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29467 # . prologue -29468 55/push-ebp -29469 89/<- %ebp 4/r32/esp -29470 # . save registers -29471 50/push-eax -29472 51/push-ecx -29473 52/push-edx -29474 53/push-ebx -29475 # -29476 (emit-indent *(ebp+8) *Curr-block-depth) -29477 (write-buffered *(ebp+8) "8d/copy-address *(") -29478 # TODO: ensure inouts[0] is in a register and not dereferenced -29479 $translate-mu-index-stmt-with-array-in-register:emit-base: -29480 # ecx = stmt -29481 8b/-> *(ebp+0xc) 1/r32/ecx -29482 # var base/ebx: (addr var) = inouts[0] -29483 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29484 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29485 89/<- %ebx 0/r32/eax -29486 # print base->register " + " -29487 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax -29488 (write-buffered *(ebp+8) %eax) -29489 (write-buffered *(ebp+8) " + ") -29490 # var index/edx: (addr var) = inouts[1] -29491 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29492 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -29493 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29494 89/<- %edx 0/r32/eax -29495 # if index->register -29496 81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register -29497 { -29498 0f 84/jump-if-= break/disp32 -29499 $translate-mu-index-stmt-with-array-in-register:emit-register-index: -29500 # if index is an int -29501 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29502 (simple-mu-type? %eax 1) # int => eax -29503 3d/compare-eax-and 0/imm32/false -29504 { -29505 0f 84/jump-if-= break/disp32 -29506 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index: -29507 # print index->register "<<" log2(array-element-size(base)) " + 4) " -29508 # . index->register "<<" -29509 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -29510 (write-buffered *(ebp+8) %eax) -29511 (write-buffered *(ebp+8) "<<") -29512 # . log2(array-element-size(base->type)) -29513 # we know size is a power of 2 -29514 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax -29515 (num-shift-rights %eax) # => eax -29516 (write-int32-hex-buffered *(ebp+8) %eax) -29517 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32 -29518 } -29519 # if index->type is any other atom, abort -29520 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29521 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29522 0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32 -29523 # if index has type (offset ...) -29524 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29525 (simple-mu-type? %eax 7) # => eax -29526 3d/compare-eax-and 0/imm32/false -29527 { -29528 0f 84/jump-if-= break/disp32 -29529 # print index->register -29530 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index: -29531 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -29532 (write-buffered *(ebp+8) %eax) -29533 } -29534 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done: -29535 (write-buffered *(ebp+8) " + 4) ") -29536 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 -29537 } -29538 # otherwise if index is a literal -29539 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29540 (simple-mu-type? %eax 0) # => eax -29541 3d/compare-eax-and 0/imm32/false -29542 { -29543 0f 84/jump-if-= break/disp32 -29544 $translate-mu-index-stmt-with-array-in-register:emit-literal-index: -29545 # var index-value/edx: int = parse-hex-int(index->name) -29546 (lookup *edx *(edx+4)) # Var-name Var-name => eax -29547 (parse-hex-int %eax) # => eax -29548 89/<- %edx 0/r32/eax -29549 # offset = idx-value * array-element-size(base->type) -29550 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax -29551 f7 4/subop/multiply-into-edx-eax %edx # clobbers edx -29552 # offset += 4 for array size -29553 05/add-to-eax 4/imm32 -29554 # TODO: check edx for overflow -29555 # print offset -29556 (write-int32-hex-buffered *(ebp+8) %eax) -29557 (write-buffered *(ebp+8) ") ") -29558 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 -29559 } -29560 # otherwise abort -29561 e9/jump $translate-mu-index-stmt:error1/disp32 -29562 $translate-mu-index-stmt-with-array-in-register:emit-output: -29563 # outputs[0] "/r32" -29564 8b/-> *(ebp+0xc) 1/r32/ecx -29565 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax -29566 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29567 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29568 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) -29569 (write-int32-hex-buffered *(ebp+8) *eax) -29570 (write-buffered *(ebp+8) "/r32\n") -29571 $translate-mu-index-stmt-with-array-in-register:end: -29572 # . restore registers -29573 5b/pop-to-ebx -29574 5a/pop-to-edx -29575 59/pop-to-ecx -29576 58/pop-to-eax -29577 # . epilogue -29578 89/<- %esp 5/r32/ebp -29579 5d/pop-to-ebp -29580 c3/return -29581 -29582 translate-mu-index-stmt-with-array-on-stack: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29583 # . prologue -29584 55/push-ebp -29585 89/<- %ebp 4/r32/esp -29586 # . save registers -29587 50/push-eax -29588 51/push-ecx -29589 52/push-edx -29590 53/push-ebx -29591 # -29592 (emit-indent *(ebp+8) *Curr-block-depth) -29593 (write-buffered *(ebp+8) "8d/copy-address *(ebp + ") -29594 # var curr/edx: (addr stmt-var) = lookup(stmt->inouts) -29595 8b/-> *(ebp+0xc) 0/r32/eax -29596 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29597 89/<- %edx 0/r32/eax -29598 # var base/ecx: (addr var) = lookup(curr->value) -29599 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29600 89/<- %ecx 0/r32/eax -29601 # var curr2/eax: (addr stmt-var) = lookup(curr->next) -29602 (lookup *(edx+8) *(edx+0xc)) # Stmt-var-next Stmt-var-next => eax -29603 # var index/edx: (handle var) = curr2->value +29418 0f 84/jump-if-= break/disp32 +29419 (lookup *edx *(edx+4)) # Var-name Var-name => eax +29420 (write-buffered *(ebp+8) %eax) +29421 } +29422 $emit-mu-index-bounds-check:index-done: +29423 (write-buffered *(ebp+8) " ") +29424 $emit-mu-index-bounds-check:emit-element-size: +29425 # if index is a literal or int, print size of array element +29426 { +29427 { +29428 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29429 (simple-mu-type? %eax 0) # literal => eax +29430 3d/compare-eax-and 0/imm32/false +29431 75/jump-if-!= break/disp8 +29432 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29433 (simple-mu-type? %eax 1) # int => eax +29434 3d/compare-eax-and 0/imm32/false +29435 75/jump-if-!= break/disp8 +29436 eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8 +29437 } +29438 $emit-mu-index-bounds-check:emit-int-register-index: +29439 (array-element-size %ebx *(ebp+0x14) *(ebp+0x18)) # => eax +29440 (write-int32-hex-buffered *(ebp+8) %eax) +29441 e9/jump $emit-mu-index-bounds-check:emit-base/disp32 +29442 } +29443 $emit-mu-index-bounds-check:emit-element-size-offset: +29444 # if index has type (offset ...), print "1" +29445 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29446 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29447 { +29448 75/jump-if-!= break/disp8 +29449 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29450 (simple-mu-type? %eax 7) # => eax +29451 3d/compare-eax-and 0/imm32/false +29452 { +29453 0f 84/jump-if-= break/disp32 +29454 $emit-mu-index-bounds-check:emit-offset-register-index: +29455 (write-buffered *(ebp+8) "1") +29456 } +29457 } +29458 $emit-mu-index-bounds-check:emit-base: +29459 # if base is in a register, print " *" base->register +29460 81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register +29461 { +29462 74/jump-if-= break/disp8 +29463 (write-buffered *(ebp+8) " *") +29464 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +29465 (write-buffered *(ebp+8) %eax) +29466 e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32 +29467 } +29468 # otherwise print " *(ebp+" base->offset ")" +29469 (write-buffered *(ebp+8) " *(ebp+") +29470 (write-int32-hex-buffered *(ebp+8) *(ebx+0x14)) # Var-offset +29471 (write-buffered *(ebp+8) ")") +29472 $emit-mu-index-bounds-check:emit-function-name: +29473 # " \"" function-name "\"" +29474 (write-buffered *(ebp+8) " \"") +29475 8b/-> *(ebp+0x10) 1/r32/ecx +29476 (lookup *ecx *(ecx+4)) # Function-name Function-name => eax +29477 (write-buffered *(ebp+8) %eax) +29478 (write-buffered *(ebp+8) "\"") +29479 $emit-mu-index-bounds-check:emit-array-name: +29480 # " \"" base->name "\"" +29481 (write-buffered *(ebp+8) " \"") +29482 (lookup *ebx *(ebx+4)) # Var-name Var-name => eax +29483 (write-buffered *(ebp+8) %eax) +29484 (write-buffered *(ebp+8) "\")\n") +29485 $emit-mu-index-bounds-check:end: +29486 # . restore registers +29487 5b/pop-to-ebx +29488 5a/pop-to-edx +29489 59/pop-to-ecx +29490 58/pop-to-eax +29491 # . epilogue +29492 89/<- %esp 5/r32/ebp +29493 5d/pop-to-ebp +29494 c3/return +29495 +29496 translate-mu-index-stmt-with-array-in-register: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29497 # . prologue +29498 55/push-ebp +29499 89/<- %ebp 4/r32/esp +29500 # . save registers +29501 50/push-eax +29502 51/push-ecx +29503 52/push-edx +29504 53/push-ebx +29505 # ecx = stmt +29506 8b/-> *(ebp+0xc) 1/r32/ecx +29507 # var base/ebx: (addr var) = inouts[0] +29508 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29509 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29510 89/<- %ebx 0/r32/eax +29511 # emit null check +29512 (emit-indent *(ebp+8) *Curr-block-depth) +29513 (write-buffered *(ebp+8) "81 7/subop/compare %") +29514 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +29515 (write-buffered *(ebp+8) %eax) +29516 (write-buffered *(ebp+8) " 0/imm32\n") +29517 (emit-indent *(ebp+8) *Curr-block-depth) +29518 (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-index-base-address/disp32\n") +29519 # +29520 (emit-indent *(ebp+8) *Curr-block-depth) +29521 (write-buffered *(ebp+8) "8d/copy-address *(") +29522 # TODO: ensure inouts[0] is in a register and not dereferenced +29523 $translate-mu-index-stmt-with-array-in-register:emit-base: +29524 # print base->register " + " +29525 (lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax +29526 (write-buffered *(ebp+8) %eax) +29527 (write-buffered *(ebp+8) " + ") +29528 # var index/edx: (addr var) = inouts[1] +29529 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29530 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +29531 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29532 89/<- %edx 0/r32/eax +29533 # if index->register +29534 81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register +29535 { +29536 0f 84/jump-if-= break/disp32 +29537 $translate-mu-index-stmt-with-array-in-register:emit-register-index: +29538 # if index is an int +29539 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29540 (simple-mu-type? %eax 1) # int => eax +29541 3d/compare-eax-and 0/imm32/false +29542 { +29543 0f 84/jump-if-= break/disp32 +29544 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index: +29545 # print index->register "<<" log2(array-element-size(base)) " + 4) " +29546 # . index->register "<<" +29547 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +29548 (write-buffered *(ebp+8) %eax) +29549 (write-buffered *(ebp+8) "<<") +29550 # . log2(array-element-size(base->type)) +29551 # we know size is a power of 2 +29552 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax +29553 (num-shift-rights %eax) # => eax +29554 (write-int32-hex-buffered *(ebp+8) %eax) +29555 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32 +29556 } +29557 # if index->type is any other atom, abort +29558 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29559 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29560 0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32 +29561 # if index has type (offset ...) +29562 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29563 (simple-mu-type? %eax 7) # => eax +29564 3d/compare-eax-and 0/imm32/false +29565 { +29566 0f 84/jump-if-= break/disp32 +29567 # print index->register +29568 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index: +29569 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +29570 (write-buffered *(ebp+8) %eax) +29571 } +29572 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done: +29573 (write-buffered *(ebp+8) " + 4) ") +29574 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 +29575 } +29576 # otherwise if index is a literal +29577 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29578 (simple-mu-type? %eax 0) # => eax +29579 3d/compare-eax-and 0/imm32/false +29580 { +29581 0f 84/jump-if-= break/disp32 +29582 $translate-mu-index-stmt-with-array-in-register:emit-literal-index: +29583 # var index-value/edx: int = parse-hex-int(index->name) +29584 (lookup *edx *(edx+4)) # Var-name Var-name => eax +29585 (parse-hex-int %eax) # => eax +29586 89/<- %edx 0/r32/eax +29587 # offset = idx-value * array-element-size(base->type) +29588 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax +29589 f7 4/subop/multiply-into-edx-eax %edx # clobbers edx +29590 # offset += 4 for array size +29591 05/add-to-eax 4/imm32 +29592 # TODO: check edx for overflow +29593 # print offset +29594 (write-int32-hex-buffered *(ebp+8) %eax) +29595 (write-buffered *(ebp+8) ") ") +29596 e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32 +29597 } +29598 # otherwise abort +29599 e9/jump $translate-mu-index-stmt:error1/disp32 +29600 $translate-mu-index-stmt-with-array-in-register:emit-output: +29601 # outputs[0] "/r32" +29602 8b/-> *(ebp+0xc) 1/r32/ecx +29603 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax 29604 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29605 89/<- %edx 0/r32/eax -29606 # if index->register -29607 81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register -29608 { -29609 0f 84/jump-if-= break/disp32 -29610 $translate-mu-index-stmt-with-array-on-stack:emit-register-index: -29611 # if index is an int -29612 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29613 (simple-mu-type? %eax 1) # int => eax -29614 3d/compare-eax-and 0/imm32/false -29615 { -29616 0f 84/jump-if-= break/disp32 -29617 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index: -29618 # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4 -29619 # . inouts[1]->register "<<" -29620 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -29621 (write-buffered *(ebp+8) %eax) -29622 (write-buffered *(ebp+8) "<<") -29623 # . log2(array-element-size(base)) -29624 # TODO: ensure size is a power of 2 -29625 (array-element-size %ecx *(ebp+0x10) *(ebp+0x14)) # => eax -29626 (num-shift-rights %eax) # => eax -29627 (write-int32-hex-buffered *(ebp+8) %eax) -29628 # -29629 (write-buffered *(ebp+8) " + ") -29630 # -29631 8b/-> *(ecx+0x14) 0/r32/eax # Var-offset -29632 05/add-to-eax 4/imm32 # for array length -29633 (write-int32-hex-buffered *(ebp+8) %eax) -29634 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32 -29635 } -29636 # if index->type is any other atom, abort -29637 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29638 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -29639 0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32 -29640 # if index has type (offset ...) -29641 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29642 (simple-mu-type? %eax 7) # => eax -29643 3d/compare-eax-and 0/imm32/false -29644 { -29645 0f 84/jump-if-= break/disp32 -29646 # print index->register -29647 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index: -29648 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax -29649 (write-buffered *(ebp+8) %eax) -29650 } -29651 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done: -29652 (write-buffered *(ebp+8) ") ") -29653 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 -29654 } -29655 # otherwise if index is a literal -29656 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax -29657 (simple-mu-type? %eax 0) # => eax -29658 3d/compare-eax-and 0/imm32/false -29659 { -29660 0f 84/jump-if-= break/disp32 -29661 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index: -29662 # var idx-value/edx: int = parse-hex-int(index->name) -29663 (lookup *edx *(edx+4)) # Var-name Var-name => eax -29664 (parse-hex-int %eax) # Var-name => eax -29665 89/<- %edx 0/r32/eax -29666 # offset = idx-value * array-element-size(base) -29667 (array-element-size %ecx *(ebp+0x10) *(ebp+0x14)) # => eax -29668 f7 4/subop/multiply-into-edx-eax %edx # clobbers edx -29669 # offset += base->offset -29670 03/add *(ecx+0x14) 0/r32/eax # Var-offset -29671 # offset += 4 for array size -29672 05/add-to-eax 4/imm32 -29673 # TODO: check edx for overflow -29674 # print offset -29675 (write-int32-hex-buffered *(ebp+8) %eax) -29676 (write-buffered *(ebp+8) ") ") -29677 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 -29678 } -29679 # otherwise abort -29680 e9/jump $translate-mu-index-stmt:error1/disp32 -29681 $translate-mu-index-stmt-with-array-on-stack:emit-output: -29682 # outputs[0] "/r32" -29683 8b/-> *(ebp+0xc) 0/r32/eax -29684 (lookup *(eax+0x14) *(eax+0x18)) # Stmt1-outputs Stmt1-outputs => eax -29685 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29686 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29687 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) -29688 (write-int32-hex-buffered *(ebp+8) *eax) -29689 (write-buffered *(ebp+8) "/r32\n") -29690 $translate-mu-index-stmt-with-array-on-stack:end: -29691 # . restore registers -29692 5b/pop-to-ebx -29693 5a/pop-to-edx -29694 59/pop-to-ecx -29695 58/pop-to-eax -29696 # . epilogue -29697 89/<- %esp 5/r32/ebp -29698 5d/pop-to-ebp -29699 c3/return -29700 -29701 translate-mu-compute-index-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29702 # . prologue -29703 55/push-ebp -29704 89/<- %ebp 4/r32/esp -29705 # . save registers -29706 50/push-eax -29707 51/push-ecx -29708 52/push-edx -29709 53/push-ebx -29710 # -29711 (emit-indent *(ebp+8) *Curr-block-depth) -29712 (write-buffered *(ebp+8) "69/multiply") -29713 # ecx = stmt -29714 8b/-> *(ebp+0xc) 1/r32/ecx -29715 # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0] -29716 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29717 89/<- %ebx 0/r32/eax -29718 $translate-mu-compute-index-stmt:emit-index: -29719 (lookup *(ebx+8) *(ebx+0xc)) # Stmt-var-next Stmt-var-next => eax -29720 (emit-subx-var-as-rm32 *(ebp+8) %eax) -29721 (write-buffered *(ebp+8) Space) -29722 $translate-mu-compute-index-stmt:emit-elem-size: -29723 # var base/ebx: (addr var) -29724 (lookup *ebx *(ebx+4)) # Stmt-var-value Stmt-var-value => eax -29725 89/<- %ebx 0/r32/eax -29726 # print array-element-size(base) -29727 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax -29728 (write-int32-hex-buffered *(ebp+8) %eax) -29729 (write-buffered *(ebp+8) "/imm32 ") -29730 $translate-mu-compute-index-stmt:emit-output: -29731 # outputs[0] "/r32" -29732 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax -29733 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29734 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29735 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) -29736 (write-int32-hex-buffered *(ebp+8) *eax) -29737 (write-buffered *(ebp+8) "/r32\n") -29738 $translate-mu-compute-index-stmt:end: -29739 # . restore registers -29740 5b/pop-to-ebx -29741 5a/pop-to-edx -29742 59/pop-to-ecx -29743 58/pop-to-eax -29744 # . epilogue -29745 89/<- %esp 5/r32/ebp -29746 5d/pop-to-ebp -29747 c3/return -29748 -29749 translate-mu-get-stmt: # out: (addr buffered-file), stmt: (addr stmt) -29750 # . prologue -29751 55/push-ebp -29752 89/<- %ebp 4/r32/esp -29753 # . save registers -29754 50/push-eax -29755 51/push-ecx -29756 52/push-edx -29757 # -29758 (emit-indent *(ebp+8) *Curr-block-depth) -29759 (write-buffered *(ebp+8) "8d/copy-address ") -29760 # ecx = stmt -29761 8b/-> *(ebp+0xc) 1/r32/ecx -29762 # var offset/edx: int = get offset of stmt -29763 (mu-get-offset %ecx) # => eax -29764 89/<- %edx 0/r32/eax -29765 # var base/eax: (addr var) = stmt->inouts->value -29766 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29767 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29768 # if base is in a register -29769 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register -29770 { -29771 0f 84/jump-if-= break/disp32 -29772 $translate-mu-get-stmt:emit-register-input: -29773 # emit "*(" base->register " + " offset ") " -29774 (write-buffered *(ebp+8) "*(") -29775 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29776 (write-buffered *(ebp+8) %eax) -29777 (write-buffered *(ebp+8) " + ") -29778 (write-int32-hex-buffered *(ebp+8) %edx) -29779 (write-buffered *(ebp+8) ") ") -29780 e9/jump $translate-mu-get-stmt:emit-output/disp32 -29781 } -29782 # otherwise base is on the stack -29783 { -29784 $translate-mu-get-stmt:emit-stack-input: -29785 # emit "*(ebp + " inouts[0]->stack-offset + offset ") " -29786 (write-buffered *(ebp+8) "*(ebp+") -29787 03/add *(eax+0x14) 2/r32/edx # Var-offset -29788 (write-int32-hex-buffered *(ebp+8) %edx) -29789 (write-buffered *(ebp+8) ") ") -29790 eb/jump $translate-mu-get-stmt:emit-output/disp8 -29791 } -29792 $translate-mu-get-stmt:emit-output: -29793 # var output/eax: (addr var) = stmt->outputs->value -29794 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax -29795 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29796 # emit offset->register "/r32" -29797 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -29798 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) -29799 (write-int32-hex-buffered *(ebp+8) *eax) -29800 (write-buffered *(ebp+8) "/r32\n") -29801 $translate-mu-get-stmt:end: -29802 # . restore registers -29803 5a/pop-to-edx -29804 59/pop-to-ecx -29805 58/pop-to-eax -29806 # . epilogue -29807 89/<- %esp 5/r32/ebp -29808 5d/pop-to-ebp -29809 c3/return -29810 -29811 translate-mu-copy-object-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29812 # . prologue -29813 55/push-ebp -29814 89/<- %ebp 4/r32/esp -29815 # . save registers -29816 50/push-eax -29817 # -29818 (emit-indent *(ebp+8) *Curr-block-depth) -29819 (write-buffered *(ebp+8) "(copy-bytes") -29820 # eax = stmt -29821 8b/-> *(ebp+0xc) 0/r32/eax -29822 # var first-inout/eax: (addr stmt-var) = stmt->inouts[0] -29823 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29824 (emit-subx-call-operand *(ebp+8) %eax) -29825 # var second-inout/eax: (addr stmt-var) = stmt->inouts[1] -29826 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -29827 (emit-subx-call-operand *(ebp+8) %eax) -29828 # emit size of inouts -29829 (write-buffered *(ebp+8) Space) -29830 (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14)) # => eax -29831 (write-int32-hex-buffered *(ebp+8) %eax) -29832 (write-buffered *(ebp+8) ")\n") -29833 $translate-mu-copy-object-stmt:end: -29834 # . restore registers -29835 58/pop-to-eax -29836 # . epilogue -29837 89/<- %esp 5/r32/ebp -29838 5d/pop-to-ebp -29839 c3/return -29840 -29841 translate-mu-clear-object-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29842 # . prologue -29843 55/push-ebp -29844 89/<- %ebp 4/r32/esp -29845 # . save registers -29846 50/push-eax -29847 # -29848 (emit-indent *(ebp+8) *Curr-block-depth) -29849 (write-buffered *(ebp+8) "(zero-out") -29850 # eax = stmt -29851 8b/-> *(ebp+0xc) 0/r32/eax -29852 # var dest/eax: (addr stmt-var) = stmt->inouts[0] -29853 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29854 # -29855 (emit-subx-call-operand *(ebp+8) %eax) -29856 (write-buffered *(ebp+8) Space) -29857 (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14)) # => eax -29858 (write-int32-hex-buffered *(ebp+8) %eax) -29859 (write-buffered *(ebp+8) ")\n") -29860 $translate-mu-clear-object-stmt:end: -29861 # . restore registers -29862 58/pop-to-eax -29863 # . epilogue -29864 89/<- %esp 5/r32/ebp -29865 5d/pop-to-ebp -29866 c3/return -29867 -29868 translate-mu-allocate-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29869 # . prologue -29870 55/push-ebp -29871 89/<- %ebp 4/r32/esp -29872 # . save registers -29873 50/push-eax -29874 56/push-esi -29875 57/push-edi -29876 # esi = stmt -29877 8b/-> *(ebp+0xc) 6/r32/esi -29878 # var target/edi: (addr stmt-var) = stmt->inouts[0] -29879 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29880 89/<- %edi 0/r32/eax -29881 # -29882 (emit-indent *(ebp+8) *Curr-block-depth) -29883 (write-buffered *(ebp+8) "(allocate Heap ") -29884 (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax -29885 (write-int32-hex-buffered *(ebp+8) %eax) -29886 (emit-subx-call-operand *(ebp+8) %edi) -29887 (write-buffered *(ebp+8) ")\n") -29888 $translate-mu-allocate-stmt:end: -29889 # . restore registers -29890 5f/pop-to-edi -29891 5e/pop-to-esi -29892 58/pop-to-eax -29893 # . epilogue -29894 89/<- %esp 5/r32/ebp -29895 5d/pop-to-ebp -29896 c3/return -29897 -29898 addr-handle-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -29899 # . prologue -29900 55/push-ebp -29901 89/<- %ebp 4/r32/esp -29902 # var t/eax: (addr type-tree) = s->value->type -29903 8b/-> *(ebp+8) 0/r32/eax -29904 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29905 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -29906 # TODO: check eax != 0 -29907 # TODO: check !t->is-atom? -29908 # TODO: check t->left == addr -29909 # t = t->right -29910 $addr-handle-payload-size:skip-addr: -29911 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -29912 # TODO: check eax != 0 -29913 # TODO: check !t->is-atom? -29914 # TODO: check t->left == handle -29915 # t = t->right -29916 $addr-handle-payload-size:skip-handle: -29917 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -29918 # TODO: check eax != 0 -29919 # if !t->is-atom? t = t->left -29920 81 7/subop/compare *eax 0/imm32/false -29921 { -29922 75/jump-if-!= break/disp8 -29923 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29924 } -29925 # TODO: check t->is-atom? -29926 # return size(t->value) -29927 (size-of-type-id *(eax+4)) # Type-tree-value => eax -29928 $addr-handle-payload-size:end: -29929 # . epilogue -29930 89/<- %esp 5/r32/ebp -29931 5d/pop-to-ebp -29932 c3/return -29933 -29934 addr-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -29935 # . prologue -29936 55/push-ebp -29937 89/<- %ebp 4/r32/esp -29938 # var t/eax: (addr type-tree) = s->value->type -29939 8b/-> *(ebp+8) 0/r32/eax -29940 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -29941 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -29942 # TODO: check eax != 0 -29943 # TODO: check !t->is-atom? -29944 # TODO: check t->left == addr -29945 # t = t->right -29946 $addr-payload-size:skip-addr: -29947 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -29948 # TODO: check eax != 0 -29949 # if !t->is-atom? t = t->left -29950 81 7/subop/compare *eax 0/imm32/false -29951 { -29952 75/jump-if-!= break/disp8 -29953 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -29954 } -29955 # TODO: check t->is-atom? -29956 # return size(t->value) -29957 (size-of-type-id *(eax+4)) # Type-tree-value => eax -29958 $addr-payload-size:end: -29959 # . epilogue -29960 89/<- %esp 5/r32/ebp -29961 5d/pop-to-ebp -29962 c3/return -29963 -29964 translate-mu-populate-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -29965 # . prologue -29966 55/push-ebp -29967 89/<- %ebp 4/r32/esp -29968 # . save registers -29969 50/push-eax -29970 51/push-ecx -29971 56/push-esi -29972 57/push-edi -29973 # esi = stmt -29974 8b/-> *(ebp+0xc) 6/r32/esi -29975 # var target/edi: (addr stmt-var) = stmt->inouts[0] -29976 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -29977 89/<- %edi 0/r32/eax -29978 # var len/ecx: (addr stmt-var) = stmt->inouts[1] -29979 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -29980 89/<- %ecx 0/r32/eax -29981 # -29982 (emit-indent *(ebp+8) *Curr-block-depth) -29983 (write-buffered *(ebp+8) "(allocate-array2 Heap ") -29984 (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax -29985 (write-int32-hex-buffered *(ebp+8) %eax) -29986 (emit-subx-call-operand *(ebp+8) %ecx) -29987 (emit-subx-call-operand *(ebp+8) %edi) -29988 (write-buffered *(ebp+8) ")\n") -29989 $translate-mu-populate-stmt:end: -29990 # . restore registers -29991 5f/pop-to-edi -29992 5e/pop-to-esi -29993 59/pop-to-ecx -29994 58/pop-to-eax -29995 # . epilogue -29996 89/<- %esp 5/r32/ebp -29997 5d/pop-to-ebp -29998 c3/return -29999 -30000 translate-mu-populate-stream-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -30001 # . prologue -30002 55/push-ebp -30003 89/<- %ebp 4/r32/esp -30004 # . save registers -30005 50/push-eax -30006 51/push-ecx -30007 56/push-esi -30008 57/push-edi -30009 # esi = stmt -30010 8b/-> *(ebp+0xc) 6/r32/esi -30011 # var target/edi: (addr stmt-var) = stmt->inouts[0] -30012 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -30013 89/<- %edi 0/r32/eax -30014 # var len/ecx: (addr stmt-var) = stmt->inouts[1] -30015 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax -30016 89/<- %ecx 0/r32/eax -30017 # -30018 (emit-indent *(ebp+8) *Curr-block-depth) -30019 (write-buffered *(ebp+8) "(new-stream Heap ") -30020 (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax -30021 (write-int32-hex-buffered *(ebp+8) %eax) -30022 (emit-subx-call-operand *(ebp+8) %ecx) -30023 (emit-subx-call-operand *(ebp+8) %edi) -30024 (write-buffered *(ebp+8) ")\n") -30025 $translate-mu-populate-stream-stmt:end: -30026 # . restore registers -30027 5f/pop-to-edi -30028 5e/pop-to-esi -30029 59/pop-to-ecx -30030 58/pop-to-eax -30031 # . epilogue -30032 89/<- %esp 5/r32/ebp -30033 5d/pop-to-ebp -30034 c3/return -30035 -30036 translate-mu-read-from-stream-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -30037 # . prologue -30038 55/push-ebp -30039 89/<- %ebp 4/r32/esp -30040 # . save registers -30041 50/push-eax -30042 51/push-ecx -30043 56/push-esi -30044 57/push-edi -30045 # esi = stmt -30046 8b/-> *(ebp+0xc) 6/r32/esi -30047 # var stream/ecx: (addr stmt-var) = stmt->inouts[0] -30048 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -30049 89/<- %ecx 0/r32/eax -30050 # var target/edi: (addr stmt-var) = stmt->inouts[1] -30051 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax -30052 89/<- %edi 0/r32/eax -30053 # -30054 (emit-indent *(ebp+8) *Curr-block-depth) -30055 (write-buffered *(ebp+8) "(read-from-stream") -30056 (emit-subx-call-operand *(ebp+8) %ecx) -30057 (emit-subx-call-operand *(ebp+8) %edi) -30058 (write-buffered *(ebp+8) Space) -30059 (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax -30060 (write-int32-hex-buffered *(ebp+8) %eax) -30061 (write-buffered *(ebp+8) ")\n") -30062 $translate-mu-read-from-stream-stmt:end: -30063 # . restore registers -30064 5f/pop-to-edi -30065 5e/pop-to-esi -30066 59/pop-to-ecx -30067 58/pop-to-eax -30068 # . epilogue -30069 89/<- %esp 5/r32/ebp -30070 5d/pop-to-ebp -30071 c3/return -30072 -30073 translate-mu-write-to-stream-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -30074 # . prologue -30075 55/push-ebp -30076 89/<- %ebp 4/r32/esp -30077 # . save registers -30078 50/push-eax -30079 51/push-ecx -30080 56/push-esi -30081 57/push-edi -30082 # esi = stmt -30083 8b/-> *(ebp+0xc) 6/r32/esi -30084 # var stream/ecx: (addr stmt-var) = stmt->inouts[0] -30085 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax -30086 89/<- %ecx 0/r32/eax -30087 # var target/edi: (addr stmt-var) = stmt->inouts[1] -30088 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax -30089 89/<- %edi 0/r32/eax -30090 # -30091 (emit-indent *(ebp+8) *Curr-block-depth) -30092 (write-buffered *(ebp+8) "(write-to-stream") -30093 (emit-subx-call-operand *(ebp+8) %ecx) -30094 (flush *(ebp+8)) -30095 (emit-subx-call-operand *(ebp+8) %edi) -30096 (flush *(ebp+8)) -30097 (write-buffered *(ebp+8) Space) -30098 (flush *(ebp+8)) -30099 (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax -30100 (write-int32-hex-buffered *(ebp+8) %eax) -30101 (write-buffered *(ebp+8) ")\n") -30102 $translate-mu-write-to-stream-stmt:end: -30103 # . restore registers -30104 5f/pop-to-edi -30105 5e/pop-to-esi -30106 59/pop-to-ecx -30107 58/pop-to-eax -30108 # . epilogue -30109 89/<- %esp 5/r32/ebp -30110 5d/pop-to-ebp -30111 c3/return -30112 -30113 addr-handle-array-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -30114 # . prologue -30115 55/push-ebp -30116 89/<- %ebp 4/r32/esp -30117 # var t/eax: (addr type-tree) = s->value->type -30118 8b/-> *(ebp+8) 0/r32/eax -30119 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -30120 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -30121 # TODO: check eax != 0 -30122 # TODO: check !t->is-atom? -30123 # TODO: check t->left == addr -30124 # t = t->right -30125 $addr-handle-array-payload-size:skip-addr: -30126 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -30127 # TODO: check eax != 0 -30128 # TODO: check !t->is-atom? -30129 # TODO: check t->left == handle -30130 # t = t->right -30131 $addr-handle-array-payload-size:skip-handle: -30132 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -30133 # TODO: check eax != 0 -30134 # TODO: check !t->is-atom? -30135 # TODO: check t->left == array -30136 # t = t->right -30137 $addr-handle-array-payload-size:skip-array: -30138 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -30139 # TODO: check eax != 0 -30140 # if !t->is-atom? t = t->left -30141 81 7/subop/compare *eax 0/imm32/false -30142 { -30143 75/jump-if-!= break/disp8 -30144 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -30145 } -30146 $addr-handle-array-payload-size:compute-size: -30147 # TODO: check t->is-atom? -30148 # return size(t->value) -30149 (size-of-type-id-as-array-element *(eax+4)) # Type-tree-value => eax -30150 $addr-handle-array-payload-size:end: -30151 # . epilogue -30152 89/<- %esp 5/r32/ebp -30153 5d/pop-to-ebp -30154 c3/return -30155 -30156 addr-handle-stream-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int -30157 # . prologue -30158 55/push-ebp -30159 89/<- %ebp 4/r32/esp -30160 # var t/eax: (addr type-tree) = s->value->type -30161 8b/-> *(ebp+8) 0/r32/eax -30162 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -30163 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax -30164 # TODO: check eax != 0 -30165 # TODO: check !t->is-atom? -30166 # TODO: check t->left == addr -30167 # t = t->right -30168 $addr-handle-stream-payload-size:skip-addr: -30169 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -30170 # TODO: check eax != 0 -30171 # TODO: check !t->is-atom? -30172 # TODO: check t->left == handle -30173 # t = t->right -30174 $addr-handle-stream-payload-size:skip-handle: -30175 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -30176 # TODO: check eax != 0 -30177 # TODO: check !t->is-atom? -30178 # TODO: check t->left == stream -30179 # t = t->right -30180 $addr-handle-stream-payload-size:skip-stream: -30181 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -30182 # TODO: check eax != 0 -30183 # if !t->is-atom? t = t->left -30184 81 7/subop/compare *eax 0/imm32/false -30185 { -30186 75/jump-if-!= break/disp8 -30187 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -30188 } -30189 $addr-handle-stream-payload-size:compute-size: -30190 # TODO: check t->is-atom? -30191 # return size(t->value) -30192 (size-of-type-id-as-array-element *(eax+4)) # Type-tree-value => eax -30193 $addr-handle-stream-payload-size:end: -30194 # . epilogue -30195 89/<- %esp 5/r32/ebp -30196 5d/pop-to-ebp -30197 c3/return -30198 -30199 power-of-2?: # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean -30200 # precondition: n is positive -30201 # . prologue -30202 55/push-ebp -30203 89/<- %ebp 4/r32/esp -30204 # eax = n -30205 8b/-> *(ebp+8) 0/r32/eax -30206 # if (n < 0) abort -30207 3d/compare-eax-with 0/imm32 -30208 0f 8c/jump-if-< $power-of-2?:abort/disp32 -30209 # var tmp/eax: int = n-1 -30210 48/decrement-eax -30211 # var tmp2/eax: int = n & tmp -30212 23/and-> *(ebp+8) 0/r32/eax -30213 # return (tmp2 == 0) -30214 3d/compare-eax-and 0/imm32 -30215 0f 94/set-byte-if-= %al -30216 81 4/subop/and %eax 0xff/imm32 -30217 $power-of-2?:end: -30218 # . epilogue -30219 89/<- %esp 5/r32/ebp -30220 5d/pop-to-ebp -30221 c3/return -30222 -30223 $power-of-2?:abort: -30224 (write-buffered *(ebp+0xc) "power-of-2?: negative number\n") -30225 (flush *(ebp+0xc)) -30226 (stop *(ebp+0x10) 1) -30227 # never gets here -30228 -30229 num-shift-rights: # n: int -> result/eax: int -30230 # precondition: n is a positive power of 2 -30231 # . prologue -30232 55/push-ebp -30233 89/<- %ebp 4/r32/esp -30234 # . save registers -30235 51/push-ecx -30236 # var curr/ecx: int = n -30237 8b/-> *(ebp+8) 1/r32/ecx -30238 # result = 0 -30239 b8/copy-to-eax 0/imm32 -30240 { -30241 # if (curr <= 1) break -30242 81 7/subop/compare %ecx 1/imm32 -30243 7e/jump-if-<= break/disp8 -30244 40/increment-eax -30245 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 -30246 eb/jump loop/disp8 -30247 } -30248 $num-shift-rights:end: -30249 # . restore registers -30250 59/pop-to-ecx -30251 # . epilogue -30252 89/<- %esp 5/r32/ebp -30253 5d/pop-to-ebp -30254 c3/return -30255 -30256 mu-get-offset: # stmt: (addr stmt) -> result/eax: int +29605 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29606 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) +29607 (write-int32-hex-buffered *(ebp+8) *eax) +29608 (write-buffered *(ebp+8) "/r32\n") +29609 $translate-mu-index-stmt-with-array-in-register:end: +29610 # . restore registers +29611 5b/pop-to-ebx +29612 5a/pop-to-edx +29613 59/pop-to-ecx +29614 58/pop-to-eax +29615 # . epilogue +29616 89/<- %esp 5/r32/ebp +29617 5d/pop-to-ebp +29618 c3/return +29619 +29620 translate-mu-index-stmt-with-array-on-stack: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29621 # . prologue +29622 55/push-ebp +29623 89/<- %ebp 4/r32/esp +29624 # . save registers +29625 50/push-eax +29626 51/push-ecx +29627 52/push-edx +29628 53/push-ebx +29629 # +29630 (emit-indent *(ebp+8) *Curr-block-depth) +29631 (write-buffered *(ebp+8) "8d/copy-address *(ebp + ") +29632 # var curr/edx: (addr stmt-var) = lookup(stmt->inouts) +29633 8b/-> *(ebp+0xc) 0/r32/eax +29634 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29635 89/<- %edx 0/r32/eax +29636 # var base/ecx: (addr var) = lookup(curr->value) +29637 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29638 89/<- %ecx 0/r32/eax +29639 # var curr2/eax: (addr stmt-var) = lookup(curr->next) +29640 (lookup *(edx+8) *(edx+0xc)) # Stmt-var-next Stmt-var-next => eax +29641 # var index/edx: (handle var) = curr2->value +29642 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29643 89/<- %edx 0/r32/eax +29644 # if index->register +29645 81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register +29646 { +29647 0f 84/jump-if-= break/disp32 +29648 $translate-mu-index-stmt-with-array-on-stack:emit-register-index: +29649 # if index is an int +29650 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29651 (simple-mu-type? %eax 1) # int => eax +29652 3d/compare-eax-and 0/imm32/false +29653 { +29654 0f 84/jump-if-= break/disp32 +29655 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index: +29656 # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4 +29657 # . inouts[1]->register "<<" +29658 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +29659 (write-buffered *(ebp+8) %eax) +29660 (write-buffered *(ebp+8) "<<") +29661 # . log2(array-element-size(base)) +29662 # TODO: ensure size is a power of 2 +29663 (array-element-size %ecx *(ebp+0x10) *(ebp+0x14)) # => eax +29664 (num-shift-rights %eax) # => eax +29665 (write-int32-hex-buffered *(ebp+8) %eax) +29666 # +29667 (write-buffered *(ebp+8) " + ") +29668 # +29669 8b/-> *(ecx+0x14) 0/r32/eax # Var-offset +29670 05/add-to-eax 4/imm32 # for array length +29671 (write-int32-hex-buffered *(ebp+8) %eax) +29672 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32 +29673 } +29674 # if index->type is any other atom, abort +29675 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29676 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +29677 0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32 +29678 # if index has type (offset ...) +29679 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29680 (simple-mu-type? %eax 7) # => eax +29681 3d/compare-eax-and 0/imm32/false +29682 { +29683 0f 84/jump-if-= break/disp32 +29684 # print index->register +29685 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index: +29686 (lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax +29687 (write-buffered *(ebp+8) %eax) +29688 } +29689 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done: +29690 (write-buffered *(ebp+8) ") ") +29691 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 +29692 } +29693 # otherwise if index is a literal +29694 (lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax +29695 (simple-mu-type? %eax 0) # => eax +29696 3d/compare-eax-and 0/imm32/false +29697 { +29698 0f 84/jump-if-= break/disp32 +29699 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index: +29700 # var idx-value/edx: int = parse-hex-int(index->name) +29701 (lookup *edx *(edx+4)) # Var-name Var-name => eax +29702 (parse-hex-int %eax) # Var-name => eax +29703 89/<- %edx 0/r32/eax +29704 # offset = idx-value * array-element-size(base) +29705 (array-element-size %ecx *(ebp+0x10) *(ebp+0x14)) # => eax +29706 f7 4/subop/multiply-into-edx-eax %edx # clobbers edx +29707 # offset += base->offset +29708 03/add *(ecx+0x14) 0/r32/eax # Var-offset +29709 # offset += 4 for array size +29710 05/add-to-eax 4/imm32 +29711 # TODO: check edx for overflow +29712 # print offset +29713 (write-int32-hex-buffered *(ebp+8) %eax) +29714 (write-buffered *(ebp+8) ") ") +29715 e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32 +29716 } +29717 # otherwise abort +29718 e9/jump $translate-mu-index-stmt:error1/disp32 +29719 $translate-mu-index-stmt-with-array-on-stack:emit-output: +29720 # outputs[0] "/r32" +29721 8b/-> *(ebp+0xc) 0/r32/eax +29722 (lookup *(eax+0x14) *(eax+0x18)) # Stmt1-outputs Stmt1-outputs => eax +29723 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29724 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29725 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) +29726 (write-int32-hex-buffered *(ebp+8) *eax) +29727 (write-buffered *(ebp+8) "/r32\n") +29728 $translate-mu-index-stmt-with-array-on-stack:end: +29729 # . restore registers +29730 5b/pop-to-ebx +29731 5a/pop-to-edx +29732 59/pop-to-ecx +29733 58/pop-to-eax +29734 # . epilogue +29735 89/<- %esp 5/r32/ebp +29736 5d/pop-to-ebp +29737 c3/return +29738 +29739 translate-mu-compute-index-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29740 # . prologue +29741 55/push-ebp +29742 89/<- %ebp 4/r32/esp +29743 # . save registers +29744 50/push-eax +29745 51/push-ecx +29746 52/push-edx +29747 53/push-ebx +29748 # +29749 (emit-indent *(ebp+8) *Curr-block-depth) +29750 (write-buffered *(ebp+8) "69/multiply") +29751 # ecx = stmt +29752 8b/-> *(ebp+0xc) 1/r32/ecx +29753 # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0] +29754 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29755 89/<- %ebx 0/r32/eax +29756 $translate-mu-compute-index-stmt:emit-index: +29757 (lookup *(ebx+8) *(ebx+0xc)) # Stmt-var-next Stmt-var-next => eax +29758 (emit-subx-var-as-rm32 *(ebp+8) %eax) +29759 (write-buffered *(ebp+8) Space) +29760 $translate-mu-compute-index-stmt:emit-elem-size: +29761 # var base/ebx: (addr var) +29762 (lookup *ebx *(ebx+4)) # Stmt-var-value Stmt-var-value => eax +29763 89/<- %ebx 0/r32/eax +29764 # print array-element-size(base) +29765 (array-element-size %ebx *(ebp+0x10) *(ebp+0x14)) # => eax +29766 (write-int32-hex-buffered *(ebp+8) %eax) +29767 (write-buffered *(ebp+8) "/imm32 ") +29768 $translate-mu-compute-index-stmt:emit-output: +29769 # outputs[0] "/r32" +29770 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax +29771 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29772 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29773 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) +29774 (write-int32-hex-buffered *(ebp+8) *eax) +29775 (write-buffered *(ebp+8) "/r32\n") +29776 $translate-mu-compute-index-stmt:end: +29777 # . restore registers +29778 5b/pop-to-ebx +29779 5a/pop-to-edx +29780 59/pop-to-ecx +29781 58/pop-to-eax +29782 # . epilogue +29783 89/<- %esp 5/r32/ebp +29784 5d/pop-to-ebp +29785 c3/return +29786 +29787 translate-mu-get-stmt: # out: (addr buffered-file), stmt: (addr stmt) +29788 # . prologue +29789 55/push-ebp +29790 89/<- %ebp 4/r32/esp +29791 # . save registers +29792 50/push-eax +29793 51/push-ecx +29794 52/push-edx +29795 # ecx = stmt +29796 8b/-> *(ebp+0xc) 1/r32/ecx +29797 # var base/eax: (addr var) = stmt->inouts->value +29798 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29799 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29800 # if base is in a register, insert a null check +29801 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +29802 { +29803 0f 84/jump-if-= break/disp32 +29804 $translate-mu-get-stmt:emit-null-check-for-register-input: +29805 # emit "81 7/subop/compare %" base->register " 0/imm32\n" +29806 (emit-indent *(ebp+8) *Curr-block-depth) +29807 (write-buffered *(ebp+8) "81 7/subop/compare %") +29808 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29809 (write-buffered *(ebp+8) %eax) +29810 (write-buffered *(ebp+8) " 0/imm32\n") +29811 # +29812 (emit-indent *(ebp+8) *Curr-block-depth) +29813 (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32\n") +29814 } +29815 # var offset/edx: int = get offset of stmt +29816 (mu-get-offset %ecx) # => eax +29817 89/<- %edx 0/r32/eax +29818 # var base/eax: (addr var) = stmt->inouts->value +29819 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29820 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29821 # +29822 (emit-indent *(ebp+8) *Curr-block-depth) +29823 (write-buffered *(ebp+8) "8d/copy-address ") +29824 # if base is in a register +29825 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register +29826 { +29827 0f 84/jump-if-= break/disp32 +29828 $translate-mu-get-stmt:emit-register-input: +29829 # emit "*(" base->register " + " offset ") " +29830 (write-buffered *(ebp+8) "*(") +29831 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29832 (write-buffered *(ebp+8) %eax) +29833 (write-buffered *(ebp+8) " + ") +29834 (write-int32-hex-buffered *(ebp+8) %edx) +29835 (write-buffered *(ebp+8) ") ") +29836 e9/jump $translate-mu-get-stmt:emit-output/disp32 +29837 } +29838 # otherwise base is on the stack +29839 { +29840 $translate-mu-get-stmt:emit-stack-input: +29841 # emit "*(ebp + " inouts[0]->stack-offset + offset ") " +29842 (write-buffered *(ebp+8) "*(ebp+") +29843 03/add *(eax+0x14) 2/r32/edx # Var-offset +29844 (write-int32-hex-buffered *(ebp+8) %edx) +29845 (write-buffered *(ebp+8) ") ") +29846 eb/jump $translate-mu-get-stmt:emit-output/disp8 +29847 } +29848 $translate-mu-get-stmt:emit-output: +29849 # var output/eax: (addr var) = stmt->outputs->value +29850 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax +29851 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29852 # emit offset->register "/r32" +29853 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +29854 (get Mu-registers %eax 0xc "Mu-registers") # => eax: (addr int) +29855 (write-int32-hex-buffered *(ebp+8) *eax) +29856 (write-buffered *(ebp+8) "/r32\n") +29857 $translate-mu-get-stmt:end: +29858 # . restore registers +29859 5a/pop-to-edx +29860 59/pop-to-ecx +29861 58/pop-to-eax +29862 # . epilogue +29863 89/<- %esp 5/r32/ebp +29864 5d/pop-to-ebp +29865 c3/return +29866 +29867 translate-mu-copy-object-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29868 # . prologue +29869 55/push-ebp +29870 89/<- %ebp 4/r32/esp +29871 # . save registers +29872 50/push-eax +29873 # +29874 (emit-indent *(ebp+8) *Curr-block-depth) +29875 (write-buffered *(ebp+8) "(copy-bytes") +29876 # eax = stmt +29877 8b/-> *(ebp+0xc) 0/r32/eax +29878 # var first-inout/eax: (addr stmt-var) = stmt->inouts[0] +29879 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29880 (emit-subx-call-operand *(ebp+8) %eax) +29881 # var second-inout/eax: (addr stmt-var) = stmt->inouts[1] +29882 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +29883 (emit-subx-call-operand *(ebp+8) %eax) +29884 # emit size of inouts +29885 (write-buffered *(ebp+8) Space) +29886 (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14)) # => eax +29887 (write-int32-hex-buffered *(ebp+8) %eax) +29888 (write-buffered *(ebp+8) ")\n") +29889 $translate-mu-copy-object-stmt:end: +29890 # . restore registers +29891 58/pop-to-eax +29892 # . epilogue +29893 89/<- %esp 5/r32/ebp +29894 5d/pop-to-ebp +29895 c3/return +29896 +29897 translate-mu-clear-object-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29898 # . prologue +29899 55/push-ebp +29900 89/<- %ebp 4/r32/esp +29901 # . save registers +29902 50/push-eax +29903 # +29904 (emit-indent *(ebp+8) *Curr-block-depth) +29905 (write-buffered *(ebp+8) "(zero-out") +29906 # eax = stmt +29907 8b/-> *(ebp+0xc) 0/r32/eax +29908 # var dest/eax: (addr stmt-var) = stmt->inouts[0] +29909 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29910 # +29911 (emit-subx-call-operand *(ebp+8) %eax) +29912 (write-buffered *(ebp+8) Space) +29913 (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14)) # => eax +29914 (write-int32-hex-buffered *(ebp+8) %eax) +29915 (write-buffered *(ebp+8) ")\n") +29916 $translate-mu-clear-object-stmt:end: +29917 # . restore registers +29918 58/pop-to-eax +29919 # . epilogue +29920 89/<- %esp 5/r32/ebp +29921 5d/pop-to-ebp +29922 c3/return +29923 +29924 translate-mu-allocate-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +29925 # . prologue +29926 55/push-ebp +29927 89/<- %ebp 4/r32/esp +29928 # . save registers +29929 50/push-eax +29930 56/push-esi +29931 57/push-edi +29932 # esi = stmt +29933 8b/-> *(ebp+0xc) 6/r32/esi +29934 # var target/edi: (addr stmt-var) = stmt->inouts[0] +29935 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +29936 89/<- %edi 0/r32/eax +29937 # +29938 (emit-indent *(ebp+8) *Curr-block-depth) +29939 (write-buffered *(ebp+8) "(allocate Heap ") +29940 (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax +29941 (write-int32-hex-buffered *(ebp+8) %eax) +29942 (emit-subx-call-operand *(ebp+8) %edi) +29943 (write-buffered *(ebp+8) ")\n") +29944 $translate-mu-allocate-stmt:end: +29945 # . restore registers +29946 5f/pop-to-edi +29947 5e/pop-to-esi +29948 58/pop-to-eax +29949 # . epilogue +29950 89/<- %esp 5/r32/ebp +29951 5d/pop-to-ebp +29952 c3/return +29953 +29954 addr-handle-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +29955 # . prologue +29956 55/push-ebp +29957 89/<- %ebp 4/r32/esp +29958 # var t/eax: (addr type-tree) = s->value->type +29959 8b/-> *(ebp+8) 0/r32/eax +29960 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29961 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +29962 # TODO: check eax != 0 +29963 # TODO: check !t->is-atom? +29964 # TODO: check t->left == addr +29965 # t = t->right +29966 $addr-handle-payload-size:skip-addr: +29967 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +29968 # TODO: check eax != 0 +29969 # TODO: check !t->is-atom? +29970 # TODO: check t->left == handle +29971 # t = t->right +29972 $addr-handle-payload-size:skip-handle: +29973 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +29974 # TODO: check eax != 0 +29975 # if !t->is-atom? t = t->left +29976 81 7/subop/compare *eax 0/imm32/false +29977 { +29978 75/jump-if-!= break/disp8 +29979 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +29980 } +29981 # TODO: check t->is-atom? +29982 # return size(t->value) +29983 (size-of-type-id *(eax+4)) # Type-tree-value => eax +29984 $addr-handle-payload-size:end: +29985 # . epilogue +29986 89/<- %esp 5/r32/ebp +29987 5d/pop-to-ebp +29988 c3/return +29989 +29990 addr-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +29991 # . prologue +29992 55/push-ebp +29993 89/<- %ebp 4/r32/esp +29994 # var t/eax: (addr type-tree) = s->value->type +29995 8b/-> *(ebp+8) 0/r32/eax +29996 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +29997 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +29998 # TODO: check eax != 0 +29999 # TODO: check !t->is-atom? +30000 # TODO: check t->left == addr +30001 # t = t->right +30002 $addr-payload-size:skip-addr: +30003 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30004 # TODO: check eax != 0 +30005 # if !t->is-atom? t = t->left +30006 81 7/subop/compare *eax 0/imm32/false +30007 { +30008 75/jump-if-!= break/disp8 +30009 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +30010 } +30011 # TODO: check t->is-atom? +30012 # return size(t->value) +30013 (size-of-type-id *(eax+4)) # Type-tree-value => eax +30014 $addr-payload-size:end: +30015 # . epilogue +30016 89/<- %esp 5/r32/ebp +30017 5d/pop-to-ebp +30018 c3/return +30019 +30020 translate-mu-populate-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +30021 # . prologue +30022 55/push-ebp +30023 89/<- %ebp 4/r32/esp +30024 # . save registers +30025 50/push-eax +30026 51/push-ecx +30027 56/push-esi +30028 57/push-edi +30029 # esi = stmt +30030 8b/-> *(ebp+0xc) 6/r32/esi +30031 # var target/edi: (addr stmt-var) = stmt->inouts[0] +30032 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +30033 89/<- %edi 0/r32/eax +30034 # var len/ecx: (addr stmt-var) = stmt->inouts[1] +30035 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +30036 89/<- %ecx 0/r32/eax +30037 # +30038 (emit-indent *(ebp+8) *Curr-block-depth) +30039 (write-buffered *(ebp+8) "(allocate-array2 Heap ") +30040 (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax +30041 (write-int32-hex-buffered *(ebp+8) %eax) +30042 (emit-subx-call-operand *(ebp+8) %ecx) +30043 (emit-subx-call-operand *(ebp+8) %edi) +30044 (write-buffered *(ebp+8) ")\n") +30045 $translate-mu-populate-stmt:end: +30046 # . restore registers +30047 5f/pop-to-edi +30048 5e/pop-to-esi +30049 59/pop-to-ecx +30050 58/pop-to-eax +30051 # . epilogue +30052 89/<- %esp 5/r32/ebp +30053 5d/pop-to-ebp +30054 c3/return +30055 +30056 translate-mu-populate-stream-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +30057 # . prologue +30058 55/push-ebp +30059 89/<- %ebp 4/r32/esp +30060 # . save registers +30061 50/push-eax +30062 51/push-ecx +30063 56/push-esi +30064 57/push-edi +30065 # esi = stmt +30066 8b/-> *(ebp+0xc) 6/r32/esi +30067 # var target/edi: (addr stmt-var) = stmt->inouts[0] +30068 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +30069 89/<- %edi 0/r32/eax +30070 # var len/ecx: (addr stmt-var) = stmt->inouts[1] +30071 (lookup *(edi+8) *(edi+0xc)) # Stmt-var-next Stmt-var-next => eax +30072 89/<- %ecx 0/r32/eax +30073 # +30074 (emit-indent *(ebp+8) *Curr-block-depth) +30075 (write-buffered *(ebp+8) "(new-stream Heap ") +30076 (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax +30077 (write-int32-hex-buffered *(ebp+8) %eax) +30078 (emit-subx-call-operand *(ebp+8) %ecx) +30079 (emit-subx-call-operand *(ebp+8) %edi) +30080 (write-buffered *(ebp+8) ")\n") +30081 $translate-mu-populate-stream-stmt:end: +30082 # . restore registers +30083 5f/pop-to-edi +30084 5e/pop-to-esi +30085 59/pop-to-ecx +30086 58/pop-to-eax +30087 # . epilogue +30088 89/<- %esp 5/r32/ebp +30089 5d/pop-to-ebp +30090 c3/return +30091 +30092 translate-mu-read-from-stream-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +30093 # . prologue +30094 55/push-ebp +30095 89/<- %ebp 4/r32/esp +30096 # . save registers +30097 50/push-eax +30098 51/push-ecx +30099 56/push-esi +30100 57/push-edi +30101 # esi = stmt +30102 8b/-> *(ebp+0xc) 6/r32/esi +30103 # var stream/ecx: (addr stmt-var) = stmt->inouts[0] +30104 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +30105 89/<- %ecx 0/r32/eax +30106 # var target/edi: (addr stmt-var) = stmt->inouts[1] +30107 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax +30108 89/<- %edi 0/r32/eax +30109 # +30110 (emit-indent *(ebp+8) *Curr-block-depth) +30111 (write-buffered *(ebp+8) "(read-from-stream") +30112 (emit-subx-call-operand *(ebp+8) %ecx) +30113 (emit-subx-call-operand *(ebp+8) %edi) +30114 (write-buffered *(ebp+8) Space) +30115 (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax +30116 (write-int32-hex-buffered *(ebp+8) %eax) +30117 (write-buffered *(ebp+8) ")\n") +30118 $translate-mu-read-from-stream-stmt:end: +30119 # . restore registers +30120 5f/pop-to-edi +30121 5e/pop-to-esi +30122 59/pop-to-ecx +30123 58/pop-to-eax +30124 # . epilogue +30125 89/<- %esp 5/r32/ebp +30126 5d/pop-to-ebp +30127 c3/return +30128 +30129 translate-mu-write-to-stream-stmt: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +30130 # . prologue +30131 55/push-ebp +30132 89/<- %ebp 4/r32/esp +30133 # . save registers +30134 50/push-eax +30135 51/push-ecx +30136 56/push-esi +30137 57/push-edi +30138 # esi = stmt +30139 8b/-> *(ebp+0xc) 6/r32/esi +30140 # var stream/ecx: (addr stmt-var) = stmt->inouts[0] +30141 (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax +30142 89/<- %ecx 0/r32/eax +30143 # var target/edi: (addr stmt-var) = stmt->inouts[1] +30144 (lookup *(ecx+8) *(ecx+0xc)) # Stmt-var-next Stmt-var-next => eax +30145 89/<- %edi 0/r32/eax +30146 # +30147 (emit-indent *(ebp+8) *Curr-block-depth) +30148 (write-buffered *(ebp+8) "(write-to-stream") +30149 (emit-subx-call-operand *(ebp+8) %ecx) +30150 (flush *(ebp+8)) +30151 (emit-subx-call-operand *(ebp+8) %edi) +30152 (flush *(ebp+8)) +30153 (write-buffered *(ebp+8) Space) +30154 (flush *(ebp+8)) +30155 (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14)) # => eax +30156 (write-int32-hex-buffered *(ebp+8) %eax) +30157 (write-buffered *(ebp+8) ")\n") +30158 $translate-mu-write-to-stream-stmt:end: +30159 # . restore registers +30160 5f/pop-to-edi +30161 5e/pop-to-esi +30162 59/pop-to-ecx +30163 58/pop-to-eax +30164 # . epilogue +30165 89/<- %esp 5/r32/ebp +30166 5d/pop-to-ebp +30167 c3/return +30168 +30169 addr-handle-array-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +30170 # . prologue +30171 55/push-ebp +30172 89/<- %ebp 4/r32/esp +30173 # var t/eax: (addr type-tree) = s->value->type +30174 8b/-> *(ebp+8) 0/r32/eax +30175 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +30176 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +30177 # TODO: check eax != 0 +30178 # TODO: check !t->is-atom? +30179 # TODO: check t->left == addr +30180 # t = t->right +30181 $addr-handle-array-payload-size:skip-addr: +30182 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30183 # TODO: check eax != 0 +30184 # TODO: check !t->is-atom? +30185 # TODO: check t->left == handle +30186 # t = t->right +30187 $addr-handle-array-payload-size:skip-handle: +30188 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30189 # TODO: check eax != 0 +30190 # TODO: check !t->is-atom? +30191 # TODO: check t->left == array +30192 # t = t->right +30193 $addr-handle-array-payload-size:skip-array: +30194 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30195 # TODO: check eax != 0 +30196 # if !t->is-atom? t = t->left +30197 81 7/subop/compare *eax 0/imm32/false +30198 { +30199 75/jump-if-!= break/disp8 +30200 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +30201 } +30202 $addr-handle-array-payload-size:compute-size: +30203 # TODO: check t->is-atom? +30204 # return size(t->value) +30205 (size-of-type-id-as-array-element *(eax+4)) # Type-tree-value => eax +30206 $addr-handle-array-payload-size:end: +30207 # . epilogue +30208 89/<- %esp 5/r32/ebp +30209 5d/pop-to-ebp +30210 c3/return +30211 +30212 addr-handle-stream-payload-size: # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int +30213 # . prologue +30214 55/push-ebp +30215 89/<- %ebp 4/r32/esp +30216 # var t/eax: (addr type-tree) = s->value->type +30217 8b/-> *(ebp+8) 0/r32/eax +30218 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +30219 (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax +30220 # TODO: check eax != 0 +30221 # TODO: check !t->is-atom? +30222 # TODO: check t->left == addr +30223 # t = t->right +30224 $addr-handle-stream-payload-size:skip-addr: +30225 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30226 # TODO: check eax != 0 +30227 # TODO: check !t->is-atom? +30228 # TODO: check t->left == handle +30229 # t = t->right +30230 $addr-handle-stream-payload-size:skip-handle: +30231 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30232 # TODO: check eax != 0 +30233 # TODO: check !t->is-atom? +30234 # TODO: check t->left == stream +30235 # t = t->right +30236 $addr-handle-stream-payload-size:skip-stream: +30237 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +30238 # TODO: check eax != 0 +30239 # if !t->is-atom? t = t->left +30240 81 7/subop/compare *eax 0/imm32/false +30241 { +30242 75/jump-if-!= break/disp8 +30243 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +30244 } +30245 $addr-handle-stream-payload-size:compute-size: +30246 # TODO: check t->is-atom? +30247 # return size(t->value) +30248 (size-of-type-id-as-array-element *(eax+4)) # Type-tree-value => eax +30249 $addr-handle-stream-payload-size:end: +30250 # . epilogue +30251 89/<- %esp 5/r32/ebp +30252 5d/pop-to-ebp +30253 c3/return +30254 +30255 power-of-2?: # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean +30256 # precondition: n is positive 30257 # . prologue 30258 55/push-ebp 30259 89/<- %ebp 4/r32/esp -30260 # var second-inout/eax: (addr stmt-var) = stmt->inouts->next +30260 # eax = n 30261 8b/-> *(ebp+8) 0/r32/eax -30262 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax -30263 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -30264 # var output-var/eax: (addr var) = second-inout->value -30265 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -30266 #? (write-buffered Stderr "mu-get-offset: ") -30267 #? (write-int32-hex-buffered Stderr %eax) -30268 #? (write-buffered Stderr " name: ") -30269 #? 50/push-eax -30270 #? (lookup *eax *(eax+4)) # Var-name -30271 #? (write-buffered Stderr %eax) -30272 #? 58/pop-to-eax -30273 #? (write-buffered Stderr Newline) -30274 #? (flush Stderr) -30275 # return output-var->stack-offset -30276 8b/-> *(eax+0x14) 0/r32/eax # Var-offset -30277 #? (write-buffered Stderr "=> ") -30278 #? (write-int32-hex-buffered Stderr %eax) -30279 #? (write-buffered Stderr Newline) -30280 #? (flush Stderr) -30281 $emit-get-offset:end: -30282 # . epilogue -30283 89/<- %esp 5/r32/ebp -30284 5d/pop-to-ebp -30285 c3/return -30286 -30287 emit-subx-block: # out: (addr buffered-file), block: (addr block), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) -30288 # . prologue -30289 55/push-ebp -30290 89/<- %ebp 4/r32/esp -30291 # . save registers -30292 50/push-eax -30293 51/push-ecx -30294 56/push-esi -30295 # esi = block -30296 8b/-> *(ebp+0xc) 6/r32/esi -30297 # block->var->block-depth = *Curr-block-depth -30298 (lookup *(esi+0xc) *(esi+0x10)) # Block-var Block-var => eax -30299 8b/-> *Curr-block-depth 1/r32/ecx -30300 89/<- *(eax+0x10) 1/r32/ecx # Var-block-depth -30301 # var stmts/eax: (addr list stmt) = lookup(block->statements) -30302 (lookup *(esi+4) *(esi+8)) # Block-stmts Block-stmts => eax -30303 # -30304 { -30305 $emit-subx-block:check-empty: -30306 3d/compare-eax-and 0/imm32 -30307 0f 84/jump-if-= break/disp32 -30308 (emit-indent *(ebp+8) *Curr-block-depth) -30309 (write-buffered *(ebp+8) "{\n") -30310 # var v/ecx: (addr var) = lookup(block->var) -30311 (lookup *(esi+0xc) *(esi+0x10)) # Block-var Block-var => eax -30312 89/<- %ecx 0/r32/eax -30313 # -30314 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -30315 (write-buffered *(ebp+8) %eax) -30316 (write-buffered *(ebp+8) ":loop:\n") -30317 ff 0/subop/increment *Curr-block-depth -30318 (push *(ebp+0x10) *(esi+0xc)) # Block-var -30319 (push *(ebp+0x10) *(esi+0x10)) # Block-var -30320 (push *(ebp+0x10) 0) # false -30321 # emit block->statements -30322 (lookup *(esi+4) *(esi+8)) # Block-stmts Block-stmts => eax -30323 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) -30324 (pop *(ebp+0x10)) # => eax -30325 (pop *(ebp+0x10)) # => eax -30326 (pop *(ebp+0x10)) # => eax -30327 ff 1/subop/decrement *Curr-block-depth -30328 (emit-indent *(ebp+8) *Curr-block-depth) -30329 (write-buffered *(ebp+8) "}\n") -30330 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax -30331 (write-buffered *(ebp+8) %eax) -30332 (write-buffered *(ebp+8) ":break:\n") -30333 } -30334 $emit-subx-block:end: -30335 # . restore registers -30336 5e/pop-to-esi -30337 59/pop-to-ecx -30338 58/pop-to-eax -30339 # . epilogue -30340 89/<- %esp 5/r32/ebp -30341 5d/pop-to-ebp -30342 c3/return -30343 -30344 # Primitives supported -30345 # See mu_instructions for a summary of this linked-list data structure. -30346 # -30347 # For each operation, put variants with hard-coded registers before flexible ones. -30348 # -30349 # Unfortunately, our restrictions on addresses require that various fields in -30350 # primitives be handles, which complicates these definitions. -30351 # - we need to insert dummy fields all over the place for fake alloc-ids -30352 # - we can't use our syntax sugar of quoted literals for string fields -30353 # -30354 # Fake alloc-ids are needed because our type definitions up top require -30355 # handles but it's clearer to statically allocate these long-lived objects. -30356 # Fake alloc-ids are perfectly safe, but they can't be reclaimed. -30357 # -30358 # Every 'object' below starts with a fake alloc-id. It may also contain other -30359 # fake alloc-ids for various handle fields. -30360 # -30361 # I think of objects starting with a fake alloc-id as having type 'payload'. -30362 # It's not really intended to be created dynamically; for that use `allocate` -30363 # as usual. -30364 # -30365 # Idea for a notation to simplify such definitions: -30366 # _Primitive-increment-eax: # (payload primitive) -30367 # 0x11/alloc-id:fake:payload -30368 # 0x11 @(0x11 "increment") # name -30369 # 0 0 # inouts -30370 # 0x11 @(0x11/payload -30371 # 0x11 @(0x11/payload # List-value -30372 # 0 0 # Var-name -30373 # 0x11 @(0x11 # Var-type -30374 # 1/is-atom -30375 # 1/value 0/unused # Type-tree-left -30376 # 0 0 # Type-tree-right -30377 # ) -30378 # 1 # block-depth -30379 # 0 # stack-offset -30380 # 0x11 @(0x11 "eax") # Var-register -30381 # ) -30382 # 0 0) # List-next -30383 # ... -30384 # _Primitive-increment-ecx/imm32/next -30385 # ... -30386 # Awfully complex and non-obvious. But also clearly signals there's something -30387 # to learn here, so may be worth trying. -30388 # -30389 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / " -30390 # -30391 # For now we'll continue to just use comments and manually ensure they stay up -30392 # to date. -30393 == data -30394 Primitives: # (addr primitive) -30395 # - increment/decrement -30396 _Primitive-increment-eax: # (addr primitive) -30397 # var/eax <- increment => 40/increment-eax -30398 0x11/imm32/alloc-id:fake -30399 _string-increment/imm32/name -30400 0/imm32/no-inouts -30401 0/imm32/no-inouts -30402 0x11/imm32/alloc-id:fake -30403 Single-int-var-in-eax/imm32/outputs -30404 0x11/imm32/alloc-id:fake -30405 _string_40_increment_eax/imm32/subx-name -30406 0/imm32/no-rm32 -30407 0/imm32/no-r32 -30408 0/imm32/no-imm32 -30409 0/imm32/no-imm8 -30410 0/imm32/no-disp32 -30411 0/imm32/no-xm32 -30412 0/imm32/no-x32 -30413 0x11/imm32/alloc-id:fake -30414 _Primitive-increment-ecx/imm32/next -30415 _Primitive-increment-ecx: # (payload primitive) -30416 0x11/imm32/alloc-id:fake:payload -30417 # var/ecx <- increment => 41/increment-ecx -30418 0x11/imm32/alloc-id:fake -30419 _string-increment/imm32/name -30420 0/imm32/no-inouts -30421 0/imm32/no-inouts -30422 0x11/imm32/alloc-id:fake -30423 Single-int-var-in-ecx/imm32/outputs -30424 0x11/imm32/alloc-id:fake -30425 _string_41_increment_ecx/imm32/subx-name -30426 0/imm32/no-rm32 -30427 0/imm32/no-r32 -30428 0/imm32/no-imm32 -30429 0/imm32/no-imm8 -30430 0/imm32/no-disp32 -30431 0/imm32/no-xm32 -30432 0/imm32/no-x32 -30433 0x11/imm32/alloc-id:fake -30434 _Primitive-increment-edx/imm32/next -30435 _Primitive-increment-edx: # (payload primitive) -30436 0x11/imm32/alloc-id:fake:payload -30437 # var/edx <- increment => 42/increment-edx -30438 0x11/imm32/alloc-id:fake -30439 _string-increment/imm32/name -30440 0/imm32/no-inouts -30441 0/imm32/no-inouts -30442 0x11/imm32/alloc-id:fake -30443 Single-int-var-in-edx/imm32/outputs -30444 0x11/imm32/alloc-id:fake -30445 _string_42_increment_edx/imm32/subx-name -30446 0/imm32/no-rm32 -30447 0/imm32/no-r32 -30448 0/imm32/no-imm32 -30449 0/imm32/no-imm8 -30450 0/imm32/no-disp32 -30451 0/imm32/no-xm32 -30452 0/imm32/no-x32 -30453 0x11/imm32/alloc-id:fake -30454 _Primitive-increment-ebx/imm32/next -30455 _Primitive-increment-ebx: # (payload primitive) -30456 0x11/imm32/alloc-id:fake:payload -30457 # var/ebx <- increment => 43/increment-ebx +30262 # if (n < 0) abort +30263 3d/compare-eax-with 0/imm32 +30264 0f 8c/jump-if-< $power-of-2?:abort/disp32 +30265 # var tmp/eax: int = n-1 +30266 48/decrement-eax +30267 # var tmp2/eax: int = n & tmp +30268 23/and-> *(ebp+8) 0/r32/eax +30269 # return (tmp2 == 0) +30270 3d/compare-eax-and 0/imm32 +30271 0f 94/set-byte-if-= %al +30272 25/and-eax-with 0xff/imm32 +30273 $power-of-2?:end: +30274 # . epilogue +30275 89/<- %esp 5/r32/ebp +30276 5d/pop-to-ebp +30277 c3/return +30278 +30279 $power-of-2?:abort: +30280 (write-buffered *(ebp+0xc) "power-of-2?: negative number\n") +30281 (flush *(ebp+0xc)) +30282 (stop *(ebp+0x10) 1) +30283 # never gets here +30284 +30285 num-shift-rights: # n: int -> result/eax: int +30286 # precondition: n is a positive power of 2 +30287 # . prologue +30288 55/push-ebp +30289 89/<- %ebp 4/r32/esp +30290 # . save registers +30291 51/push-ecx +30292 # var curr/ecx: int = n +30293 8b/-> *(ebp+8) 1/r32/ecx +30294 # result = 0 +30295 b8/copy-to-eax 0/imm32 +30296 { +30297 # if (curr <= 1) break +30298 81 7/subop/compare %ecx 1/imm32 +30299 7e/jump-if-<= break/disp8 +30300 40/increment-eax +30301 c1/shift 5/subop/arithmetic-right %ecx 1/imm8 +30302 eb/jump loop/disp8 +30303 } +30304 $num-shift-rights:end: +30305 # . restore registers +30306 59/pop-to-ecx +30307 # . epilogue +30308 89/<- %esp 5/r32/ebp +30309 5d/pop-to-ebp +30310 c3/return +30311 +30312 mu-get-offset: # stmt: (addr stmt) -> result/eax: int +30313 # . prologue +30314 55/push-ebp +30315 89/<- %ebp 4/r32/esp +30316 # var second-inout/eax: (addr stmt-var) = stmt->inouts->next +30317 8b/-> *(ebp+8) 0/r32/eax +30318 (lookup *(eax+0xc) *(eax+0x10)) # Stmt1-inouts Stmt1-inouts => eax +30319 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +30320 # var output-var/eax: (addr var) = second-inout->value +30321 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +30322 #? (write-buffered Stderr "mu-get-offset: ") +30323 #? (write-int32-hex-buffered Stderr %eax) +30324 #? (write-buffered Stderr " name: ") +30325 #? 50/push-eax +30326 #? (lookup *eax *(eax+4)) # Var-name +30327 #? (write-buffered Stderr %eax) +30328 #? 58/pop-to-eax +30329 #? (write-buffered Stderr Newline) +30330 #? (flush Stderr) +30331 # return output-var->stack-offset +30332 8b/-> *(eax+0x14) 0/r32/eax # Var-offset +30333 #? (write-buffered Stderr "=> ") +30334 #? (write-int32-hex-buffered Stderr %eax) +30335 #? (write-buffered Stderr Newline) +30336 #? (flush Stderr) +30337 $emit-get-offset:end: +30338 # . epilogue +30339 89/<- %esp 5/r32/ebp +30340 5d/pop-to-ebp +30341 c3/return +30342 +30343 emit-subx-block: # out: (addr buffered-file), block: (addr block), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) +30344 # . prologue +30345 55/push-ebp +30346 89/<- %ebp 4/r32/esp +30347 # . save registers +30348 50/push-eax +30349 51/push-ecx +30350 56/push-esi +30351 # esi = block +30352 8b/-> *(ebp+0xc) 6/r32/esi +30353 # block->var->block-depth = *Curr-block-depth +30354 (lookup *(esi+0xc) *(esi+0x10)) # Block-var Block-var => eax +30355 8b/-> *Curr-block-depth 1/r32/ecx +30356 89/<- *(eax+0x10) 1/r32/ecx # Var-block-depth +30357 # var stmts/eax: (addr list stmt) = lookup(block->statements) +30358 (lookup *(esi+4) *(esi+8)) # Block-stmts Block-stmts => eax +30359 # +30360 { +30361 $emit-subx-block:check-empty: +30362 3d/compare-eax-and 0/imm32 +30363 0f 84/jump-if-= break/disp32 +30364 (emit-indent *(ebp+8) *Curr-block-depth) +30365 (write-buffered *(ebp+8) "{\n") +30366 # var v/ecx: (addr var) = lookup(block->var) +30367 (lookup *(esi+0xc) *(esi+0x10)) # Block-var Block-var => eax +30368 89/<- %ecx 0/r32/eax +30369 # +30370 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +30371 (write-buffered *(ebp+8) %eax) +30372 (write-buffered *(ebp+8) ":loop:\n") +30373 ff 0/subop/increment *Curr-block-depth +30374 (push *(ebp+0x10) *(esi+0xc)) # Block-var +30375 (push *(ebp+0x10) *(esi+0x10)) # Block-var +30376 (push *(ebp+0x10) 0) # false +30377 # emit block->statements +30378 (lookup *(esi+4) *(esi+8)) # Block-stmts Block-stmts => eax +30379 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c)) +30380 (pop *(ebp+0x10)) # => eax +30381 (pop *(ebp+0x10)) # => eax +30382 (pop *(ebp+0x10)) # => eax +30383 ff 1/subop/decrement *Curr-block-depth +30384 (emit-indent *(ebp+8) *Curr-block-depth) +30385 (write-buffered *(ebp+8) "}\n") +30386 (lookup *ecx *(ecx+4)) # Var-name Var-name => eax +30387 (write-buffered *(ebp+8) %eax) +30388 (write-buffered *(ebp+8) ":break:\n") +30389 } +30390 $emit-subx-block:end: +30391 # . restore registers +30392 5e/pop-to-esi +30393 59/pop-to-ecx +30394 58/pop-to-eax +30395 # . epilogue +30396 89/<- %esp 5/r32/ebp +30397 5d/pop-to-ebp +30398 c3/return +30399 +30400 # Primitives supported +30401 # See mu_instructions for a summary of this linked-list data structure. +30402 # +30403 # For each operation, put variants with hard-coded registers before flexible ones. +30404 # +30405 # Unfortunately, our restrictions on addresses require that various fields in +30406 # primitives be handles, which complicates these definitions. +30407 # - we need to insert dummy fields all over the place for fake alloc-ids +30408 # - we can't use our syntax sugar of quoted literals for string fields +30409 # +30410 # Fake alloc-ids are needed because our type definitions up top require +30411 # handles but it's clearer to statically allocate these long-lived objects. +30412 # Fake alloc-ids are perfectly safe, but they can't be reclaimed. +30413 # +30414 # Every 'object' below starts with a fake alloc-id. It may also contain other +30415 # fake alloc-ids for various handle fields. +30416 # +30417 # I think of objects starting with a fake alloc-id as having type 'payload'. +30418 # It's not really intended to be created dynamically; for that use `allocate` +30419 # as usual. +30420 # +30421 # Idea for a notation to simplify such definitions: +30422 # _Primitive-increment-eax: # (payload primitive) +30423 # 0x11/alloc-id:fake:payload +30424 # 0x11 @(0x11 "increment") # name +30425 # 0 0 # inouts +30426 # 0x11 @(0x11/payload +30427 # 0x11 @(0x11/payload # List-value +30428 # 0 0 # Var-name +30429 # 0x11 @(0x11 # Var-type +30430 # 1/is-atom +30431 # 1/value 0/unused # Type-tree-left +30432 # 0 0 # Type-tree-right +30433 # ) +30434 # 1 # block-depth +30435 # 0 # stack-offset +30436 # 0x11 @(0x11 "eax") # Var-register +30437 # ) +30438 # 0 0) # List-next +30439 # ... +30440 # _Primitive-increment-ecx/imm32/next +30441 # ... +30442 # Awfully complex and non-obvious. But also clearly signals there's something +30443 # to learn here, so may be worth trying. +30444 # +30445 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / " +30446 # +30447 # For now we'll continue to just use comments and manually ensure they stay up +30448 # to date. +30449 == data +30450 Primitives: # (addr primitive) +30451 # - increment/decrement +30452 _Primitive-increment-eax: # (addr primitive) +30453 # var/eax <- increment => 40/increment-eax +30454 0x11/imm32/alloc-id:fake +30455 _string-increment/imm32/name +30456 0/imm32/no-inouts +30457 0/imm32/no-inouts 30458 0x11/imm32/alloc-id:fake -30459 _string-increment/imm32/name -30460 0/imm32/no-inouts -30461 0/imm32/no-inouts -30462 0x11/imm32/alloc-id:fake -30463 Single-int-var-in-ebx/imm32/outputs -30464 0x11/imm32/alloc-id:fake -30465 _string_43_increment_ebx/imm32/subx-name -30466 0/imm32/no-rm32 -30467 0/imm32/no-r32 -30468 0/imm32/no-imm32 -30469 0/imm32/no-imm8 -30470 0/imm32/no-disp32 -30471 0/imm32/no-xm32 -30472 0/imm32/no-x32 -30473 0x11/imm32/alloc-id:fake -30474 _Primitive-increment-esi/imm32/next -30475 _Primitive-increment-esi: # (payload primitive) -30476 0x11/imm32/alloc-id:fake:payload -30477 # var/esi <- increment => 46/increment-esi +30459 Single-int-var-in-eax/imm32/outputs +30460 0x11/imm32/alloc-id:fake +30461 _string_40_increment_eax/imm32/subx-name +30462 0/imm32/no-rm32 +30463 0/imm32/no-r32 +30464 0/imm32/no-imm32 +30465 0/imm32/no-imm8 +30466 0/imm32/no-disp32 +30467 0/imm32/no-xm32 +30468 0/imm32/no-x32 +30469 0x11/imm32/alloc-id:fake +30470 _Primitive-increment-ecx/imm32/next +30471 _Primitive-increment-ecx: # (payload primitive) +30472 0x11/imm32/alloc-id:fake:payload +30473 # var/ecx <- increment => 41/increment-ecx +30474 0x11/imm32/alloc-id:fake +30475 _string-increment/imm32/name +30476 0/imm32/no-inouts +30477 0/imm32/no-inouts 30478 0x11/imm32/alloc-id:fake -30479 _string-increment/imm32/name -30480 0/imm32/no-inouts -30481 0/imm32/no-inouts -30482 0x11/imm32/alloc-id:fake -30483 Single-int-var-in-esi/imm32/outputs -30484 0x11/imm32/alloc-id:fake -30485 _string_46_increment_esi/imm32/subx-name -30486 0/imm32/no-rm32 -30487 0/imm32/no-r32 -30488 0/imm32/no-imm32 -30489 0/imm32/no-imm8 -30490 0/imm32/no-disp32 -30491 0/imm32/no-xm32 -30492 0/imm32/no-x32 -30493 0x11/imm32/alloc-id:fake -30494 _Primitive-increment-edi/imm32/next -30495 _Primitive-increment-edi: # (payload primitive) -30496 0x11/imm32/alloc-id:fake:payload -30497 # var/edi <- increment => 47/increment-edi +30479 Single-int-var-in-ecx/imm32/outputs +30480 0x11/imm32/alloc-id:fake +30481 _string_41_increment_ecx/imm32/subx-name +30482 0/imm32/no-rm32 +30483 0/imm32/no-r32 +30484 0/imm32/no-imm32 +30485 0/imm32/no-imm8 +30486 0/imm32/no-disp32 +30487 0/imm32/no-xm32 +30488 0/imm32/no-x32 +30489 0x11/imm32/alloc-id:fake +30490 _Primitive-increment-edx/imm32/next +30491 _Primitive-increment-edx: # (payload primitive) +30492 0x11/imm32/alloc-id:fake:payload +30493 # var/edx <- increment => 42/increment-edx +30494 0x11/imm32/alloc-id:fake +30495 _string-increment/imm32/name +30496 0/imm32/no-inouts +30497 0/imm32/no-inouts 30498 0x11/imm32/alloc-id:fake -30499 _string-increment/imm32/name -30500 0/imm32/no-inouts -30501 0/imm32/no-inouts -30502 0x11/imm32/alloc-id:fake -30503 Single-int-var-in-edi/imm32/outputs -30504 0x11/imm32/alloc-id:fake -30505 _string_47_increment_edi/imm32/subx-name -30506 0/imm32/no-rm32 -30507 0/imm32/no-r32 -30508 0/imm32/no-imm32 -30509 0/imm32/no-imm8 -30510 0/imm32/no-disp32 -30511 0/imm32/no-xm32 -30512 0/imm32/no-x32 -30513 0x11/imm32/alloc-id:fake -30514 _Primitive-decrement-eax/imm32/next -30515 _Primitive-decrement-eax: # (payload primitive) -30516 0x11/imm32/alloc-id:fake:payload -30517 # var/eax <- decrement => 48/decrement-eax +30499 Single-int-var-in-edx/imm32/outputs +30500 0x11/imm32/alloc-id:fake +30501 _string_42_increment_edx/imm32/subx-name +30502 0/imm32/no-rm32 +30503 0/imm32/no-r32 +30504 0/imm32/no-imm32 +30505 0/imm32/no-imm8 +30506 0/imm32/no-disp32 +30507 0/imm32/no-xm32 +30508 0/imm32/no-x32 +30509 0x11/imm32/alloc-id:fake +30510 _Primitive-increment-ebx/imm32/next +30511 _Primitive-increment-ebx: # (payload primitive) +30512 0x11/imm32/alloc-id:fake:payload +30513 # var/ebx <- increment => 43/increment-ebx +30514 0x11/imm32/alloc-id:fake +30515 _string-increment/imm32/name +30516 0/imm32/no-inouts +30517 0/imm32/no-inouts 30518 0x11/imm32/alloc-id:fake -30519 _string-decrement/imm32/name -30520 0/imm32/no-inouts -30521 0/imm32/no-inouts -30522 0x11/imm32/alloc-id:fake -30523 Single-int-var-in-eax/imm32/outputs -30524 0x11/imm32/alloc-id:fake -30525 _string_48_decrement_eax/imm32/subx-name -30526 0/imm32/no-rm32 -30527 0/imm32/no-r32 -30528 0/imm32/no-imm32 -30529 0/imm32/no-imm8 -30530 0/imm32/no-disp32 -30531 0/imm32/no-xm32 -30532 0/imm32/no-x32 -30533 0x11/imm32/alloc-id:fake -30534 _Primitive-decrement-ecx/imm32/next -30535 _Primitive-decrement-ecx: # (payload primitive) -30536 0x11/imm32/alloc-id:fake:payload -30537 # var/ecx <- decrement => 49/decrement-ecx +30519 Single-int-var-in-ebx/imm32/outputs +30520 0x11/imm32/alloc-id:fake +30521 _string_43_increment_ebx/imm32/subx-name +30522 0/imm32/no-rm32 +30523 0/imm32/no-r32 +30524 0/imm32/no-imm32 +30525 0/imm32/no-imm8 +30526 0/imm32/no-disp32 +30527 0/imm32/no-xm32 +30528 0/imm32/no-x32 +30529 0x11/imm32/alloc-id:fake +30530 _Primitive-increment-esi/imm32/next +30531 _Primitive-increment-esi: # (payload primitive) +30532 0x11/imm32/alloc-id:fake:payload +30533 # var/esi <- increment => 46/increment-esi +30534 0x11/imm32/alloc-id:fake +30535 _string-increment/imm32/name +30536 0/imm32/no-inouts +30537 0/imm32/no-inouts 30538 0x11/imm32/alloc-id:fake -30539 _string-decrement/imm32/name -30540 0/imm32/no-inouts -30541 0/imm32/no-inouts -30542 0x11/imm32/alloc-id:fake -30543 Single-int-var-in-ecx/imm32/outputs -30544 0x11/imm32/alloc-id:fake -30545 _string_49_decrement_ecx/imm32/subx-name -30546 0/imm32/no-rm32 -30547 0/imm32/no-r32 -30548 0/imm32/no-imm32 -30549 0/imm32/no-imm8 -30550 0/imm32/no-disp32 -30551 0/imm32/no-xm32 -30552 0/imm32/no-x32 -30553 0x11/imm32/alloc-id:fake -30554 _Primitive-decrement-edx/imm32/next -30555 _Primitive-decrement-edx: # (payload primitive) -30556 0x11/imm32/alloc-id:fake:payload -30557 # var/edx <- decrement => 4a/decrement-edx +30539 Single-int-var-in-esi/imm32/outputs +30540 0x11/imm32/alloc-id:fake +30541 _string_46_increment_esi/imm32/subx-name +30542 0/imm32/no-rm32 +30543 0/imm32/no-r32 +30544 0/imm32/no-imm32 +30545 0/imm32/no-imm8 +30546 0/imm32/no-disp32 +30547 0/imm32/no-xm32 +30548 0/imm32/no-x32 +30549 0x11/imm32/alloc-id:fake +30550 _Primitive-increment-edi/imm32/next +30551 _Primitive-increment-edi: # (payload primitive) +30552 0x11/imm32/alloc-id:fake:payload +30553 # var/edi <- increment => 47/increment-edi +30554 0x11/imm32/alloc-id:fake +30555 _string-increment/imm32/name +30556 0/imm32/no-inouts +30557 0/imm32/no-inouts 30558 0x11/imm32/alloc-id:fake -30559 _string-decrement/imm32/name -30560 0/imm32/no-inouts -30561 0/imm32/no-inouts -30562 0x11/imm32/alloc-id:fake -30563 Single-int-var-in-edx/imm32/outputs -30564 0x11/imm32/alloc-id:fake -30565 _string_4a_decrement_edx/imm32/subx-name -30566 0/imm32/no-rm32 -30567 0/imm32/no-r32 -30568 0/imm32/no-imm32 -30569 0/imm32/no-imm8 -30570 0/imm32/no-disp32 -30571 0/imm32/no-xm32 -30572 0/imm32/no-x32 -30573 0x11/imm32/alloc-id:fake -30574 _Primitive-decrement-ebx/imm32/next -30575 _Primitive-decrement-ebx: # (payload primitive) -30576 0x11/imm32/alloc-id:fake:payload -30577 # var/ebx <- decrement => 4b/decrement-ebx +30559 Single-int-var-in-edi/imm32/outputs +30560 0x11/imm32/alloc-id:fake +30561 _string_47_increment_edi/imm32/subx-name +30562 0/imm32/no-rm32 +30563 0/imm32/no-r32 +30564 0/imm32/no-imm32 +30565 0/imm32/no-imm8 +30566 0/imm32/no-disp32 +30567 0/imm32/no-xm32 +30568 0/imm32/no-x32 +30569 0x11/imm32/alloc-id:fake +30570 _Primitive-decrement-eax/imm32/next +30571 _Primitive-decrement-eax: # (payload primitive) +30572 0x11/imm32/alloc-id:fake:payload +30573 # var/eax <- decrement => 48/decrement-eax +30574 0x11/imm32/alloc-id:fake +30575 _string-decrement/imm32/name +30576 0/imm32/no-inouts +30577 0/imm32/no-inouts 30578 0x11/imm32/alloc-id:fake -30579 _string-decrement/imm32/name -30580 0/imm32/no-inouts -30581 0/imm32/no-inouts -30582 0x11/imm32/alloc-id:fake -30583 Single-int-var-in-ebx/imm32/outputs -30584 0x11/imm32/alloc-id:fake -30585 _string_4b_decrement_ebx/imm32/subx-name -30586 0/imm32/no-rm32 -30587 0/imm32/no-r32 -30588 0/imm32/no-imm32 -30589 0/imm32/no-imm8 -30590 0/imm32/no-disp32 -30591 0/imm32/no-xm32 -30592 0/imm32/no-x32 -30593 0x11/imm32/alloc-id:fake -30594 _Primitive-decrement-esi/imm32/next -30595 _Primitive-decrement-esi: # (payload primitive) -30596 0x11/imm32/alloc-id:fake:payload -30597 # var/esi <- decrement => 4e/decrement-esi +30579 Single-int-var-in-eax/imm32/outputs +30580 0x11/imm32/alloc-id:fake +30581 _string_48_decrement_eax/imm32/subx-name +30582 0/imm32/no-rm32 +30583 0/imm32/no-r32 +30584 0/imm32/no-imm32 +30585 0/imm32/no-imm8 +30586 0/imm32/no-disp32 +30587 0/imm32/no-xm32 +30588 0/imm32/no-x32 +30589 0x11/imm32/alloc-id:fake +30590 _Primitive-decrement-ecx/imm32/next +30591 _Primitive-decrement-ecx: # (payload primitive) +30592 0x11/imm32/alloc-id:fake:payload +30593 # var/ecx <- decrement => 49/decrement-ecx +30594 0x11/imm32/alloc-id:fake +30595 _string-decrement/imm32/name +30596 0/imm32/no-inouts +30597 0/imm32/no-inouts 30598 0x11/imm32/alloc-id:fake -30599 _string-decrement/imm32/name -30600 0/imm32/no-inouts -30601 0/imm32/no-inouts -30602 0x11/imm32/alloc-id:fake -30603 Single-int-var-in-esi/imm32/outputs -30604 0x11/imm32/alloc-id:fake -30605 _string_4e_decrement_esi/imm32/subx-name -30606 0/imm32/no-rm32 -30607 0/imm32/no-r32 -30608 0/imm32/no-imm32 -30609 0/imm32/no-imm8 -30610 0/imm32/no-disp32 -30611 0/imm32/no-xm32 -30612 0/imm32/no-x32 -30613 0x11/imm32/alloc-id:fake -30614 _Primitive-decrement-edi/imm32/next -30615 _Primitive-decrement-edi: # (payload primitive) -30616 0x11/imm32/alloc-id:fake:payload -30617 # var/edi <- decrement => 4f/decrement-edi +30599 Single-int-var-in-ecx/imm32/outputs +30600 0x11/imm32/alloc-id:fake +30601 _string_49_decrement_ecx/imm32/subx-name +30602 0/imm32/no-rm32 +30603 0/imm32/no-r32 +30604 0/imm32/no-imm32 +30605 0/imm32/no-imm8 +30606 0/imm32/no-disp32 +30607 0/imm32/no-xm32 +30608 0/imm32/no-x32 +30609 0x11/imm32/alloc-id:fake +30610 _Primitive-decrement-edx/imm32/next +30611 _Primitive-decrement-edx: # (payload primitive) +30612 0x11/imm32/alloc-id:fake:payload +30613 # var/edx <- decrement => 4a/decrement-edx +30614 0x11/imm32/alloc-id:fake +30615 _string-decrement/imm32/name +30616 0/imm32/no-inouts +30617 0/imm32/no-inouts 30618 0x11/imm32/alloc-id:fake -30619 _string-decrement/imm32/name -30620 0/imm32/no-inouts -30621 0/imm32/no-inouts -30622 0x11/imm32/alloc-id:fake -30623 Single-int-var-in-edi/imm32/outputs -30624 0x11/imm32/alloc-id:fake -30625 _string_4f_decrement_edi/imm32/subx-name -30626 0/imm32/no-rm32 -30627 0/imm32/no-r32 -30628 0/imm32/no-imm32 -30629 0/imm32/no-imm8 -30630 0/imm32/no-disp32 -30631 0/imm32/no-xm32 -30632 0/imm32/no-x32 -30633 0x11/imm32/alloc-id:fake -30634 _Primitive-increment-mem/imm32/next -30635 _Primitive-increment-mem: # (payload primitive) -30636 0x11/imm32/alloc-id:fake:payload -30637 # increment var => ff 0/subop/increment *(ebp+__) +30619 Single-int-var-in-edx/imm32/outputs +30620 0x11/imm32/alloc-id:fake +30621 _string_4a_decrement_edx/imm32/subx-name +30622 0/imm32/no-rm32 +30623 0/imm32/no-r32 +30624 0/imm32/no-imm32 +30625 0/imm32/no-imm8 +30626 0/imm32/no-disp32 +30627 0/imm32/no-xm32 +30628 0/imm32/no-x32 +30629 0x11/imm32/alloc-id:fake +30630 _Primitive-decrement-ebx/imm32/next +30631 _Primitive-decrement-ebx: # (payload primitive) +30632 0x11/imm32/alloc-id:fake:payload +30633 # var/ebx <- decrement => 4b/decrement-ebx +30634 0x11/imm32/alloc-id:fake +30635 _string-decrement/imm32/name +30636 0/imm32/no-inouts +30637 0/imm32/no-inouts 30638 0x11/imm32/alloc-id:fake -30639 _string-increment/imm32/name +30639 Single-int-var-in-ebx/imm32/outputs 30640 0x11/imm32/alloc-id:fake -30641 Single-int-var-in-mem/imm32/inouts -30642 0/imm32/no-outputs -30643 0/imm32/no-outputs -30644 0x11/imm32/alloc-id:fake -30645 _string_ff_subop_increment/imm32/subx-name -30646 1/imm32/rm32-is-first-inout -30647 0/imm32/no-r32 -30648 0/imm32/no-imm32 -30649 0/imm32/no-imm8 -30650 0/imm32/no-disp32 -30651 0/imm32/no-xm32 -30652 0/imm32/no-x32 -30653 0x11/imm32/alloc-id:fake -30654 _Primitive-increment-reg/imm32/next -30655 _Primitive-increment-reg: # (payload primitive) -30656 0x11/imm32/alloc-id:fake:payload -30657 # var/reg <- increment => ff 0/subop/increment %__ +30641 _string_4b_decrement_ebx/imm32/subx-name +30642 0/imm32/no-rm32 +30643 0/imm32/no-r32 +30644 0/imm32/no-imm32 +30645 0/imm32/no-imm8 +30646 0/imm32/no-disp32 +30647 0/imm32/no-xm32 +30648 0/imm32/no-x32 +30649 0x11/imm32/alloc-id:fake +30650 _Primitive-decrement-esi/imm32/next +30651 _Primitive-decrement-esi: # (payload primitive) +30652 0x11/imm32/alloc-id:fake:payload +30653 # var/esi <- decrement => 4e/decrement-esi +30654 0x11/imm32/alloc-id:fake +30655 _string-decrement/imm32/name +30656 0/imm32/no-inouts +30657 0/imm32/no-inouts 30658 0x11/imm32/alloc-id:fake -30659 _string-increment/imm32/name -30660 0/imm32/no-inouts -30661 0/imm32/no-inouts -30662 0x11/imm32/alloc-id:fake -30663 Single-int-var-in-some-register/imm32/outputs -30664 0x11/imm32/alloc-id:fake -30665 _string_ff_subop_increment/imm32/subx-name -30666 3/imm32/rm32-is-first-output -30667 0/imm32/no-r32 -30668 0/imm32/no-imm32 -30669 0/imm32/no-imm8 -30670 0/imm32/no-disp32 -30671 0/imm32/no-xm32 -30672 0/imm32/no-x32 -30673 0x11/imm32/alloc-id:fake -30674 _Primitive-decrement-mem/imm32/next -30675 _Primitive-decrement-mem: # (payload primitive) -30676 0x11/imm32/alloc-id:fake:payload -30677 # decrement var => ff 1/subop/decrement *(ebp+__) +30659 Single-int-var-in-esi/imm32/outputs +30660 0x11/imm32/alloc-id:fake +30661 _string_4e_decrement_esi/imm32/subx-name +30662 0/imm32/no-rm32 +30663 0/imm32/no-r32 +30664 0/imm32/no-imm32 +30665 0/imm32/no-imm8 +30666 0/imm32/no-disp32 +30667 0/imm32/no-xm32 +30668 0/imm32/no-x32 +30669 0x11/imm32/alloc-id:fake +30670 _Primitive-decrement-edi/imm32/next +30671 _Primitive-decrement-edi: # (payload primitive) +30672 0x11/imm32/alloc-id:fake:payload +30673 # var/edi <- decrement => 4f/decrement-edi +30674 0x11/imm32/alloc-id:fake +30675 _string-decrement/imm32/name +30676 0/imm32/no-inouts +30677 0/imm32/no-inouts 30678 0x11/imm32/alloc-id:fake -30679 _string-decrement/imm32/name +30679 Single-int-var-in-edi/imm32/outputs 30680 0x11/imm32/alloc-id:fake -30681 Single-int-var-in-mem/imm32/inouts -30682 0/imm32/no-outputs -30683 0/imm32/no-outputs -30684 0x11/imm32/alloc-id:fake -30685 _string_ff_subop_decrement/imm32/subx-name -30686 1/imm32/rm32-is-first-inout -30687 0/imm32/no-r32 -30688 0/imm32/no-imm32 -30689 0/imm32/no-imm8 -30690 0/imm32/no-disp32 -30691 0/imm32/no-xm32 -30692 0/imm32/no-x32 -30693 0x11/imm32/alloc-id:fake -30694 _Primitive-decrement-reg/imm32/next -30695 _Primitive-decrement-reg: # (payload primitive) -30696 0x11/imm32/alloc-id:fake:payload -30697 # var/reg <- decrement => ff 1/subop/decrement %__ -30698 0x11/imm32/alloc-id:fake -30699 _string-decrement/imm32/name -30700 0/imm32/no-inouts -30701 0/imm32/no-inouts -30702 0x11/imm32/alloc-id:fake -30703 Single-int-var-in-some-register/imm32/outputs -30704 0x11/imm32/alloc-id:fake -30705 _string_ff_subop_decrement/imm32/subx-name -30706 3/imm32/rm32-is-first-output -30707 0/imm32/no-r32 -30708 0/imm32/no-imm32 -30709 0/imm32/no-imm8 -30710 0/imm32/no-disp32 -30711 0/imm32/no-xm32 -30712 0/imm32/no-x32 -30713 0x11/imm32/alloc-id:fake -30714 _Primitive-add-to-eax/imm32/next -30715 # - add -30716 _Primitive-add-to-eax: # (payload primitive) -30717 0x11/imm32/alloc-id:fake:payload -30718 # var/eax <- add lit => 05/add-to-eax lit/imm32 -30719 0x11/imm32/alloc-id:fake -30720 _string-add/imm32/name -30721 0x11/imm32/alloc-id:fake -30722 Single-lit-var/imm32/inouts -30723 0x11/imm32/alloc-id:fake -30724 Single-int-var-in-eax/imm32/outputs -30725 0x11/imm32/alloc-id:fake -30726 _string_05_add_to_eax/imm32/subx-name -30727 0/imm32/no-rm32 -30728 0/imm32/no-r32 -30729 1/imm32/imm32-is-first-inout -30730 0/imm32/no-imm8 -30731 0/imm32/no-disp32 -30732 0/imm32/no-xm32 -30733 0/imm32/no-x32 +30681 _string_4f_decrement_edi/imm32/subx-name +30682 0/imm32/no-rm32 +30683 0/imm32/no-r32 +30684 0/imm32/no-imm32 +30685 0/imm32/no-imm8 +30686 0/imm32/no-disp32 +30687 0/imm32/no-xm32 +30688 0/imm32/no-x32 +30689 0x11/imm32/alloc-id:fake +30690 _Primitive-increment-mem/imm32/next +30691 _Primitive-increment-mem: # (payload primitive) +30692 0x11/imm32/alloc-id:fake:payload +30693 # increment var => ff 0/subop/increment *(ebp+__) +30694 0x11/imm32/alloc-id:fake +30695 _string-increment/imm32/name +30696 0x11/imm32/alloc-id:fake +30697 Single-int-var-in-mem/imm32/inouts +30698 0/imm32/no-outputs +30699 0/imm32/no-outputs +30700 0x11/imm32/alloc-id:fake +30701 _string_ff_subop_increment/imm32/subx-name +30702 1/imm32/rm32-is-first-inout +30703 0/imm32/no-r32 +30704 0/imm32/no-imm32 +30705 0/imm32/no-imm8 +30706 0/imm32/no-disp32 +30707 0/imm32/no-xm32 +30708 0/imm32/no-x32 +30709 0x11/imm32/alloc-id:fake +30710 _Primitive-increment-reg/imm32/next +30711 _Primitive-increment-reg: # (payload primitive) +30712 0x11/imm32/alloc-id:fake:payload +30713 # var/reg <- increment => ff 0/subop/increment %__ +30714 0x11/imm32/alloc-id:fake +30715 _string-increment/imm32/name +30716 0/imm32/no-inouts +30717 0/imm32/no-inouts +30718 0x11/imm32/alloc-id:fake +30719 Single-int-var-in-some-register/imm32/outputs +30720 0x11/imm32/alloc-id:fake +30721 _string_ff_subop_increment/imm32/subx-name +30722 3/imm32/rm32-is-first-output +30723 0/imm32/no-r32 +30724 0/imm32/no-imm32 +30725 0/imm32/no-imm8 +30726 0/imm32/no-disp32 +30727 0/imm32/no-xm32 +30728 0/imm32/no-x32 +30729 0x11/imm32/alloc-id:fake +30730 _Primitive-decrement-mem/imm32/next +30731 _Primitive-decrement-mem: # (payload primitive) +30732 0x11/imm32/alloc-id:fake:payload +30733 # decrement var => ff 1/subop/decrement *(ebp+__) 30734 0x11/imm32/alloc-id:fake -30735 _Primitive-add-reg-to-reg/imm32/next -30736 _Primitive-add-reg-to-reg: # (payload primitive) -30737 0x11/imm32/alloc-id:fake:payload -30738 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -30739 0x11/imm32/alloc-id:fake -30740 _string-add/imm32/name -30741 0x11/imm32/alloc-id:fake -30742 Single-int-var-in-some-register/imm32/inouts -30743 0x11/imm32/alloc-id:fake -30744 Single-int-var-in-some-register/imm32/outputs -30745 0x11/imm32/alloc-id:fake -30746 _string_01_add_to/imm32/subx-name -30747 3/imm32/rm32-is-first-output -30748 1/imm32/r32-is-first-inout -30749 0/imm32/no-imm32 -30750 0/imm32/no-imm8 -30751 0/imm32/no-disp32 -30752 0/imm32/no-xm32 -30753 0/imm32/no-x32 +30735 _string-decrement/imm32/name +30736 0x11/imm32/alloc-id:fake +30737 Single-int-var-in-mem/imm32/inouts +30738 0/imm32/no-outputs +30739 0/imm32/no-outputs +30740 0x11/imm32/alloc-id:fake +30741 _string_ff_subop_decrement/imm32/subx-name +30742 1/imm32/rm32-is-first-inout +30743 0/imm32/no-r32 +30744 0/imm32/no-imm32 +30745 0/imm32/no-imm8 +30746 0/imm32/no-disp32 +30747 0/imm32/no-xm32 +30748 0/imm32/no-x32 +30749 0x11/imm32/alloc-id:fake +30750 _Primitive-decrement-reg/imm32/next +30751 _Primitive-decrement-reg: # (payload primitive) +30752 0x11/imm32/alloc-id:fake:payload +30753 # var/reg <- decrement => ff 1/subop/decrement %__ 30754 0x11/imm32/alloc-id:fake -30755 _Primitive-add-reg-to-mem/imm32/next -30756 _Primitive-add-reg-to-mem: # (payload primitive) -30757 0x11/imm32/alloc-id:fake:payload -30758 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -30759 0x11/imm32/alloc-id:fake -30760 _string-add-to/imm32/name -30761 0x11/imm32/alloc-id:fake -30762 Two-args-int-stack-int-reg/imm32/inouts -30763 0/imm32/no-outputs -30764 0/imm32/no-outputs -30765 0x11/imm32/alloc-id:fake -30766 _string_01_add_to/imm32/subx-name -30767 1/imm32/rm32-is-first-inout -30768 2/imm32/r32-is-second-inout -30769 0/imm32/no-imm32 -30770 0/imm32/no-imm8 -30771 0/imm32/no-disp32 -30772 0/imm32/no-xm32 -30773 0/imm32/no-x32 -30774 0x11/imm32/alloc-id:fake -30775 _Primitive-add-mem-to-reg/imm32/next -30776 _Primitive-add-mem-to-reg: # (payload primitive) -30777 0x11/imm32/alloc-id:fake:payload -30778 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +30755 _string-decrement/imm32/name +30756 0/imm32/no-inouts +30757 0/imm32/no-inouts +30758 0x11/imm32/alloc-id:fake +30759 Single-int-var-in-some-register/imm32/outputs +30760 0x11/imm32/alloc-id:fake +30761 _string_ff_subop_decrement/imm32/subx-name +30762 3/imm32/rm32-is-first-output +30763 0/imm32/no-r32 +30764 0/imm32/no-imm32 +30765 0/imm32/no-imm8 +30766 0/imm32/no-disp32 +30767 0/imm32/no-xm32 +30768 0/imm32/no-x32 +30769 0x11/imm32/alloc-id:fake +30770 _Primitive-add-to-eax/imm32/next +30771 # - add +30772 _Primitive-add-to-eax: # (payload primitive) +30773 0x11/imm32/alloc-id:fake:payload +30774 # var/eax <- add lit => 05/add-to-eax lit/imm32 +30775 0x11/imm32/alloc-id:fake +30776 _string-add/imm32/name +30777 0x11/imm32/alloc-id:fake +30778 Single-lit-var/imm32/inouts 30779 0x11/imm32/alloc-id:fake -30780 _string-add/imm32/name +30780 Single-int-var-in-eax/imm32/outputs 30781 0x11/imm32/alloc-id:fake -30782 Single-int-var-in-mem/imm32/inouts -30783 0x11/imm32/alloc-id:fake -30784 Single-int-var-in-some-register/imm32/outputs -30785 0x11/imm32/alloc-id:fake -30786 _string_03_add/imm32/subx-name -30787 1/imm32/rm32-is-first-inout -30788 3/imm32/r32-is-first-output -30789 0/imm32/no-imm32 -30790 0/imm32/no-imm8 -30791 0/imm32/no-disp32 -30792 0/imm32/no-xm32 -30793 0/imm32/no-x32 -30794 0x11/imm32/alloc-id:fake -30795 _Primitive-add-lit-to-reg/imm32/next -30796 _Primitive-add-lit-to-reg: # (payload primitive) -30797 0x11/imm32/alloc-id:fake:payload -30798 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 +30782 _string_05_add_to_eax/imm32/subx-name +30783 0/imm32/no-rm32 +30784 0/imm32/no-r32 +30785 1/imm32/imm32-is-first-inout +30786 0/imm32/no-imm8 +30787 0/imm32/no-disp32 +30788 0/imm32/no-xm32 +30789 0/imm32/no-x32 +30790 0x11/imm32/alloc-id:fake +30791 _Primitive-add-reg-to-reg/imm32/next +30792 _Primitive-add-reg-to-reg: # (payload primitive) +30793 0x11/imm32/alloc-id:fake:payload +30794 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 +30795 0x11/imm32/alloc-id:fake +30796 _string-add/imm32/name +30797 0x11/imm32/alloc-id:fake +30798 Single-int-var-in-some-register/imm32/inouts 30799 0x11/imm32/alloc-id:fake -30800 _string-add/imm32/name +30800 Single-int-var-in-some-register/imm32/outputs 30801 0x11/imm32/alloc-id:fake -30802 Single-lit-var/imm32/inouts -30803 0x11/imm32/alloc-id:fake -30804 Single-int-var-in-some-register/imm32/outputs -30805 0x11/imm32/alloc-id:fake -30806 _string_81_subop_add/imm32/subx-name -30807 3/imm32/rm32-is-first-output -30808 0/imm32/no-r32 -30809 1/imm32/imm32-is-first-inout -30810 0/imm32/no-imm8 -30811 0/imm32/no-disp32 -30812 0/imm32/no-xm32 -30813 0/imm32/no-x32 -30814 0x11/imm32/alloc-id:fake -30815 _Primitive-add-lit-to-mem/imm32/next -30816 _Primitive-add-lit-to-mem: # (payload primitive) -30817 0x11/imm32/alloc-id:fake:payload -30818 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -30819 0x11/imm32/alloc-id:fake -30820 _string-add-to/imm32/name +30802 _string_01_add_to/imm32/subx-name +30803 3/imm32/rm32-is-first-output +30804 1/imm32/r32-is-first-inout +30805 0/imm32/no-imm32 +30806 0/imm32/no-imm8 +30807 0/imm32/no-disp32 +30808 0/imm32/no-xm32 +30809 0/imm32/no-x32 +30810 0x11/imm32/alloc-id:fake +30811 _Primitive-add-reg-to-mem/imm32/next +30812 _Primitive-add-reg-to-mem: # (payload primitive) +30813 0x11/imm32/alloc-id:fake:payload +30814 # add-to var1 var2/reg => 01/add-to var1 var2/r32 +30815 0x11/imm32/alloc-id:fake +30816 _string-add-to/imm32/name +30817 0x11/imm32/alloc-id:fake +30818 Two-args-int-stack-int-reg/imm32/inouts +30819 0/imm32/no-outputs +30820 0/imm32/no-outputs 30821 0x11/imm32/alloc-id:fake -30822 Int-var-and-literal/imm32/inouts -30823 0/imm32/no-outputs -30824 0/imm32/no-outputs -30825 0x11/imm32/alloc-id:fake -30826 _string_81_subop_add/imm32/subx-name -30827 1/imm32/rm32-is-first-inout -30828 0/imm32/no-r32 -30829 2/imm32/imm32-is-second-inout -30830 0/imm32/no-imm8 -30831 0/imm32/no-disp32 -30832 0/imm32/no-xm32 -30833 0/imm32/no-x32 -30834 0x11/imm32/alloc-id:fake -30835 _Primitive-subtract-from-eax/imm32/next -30836 # - subtract -30837 _Primitive-subtract-from-eax: # (payload primitive) -30838 0x11/imm32/alloc-id:fake:payload -30839 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -30840 0x11/imm32/alloc-id:fake -30841 _string-subtract/imm32/name -30842 0x11/imm32/alloc-id:fake -30843 Single-lit-var/imm32/inouts -30844 0x11/imm32/alloc-id:fake -30845 Single-int-var-in-eax/imm32/outputs -30846 0x11/imm32/alloc-id:fake -30847 _string_2d_subtract_from_eax/imm32/subx-name -30848 0/imm32/no-rm32 -30849 0/imm32/no-r32 -30850 1/imm32/imm32-is-first-inout -30851 0/imm32/no-imm8 -30852 0/imm32/no-disp32 -30853 0/imm32/no-xm32 -30854 0/imm32/no-x32 +30822 _string_01_add_to/imm32/subx-name +30823 1/imm32/rm32-is-first-inout +30824 2/imm32/r32-is-second-inout +30825 0/imm32/no-imm32 +30826 0/imm32/no-imm8 +30827 0/imm32/no-disp32 +30828 0/imm32/no-xm32 +30829 0/imm32/no-x32 +30830 0x11/imm32/alloc-id:fake +30831 _Primitive-add-mem-to-reg/imm32/next +30832 _Primitive-add-mem-to-reg: # (payload primitive) +30833 0x11/imm32/alloc-id:fake:payload +30834 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +30835 0x11/imm32/alloc-id:fake +30836 _string-add/imm32/name +30837 0x11/imm32/alloc-id:fake +30838 Single-int-var-in-mem/imm32/inouts +30839 0x11/imm32/alloc-id:fake +30840 Single-int-var-in-some-register/imm32/outputs +30841 0x11/imm32/alloc-id:fake +30842 _string_03_add/imm32/subx-name +30843 1/imm32/rm32-is-first-inout +30844 3/imm32/r32-is-first-output +30845 0/imm32/no-imm32 +30846 0/imm32/no-imm8 +30847 0/imm32/no-disp32 +30848 0/imm32/no-xm32 +30849 0/imm32/no-x32 +30850 0x11/imm32/alloc-id:fake +30851 _Primitive-add-lit-to-reg/imm32/next +30852 _Primitive-add-lit-to-reg: # (payload primitive) +30853 0x11/imm32/alloc-id:fake:payload +30854 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 30855 0x11/imm32/alloc-id:fake -30856 _Primitive-subtract-reg-from-reg/imm32/next -30857 _Primitive-subtract-reg-from-reg: # (payload primitive) -30858 0x11/imm32/alloc-id:fake:payload -30859 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -30860 0x11/imm32/alloc-id:fake -30861 _string-subtract/imm32/name -30862 0x11/imm32/alloc-id:fake -30863 Single-int-var-in-some-register/imm32/inouts -30864 0x11/imm32/alloc-id:fake -30865 Single-int-var-in-some-register/imm32/outputs -30866 0x11/imm32/alloc-id:fake -30867 _string_29_subtract_from/imm32/subx-name -30868 3/imm32/rm32-is-first-output -30869 1/imm32/r32-is-first-inout -30870 0/imm32/no-imm32 -30871 0/imm32/no-imm8 -30872 0/imm32/no-disp32 -30873 0/imm32/no-xm32 -30874 0/imm32/no-x32 +30856 _string-add/imm32/name +30857 0x11/imm32/alloc-id:fake +30858 Single-lit-var/imm32/inouts +30859 0x11/imm32/alloc-id:fake +30860 Single-int-var-in-some-register/imm32/outputs +30861 0x11/imm32/alloc-id:fake +30862 _string_81_subop_add/imm32/subx-name +30863 3/imm32/rm32-is-first-output +30864 0/imm32/no-r32 +30865 1/imm32/imm32-is-first-inout +30866 0/imm32/no-imm8 +30867 0/imm32/no-disp32 +30868 0/imm32/no-xm32 +30869 0/imm32/no-x32 +30870 0x11/imm32/alloc-id:fake +30871 _Primitive-add-lit-to-mem/imm32/next +30872 _Primitive-add-lit-to-mem: # (payload primitive) +30873 0x11/imm32/alloc-id:fake:payload +30874 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 30875 0x11/imm32/alloc-id:fake -30876 _Primitive-subtract-reg-from-mem/imm32/next -30877 _Primitive-subtract-reg-from-mem: # (payload primitive) -30878 0x11/imm32/alloc-id:fake:payload -30879 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -30880 0x11/imm32/alloc-id:fake -30881 _string-subtract-from/imm32/name -30882 0x11/imm32/alloc-id:fake -30883 Two-args-int-stack-int-reg/imm32/inouts -30884 0/imm32/no-outputs -30885 0/imm32/no-outputs -30886 0x11/imm32/alloc-id:fake -30887 _string_29_subtract_from/imm32/subx-name -30888 1/imm32/rm32-is-first-inout -30889 2/imm32/r32-is-second-inout -30890 0/imm32/no-imm32 -30891 0/imm32/no-imm8 -30892 0/imm32/no-disp32 -30893 0/imm32/no-xm32 -30894 0/imm32/no-x32 -30895 0x11/imm32/alloc-id:fake -30896 _Primitive-subtract-mem-from-reg/imm32/next -30897 _Primitive-subtract-mem-from-reg: # (payload primitive) -30898 0x11/imm32/alloc-id:fake:payload -30899 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +30876 _string-add-to/imm32/name +30877 0x11/imm32/alloc-id:fake +30878 Int-var-and-literal/imm32/inouts +30879 0/imm32/no-outputs +30880 0/imm32/no-outputs +30881 0x11/imm32/alloc-id:fake +30882 _string_81_subop_add/imm32/subx-name +30883 1/imm32/rm32-is-first-inout +30884 0/imm32/no-r32 +30885 2/imm32/imm32-is-second-inout +30886 0/imm32/no-imm8 +30887 0/imm32/no-disp32 +30888 0/imm32/no-xm32 +30889 0/imm32/no-x32 +30890 0x11/imm32/alloc-id:fake +30891 _Primitive-subtract-from-eax/imm32/next +30892 # - subtract +30893 _Primitive-subtract-from-eax: # (payload primitive) +30894 0x11/imm32/alloc-id:fake:payload +30895 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 +30896 0x11/imm32/alloc-id:fake +30897 _string-subtract/imm32/name +30898 0x11/imm32/alloc-id:fake +30899 Single-lit-var/imm32/inouts 30900 0x11/imm32/alloc-id:fake -30901 _string-subtract/imm32/name +30901 Single-int-var-in-eax/imm32/outputs 30902 0x11/imm32/alloc-id:fake -30903 Single-int-var-in-mem/imm32/inouts -30904 0x11/imm32/alloc-id:fake -30905 Single-int-var-in-some-register/imm32/outputs -30906 0x11/imm32/alloc-id:fake -30907 _string_2b_subtract/imm32/subx-name -30908 1/imm32/rm32-is-first-inout -30909 3/imm32/r32-is-first-output -30910 0/imm32/no-imm32 -30911 0/imm32/no-imm8 -30912 0/imm32/no-disp32 -30913 0/imm32/no-xm32 -30914 0/imm32/no-x32 -30915 0x11/imm32/alloc-id:fake -30916 _Primitive-subtract-lit-from-reg/imm32/next -30917 _Primitive-subtract-lit-from-reg: # (payload primitive) -30918 0x11/imm32/alloc-id:fake:payload -30919 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 +30903 _string_2d_subtract_from_eax/imm32/subx-name +30904 0/imm32/no-rm32 +30905 0/imm32/no-r32 +30906 1/imm32/imm32-is-first-inout +30907 0/imm32/no-imm8 +30908 0/imm32/no-disp32 +30909 0/imm32/no-xm32 +30910 0/imm32/no-x32 +30911 0x11/imm32/alloc-id:fake +30912 _Primitive-subtract-reg-from-reg/imm32/next +30913 _Primitive-subtract-reg-from-reg: # (payload primitive) +30914 0x11/imm32/alloc-id:fake:payload +30915 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 +30916 0x11/imm32/alloc-id:fake +30917 _string-subtract/imm32/name +30918 0x11/imm32/alloc-id:fake +30919 Single-int-var-in-some-register/imm32/inouts 30920 0x11/imm32/alloc-id:fake -30921 _string-subtract/imm32/name +30921 Single-int-var-in-some-register/imm32/outputs 30922 0x11/imm32/alloc-id:fake -30923 Single-lit-var/imm32/inouts -30924 0x11/imm32/alloc-id:fake -30925 Single-int-var-in-some-register/imm32/outputs -30926 0x11/imm32/alloc-id:fake -30927 _string_81_subop_subtract/imm32/subx-name -30928 3/imm32/rm32-is-first-output -30929 0/imm32/no-r32 -30930 1/imm32/imm32-is-first-inout -30931 0/imm32/no-imm8 -30932 0/imm32/no-disp32 -30933 0/imm32/no-xm32 -30934 0/imm32/no-x32 -30935 0x11/imm32/alloc-id:fake -30936 _Primitive-subtract-lit-from-mem/imm32/next -30937 _Primitive-subtract-lit-from-mem: # (payload primitive) -30938 0x11/imm32/alloc-id:fake:payload -30939 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -30940 0x11/imm32/alloc-id:fake -30941 _string-subtract-from/imm32/name +30923 _string_29_subtract_from/imm32/subx-name +30924 3/imm32/rm32-is-first-output +30925 1/imm32/r32-is-first-inout +30926 0/imm32/no-imm32 +30927 0/imm32/no-imm8 +30928 0/imm32/no-disp32 +30929 0/imm32/no-xm32 +30930 0/imm32/no-x32 +30931 0x11/imm32/alloc-id:fake +30932 _Primitive-subtract-reg-from-mem/imm32/next +30933 _Primitive-subtract-reg-from-mem: # (payload primitive) +30934 0x11/imm32/alloc-id:fake:payload +30935 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 +30936 0x11/imm32/alloc-id:fake +30937 _string-subtract-from/imm32/name +30938 0x11/imm32/alloc-id:fake +30939 Two-args-int-stack-int-reg/imm32/inouts +30940 0/imm32/no-outputs +30941 0/imm32/no-outputs 30942 0x11/imm32/alloc-id:fake -30943 Int-var-and-literal/imm32/inouts -30944 0/imm32/no-outputs -30945 0/imm32/no-outputs -30946 0x11/imm32/alloc-id:fake -30947 _string_81_subop_subtract/imm32/subx-name -30948 1/imm32/rm32-is-first-inout -30949 0/imm32/no-r32 -30950 2/imm32/imm32-is-second-inout -30951 0/imm32/no-imm8 -30952 0/imm32/no-disp32 -30953 0/imm32/no-xm32 -30954 0/imm32/no-x32 -30955 0x11/imm32/alloc-id:fake -30956 _Primitive-and-with-eax/imm32/next -30957 # - and -30958 _Primitive-and-with-eax: # (payload primitive) -30959 0x11/imm32/alloc-id:fake:payload -30960 # var/eax <- and lit => 25/and-with-eax lit/imm32 -30961 0x11/imm32/alloc-id:fake -30962 _string-and/imm32/name -30963 0x11/imm32/alloc-id:fake -30964 Single-lit-var/imm32/inouts -30965 0x11/imm32/alloc-id:fake -30966 Single-int-var-in-eax/imm32/outputs -30967 0x11/imm32/alloc-id:fake -30968 _string_25_and_with_eax/imm32/subx-name -30969 0/imm32/no-rm32 -30970 0/imm32/no-r32 -30971 1/imm32/imm32-is-first-inout -30972 0/imm32/no-imm8 -30973 0/imm32/no-disp32 -30974 0/imm32/no-xm32 -30975 0/imm32/no-x32 +30943 _string_29_subtract_from/imm32/subx-name +30944 1/imm32/rm32-is-first-inout +30945 2/imm32/r32-is-second-inout +30946 0/imm32/no-imm32 +30947 0/imm32/no-imm8 +30948 0/imm32/no-disp32 +30949 0/imm32/no-xm32 +30950 0/imm32/no-x32 +30951 0x11/imm32/alloc-id:fake +30952 _Primitive-subtract-mem-from-reg/imm32/next +30953 _Primitive-subtract-mem-from-reg: # (payload primitive) +30954 0x11/imm32/alloc-id:fake:payload +30955 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +30956 0x11/imm32/alloc-id:fake +30957 _string-subtract/imm32/name +30958 0x11/imm32/alloc-id:fake +30959 Single-int-var-in-mem/imm32/inouts +30960 0x11/imm32/alloc-id:fake +30961 Single-int-var-in-some-register/imm32/outputs +30962 0x11/imm32/alloc-id:fake +30963 _string_2b_subtract/imm32/subx-name +30964 1/imm32/rm32-is-first-inout +30965 3/imm32/r32-is-first-output +30966 0/imm32/no-imm32 +30967 0/imm32/no-imm8 +30968 0/imm32/no-disp32 +30969 0/imm32/no-xm32 +30970 0/imm32/no-x32 +30971 0x11/imm32/alloc-id:fake +30972 _Primitive-subtract-lit-from-reg/imm32/next +30973 _Primitive-subtract-lit-from-reg: # (payload primitive) +30974 0x11/imm32/alloc-id:fake:payload +30975 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 30976 0x11/imm32/alloc-id:fake -30977 _Primitive-and-reg-with-reg/imm32/next -30978 _Primitive-and-reg-with-reg: # (payload primitive) -30979 0x11/imm32/alloc-id:fake:payload -30980 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -30981 0x11/imm32/alloc-id:fake -30982 _string-and/imm32/name -30983 0x11/imm32/alloc-id:fake -30984 Single-int-var-in-some-register/imm32/inouts -30985 0x11/imm32/alloc-id:fake -30986 Single-int-var-in-some-register/imm32/outputs -30987 0x11/imm32/alloc-id:fake -30988 _string_21_and_with/imm32/subx-name -30989 3/imm32/rm32-is-first-output -30990 1/imm32/r32-is-first-inout -30991 0/imm32/no-imm32 -30992 0/imm32/no-imm8 -30993 0/imm32/no-disp32 -30994 0/imm32/no-xm32 -30995 0/imm32/no-x32 +30977 _string-subtract/imm32/name +30978 0x11/imm32/alloc-id:fake +30979 Single-lit-var/imm32/inouts +30980 0x11/imm32/alloc-id:fake +30981 Single-int-var-in-some-register/imm32/outputs +30982 0x11/imm32/alloc-id:fake +30983 _string_81_subop_subtract/imm32/subx-name +30984 3/imm32/rm32-is-first-output +30985 0/imm32/no-r32 +30986 1/imm32/imm32-is-first-inout +30987 0/imm32/no-imm8 +30988 0/imm32/no-disp32 +30989 0/imm32/no-xm32 +30990 0/imm32/no-x32 +30991 0x11/imm32/alloc-id:fake +30992 _Primitive-subtract-lit-from-mem/imm32/next +30993 _Primitive-subtract-lit-from-mem: # (payload primitive) +30994 0x11/imm32/alloc-id:fake:payload +30995 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 30996 0x11/imm32/alloc-id:fake -30997 _Primitive-and-reg-with-mem/imm32/next -30998 _Primitive-and-reg-with-mem: # (payload primitive) -30999 0x11/imm32/alloc-id:fake:payload -31000 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -31001 0x11/imm32/alloc-id:fake -31002 _string-and-with/imm32/name -31003 0x11/imm32/alloc-id:fake -31004 Two-args-int-stack-int-reg/imm32/inouts -31005 0/imm32/no-outputs -31006 0/imm32/no-outputs -31007 0x11/imm32/alloc-id:fake -31008 _string_21_and_with/imm32/subx-name -31009 1/imm32/rm32-is-first-inout -31010 2/imm32/r32-is-second-inout -31011 0/imm32/no-imm32 -31012 0/imm32/no-imm8 -31013 0/imm32/no-disp32 -31014 0/imm32/no-xm32 -31015 0/imm32/no-x32 -31016 0x11/imm32/alloc-id:fake -31017 _Primitive-and-mem-with-reg/imm32/next -31018 _Primitive-and-mem-with-reg: # (payload primitive) -31019 0x11/imm32/alloc-id:fake:payload -31020 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +30997 _string-subtract-from/imm32/name +30998 0x11/imm32/alloc-id:fake +30999 Int-var-and-literal/imm32/inouts +31000 0/imm32/no-outputs +31001 0/imm32/no-outputs +31002 0x11/imm32/alloc-id:fake +31003 _string_81_subop_subtract/imm32/subx-name +31004 1/imm32/rm32-is-first-inout +31005 0/imm32/no-r32 +31006 2/imm32/imm32-is-second-inout +31007 0/imm32/no-imm8 +31008 0/imm32/no-disp32 +31009 0/imm32/no-xm32 +31010 0/imm32/no-x32 +31011 0x11/imm32/alloc-id:fake +31012 _Primitive-and-with-eax/imm32/next +31013 # - and +31014 _Primitive-and-with-eax: # (payload primitive) +31015 0x11/imm32/alloc-id:fake:payload +31016 # var/eax <- and lit => 25/and-with-eax lit/imm32 +31017 0x11/imm32/alloc-id:fake +31018 _string-and/imm32/name +31019 0x11/imm32/alloc-id:fake +31020 Single-lit-var/imm32/inouts 31021 0x11/imm32/alloc-id:fake -31022 _string-and/imm32/name +31022 Single-int-var-in-eax/imm32/outputs 31023 0x11/imm32/alloc-id:fake -31024 Single-int-var-in-mem/imm32/inouts -31025 0x11/imm32/alloc-id:fake -31026 Single-int-var-in-some-register/imm32/outputs -31027 0x11/imm32/alloc-id:fake -31028 _string_23_and/imm32/subx-name -31029 1/imm32/rm32-is-first-inout -31030 3/imm32/r32-is-first-output -31031 0/imm32/no-imm32 -31032 0/imm32/no-imm8 -31033 0/imm32/no-disp32 -31034 0/imm32/no-xm32 -31035 0/imm32/no-x32 -31036 0x11/imm32/alloc-id:fake -31037 _Primitive-and-lit-with-reg/imm32/next -31038 _Primitive-and-lit-with-reg: # (payload primitive) -31039 0x11/imm32/alloc-id:fake:payload -31040 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 +31024 _string_25_and_with_eax/imm32/subx-name +31025 0/imm32/no-rm32 +31026 0/imm32/no-r32 +31027 1/imm32/imm32-is-first-inout +31028 0/imm32/no-imm8 +31029 0/imm32/no-disp32 +31030 0/imm32/no-xm32 +31031 0/imm32/no-x32 +31032 0x11/imm32/alloc-id:fake +31033 _Primitive-and-reg-with-reg/imm32/next +31034 _Primitive-and-reg-with-reg: # (payload primitive) +31035 0x11/imm32/alloc-id:fake:payload +31036 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 +31037 0x11/imm32/alloc-id:fake +31038 _string-and/imm32/name +31039 0x11/imm32/alloc-id:fake +31040 Single-int-var-in-some-register/imm32/inouts 31041 0x11/imm32/alloc-id:fake -31042 _string-and/imm32/name +31042 Single-int-var-in-some-register/imm32/outputs 31043 0x11/imm32/alloc-id:fake -31044 Single-lit-var/imm32/inouts -31045 0x11/imm32/alloc-id:fake -31046 Single-int-var-in-some-register/imm32/outputs -31047 0x11/imm32/alloc-id:fake -31048 _string_81_subop_and/imm32/subx-name -31049 3/imm32/rm32-is-first-output -31050 0/imm32/no-r32 -31051 1/imm32/imm32-is-first-inout -31052 0/imm32/no-imm8 -31053 0/imm32/no-disp32 -31054 0/imm32/no-xm32 -31055 0/imm32/no-x32 -31056 0x11/imm32/alloc-id:fake -31057 _Primitive-and-lit-with-mem/imm32/next -31058 _Primitive-and-lit-with-mem: # (payload primitive) -31059 0x11/imm32/alloc-id:fake:payload -31060 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -31061 0x11/imm32/alloc-id:fake -31062 _string-and-with/imm32/name +31044 _string_21_and_with/imm32/subx-name +31045 3/imm32/rm32-is-first-output +31046 1/imm32/r32-is-first-inout +31047 0/imm32/no-imm32 +31048 0/imm32/no-imm8 +31049 0/imm32/no-disp32 +31050 0/imm32/no-xm32 +31051 0/imm32/no-x32 +31052 0x11/imm32/alloc-id:fake +31053 _Primitive-and-reg-with-mem/imm32/next +31054 _Primitive-and-reg-with-mem: # (payload primitive) +31055 0x11/imm32/alloc-id:fake:payload +31056 # and-with var1 var2/reg => 21/and-with var1 var2/r32 +31057 0x11/imm32/alloc-id:fake +31058 _string-and-with/imm32/name +31059 0x11/imm32/alloc-id:fake +31060 Two-args-int-stack-int-reg/imm32/inouts +31061 0/imm32/no-outputs +31062 0/imm32/no-outputs 31063 0x11/imm32/alloc-id:fake -31064 Int-var-and-literal/imm32/inouts -31065 0/imm32/no-outputs -31066 0/imm32/no-outputs -31067 0x11/imm32/alloc-id:fake -31068 _string_81_subop_and/imm32/subx-name -31069 1/imm32/rm32-is-first-inout -31070 0/imm32/no-r32 -31071 2/imm32/imm32-is-second-inout -31072 0/imm32/no-imm8 -31073 0/imm32/no-disp32 -31074 0/imm32/no-xm32 -31075 0/imm32/no-x32 -31076 0x11/imm32/alloc-id:fake -31077 _Primitive-or-with-eax/imm32/next -31078 # - or -31079 _Primitive-or-with-eax: # (payload primitive) -31080 0x11/imm32/alloc-id:fake:payload -31081 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -31082 0x11/imm32/alloc-id:fake -31083 _string-or/imm32/name -31084 0x11/imm32/alloc-id:fake -31085 Single-lit-var/imm32/inouts -31086 0x11/imm32/alloc-id:fake -31087 Single-int-var-in-eax/imm32/outputs -31088 0x11/imm32/alloc-id:fake -31089 _string_0d_or_with_eax/imm32/subx-name -31090 0/imm32/no-rm32 -31091 0/imm32/no-r32 -31092 1/imm32/imm32-is-first-inout -31093 0/imm32/no-imm8 -31094 0/imm32/no-disp32 -31095 0/imm32/no-xm32 -31096 0/imm32/no-x32 +31064 _string_21_and_with/imm32/subx-name +31065 1/imm32/rm32-is-first-inout +31066 2/imm32/r32-is-second-inout +31067 0/imm32/no-imm32 +31068 0/imm32/no-imm8 +31069 0/imm32/no-disp32 +31070 0/imm32/no-xm32 +31071 0/imm32/no-x32 +31072 0x11/imm32/alloc-id:fake +31073 _Primitive-and-mem-with-reg/imm32/next +31074 _Primitive-and-mem-with-reg: # (payload primitive) +31075 0x11/imm32/alloc-id:fake:payload +31076 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +31077 0x11/imm32/alloc-id:fake +31078 _string-and/imm32/name +31079 0x11/imm32/alloc-id:fake +31080 Single-int-var-in-mem/imm32/inouts +31081 0x11/imm32/alloc-id:fake +31082 Single-int-var-in-some-register/imm32/outputs +31083 0x11/imm32/alloc-id:fake +31084 _string_23_and/imm32/subx-name +31085 1/imm32/rm32-is-first-inout +31086 3/imm32/r32-is-first-output +31087 0/imm32/no-imm32 +31088 0/imm32/no-imm8 +31089 0/imm32/no-disp32 +31090 0/imm32/no-xm32 +31091 0/imm32/no-x32 +31092 0x11/imm32/alloc-id:fake +31093 _Primitive-and-lit-with-reg/imm32/next +31094 _Primitive-and-lit-with-reg: # (payload primitive) +31095 0x11/imm32/alloc-id:fake:payload +31096 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 31097 0x11/imm32/alloc-id:fake -31098 _Primitive-or-reg-with-reg/imm32/next -31099 _Primitive-or-reg-with-reg: # (payload primitive) -31100 0x11/imm32/alloc-id:fake:payload -31101 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -31102 0x11/imm32/alloc-id:fake -31103 _string-or/imm32/name -31104 0x11/imm32/alloc-id:fake -31105 Single-int-var-in-some-register/imm32/inouts -31106 0x11/imm32/alloc-id:fake -31107 Single-int-var-in-some-register/imm32/outputs -31108 0x11/imm32/alloc-id:fake -31109 _string_09_or_with/imm32/subx-name -31110 3/imm32/rm32-is-first-output -31111 1/imm32/r32-is-first-inout -31112 0/imm32/no-imm32 -31113 0/imm32/no-imm8 -31114 0/imm32/no-disp32 -31115 0/imm32/no-xm32 -31116 0/imm32/no-x32 +31098 _string-and/imm32/name +31099 0x11/imm32/alloc-id:fake +31100 Single-lit-var/imm32/inouts +31101 0x11/imm32/alloc-id:fake +31102 Single-int-var-in-some-register/imm32/outputs +31103 0x11/imm32/alloc-id:fake +31104 _string_81_subop_and/imm32/subx-name +31105 3/imm32/rm32-is-first-output +31106 0/imm32/no-r32 +31107 1/imm32/imm32-is-first-inout +31108 0/imm32/no-imm8 +31109 0/imm32/no-disp32 +31110 0/imm32/no-xm32 +31111 0/imm32/no-x32 +31112 0x11/imm32/alloc-id:fake +31113 _Primitive-and-lit-with-mem/imm32/next +31114 _Primitive-and-lit-with-mem: # (payload primitive) +31115 0x11/imm32/alloc-id:fake:payload +31116 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 31117 0x11/imm32/alloc-id:fake -31118 _Primitive-or-reg-with-mem/imm32/next -31119 _Primitive-or-reg-with-mem: # (payload primitive) -31120 0x11/imm32/alloc-id:fake:payload -31121 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -31122 0x11/imm32/alloc-id:fake -31123 _string-or-with/imm32/name -31124 0x11/imm32/alloc-id:fake -31125 Two-args-int-stack-int-reg/imm32/inouts -31126 0/imm32/no-outputs -31127 0/imm32/no-outputs -31128 0x11/imm32/alloc-id:fake -31129 _string_09_or_with/imm32/subx-name -31130 1/imm32/rm32-is-first-inout -31131 2/imm32/r32-is-second-inout -31132 0/imm32/no-imm32 -31133 0/imm32/no-imm8 -31134 0/imm32/no-disp32 -31135 0/imm32/no-xm32 -31136 0/imm32/no-x32 -31137 0x11/imm32/alloc-id:fake -31138 _Primitive-or-mem-with-reg/imm32/next -31139 _Primitive-or-mem-with-reg: # (payload primitive) -31140 0x11/imm32/alloc-id:fake:payload -31141 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +31118 _string-and-with/imm32/name +31119 0x11/imm32/alloc-id:fake +31120 Int-var-and-literal/imm32/inouts +31121 0/imm32/no-outputs +31122 0/imm32/no-outputs +31123 0x11/imm32/alloc-id:fake +31124 _string_81_subop_and/imm32/subx-name +31125 1/imm32/rm32-is-first-inout +31126 0/imm32/no-r32 +31127 2/imm32/imm32-is-second-inout +31128 0/imm32/no-imm8 +31129 0/imm32/no-disp32 +31130 0/imm32/no-xm32 +31131 0/imm32/no-x32 +31132 0x11/imm32/alloc-id:fake +31133 _Primitive-or-with-eax/imm32/next +31134 # - or +31135 _Primitive-or-with-eax: # (payload primitive) +31136 0x11/imm32/alloc-id:fake:payload +31137 # var/eax <- or lit => 0d/or-with-eax lit/imm32 +31138 0x11/imm32/alloc-id:fake +31139 _string-or/imm32/name +31140 0x11/imm32/alloc-id:fake +31141 Single-lit-var/imm32/inouts 31142 0x11/imm32/alloc-id:fake -31143 _string-or/imm32/name +31143 Single-int-var-in-eax/imm32/outputs 31144 0x11/imm32/alloc-id:fake -31145 Single-int-var-in-mem/imm32/inouts -31146 0x11/imm32/alloc-id:fake -31147 Single-int-var-in-some-register/imm32/outputs -31148 0x11/imm32/alloc-id:fake -31149 _string_0b_or/imm32/subx-name -31150 1/imm32/rm32-is-first-inout -31151 3/imm32/r32-is-first-output -31152 0/imm32/no-imm32 -31153 0/imm32/no-imm8 -31154 0/imm32/no-disp32 -31155 0/imm32/no-xm32 -31156 0/imm32/no-x32 -31157 0x11/imm32/alloc-id:fake -31158 _Primitive-or-lit-with-reg/imm32/next -31159 _Primitive-or-lit-with-reg: # (payload primitive) -31160 0x11/imm32/alloc-id:fake:payload -31161 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 +31145 _string_0d_or_with_eax/imm32/subx-name +31146 0/imm32/no-rm32 +31147 0/imm32/no-r32 +31148 1/imm32/imm32-is-first-inout +31149 0/imm32/no-imm8 +31150 0/imm32/no-disp32 +31151 0/imm32/no-xm32 +31152 0/imm32/no-x32 +31153 0x11/imm32/alloc-id:fake +31154 _Primitive-or-reg-with-reg/imm32/next +31155 _Primitive-or-reg-with-reg: # (payload primitive) +31156 0x11/imm32/alloc-id:fake:payload +31157 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 +31158 0x11/imm32/alloc-id:fake +31159 _string-or/imm32/name +31160 0x11/imm32/alloc-id:fake +31161 Single-int-var-in-some-register/imm32/inouts 31162 0x11/imm32/alloc-id:fake -31163 _string-or/imm32/name +31163 Single-int-var-in-some-register/imm32/outputs 31164 0x11/imm32/alloc-id:fake -31165 Single-lit-var/imm32/inouts -31166 0x11/imm32/alloc-id:fake -31167 Single-int-var-in-some-register/imm32/outputs -31168 0x11/imm32/alloc-id:fake -31169 _string_81_subop_or/imm32/subx-name -31170 3/imm32/rm32-is-first-output -31171 0/imm32/no-r32 -31172 1/imm32/imm32-is-first-inout -31173 0/imm32/no-imm8 -31174 0/imm32/no-disp32 -31175 0/imm32/no-xm32 -31176 0/imm32/no-x32 -31177 0x11/imm32/alloc-id:fake -31178 _Primitive-or-lit-with-mem/imm32/next -31179 _Primitive-or-lit-with-mem: # (payload primitive) -31180 0x11/imm32/alloc-id:fake:payload -31181 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -31182 0x11/imm32/alloc-id:fake -31183 _string-or-with/imm32/name +31165 _string_09_or_with/imm32/subx-name +31166 3/imm32/rm32-is-first-output +31167 1/imm32/r32-is-first-inout +31168 0/imm32/no-imm32 +31169 0/imm32/no-imm8 +31170 0/imm32/no-disp32 +31171 0/imm32/no-xm32 +31172 0/imm32/no-x32 +31173 0x11/imm32/alloc-id:fake +31174 _Primitive-or-reg-with-mem/imm32/next +31175 _Primitive-or-reg-with-mem: # (payload primitive) +31176 0x11/imm32/alloc-id:fake:payload +31177 # or-with var1 var2/reg => 09/or-with var1 var2/r32 +31178 0x11/imm32/alloc-id:fake +31179 _string-or-with/imm32/name +31180 0x11/imm32/alloc-id:fake +31181 Two-args-int-stack-int-reg/imm32/inouts +31182 0/imm32/no-outputs +31183 0/imm32/no-outputs 31184 0x11/imm32/alloc-id:fake -31185 Int-var-and-literal/imm32/inouts -31186 0/imm32/no-outputs -31187 0/imm32/no-outputs -31188 0x11/imm32/alloc-id:fake -31189 _string_81_subop_or/imm32/subx-name -31190 1/imm32/rm32-is-first-inout -31191 0/imm32/no-r32 -31192 2/imm32/imm32-is-second-inout -31193 0/imm32/no-imm8 -31194 0/imm32/no-disp32 -31195 0/imm32/no-xm32 -31196 0/imm32/no-x32 -31197 0x11/imm32/alloc-id:fake -31198 _Primitive-xor-with-eax/imm32/next -31199 # - xor -31200 _Primitive-xor-with-eax: # (payload primitive) -31201 0x11/imm32/alloc-id:fake:payload -31202 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -31203 0x11/imm32/alloc-id:fake -31204 _string-xor/imm32/name -31205 0x11/imm32/alloc-id:fake -31206 Single-lit-var/imm32/inouts -31207 0x11/imm32/alloc-id:fake -31208 Single-int-var-in-eax/imm32/outputs -31209 0x11/imm32/alloc-id:fake -31210 _string_35_xor_with_eax/imm32/subx-name -31211 0/imm32/no-rm32 -31212 0/imm32/no-r32 -31213 1/imm32/imm32-is-first-inout -31214 0/imm32/no-imm8 -31215 0/imm32/no-disp32 -31216 0/imm32/no-xm32 -31217 0/imm32/no-x32 +31185 _string_09_or_with/imm32/subx-name +31186 1/imm32/rm32-is-first-inout +31187 2/imm32/r32-is-second-inout +31188 0/imm32/no-imm32 +31189 0/imm32/no-imm8 +31190 0/imm32/no-disp32 +31191 0/imm32/no-xm32 +31192 0/imm32/no-x32 +31193 0x11/imm32/alloc-id:fake +31194 _Primitive-or-mem-with-reg/imm32/next +31195 _Primitive-or-mem-with-reg: # (payload primitive) +31196 0x11/imm32/alloc-id:fake:payload +31197 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +31198 0x11/imm32/alloc-id:fake +31199 _string-or/imm32/name +31200 0x11/imm32/alloc-id:fake +31201 Single-int-var-in-mem/imm32/inouts +31202 0x11/imm32/alloc-id:fake +31203 Single-int-var-in-some-register/imm32/outputs +31204 0x11/imm32/alloc-id:fake +31205 _string_0b_or/imm32/subx-name +31206 1/imm32/rm32-is-first-inout +31207 3/imm32/r32-is-first-output +31208 0/imm32/no-imm32 +31209 0/imm32/no-imm8 +31210 0/imm32/no-disp32 +31211 0/imm32/no-xm32 +31212 0/imm32/no-x32 +31213 0x11/imm32/alloc-id:fake +31214 _Primitive-or-lit-with-reg/imm32/next +31215 _Primitive-or-lit-with-reg: # (payload primitive) +31216 0x11/imm32/alloc-id:fake:payload +31217 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 31218 0x11/imm32/alloc-id:fake -31219 _Primitive-xor-reg-with-reg/imm32/next -31220 _Primitive-xor-reg-with-reg: # (payload primitive) -31221 0x11/imm32/alloc-id:fake:payload -31222 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -31223 0x11/imm32/alloc-id:fake -31224 _string-xor/imm32/name -31225 0x11/imm32/alloc-id:fake -31226 Single-int-var-in-some-register/imm32/inouts -31227 0x11/imm32/alloc-id:fake -31228 Single-int-var-in-some-register/imm32/outputs -31229 0x11/imm32/alloc-id:fake -31230 _string_31_xor_with/imm32/subx-name -31231 3/imm32/rm32-is-first-output -31232 1/imm32/r32-is-first-inout -31233 0/imm32/no-imm32 -31234 0/imm32/no-imm8 -31235 0/imm32/no-disp32 -31236 0/imm32/no-xm32 -31237 0/imm32/no-x32 +31219 _string-or/imm32/name +31220 0x11/imm32/alloc-id:fake +31221 Single-lit-var/imm32/inouts +31222 0x11/imm32/alloc-id:fake +31223 Single-int-var-in-some-register/imm32/outputs +31224 0x11/imm32/alloc-id:fake +31225 _string_81_subop_or/imm32/subx-name +31226 3/imm32/rm32-is-first-output +31227 0/imm32/no-r32 +31228 1/imm32/imm32-is-first-inout +31229 0/imm32/no-imm8 +31230 0/imm32/no-disp32 +31231 0/imm32/no-xm32 +31232 0/imm32/no-x32 +31233 0x11/imm32/alloc-id:fake +31234 _Primitive-or-lit-with-mem/imm32/next +31235 _Primitive-or-lit-with-mem: # (payload primitive) +31236 0x11/imm32/alloc-id:fake:payload +31237 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 31238 0x11/imm32/alloc-id:fake -31239 _Primitive-xor-reg-with-mem/imm32/next -31240 _Primitive-xor-reg-with-mem: # (payload primitive) -31241 0x11/imm32/alloc-id:fake:payload -31242 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -31243 0x11/imm32/alloc-id:fake -31244 _string-xor-with/imm32/name -31245 0x11/imm32/alloc-id:fake -31246 Two-args-int-stack-int-reg/imm32/inouts -31247 0/imm32/no-outputs -31248 0/imm32/no-outputs -31249 0x11/imm32/alloc-id:fake -31250 _string_31_xor_with/imm32/subx-name -31251 1/imm32/rm32-is-first-inout -31252 2/imm32/r32-is-second-inout -31253 0/imm32/no-imm32 -31254 0/imm32/no-imm8 -31255 0/imm32/no-disp32 -31256 0/imm32/no-xm32 -31257 0/imm32/no-x32 -31258 0x11/imm32/alloc-id:fake -31259 _Primitive-xor-mem-with-reg/imm32/next -31260 _Primitive-xor-mem-with-reg: # (payload primitive) -31261 0x11/imm32/alloc-id:fake:payload -31262 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +31239 _string-or-with/imm32/name +31240 0x11/imm32/alloc-id:fake +31241 Int-var-and-literal/imm32/inouts +31242 0/imm32/no-outputs +31243 0/imm32/no-outputs +31244 0x11/imm32/alloc-id:fake +31245 _string_81_subop_or/imm32/subx-name +31246 1/imm32/rm32-is-first-inout +31247 0/imm32/no-r32 +31248 2/imm32/imm32-is-second-inout +31249 0/imm32/no-imm8 +31250 0/imm32/no-disp32 +31251 0/imm32/no-xm32 +31252 0/imm32/no-x32 +31253 0x11/imm32/alloc-id:fake +31254 _Primitive-not-reg/imm32/next +31255 # - not +31256 _Primitive-not-reg: # (payload primitive) +31257 0x11/imm32/alloc-id:fake:payload +31258 # var1/reg <- not => f7 2/subop/not var1/rm32 +31259 0x11/imm32/alloc-id:fake +31260 _string-not/imm32/name +31261 0/imm32/no-inouts +31262 0/imm32/no-inouts 31263 0x11/imm32/alloc-id:fake -31264 _string-xor/imm32/name +31264 Single-int-var-in-some-register/imm32/outputs 31265 0x11/imm32/alloc-id:fake -31266 Single-int-var-in-mem/imm32/inouts -31267 0x11/imm32/alloc-id:fake -31268 Single-int-var-in-some-register/imm32/outputs -31269 0x11/imm32/alloc-id:fake -31270 _string_33_xor/imm32/subx-name -31271 1/imm32/rm32-is-first-inout -31272 3/imm32/r32-is-first-output -31273 0/imm32/no-imm32 -31274 0/imm32/no-imm8 -31275 0/imm32/no-disp32 -31276 0/imm32/no-xm32 -31277 0/imm32/no-x32 -31278 0x11/imm32/alloc-id:fake -31279 _Primitive-xor-lit-with-reg/imm32/next -31280 _Primitive-xor-lit-with-reg: # (payload primitive) -31281 0x11/imm32/alloc-id:fake:payload -31282 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -31283 0x11/imm32/alloc-id:fake -31284 _string-xor/imm32/name +31266 _string_f7_subop_not/imm32/subx-name +31267 3/imm32/rm32-is-first-output +31268 0/imm32/no-r32 +31269 0/imm32/no-imm32 +31270 0/imm32/no-imm8 +31271 0/imm32/no-disp32 +31272 0/imm32/no-xm32 +31273 0/imm32/no-x32 +31274 0x11/imm32/alloc-id:fake +31275 _Primitive-not-mem/imm32/next +31276 _Primitive-not-mem: # (payload primitive) +31277 0x11/imm32/alloc-id:fake:payload +31278 # not var1 => f7 2/subop/not var1/rm32 +31279 0x11/imm32/alloc-id:fake +31280 _string-not/imm32/name +31281 0x11/imm32/alloc-id:fake +31282 Single-int-var-in-mem/imm32/inouts +31283 0/imm32/no-outputs +31284 0/imm32/no-outputs 31285 0x11/imm32/alloc-id:fake -31286 Single-lit-var/imm32/inouts -31287 0x11/imm32/alloc-id:fake -31288 Single-int-var-in-some-register/imm32/outputs -31289 0x11/imm32/alloc-id:fake -31290 _string_81_subop_xor/imm32/subx-name -31291 3/imm32/rm32-is-first-output -31292 0/imm32/no-r32 -31293 1/imm32/imm32-is-first-inout -31294 0/imm32/no-imm8 -31295 0/imm32/no-disp32 -31296 0/imm32/no-xm32 -31297 0/imm32/no-x32 -31298 0x11/imm32/alloc-id:fake -31299 _Primitive-xor-lit-with-mem/imm32/next -31300 _Primitive-xor-lit-with-mem: # (payload primitive) -31301 0x11/imm32/alloc-id:fake:payload -31302 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -31303 0x11/imm32/alloc-id:fake -31304 _string-xor-with/imm32/name -31305 0x11/imm32/alloc-id:fake -31306 Int-var-and-literal/imm32/inouts -31307 0/imm32/no-outputs -31308 0/imm32/no-outputs -31309 0x11/imm32/alloc-id:fake -31310 _string_81_subop_xor/imm32/subx-name -31311 1/imm32/rm32-is-first-inout -31312 0/imm32/no-r32 -31313 2/imm32/imm32-is-second-inout -31314 0/imm32/no-imm8 -31315 0/imm32/no-disp32 -31316 0/imm32/no-xm32 -31317 0/imm32/no-x32 -31318 0x11/imm32/alloc-id:fake -31319 _Primitive-shift-reg-left-by-lit/imm32/next -31320 _Primitive-shift-reg-left-by-lit: # (payload primitive) -31321 0x11/imm32/alloc-id:fake:payload -31322 # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32 -31323 0x11/imm32/alloc-id:fake -31324 _string-shift-left/imm32/name -31325 0x11/imm32/alloc-id:fake -31326 Single-lit-var/imm32/inouts -31327 0x11/imm32/alloc-id:fake -31328 Single-int-var-in-some-register/imm32/outputs -31329 0x11/imm32/alloc-id:fake -31330 _string_c1_subop_shift_left/imm32/subx-name -31331 3/imm32/rm32-is-first-output -31332 0/imm32/no-r32 -31333 0/imm32/no-imm32 -31334 1/imm32/imm8-is-first-inout -31335 0/imm32/no-disp32 -31336 0/imm32/no-xm32 -31337 0/imm32/no-x32 -31338 0x11/imm32/alloc-id:fake -31339 _Primitive-shift-reg-right-by-lit/imm32/next -31340 _Primitive-shift-reg-right-by-lit: # (payload primitive) -31341 0x11/imm32/alloc-id:fake:payload -31342 # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32 -31343 0x11/imm32/alloc-id:fake -31344 _string-shift-right/imm32/name -31345 0x11/imm32/alloc-id:fake -31346 Single-lit-var/imm32/inouts -31347 0x11/imm32/alloc-id:fake -31348 Single-int-var-in-some-register/imm32/outputs -31349 0x11/imm32/alloc-id:fake -31350 _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name -31351 3/imm32/rm32-is-first-output -31352 0/imm32/no-r32 -31353 0/imm32/no-imm32 -31354 1/imm32/imm8-is-first-inout -31355 0/imm32/no-disp32 -31356 0/imm32/no-xm32 -31357 0/imm32/no-x32 -31358 0x11/imm32/alloc-id:fake -31359 _Primitive-shift-reg-right-signed-by-lit/imm32/next -31360 _Primitive-shift-reg-right-signed-by-lit: # (payload primitive) -31361 0x11/imm32/alloc-id:fake:payload -31362 # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32 -31363 0x11/imm32/alloc-id:fake -31364 _string-shift-right-signed/imm32/name -31365 0x11/imm32/alloc-id:fake -31366 Single-lit-var/imm32/inouts -31367 0x11/imm32/alloc-id:fake -31368 Single-int-var-in-some-register/imm32/outputs -31369 0x11/imm32/alloc-id:fake -31370 _string_c1_subop_shift_right_preserving_sign/imm32/subx-name -31371 3/imm32/rm32-is-first-output -31372 0/imm32/no-r32 -31373 0/imm32/no-imm32 -31374 1/imm32/imm8-is-first-inout -31375 0/imm32/no-disp32 -31376 0/imm32/no-xm32 -31377 0/imm32/no-x32 -31378 0x11/imm32/alloc-id:fake -31379 _Primitive-shift-mem-left-by-lit/imm32/next -31380 _Primitive-shift-mem-left-by-lit: # (payload primitive) -31381 0x11/imm32/alloc-id:fake:payload -31382 # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32 -31383 0x11/imm32/alloc-id:fake -31384 _string-shift-left/imm32/name -31385 0x11/imm32/alloc-id:fake -31386 Int-var-and-literal/imm32/inouts -31387 0/imm32/no-outputs -31388 0/imm32/no-outputs -31389 0x11/imm32/alloc-id:fake -31390 _string_c1_subop_shift_left/imm32/subx-name -31391 1/imm32/rm32-is-first-inout -31392 0/imm32/no-r32 -31393 0/imm32/no-imm32 -31394 2/imm32/imm8-is-second-inout -31395 0/imm32/no-disp32 -31396 0/imm32/no-xm32 -31397 0/imm32/no-x32 -31398 0x11/imm32/alloc-id:fake -31399 _Primitive-shift-mem-right-by-lit/imm32/next -31400 _Primitive-shift-mem-right-by-lit: # (payload primitive) -31401 0x11/imm32/alloc-id:fake:payload -31402 # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32 -31403 0x11/imm32/alloc-id:fake -31404 _string-shift-right/imm32/name -31405 0x11/imm32/alloc-id:fake -31406 Int-var-and-literal/imm32/inouts -31407 0/imm32/no-outputs -31408 0/imm32/no-outputs -31409 0x11/imm32/alloc-id:fake -31410 _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name -31411 1/imm32/rm32-is-first-inout -31412 0/imm32/no-r32 -31413 0/imm32/no-imm32 -31414 2/imm32/imm8-is-second-inout -31415 0/imm32/no-disp32 -31416 0/imm32/no-xm32 -31417 0/imm32/no-x32 -31418 0x11/imm32/alloc-id:fake -31419 _Primitive-shift-mem-right-signed-by-lit/imm32/next -31420 _Primitive-shift-mem-right-signed-by-lit: # (payload primitive) -31421 0x11/imm32/alloc-id:fake:payload -31422 # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32 -31423 0x11/imm32/alloc-id:fake -31424 _string-shift-right-signed/imm32/name -31425 0x11/imm32/alloc-id:fake -31426 Int-var-and-literal/imm32/inouts -31427 0/imm32/no-outputs -31428 0/imm32/no-outputs -31429 0x11/imm32/alloc-id:fake -31430 _string_c1_subop_shift_right_preserving_sign/imm32/subx-name -31431 1/imm32/rm32-is-first-inout -31432 0/imm32/no-r32 -31433 0/imm32/no-imm32 -31434 2/imm32/imm8-is-second-inout -31435 0/imm32/no-disp32 -31436 0/imm32/no-xm32 -31437 0/imm32/no-x32 -31438 0x11/imm32/alloc-id:fake -31439 _Primitive-copy-to-eax/imm32/next -31440 # - copy -31441 _Primitive-copy-to-eax: # (payload primitive) -31442 0x11/imm32/alloc-id:fake:payload -31443 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +31286 _string_f7_subop_not/imm32/subx-name +31287 1/imm32/rm32-is-first-inout +31288 0/imm32/no-r32 +31289 0/imm32/no-imm32 +31290 0/imm32/no-imm8 +31291 0/imm32/no-disp32 +31292 0/imm32/no-xm32 +31293 0/imm32/no-x32 +31294 0x11/imm32/alloc-id:fake +31295 _Primitive-xor-with-eax/imm32/next +31296 # - xor +31297 _Primitive-xor-with-eax: # (payload primitive) +31298 0x11/imm32/alloc-id:fake:payload +31299 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 +31300 0x11/imm32/alloc-id:fake +31301 _string-xor/imm32/name +31302 0x11/imm32/alloc-id:fake +31303 Single-lit-var/imm32/inouts +31304 0x11/imm32/alloc-id:fake +31305 Single-int-var-in-eax/imm32/outputs +31306 0x11/imm32/alloc-id:fake +31307 _string_35_xor_with_eax/imm32/subx-name +31308 0/imm32/no-rm32 +31309 0/imm32/no-r32 +31310 1/imm32/imm32-is-first-inout +31311 0/imm32/no-imm8 +31312 0/imm32/no-disp32 +31313 0/imm32/no-xm32 +31314 0/imm32/no-x32 +31315 0x11/imm32/alloc-id:fake +31316 _Primitive-xor-reg-with-reg/imm32/next +31317 _Primitive-xor-reg-with-reg: # (payload primitive) +31318 0x11/imm32/alloc-id:fake:payload +31319 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 +31320 0x11/imm32/alloc-id:fake +31321 _string-xor/imm32/name +31322 0x11/imm32/alloc-id:fake +31323 Single-int-var-in-some-register/imm32/inouts +31324 0x11/imm32/alloc-id:fake +31325 Single-int-var-in-some-register/imm32/outputs +31326 0x11/imm32/alloc-id:fake +31327 _string_31_xor_with/imm32/subx-name +31328 3/imm32/rm32-is-first-output +31329 1/imm32/r32-is-first-inout +31330 0/imm32/no-imm32 +31331 0/imm32/no-imm8 +31332 0/imm32/no-disp32 +31333 0/imm32/no-xm32 +31334 0/imm32/no-x32 +31335 0x11/imm32/alloc-id:fake +31336 _Primitive-xor-reg-with-mem/imm32/next +31337 _Primitive-xor-reg-with-mem: # (payload primitive) +31338 0x11/imm32/alloc-id:fake:payload +31339 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 +31340 0x11/imm32/alloc-id:fake +31341 _string-xor-with/imm32/name +31342 0x11/imm32/alloc-id:fake +31343 Two-args-int-stack-int-reg/imm32/inouts +31344 0/imm32/no-outputs +31345 0/imm32/no-outputs +31346 0x11/imm32/alloc-id:fake +31347 _string_31_xor_with/imm32/subx-name +31348 1/imm32/rm32-is-first-inout +31349 2/imm32/r32-is-second-inout +31350 0/imm32/no-imm32 +31351 0/imm32/no-imm8 +31352 0/imm32/no-disp32 +31353 0/imm32/no-xm32 +31354 0/imm32/no-x32 +31355 0x11/imm32/alloc-id:fake +31356 _Primitive-xor-mem-with-reg/imm32/next +31357 _Primitive-xor-mem-with-reg: # (payload primitive) +31358 0x11/imm32/alloc-id:fake:payload +31359 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +31360 0x11/imm32/alloc-id:fake +31361 _string-xor/imm32/name +31362 0x11/imm32/alloc-id:fake +31363 Single-int-var-in-mem/imm32/inouts +31364 0x11/imm32/alloc-id:fake +31365 Single-int-var-in-some-register/imm32/outputs +31366 0x11/imm32/alloc-id:fake +31367 _string_33_xor/imm32/subx-name +31368 1/imm32/rm32-is-first-inout +31369 3/imm32/r32-is-first-output +31370 0/imm32/no-imm32 +31371 0/imm32/no-imm8 +31372 0/imm32/no-disp32 +31373 0/imm32/no-xm32 +31374 0/imm32/no-x32 +31375 0x11/imm32/alloc-id:fake +31376 _Primitive-xor-lit-with-reg/imm32/next +31377 _Primitive-xor-lit-with-reg: # (payload primitive) +31378 0x11/imm32/alloc-id:fake:payload +31379 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 +31380 0x11/imm32/alloc-id:fake +31381 _string-xor/imm32/name +31382 0x11/imm32/alloc-id:fake +31383 Single-lit-var/imm32/inouts +31384 0x11/imm32/alloc-id:fake +31385 Single-int-var-in-some-register/imm32/outputs +31386 0x11/imm32/alloc-id:fake +31387 _string_81_subop_xor/imm32/subx-name +31388 3/imm32/rm32-is-first-output +31389 0/imm32/no-r32 +31390 1/imm32/imm32-is-first-inout +31391 0/imm32/no-imm8 +31392 0/imm32/no-disp32 +31393 0/imm32/no-xm32 +31394 0/imm32/no-x32 +31395 0x11/imm32/alloc-id:fake +31396 _Primitive-xor-lit-with-mem/imm32/next +31397 _Primitive-xor-lit-with-mem: # (payload primitive) +31398 0x11/imm32/alloc-id:fake:payload +31399 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 +31400 0x11/imm32/alloc-id:fake +31401 _string-xor-with/imm32/name +31402 0x11/imm32/alloc-id:fake +31403 Int-var-and-literal/imm32/inouts +31404 0/imm32/no-outputs +31405 0/imm32/no-outputs +31406 0x11/imm32/alloc-id:fake +31407 _string_81_subop_xor/imm32/subx-name +31408 1/imm32/rm32-is-first-inout +31409 0/imm32/no-r32 +31410 2/imm32/imm32-is-second-inout +31411 0/imm32/no-imm8 +31412 0/imm32/no-disp32 +31413 0/imm32/no-xm32 +31414 0/imm32/no-x32 +31415 0x11/imm32/alloc-id:fake +31416 _Primitive-shift-reg-left-by-lit/imm32/next +31417 _Primitive-shift-reg-left-by-lit: # (payload primitive) +31418 0x11/imm32/alloc-id:fake:payload +31419 # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32 +31420 0x11/imm32/alloc-id:fake +31421 _string-shift-left/imm32/name +31422 0x11/imm32/alloc-id:fake +31423 Single-lit-var/imm32/inouts +31424 0x11/imm32/alloc-id:fake +31425 Single-int-var-in-some-register/imm32/outputs +31426 0x11/imm32/alloc-id:fake +31427 _string_c1_subop_shift_left/imm32/subx-name +31428 3/imm32/rm32-is-first-output +31429 0/imm32/no-r32 +31430 0/imm32/no-imm32 +31431 1/imm32/imm8-is-first-inout +31432 0/imm32/no-disp32 +31433 0/imm32/no-xm32 +31434 0/imm32/no-x32 +31435 0x11/imm32/alloc-id:fake +31436 _Primitive-shift-reg-right-by-lit/imm32/next +31437 _Primitive-shift-reg-right-by-lit: # (payload primitive) +31438 0x11/imm32/alloc-id:fake:payload +31439 # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32 +31440 0x11/imm32/alloc-id:fake +31441 _string-shift-right/imm32/name +31442 0x11/imm32/alloc-id:fake +31443 Single-lit-var/imm32/inouts 31444 0x11/imm32/alloc-id:fake -31445 _string-copy/imm32/name +31445 Single-int-var-in-some-register/imm32/outputs 31446 0x11/imm32/alloc-id:fake -31447 Single-lit-var/imm32/inouts -31448 0x11/imm32/alloc-id:fake -31449 Single-int-var-in-eax/imm32/outputs -31450 0x11/imm32/alloc-id:fake -31451 _string_b8_copy_to_eax/imm32/subx-name -31452 0/imm32/no-rm32 -31453 0/imm32/no-r32 -31454 1/imm32/imm32-is-first-inout -31455 0/imm32/no-imm8 -31456 0/imm32/no-disp32 -31457 0/imm32/no-xm32 -31458 0/imm32/no-x32 -31459 0x11/imm32/alloc-id:fake -31460 _Primitive-copy-to-ecx/imm32/next -31461 _Primitive-copy-to-ecx: # (payload primitive) -31462 0x11/imm32/alloc-id:fake:payload -31463 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +31447 _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name +31448 3/imm32/rm32-is-first-output +31449 0/imm32/no-r32 +31450 0/imm32/no-imm32 +31451 1/imm32/imm8-is-first-inout +31452 0/imm32/no-disp32 +31453 0/imm32/no-xm32 +31454 0/imm32/no-x32 +31455 0x11/imm32/alloc-id:fake +31456 _Primitive-shift-reg-right-signed-by-lit/imm32/next +31457 _Primitive-shift-reg-right-signed-by-lit: # (payload primitive) +31458 0x11/imm32/alloc-id:fake:payload +31459 # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32 +31460 0x11/imm32/alloc-id:fake +31461 _string-shift-right-signed/imm32/name +31462 0x11/imm32/alloc-id:fake +31463 Single-lit-var/imm32/inouts 31464 0x11/imm32/alloc-id:fake -31465 _string-copy/imm32/name +31465 Single-int-var-in-some-register/imm32/outputs 31466 0x11/imm32/alloc-id:fake -31467 Single-lit-var/imm32/inouts -31468 0x11/imm32/alloc-id:fake -31469 Single-int-var-in-ecx/imm32/outputs -31470 0x11/imm32/alloc-id:fake -31471 _string_b9_copy_to_ecx/imm32/subx-name -31472 0/imm32/no-rm32 -31473 0/imm32/no-r32 -31474 1/imm32/imm32-is-first-inout -31475 0/imm32/no-imm8 -31476 0/imm32/no-disp32 -31477 0/imm32/no-xm32 -31478 0/imm32/no-x32 -31479 0x11/imm32/alloc-id:fake -31480 _Primitive-copy-to-edx/imm32/next -31481 _Primitive-copy-to-edx: # (payload primitive) -31482 0x11/imm32/alloc-id:fake:payload -31483 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -31484 0x11/imm32/alloc-id:fake -31485 _string-copy/imm32/name +31467 _string_c1_subop_shift_right_preserving_sign/imm32/subx-name +31468 3/imm32/rm32-is-first-output +31469 0/imm32/no-r32 +31470 0/imm32/no-imm32 +31471 1/imm32/imm8-is-first-inout +31472 0/imm32/no-disp32 +31473 0/imm32/no-xm32 +31474 0/imm32/no-x32 +31475 0x11/imm32/alloc-id:fake +31476 _Primitive-shift-mem-left-by-lit/imm32/next +31477 _Primitive-shift-mem-left-by-lit: # (payload primitive) +31478 0x11/imm32/alloc-id:fake:payload +31479 # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32 +31480 0x11/imm32/alloc-id:fake +31481 _string-shift-left/imm32/name +31482 0x11/imm32/alloc-id:fake +31483 Int-var-and-literal/imm32/inouts +31484 0/imm32/no-outputs +31485 0/imm32/no-outputs 31486 0x11/imm32/alloc-id:fake -31487 Single-lit-var/imm32/inouts -31488 0x11/imm32/alloc-id:fake -31489 Single-int-var-in-edx/imm32/outputs -31490 0x11/imm32/alloc-id:fake -31491 _string_ba_copy_to_edx/imm32/subx-name -31492 0/imm32/no-rm32 -31493 0/imm32/no-r32 -31494 1/imm32/imm32-is-first-inout -31495 0/imm32/no-imm8 -31496 0/imm32/no-disp32 -31497 0/imm32/no-xm32 -31498 0/imm32/no-x32 -31499 0x11/imm32/alloc-id:fake -31500 _Primitive-copy-to-ebx/imm32/next -31501 _Primitive-copy-to-ebx: # (payload primitive) -31502 0x11/imm32/alloc-id:fake:payload -31503 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -31504 0x11/imm32/alloc-id:fake -31505 _string-copy/imm32/name +31487 _string_c1_subop_shift_left/imm32/subx-name +31488 1/imm32/rm32-is-first-inout +31489 0/imm32/no-r32 +31490 0/imm32/no-imm32 +31491 2/imm32/imm8-is-second-inout +31492 0/imm32/no-disp32 +31493 0/imm32/no-xm32 +31494 0/imm32/no-x32 +31495 0x11/imm32/alloc-id:fake +31496 _Primitive-shift-mem-right-by-lit/imm32/next +31497 _Primitive-shift-mem-right-by-lit: # (payload primitive) +31498 0x11/imm32/alloc-id:fake:payload +31499 # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32 +31500 0x11/imm32/alloc-id:fake +31501 _string-shift-right/imm32/name +31502 0x11/imm32/alloc-id:fake +31503 Int-var-and-literal/imm32/inouts +31504 0/imm32/no-outputs +31505 0/imm32/no-outputs 31506 0x11/imm32/alloc-id:fake -31507 Single-lit-var/imm32/inouts -31508 0x11/imm32/alloc-id:fake -31509 Single-int-var-in-ebx/imm32/outputs -31510 0x11/imm32/alloc-id:fake -31511 _string_bb_copy_to_ebx/imm32/subx-name -31512 0/imm32/no-rm32 -31513 0/imm32/no-r32 -31514 1/imm32/imm32-is-first-inout -31515 0/imm32/no-imm8 -31516 0/imm32/no-disp32 -31517 0/imm32/no-xm32 -31518 0/imm32/no-x32 -31519 0x11/imm32/alloc-id:fake -31520 _Primitive-copy-to-esi/imm32/next -31521 _Primitive-copy-to-esi: # (payload primitive) -31522 0x11/imm32/alloc-id:fake:payload -31523 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -31524 0x11/imm32/alloc-id:fake -31525 _string-copy/imm32/name +31507 _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name +31508 1/imm32/rm32-is-first-inout +31509 0/imm32/no-r32 +31510 0/imm32/no-imm32 +31511 2/imm32/imm8-is-second-inout +31512 0/imm32/no-disp32 +31513 0/imm32/no-xm32 +31514 0/imm32/no-x32 +31515 0x11/imm32/alloc-id:fake +31516 _Primitive-shift-mem-right-signed-by-lit/imm32/next +31517 _Primitive-shift-mem-right-signed-by-lit: # (payload primitive) +31518 0x11/imm32/alloc-id:fake:payload +31519 # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32 +31520 0x11/imm32/alloc-id:fake +31521 _string-shift-right-signed/imm32/name +31522 0x11/imm32/alloc-id:fake +31523 Int-var-and-literal/imm32/inouts +31524 0/imm32/no-outputs +31525 0/imm32/no-outputs 31526 0x11/imm32/alloc-id:fake -31527 Single-lit-var/imm32/inouts -31528 0x11/imm32/alloc-id:fake -31529 Single-int-var-in-esi/imm32/outputs -31530 0x11/imm32/alloc-id:fake -31531 _string_be_copy_to_esi/imm32/subx-name -31532 0/imm32/no-rm32 -31533 0/imm32/no-r32 -31534 1/imm32/imm32-is-first-inout -31535 0/imm32/no-imm8 -31536 0/imm32/no-disp32 -31537 0/imm32/no-xm32 -31538 0/imm32/no-x32 -31539 0x11/imm32/alloc-id:fake -31540 _Primitive-copy-to-edi/imm32/next -31541 _Primitive-copy-to-edi: # (payload primitive) -31542 0x11/imm32/alloc-id:fake:payload -31543 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -31544 0x11/imm32/alloc-id:fake -31545 _string-copy/imm32/name -31546 0x11/imm32/alloc-id:fake -31547 Single-lit-var/imm32/inouts -31548 0x11/imm32/alloc-id:fake -31549 Single-int-var-in-edi/imm32/outputs -31550 0x11/imm32/alloc-id:fake -31551 _string_bf_copy_to_edi/imm32/subx-name -31552 0/imm32/no-rm32 -31553 0/imm32/no-r32 -31554 1/imm32/imm32-is-first-inout -31555 0/imm32/no-imm8 -31556 0/imm32/no-disp32 -31557 0/imm32/no-xm32 -31558 0/imm32/no-x32 -31559 0x11/imm32/alloc-id:fake -31560 _Primitive-copy-reg-to-reg/imm32/next -31561 _Primitive-copy-reg-to-reg: # (payload primitive) -31562 0x11/imm32/alloc-id:fake:payload -31563 # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32 -31564 0x11/imm32/alloc-id:fake -31565 _string-copy/imm32/name -31566 0x11/imm32/alloc-id:fake -31567 Single-int-var-in-some-register/imm32/inouts -31568 0x11/imm32/alloc-id:fake -31569 Single-int-var-in-some-register/imm32/outputs -31570 0x11/imm32/alloc-id:fake -31571 _string_89_<-/imm32/subx-name -31572 3/imm32/rm32-is-first-output -31573 1/imm32/r32-is-first-inout -31574 0/imm32/no-imm32 -31575 0/imm32/no-imm8 -31576 0/imm32/no-disp32 -31577 0/imm32/no-xm32 -31578 0/imm32/no-x32 -31579 0x11/imm32/alloc-id:fake -31580 _Primitive-copy-reg-to-mem/imm32/next -31581 _Primitive-copy-reg-to-mem: # (payload primitive) -31582 0x11/imm32/alloc-id:fake:payload -31583 # copy-to var1 var2/reg => 89/<- var1 var2/r32 -31584 0x11/imm32/alloc-id:fake -31585 _string-copy-to/imm32/name -31586 0x11/imm32/alloc-id:fake -31587 Two-args-int-stack-int-reg/imm32/inouts -31588 0/imm32/no-outputs -31589 0/imm32/no-outputs -31590 0x11/imm32/alloc-id:fake -31591 _string_89_<-/imm32/subx-name -31592 1/imm32/rm32-is-first-inout -31593 2/imm32/r32-is-second-inout -31594 0/imm32/no-imm32 -31595 0/imm32/no-imm8 -31596 0/imm32/no-disp32 -31597 0/imm32/no-xm32 -31598 0/imm32/no-x32 -31599 0x11/imm32/alloc-id:fake -31600 _Primitive-copy-mem-to-reg/imm32/next -31601 _Primitive-copy-mem-to-reg: # (payload primitive) -31602 0x11/imm32/alloc-id:fake:payload -31603 # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32 -31604 0x11/imm32/alloc-id:fake -31605 _string-copy/imm32/name -31606 0x11/imm32/alloc-id:fake -31607 Single-int-var-in-mem/imm32/inouts -31608 0x11/imm32/alloc-id:fake -31609 Single-int-var-in-some-register/imm32/outputs -31610 0x11/imm32/alloc-id:fake -31611 _string_8b_->/imm32/subx-name -31612 1/imm32/rm32-is-first-inout -31613 3/imm32/r32-is-first-output -31614 0/imm32/no-imm32 -31615 0/imm32/no-imm8 -31616 0/imm32/no-disp32 -31617 0/imm32/no-xm32 -31618 0/imm32/no-x32 -31619 0x11/imm32/alloc-id:fake -31620 _Primitive-copy-lit-to-reg/imm32/next -31621 _Primitive-copy-lit-to-reg: # (payload primitive) -31622 0x11/imm32/alloc-id:fake:payload -31623 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -31624 0x11/imm32/alloc-id:fake -31625 _string-copy/imm32/name -31626 0x11/imm32/alloc-id:fake -31627 Single-lit-var/imm32/inouts -31628 0x11/imm32/alloc-id:fake -31629 Single-int-var-in-some-register/imm32/outputs -31630 0x11/imm32/alloc-id:fake -31631 _string_c7_subop_copy/imm32/subx-name -31632 3/imm32/rm32-is-first-output -31633 0/imm32/no-r32 -31634 1/imm32/imm32-is-first-inout -31635 0/imm32/no-imm8 -31636 0/imm32/no-disp32 -31637 0/imm32/no-xm32 -31638 0/imm32/no-x32 -31639 0x11/imm32/alloc-id:fake -31640 _Primitive-copy-lit-to-mem/imm32/next -31641 _Primitive-copy-lit-to-mem: # (payload primitive) -31642 0x11/imm32/alloc-id:fake:payload -31643 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -31644 0x11/imm32/alloc-id:fake -31645 _string-copy-to/imm32/name -31646 0x11/imm32/alloc-id:fake -31647 Int-var-and-literal/imm32/inouts -31648 0/imm32/no-outputs -31649 0/imm32/no-outputs -31650 0x11/imm32/alloc-id:fake -31651 _string_c7_subop_copy/imm32/subx-name -31652 1/imm32/rm32-is-first-inout -31653 0/imm32/no-r32 -31654 2/imm32/imm32-is-second-inout -31655 0/imm32/no-imm8 -31656 0/imm32/no-disp32 -31657 0/imm32/no-xm32 -31658 0/imm32/no-x32 -31659 0x11/imm32/alloc-id:fake -31660 _Primitive-copy-byte-from-reg/imm32/next -31661 # - copy byte -31662 _Primitive-copy-byte-from-reg: -31663 0x11/imm32/alloc-id:fake:payload -31664 # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32 +31527 _string_c1_subop_shift_right_preserving_sign/imm32/subx-name +31528 1/imm32/rm32-is-first-inout +31529 0/imm32/no-r32 +31530 0/imm32/no-imm32 +31531 2/imm32/imm8-is-second-inout +31532 0/imm32/no-disp32 +31533 0/imm32/no-xm32 +31534 0/imm32/no-x32 +31535 0x11/imm32/alloc-id:fake +31536 _Primitive-copy-to-eax/imm32/next +31537 # - copy +31538 _Primitive-copy-to-eax: # (payload primitive) +31539 0x11/imm32/alloc-id:fake:payload +31540 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +31541 0x11/imm32/alloc-id:fake +31542 _string-copy/imm32/name +31543 0x11/imm32/alloc-id:fake +31544 Single-lit-var/imm32/inouts +31545 0x11/imm32/alloc-id:fake +31546 Single-int-var-in-eax/imm32/outputs +31547 0x11/imm32/alloc-id:fake +31548 _string_b8_copy_to_eax/imm32/subx-name +31549 0/imm32/no-rm32 +31550 0/imm32/no-r32 +31551 1/imm32/imm32-is-first-inout +31552 0/imm32/no-imm8 +31553 0/imm32/no-disp32 +31554 0/imm32/no-xm32 +31555 0/imm32/no-x32 +31556 0x11/imm32/alloc-id:fake +31557 _Primitive-copy-to-ecx/imm32/next +31558 _Primitive-copy-to-ecx: # (payload primitive) +31559 0x11/imm32/alloc-id:fake:payload +31560 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +31561 0x11/imm32/alloc-id:fake +31562 _string-copy/imm32/name +31563 0x11/imm32/alloc-id:fake +31564 Single-lit-var/imm32/inouts +31565 0x11/imm32/alloc-id:fake +31566 Single-int-var-in-ecx/imm32/outputs +31567 0x11/imm32/alloc-id:fake +31568 _string_b9_copy_to_ecx/imm32/subx-name +31569 0/imm32/no-rm32 +31570 0/imm32/no-r32 +31571 1/imm32/imm32-is-first-inout +31572 0/imm32/no-imm8 +31573 0/imm32/no-disp32 +31574 0/imm32/no-xm32 +31575 0/imm32/no-x32 +31576 0x11/imm32/alloc-id:fake +31577 _Primitive-copy-to-edx/imm32/next +31578 _Primitive-copy-to-edx: # (payload primitive) +31579 0x11/imm32/alloc-id:fake:payload +31580 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 +31581 0x11/imm32/alloc-id:fake +31582 _string-copy/imm32/name +31583 0x11/imm32/alloc-id:fake +31584 Single-lit-var/imm32/inouts +31585 0x11/imm32/alloc-id:fake +31586 Single-int-var-in-edx/imm32/outputs +31587 0x11/imm32/alloc-id:fake +31588 _string_ba_copy_to_edx/imm32/subx-name +31589 0/imm32/no-rm32 +31590 0/imm32/no-r32 +31591 1/imm32/imm32-is-first-inout +31592 0/imm32/no-imm8 +31593 0/imm32/no-disp32 +31594 0/imm32/no-xm32 +31595 0/imm32/no-x32 +31596 0x11/imm32/alloc-id:fake +31597 _Primitive-copy-to-ebx/imm32/next +31598 _Primitive-copy-to-ebx: # (payload primitive) +31599 0x11/imm32/alloc-id:fake:payload +31600 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 +31601 0x11/imm32/alloc-id:fake +31602 _string-copy/imm32/name +31603 0x11/imm32/alloc-id:fake +31604 Single-lit-var/imm32/inouts +31605 0x11/imm32/alloc-id:fake +31606 Single-int-var-in-ebx/imm32/outputs +31607 0x11/imm32/alloc-id:fake +31608 _string_bb_copy_to_ebx/imm32/subx-name +31609 0/imm32/no-rm32 +31610 0/imm32/no-r32 +31611 1/imm32/imm32-is-first-inout +31612 0/imm32/no-imm8 +31613 0/imm32/no-disp32 +31614 0/imm32/no-xm32 +31615 0/imm32/no-x32 +31616 0x11/imm32/alloc-id:fake +31617 _Primitive-copy-to-esi/imm32/next +31618 _Primitive-copy-to-esi: # (payload primitive) +31619 0x11/imm32/alloc-id:fake:payload +31620 # var/esi <- copy lit => be/copy-to-esi lit/imm32 +31621 0x11/imm32/alloc-id:fake +31622 _string-copy/imm32/name +31623 0x11/imm32/alloc-id:fake +31624 Single-lit-var/imm32/inouts +31625 0x11/imm32/alloc-id:fake +31626 Single-int-var-in-esi/imm32/outputs +31627 0x11/imm32/alloc-id:fake +31628 _string_be_copy_to_esi/imm32/subx-name +31629 0/imm32/no-rm32 +31630 0/imm32/no-r32 +31631 1/imm32/imm32-is-first-inout +31632 0/imm32/no-imm8 +31633 0/imm32/no-disp32 +31634 0/imm32/no-xm32 +31635 0/imm32/no-x32 +31636 0x11/imm32/alloc-id:fake +31637 _Primitive-copy-to-edi/imm32/next +31638 _Primitive-copy-to-edi: # (payload primitive) +31639 0x11/imm32/alloc-id:fake:payload +31640 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 +31641 0x11/imm32/alloc-id:fake +31642 _string-copy/imm32/name +31643 0x11/imm32/alloc-id:fake +31644 Single-lit-var/imm32/inouts +31645 0x11/imm32/alloc-id:fake +31646 Single-int-var-in-edi/imm32/outputs +31647 0x11/imm32/alloc-id:fake +31648 _string_bf_copy_to_edi/imm32/subx-name +31649 0/imm32/no-rm32 +31650 0/imm32/no-r32 +31651 1/imm32/imm32-is-first-inout +31652 0/imm32/no-imm8 +31653 0/imm32/no-disp32 +31654 0/imm32/no-xm32 +31655 0/imm32/no-x32 +31656 0x11/imm32/alloc-id:fake +31657 _Primitive-copy-reg-to-reg/imm32/next +31658 _Primitive-copy-reg-to-reg: # (payload primitive) +31659 0x11/imm32/alloc-id:fake:payload +31660 # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32 +31661 0x11/imm32/alloc-id:fake +31662 _string-copy/imm32/name +31663 0x11/imm32/alloc-id:fake +31664 Single-int-var-in-some-register/imm32/inouts 31665 0x11/imm32/alloc-id:fake -31666 _string-copy-byte/imm32/name +31666 Single-int-var-in-some-register/imm32/outputs 31667 0x11/imm32/alloc-id:fake -31668 Single-byte-var-in-some-register/imm32/inouts -31669 0x11/imm32/alloc-id:fake -31670 Single-byte-var-in-some-register/imm32/outputs -31671 0x11/imm32/alloc-id:fake -31672 _string_8a_copy_byte/imm32/subx-name -31673 1/imm32/rm32-is-first-inout -31674 3/imm32/r32-is-first-output -31675 0/imm32/no-imm32 -31676 0/imm32/no-imm8 -31677 0/imm32/no-disp32 -31678 0/imm32/no-xm32 -31679 0/imm32/no-x32 -31680 0x11/imm32/alloc-id:fake -31681 _Primitive-copy-byte-from-mem/imm32/next -31682 _Primitive-copy-byte-from-mem: -31683 0x11/imm32/alloc-id:fake:payload -31684 # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32 -31685 0x11/imm32/alloc-id:fake -31686 _string-copy-byte/imm32/name +31668 _string_89_<-/imm32/subx-name +31669 3/imm32/rm32-is-first-output +31670 1/imm32/r32-is-first-inout +31671 0/imm32/no-imm32 +31672 0/imm32/no-imm8 +31673 0/imm32/no-disp32 +31674 0/imm32/no-xm32 +31675 0/imm32/no-x32 +31676 0x11/imm32/alloc-id:fake +31677 _Primitive-copy-reg-to-mem/imm32/next +31678 _Primitive-copy-reg-to-mem: # (payload primitive) +31679 0x11/imm32/alloc-id:fake:payload +31680 # copy-to var1 var2/reg => 89/<- var1 var2/r32 +31681 0x11/imm32/alloc-id:fake +31682 _string-copy-to/imm32/name +31683 0x11/imm32/alloc-id:fake +31684 Two-args-int-stack-int-reg/imm32/inouts +31685 0/imm32/no-outputs +31686 0/imm32/no-outputs 31687 0x11/imm32/alloc-id:fake -31688 Single-byte-var-in-mem/imm32/inouts -31689 0x11/imm32/alloc-id:fake -31690 Single-byte-var-in-some-register/imm32/outputs -31691 0x11/imm32/alloc-id:fake -31692 _string_8a_copy_byte/imm32/subx-name -31693 1/imm32/rm32-is-first-inout -31694 3/imm32/r32-is-first-output -31695 0/imm32/no-imm32 -31696 0/imm32/no-imm8 -31697 0/imm32/no-disp32 -31698 0/imm32/no-xm32 -31699 0/imm32/no-x32 -31700 0x11/imm32/alloc-id:fake -31701 _Primitive-copy-byte-to-mem/imm32/next -31702 _Primitive-copy-byte-to-mem: -31703 0x11/imm32/alloc-id:fake:payload -31704 # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32 +31688 _string_89_<-/imm32/subx-name +31689 1/imm32/rm32-is-first-inout +31690 2/imm32/r32-is-second-inout +31691 0/imm32/no-imm32 +31692 0/imm32/no-imm8 +31693 0/imm32/no-disp32 +31694 0/imm32/no-xm32 +31695 0/imm32/no-x32 +31696 0x11/imm32/alloc-id:fake +31697 _Primitive-copy-mem-to-reg/imm32/next +31698 _Primitive-copy-mem-to-reg: # (payload primitive) +31699 0x11/imm32/alloc-id:fake:payload +31700 # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32 +31701 0x11/imm32/alloc-id:fake +31702 _string-copy/imm32/name +31703 0x11/imm32/alloc-id:fake +31704 Single-int-var-in-mem/imm32/inouts 31705 0x11/imm32/alloc-id:fake -31706 _string-copy-byte-to/imm32/name +31706 Single-int-var-in-some-register/imm32/outputs 31707 0x11/imm32/alloc-id:fake -31708 Two-args-byte-stack-byte-reg/imm32/inouts -31709 0/imm32/no-outputs -31710 0/imm32/no-outputs -31711 0x11/imm32/alloc-id:fake -31712 _string_88_copy_byte/imm32/subx-name -31713 1/imm32/rm32-is-first-inout -31714 2/imm32/r32-is-second-inout -31715 0/imm32/no-imm32 -31716 0/imm32/no-imm8 -31717 0/imm32/no-disp32 -31718 0/imm32/no-xm32 -31719 0/imm32/no-x32 -31720 0x11/imm32/alloc-id:fake -31721 _Primitive-address/imm32/next -31722 # - address -31723 _Primitive-address: # (payload primitive) -31724 0x11/imm32/alloc-id:fake:payload -31725 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 -31726 0x11/imm32/alloc-id:fake -31727 _string-address/imm32/name -31728 0x11/imm32/alloc-id:fake -31729 Single-int-var-in-mem/imm32/inouts -31730 0x11/imm32/alloc-id:fake -31731 Single-addr-var-in-some-register/imm32/outputs -31732 0x11/imm32/alloc-id:fake -31733 _string_8d_copy_address/imm32/subx-name -31734 1/imm32/rm32-is-first-inout -31735 3/imm32/r32-is-first-output -31736 0/imm32/no-imm32 -31737 0/imm32/no-imm8 -31738 0/imm32/no-disp32 -31739 0/imm32/no-xm32 -31740 0/imm32/no-x32 +31708 _string_8b_->/imm32/subx-name +31709 1/imm32/rm32-is-first-inout +31710 3/imm32/r32-is-first-output +31711 0/imm32/no-imm32 +31712 0/imm32/no-imm8 +31713 0/imm32/no-disp32 +31714 0/imm32/no-xm32 +31715 0/imm32/no-x32 +31716 0x11/imm32/alloc-id:fake +31717 _Primitive-copy-lit-to-reg/imm32/next +31718 _Primitive-copy-lit-to-reg: # (payload primitive) +31719 0x11/imm32/alloc-id:fake:payload +31720 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 +31721 0x11/imm32/alloc-id:fake +31722 _string-copy/imm32/name +31723 0x11/imm32/alloc-id:fake +31724 Single-lit-var/imm32/inouts +31725 0x11/imm32/alloc-id:fake +31726 Single-int-var-in-some-register/imm32/outputs +31727 0x11/imm32/alloc-id:fake +31728 _string_c7_subop_copy/imm32/subx-name +31729 3/imm32/rm32-is-first-output +31730 0/imm32/no-r32 +31731 1/imm32/imm32-is-first-inout +31732 0/imm32/no-imm8 +31733 0/imm32/no-disp32 +31734 0/imm32/no-xm32 +31735 0/imm32/no-x32 +31736 0x11/imm32/alloc-id:fake +31737 _Primitive-copy-lit-to-mem/imm32/next +31738 _Primitive-copy-lit-to-mem: # (payload primitive) +31739 0x11/imm32/alloc-id:fake:payload +31740 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 31741 0x11/imm32/alloc-id:fake -31742 _Primitive-compare-reg-with-reg/imm32/next -31743 # - compare -31744 _Primitive-compare-reg-with-reg: # (payload primitive) -31745 0x11/imm32/alloc-id:fake:payload -31746 # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32 +31742 _string-copy-to/imm32/name +31743 0x11/imm32/alloc-id:fake +31744 Int-var-and-literal/imm32/inouts +31745 0/imm32/no-outputs +31746 0/imm32/no-outputs 31747 0x11/imm32/alloc-id:fake -31748 _string-compare/imm32/name -31749 0x11/imm32/alloc-id:fake -31750 Two-int-args-in-regs/imm32/inouts -31751 0/imm32/no-outputs -31752 0/imm32/no-outputs -31753 0x11/imm32/alloc-id:fake -31754 _string_39_compare->/imm32/subx-name -31755 1/imm32/rm32-is-first-inout -31756 2/imm32/r32-is-second-inout -31757 0/imm32/no-imm32 -31758 0/imm32/no-imm8 -31759 0/imm32/no-disp32 -31760 0/imm32/no-xm32 -31761 0/imm32/no-x32 +31748 _string_c7_subop_copy/imm32/subx-name +31749 1/imm32/rm32-is-first-inout +31750 0/imm32/no-r32 +31751 2/imm32/imm32-is-second-inout +31752 0/imm32/no-imm8 +31753 0/imm32/no-disp32 +31754 0/imm32/no-xm32 +31755 0/imm32/no-x32 +31756 0x11/imm32/alloc-id:fake +31757 _Primitive-copy-byte-from-reg/imm32/next +31758 # - copy byte +31759 _Primitive-copy-byte-from-reg: +31760 0x11/imm32/alloc-id:fake:payload +31761 # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32 31762 0x11/imm32/alloc-id:fake -31763 _Primitive-compare-mem-with-reg/imm32/next -31764 _Primitive-compare-mem-with-reg: # (payload primitive) -31765 0x11/imm32/alloc-id:fake:payload -31766 # compare var1 var2/reg => 39/compare var1/rm32 var2/r32 -31767 0x11/imm32/alloc-id:fake -31768 _string-compare/imm32/name -31769 0x11/imm32/alloc-id:fake -31770 Two-args-int-stack-int-reg/imm32/inouts -31771 0/imm32/no-outputs -31772 0/imm32/no-outputs -31773 0x11/imm32/alloc-id:fake -31774 _string_39_compare->/imm32/subx-name -31775 1/imm32/rm32-is-first-inout -31776 2/imm32/r32-is-second-inout -31777 0/imm32/no-imm32 -31778 0/imm32/no-imm8 -31779 0/imm32/no-disp32 -31780 0/imm32/no-xm32 -31781 0/imm32/no-x32 +31763 _string-copy-byte/imm32/name +31764 0x11/imm32/alloc-id:fake +31765 Single-byte-var-in-some-register/imm32/inouts +31766 0x11/imm32/alloc-id:fake +31767 Single-byte-var-in-some-register/imm32/outputs +31768 0x11/imm32/alloc-id:fake +31769 _string_8a_copy_byte/imm32/subx-name +31770 1/imm32/rm32-is-first-inout +31771 3/imm32/r32-is-first-output +31772 0/imm32/no-imm32 +31773 0/imm32/no-imm8 +31774 0/imm32/no-disp32 +31775 0/imm32/no-xm32 +31776 0/imm32/no-x32 +31777 0x11/imm32/alloc-id:fake +31778 _Primitive-copy-byte-from-mem/imm32/next +31779 _Primitive-copy-byte-from-mem: +31780 0x11/imm32/alloc-id:fake:payload +31781 # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32 31782 0x11/imm32/alloc-id:fake -31783 _Primitive-compare-reg-with-mem/imm32/next -31784 _Primitive-compare-reg-with-mem: # (payload primitive) -31785 0x11/imm32/alloc-id:fake:payload -31786 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -31787 0x11/imm32/alloc-id:fake -31788 _string-compare/imm32/name -31789 0x11/imm32/alloc-id:fake -31790 Two-args-int-reg-int-stack/imm32/inouts -31791 0/imm32/no-outputs -31792 0/imm32/no-outputs -31793 0x11/imm32/alloc-id:fake -31794 _string_3b_compare<-/imm32/subx-name -31795 2/imm32/rm32-is-second-inout -31796 1/imm32/r32-is-first-inout -31797 0/imm32/no-imm32 -31798 0/imm32/no-imm8 -31799 0/imm32/no-disp32 -31800 0/imm32/no-xm32 -31801 0/imm32/no-x32 +31783 _string-copy-byte/imm32/name +31784 0x11/imm32/alloc-id:fake +31785 Single-byte-var-in-mem/imm32/inouts +31786 0x11/imm32/alloc-id:fake +31787 Single-byte-var-in-some-register/imm32/outputs +31788 0x11/imm32/alloc-id:fake +31789 _string_8a_copy_byte/imm32/subx-name +31790 1/imm32/rm32-is-first-inout +31791 3/imm32/r32-is-first-output +31792 0/imm32/no-imm32 +31793 0/imm32/no-imm8 +31794 0/imm32/no-disp32 +31795 0/imm32/no-xm32 +31796 0/imm32/no-x32 +31797 0x11/imm32/alloc-id:fake +31798 _Primitive-copy-byte-to-mem/imm32/next +31799 _Primitive-copy-byte-to-mem: +31800 0x11/imm32/alloc-id:fake:payload +31801 # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32 31802 0x11/imm32/alloc-id:fake -31803 _Primitive-compare-eax-with-literal/imm32/next -31804 _Primitive-compare-eax-with-literal: # (payload primitive) -31805 0x11/imm32/alloc-id:fake:payload -31806 # compare var1/eax n => 3d/compare-eax-with n/imm32 -31807 0x11/imm32/alloc-id:fake -31808 _string-compare/imm32/name -31809 0x11/imm32/alloc-id:fake -31810 Two-args-int-eax-int-literal/imm32/inouts -31811 0/imm32/no-outputs -31812 0/imm32/no-outputs -31813 0x11/imm32/alloc-id:fake -31814 _string_3d_compare_eax_with/imm32/subx-name -31815 0/imm32/no-rm32 -31816 0/imm32/no-r32 -31817 2/imm32/imm32-is-second-inout -31818 0/imm32/no-imm8 -31819 0/imm32/no-disp32 -31820 0/imm32/no-xm32 -31821 0/imm32/no-x32 -31822 0x11/imm32/alloc-id:fake -31823 _Primitive-compare-reg-with-literal/imm32/next -31824 _Primitive-compare-reg-with-literal: # (payload primitive) -31825 0x11/imm32/alloc-id:fake:payload -31826 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 +31803 _string-copy-byte-to/imm32/name +31804 0x11/imm32/alloc-id:fake +31805 Two-args-byte-stack-byte-reg/imm32/inouts +31806 0/imm32/no-outputs +31807 0/imm32/no-outputs +31808 0x11/imm32/alloc-id:fake +31809 _string_88_copy_byte/imm32/subx-name +31810 1/imm32/rm32-is-first-inout +31811 2/imm32/r32-is-second-inout +31812 0/imm32/no-imm32 +31813 0/imm32/no-imm8 +31814 0/imm32/no-disp32 +31815 0/imm32/no-xm32 +31816 0/imm32/no-x32 +31817 0x11/imm32/alloc-id:fake +31818 _Primitive-address/imm32/next +31819 # - address +31820 _Primitive-address: # (payload primitive) +31821 0x11/imm32/alloc-id:fake:payload +31822 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 +31823 0x11/imm32/alloc-id:fake +31824 _string-address/imm32/name +31825 0x11/imm32/alloc-id:fake +31826 Single-int-var-in-mem/imm32/inouts 31827 0x11/imm32/alloc-id:fake -31828 _string-compare/imm32/name +31828 Single-addr-var-in-some-register/imm32/outputs 31829 0x11/imm32/alloc-id:fake -31830 Int-var-in-register-and-literal/imm32/inouts -31831 0/imm32/no-outputs -31832 0/imm32/no-outputs -31833 0x11/imm32/alloc-id:fake -31834 _string_81_subop_compare/imm32/subx-name -31835 1/imm32/rm32-is-first-inout -31836 0/imm32/no-r32 -31837 2/imm32/imm32-is-second-inout -31838 0/imm32/no-imm8 -31839 0/imm32/no-disp32 -31840 0/imm32/no-xm32 -31841 0/imm32/no-x32 -31842 0x11/imm32/alloc-id:fake -31843 _Primitive-compare-mem-with-literal/imm32/next -31844 _Primitive-compare-mem-with-literal: # (payload primitive) -31845 0x11/imm32/alloc-id:fake:payload -31846 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -31847 0x11/imm32/alloc-id:fake -31848 _string-compare/imm32/name -31849 0x11/imm32/alloc-id:fake -31850 Int-var-and-literal/imm32/inouts -31851 0/imm32/no-outputs -31852 0/imm32/no-outputs -31853 0x11/imm32/alloc-id:fake -31854 _string_81_subop_compare/imm32/subx-name -31855 1/imm32/rm32-is-first-inout -31856 0/imm32/no-r32 -31857 2/imm32/imm32-is-second-inout -31858 0/imm32/no-imm8 -31859 0/imm32/no-disp32 -31860 0/imm32/no-xm32 -31861 0/imm32/no-x32 -31862 0x11/imm32/alloc-id:fake -31863 _Primitive-negate-reg/imm32/next -31864 # - negate -31865 _Primitive-negate-reg: # (payload primitive) -31866 0x11/imm32/alloc-id:fake:payload -31867 # var1/reg <- negate => f7 3/subop/negate var1/rm32 -31868 0x11/imm32/alloc-id:fake -31869 _string-negate/imm32/name -31870 0/imm32/no-inouts -31871 0/imm32/no-inouts -31872 0x11/imm32/alloc-id:fake -31873 Single-int-var-in-some-register/imm32/outputs -31874 0x11/imm32/alloc-id:fake -31875 _string_f7_subop_negate/imm32/subx-name -31876 3/imm32/rm32-is-first-output -31877 0/imm32/no-r32 -31878 0/imm32/no-imm32 -31879 0/imm32/no-imm8 -31880 0/imm32/no-disp32 -31881 0/imm32/no-xm32 -31882 0/imm32/no-x32 -31883 0x11/imm32/alloc-id:fake -31884 _Primitive-negate-mem/imm32/next -31885 _Primitive-negate-mem: # (payload primitive) -31886 0x11/imm32/alloc-id:fake:payload -31887 # negate var1 => f7 3/subop/negate var1/rm32 -31888 0x11/imm32/alloc-id:fake -31889 _string-negate/imm32/name +31830 _string_8d_copy_address/imm32/subx-name +31831 1/imm32/rm32-is-first-inout +31832 3/imm32/r32-is-first-output +31833 0/imm32/no-imm32 +31834 0/imm32/no-imm8 +31835 0/imm32/no-disp32 +31836 0/imm32/no-xm32 +31837 0/imm32/no-x32 +31838 0x11/imm32/alloc-id:fake +31839 _Primitive-compare-reg-with-reg/imm32/next +31840 # - compare +31841 _Primitive-compare-reg-with-reg: # (payload primitive) +31842 0x11/imm32/alloc-id:fake:payload +31843 # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32 +31844 0x11/imm32/alloc-id:fake +31845 _string-compare/imm32/name +31846 0x11/imm32/alloc-id:fake +31847 Two-int-args-in-regs/imm32/inouts +31848 0/imm32/no-outputs +31849 0/imm32/no-outputs +31850 0x11/imm32/alloc-id:fake +31851 _string_39_compare->/imm32/subx-name +31852 1/imm32/rm32-is-first-inout +31853 2/imm32/r32-is-second-inout +31854 0/imm32/no-imm32 +31855 0/imm32/no-imm8 +31856 0/imm32/no-disp32 +31857 0/imm32/no-xm32 +31858 0/imm32/no-x32 +31859 0x11/imm32/alloc-id:fake +31860 _Primitive-compare-mem-with-reg/imm32/next +31861 _Primitive-compare-mem-with-reg: # (payload primitive) +31862 0x11/imm32/alloc-id:fake:payload +31863 # compare var1 var2/reg => 39/compare var1/rm32 var2/r32 +31864 0x11/imm32/alloc-id:fake +31865 _string-compare/imm32/name +31866 0x11/imm32/alloc-id:fake +31867 Two-args-int-stack-int-reg/imm32/inouts +31868 0/imm32/no-outputs +31869 0/imm32/no-outputs +31870 0x11/imm32/alloc-id:fake +31871 _string_39_compare->/imm32/subx-name +31872 1/imm32/rm32-is-first-inout +31873 2/imm32/r32-is-second-inout +31874 0/imm32/no-imm32 +31875 0/imm32/no-imm8 +31876 0/imm32/no-disp32 +31877 0/imm32/no-xm32 +31878 0/imm32/no-x32 +31879 0x11/imm32/alloc-id:fake +31880 _Primitive-compare-reg-with-mem/imm32/next +31881 _Primitive-compare-reg-with-mem: # (payload primitive) +31882 0x11/imm32/alloc-id:fake:payload +31883 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 +31884 0x11/imm32/alloc-id:fake +31885 _string-compare/imm32/name +31886 0x11/imm32/alloc-id:fake +31887 Two-args-int-reg-int-stack/imm32/inouts +31888 0/imm32/no-outputs +31889 0/imm32/no-outputs 31890 0x11/imm32/alloc-id:fake -31891 Single-int-var-in-mem/imm32/inouts -31892 0/imm32/no-outputs -31893 0/imm32/no-outputs -31894 0x11/imm32/alloc-id:fake -31895 _string_f7_subop_negate/imm32/subx-name -31896 1/imm32/rm32-is-first-inout -31897 0/imm32/no-r32 -31898 0/imm32/no-imm32 -31899 0/imm32/no-imm8 -31900 0/imm32/no-disp32 -31901 0/imm32/no-xm32 -31902 0/imm32/no-x32 -31903 0x11/imm32/alloc-id:fake -31904 _Primitive-multiply-reg-by-reg/imm32/next -31905 # - multiply -31906 _Primitive-multiply-reg-by-reg: # (payload primitive) -31907 0x11/imm32/alloc-id:fake:payload -31908 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -31909 0x11/imm32/alloc-id:fake -31910 _string-multiply/imm32/name -31911 0x11/imm32/alloc-id:fake -31912 Single-int-var-in-some-register/imm32/inouts -31913 0x11/imm32/alloc-id:fake -31914 Single-int-var-in-some-register/imm32/outputs -31915 0x11/imm32/alloc-id:fake -31916 _string_0f_af_multiply/imm32/subx-name -31917 1/imm32/rm32-is-first-inout -31918 3/imm32/r32-is-first-output -31919 0/imm32/no-imm32 -31920 0/imm32/no-imm8 -31921 0/imm32/no-disp32 -31922 0/imm32/no-xm32 -31923 0/imm32/no-x32 +31891 _string_3b_compare<-/imm32/subx-name +31892 2/imm32/rm32-is-second-inout +31893 1/imm32/r32-is-first-inout +31894 0/imm32/no-imm32 +31895 0/imm32/no-imm8 +31896 0/imm32/no-disp32 +31897 0/imm32/no-xm32 +31898 0/imm32/no-x32 +31899 0x11/imm32/alloc-id:fake +31900 _Primitive-compare-eax-with-literal/imm32/next +31901 _Primitive-compare-eax-with-literal: # (payload primitive) +31902 0x11/imm32/alloc-id:fake:payload +31903 # compare var1/eax n => 3d/compare-eax-with n/imm32 +31904 0x11/imm32/alloc-id:fake +31905 _string-compare/imm32/name +31906 0x11/imm32/alloc-id:fake +31907 Two-args-int-eax-int-literal/imm32/inouts +31908 0/imm32/no-outputs +31909 0/imm32/no-outputs +31910 0x11/imm32/alloc-id:fake +31911 _string_3d_compare_eax_with/imm32/subx-name +31912 0/imm32/no-rm32 +31913 0/imm32/no-r32 +31914 2/imm32/imm32-is-second-inout +31915 0/imm32/no-imm8 +31916 0/imm32/no-disp32 +31917 0/imm32/no-xm32 +31918 0/imm32/no-x32 +31919 0x11/imm32/alloc-id:fake +31920 _Primitive-compare-reg-with-literal/imm32/next +31921 _Primitive-compare-reg-with-literal: # (payload primitive) +31922 0x11/imm32/alloc-id:fake:payload +31923 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 31924 0x11/imm32/alloc-id:fake -31925 _Primitive-multiply-reg-by-mem/imm32/next -31926 _Primitive-multiply-reg-by-mem: # (payload primitive) -31927 0x11/imm32/alloc-id:fake:payload -31928 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -31929 0x11/imm32/alloc-id:fake -31930 _string-multiply/imm32/name -31931 0x11/imm32/alloc-id:fake -31932 Single-int-var-in-mem/imm32/inouts -31933 0x11/imm32/alloc-id:fake -31934 Single-int-var-in-some-register/imm32/outputs -31935 0x11/imm32/alloc-id:fake -31936 _string_0f_af_multiply/imm32/subx-name -31937 1/imm32/rm32-is-first-inout -31938 3/imm32/r32-is-first-output -31939 0/imm32/no-imm32 -31940 0/imm32/no-imm8 -31941 0/imm32/no-disp32 -31942 0/imm32/no-xm32 -31943 0/imm32/no-x32 +31925 _string-compare/imm32/name +31926 0x11/imm32/alloc-id:fake +31927 Int-var-in-register-and-literal/imm32/inouts +31928 0/imm32/no-outputs +31929 0/imm32/no-outputs +31930 0x11/imm32/alloc-id:fake +31931 _string_81_subop_compare/imm32/subx-name +31932 1/imm32/rm32-is-first-inout +31933 0/imm32/no-r32 +31934 2/imm32/imm32-is-second-inout +31935 0/imm32/no-imm8 +31936 0/imm32/no-disp32 +31937 0/imm32/no-xm32 +31938 0/imm32/no-x32 +31939 0x11/imm32/alloc-id:fake +31940 _Primitive-compare-mem-with-literal/imm32/next +31941 _Primitive-compare-mem-with-literal: # (payload primitive) +31942 0x11/imm32/alloc-id:fake:payload +31943 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 31944 0x11/imm32/alloc-id:fake -31945 _Primitive-convert-mem-to-xreg/imm32/next -31946 # - convert int to floating point -31947 _Primitive-convert-mem-to-xreg: # (payload primitive) -31948 0x11/imm32/alloc-id:fake:payload -31949 # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32 +31945 _string-compare/imm32/name +31946 0x11/imm32/alloc-id:fake +31947 Int-var-and-literal/imm32/inouts +31948 0/imm32/no-outputs +31949 0/imm32/no-outputs 31950 0x11/imm32/alloc-id:fake -31951 _string-convert/imm32/name -31952 0x11/imm32/alloc-id:fake -31953 Single-int-var-in-mem/imm32/inouts -31954 0x11/imm32/alloc-id:fake -31955 Single-float-var-in-some-register/imm32/outputs -31956 0x11/imm32/alloc-id:fake -31957 _string_f3_0f_2a_convert_to_float/imm32/subx-name -31958 1/imm32/rm32-is-first-inout -31959 0/imm32/no-r32 -31960 0/imm32/no-imm32 -31961 0/imm32/no-imm8 -31962 0/imm32/no-disp32 -31963 0/imm32/no-xm32 -31964 3/imm32/x32-is-first-output +31951 _string_81_subop_compare/imm32/subx-name +31952 1/imm32/rm32-is-first-inout +31953 0/imm32/no-r32 +31954 2/imm32/imm32-is-second-inout +31955 0/imm32/no-imm8 +31956 0/imm32/no-disp32 +31957 0/imm32/no-xm32 +31958 0/imm32/no-x32 +31959 0x11/imm32/alloc-id:fake +31960 _Primitive-negate-reg/imm32/next +31961 # - negate +31962 _Primitive-negate-reg: # (payload primitive) +31963 0x11/imm32/alloc-id:fake:payload +31964 # var1/reg <- negate => f7 3/subop/negate var1/rm32 31965 0x11/imm32/alloc-id:fake -31966 _Primitive-convert-reg-to-xreg/imm32/next -31967 _Primitive-convert-reg-to-xreg: # (payload primitive) -31968 0x11/imm32/alloc-id:fake:payload -31969 # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32 -31970 0x11/imm32/alloc-id:fake -31971 _string-convert/imm32/name -31972 0x11/imm32/alloc-id:fake -31973 Single-int-var-in-some-register/imm32/inouts -31974 0x11/imm32/alloc-id:fake -31975 Single-float-var-in-some-register/imm32/outputs -31976 0x11/imm32/alloc-id:fake -31977 _string_f3_0f_2a_convert_to_float/imm32/subx-name -31978 1/imm32/rm32-is-first-inout -31979 0/imm32/no-r32 -31980 0/imm32/no-imm32 -31981 0/imm32/no-imm8 -31982 0/imm32/no-disp32 -31983 0/imm32/no-xm32 -31984 3/imm32/x32-is-first-output +31966 _string-negate/imm32/name +31967 0/imm32/no-inouts +31968 0/imm32/no-inouts +31969 0x11/imm32/alloc-id:fake +31970 Single-int-var-in-some-register/imm32/outputs +31971 0x11/imm32/alloc-id:fake +31972 _string_f7_subop_negate/imm32/subx-name +31973 3/imm32/rm32-is-first-output +31974 0/imm32/no-r32 +31975 0/imm32/no-imm32 +31976 0/imm32/no-imm8 +31977 0/imm32/no-disp32 +31978 0/imm32/no-xm32 +31979 0/imm32/no-x32 +31980 0x11/imm32/alloc-id:fake +31981 _Primitive-negate-mem/imm32/next +31982 _Primitive-negate-mem: # (payload primitive) +31983 0x11/imm32/alloc-id:fake:payload +31984 # negate var1 => f7 3/subop/negate var1/rm32 31985 0x11/imm32/alloc-id:fake -31986 _Primitive-convert-xmem-to-reg/imm32/next -31987 # - convert floating point to int -31988 _Primitive-convert-xmem-to-reg: # (payload primitive) -31989 0x11/imm32/alloc-id:fake:payload -31990 # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32 +31986 _string-negate/imm32/name +31987 0x11/imm32/alloc-id:fake +31988 Single-int-var-in-mem/imm32/inouts +31989 0/imm32/no-outputs +31990 0/imm32/no-outputs 31991 0x11/imm32/alloc-id:fake -31992 _string-convert/imm32/name -31993 0x11/imm32/alloc-id:fake -31994 Single-float-var-in-mem/imm32/inouts -31995 0x11/imm32/alloc-id:fake -31996 Single-int-var-in-some-register/imm32/outputs -31997 0x11/imm32/alloc-id:fake -31998 _string_f3_0f_2d_convert_to_int/imm32/subx-name -31999 0/imm32/no-rm32 -32000 3/imm32/r32-is-first-output -32001 0/imm32/no-imm32 -32002 0/imm32/no-imm8 -32003 0/imm32/no-disp32 -32004 1/imm32/xm32-is-first-inout -32005 0/imm32/no-x32 +31992 _string_f7_subop_negate/imm32/subx-name +31993 1/imm32/rm32-is-first-inout +31994 0/imm32/no-r32 +31995 0/imm32/no-imm32 +31996 0/imm32/no-imm8 +31997 0/imm32/no-disp32 +31998 0/imm32/no-xm32 +31999 0/imm32/no-x32 +32000 0x11/imm32/alloc-id:fake +32001 _Primitive-multiply-reg-by-reg/imm32/next +32002 # - multiply +32003 _Primitive-multiply-reg-by-reg: # (payload primitive) +32004 0x11/imm32/alloc-id:fake:payload +32005 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 32006 0x11/imm32/alloc-id:fake -32007 _Primitive-convert-xreg-to-reg/imm32/next -32008 _Primitive-convert-xreg-to-reg: # (payload primitive) -32009 0x11/imm32/alloc-id:fake:payload -32010 # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32 -32011 0x11/imm32/alloc-id:fake -32012 _string-convert/imm32/name -32013 0x11/imm32/alloc-id:fake -32014 Single-float-var-in-some-register/imm32/inouts -32015 0x11/imm32/alloc-id:fake -32016 Single-int-var-in-some-register/imm32/outputs -32017 0x11/imm32/alloc-id:fake -32018 _string_f3_0f_2d_convert_to_int/imm32/subx-name -32019 0/imm32/no-rm32 -32020 3/imm32/r32-is-first-output -32021 0/imm32/no-imm32 -32022 0/imm32/no-imm8 -32023 0/imm32/no-disp32 -32024 1/imm32/xm32-is-first-inout -32025 0/imm32/no-x32 +32007 _string-multiply/imm32/name +32008 0x11/imm32/alloc-id:fake +32009 Single-int-var-in-some-register/imm32/inouts +32010 0x11/imm32/alloc-id:fake +32011 Single-int-var-in-some-register/imm32/outputs +32012 0x11/imm32/alloc-id:fake +32013 _string_0f_af_multiply/imm32/subx-name +32014 1/imm32/rm32-is-first-inout +32015 3/imm32/r32-is-first-output +32016 0/imm32/no-imm32 +32017 0/imm32/no-imm8 +32018 0/imm32/no-disp32 +32019 0/imm32/no-xm32 +32020 0/imm32/no-x32 +32021 0x11/imm32/alloc-id:fake +32022 _Primitive-multiply-reg-by-mem/imm32/next +32023 _Primitive-multiply-reg-by-mem: # (payload primitive) +32024 0x11/imm32/alloc-id:fake:payload +32025 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 32026 0x11/imm32/alloc-id:fake -32027 _Primitive-truncate-xmem-to-reg/imm32/next -32028 _Primitive-truncate-xmem-to-reg: # (payload primitive) -32029 0x11/imm32/alloc-id:fake:payload -32030 # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32 -32031 0x11/imm32/alloc-id:fake -32032 _string-truncate/imm32/name -32033 0x11/imm32/alloc-id:fake -32034 Single-float-var-in-mem/imm32/inouts -32035 0x11/imm32/alloc-id:fake -32036 Single-int-var-in-some-register/imm32/outputs -32037 0x11/imm32/alloc-id:fake -32038 _string_f3_0f_2c_truncate_to_int/imm32/subx-name -32039 0/imm32/no-rm32 -32040 3/imm32/r32-is-first-output -32041 0/imm32/no-imm32 -32042 0/imm32/no-imm8 -32043 0/imm32/no-disp32 -32044 1/imm32/xm32-is-first-inout -32045 0/imm32/no-x32 -32046 0x11/imm32/alloc-id:fake -32047 _Primitive-truncate-xreg-to-reg/imm32/next -32048 _Primitive-truncate-xreg-to-reg: # (payload primitive) -32049 0x11/imm32/alloc-id:fake:payload -32050 # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32 +32027 _string-multiply/imm32/name +32028 0x11/imm32/alloc-id:fake +32029 Single-int-var-in-mem/imm32/inouts +32030 0x11/imm32/alloc-id:fake +32031 Single-int-var-in-some-register/imm32/outputs +32032 0x11/imm32/alloc-id:fake +32033 _string_0f_af_multiply/imm32/subx-name +32034 1/imm32/rm32-is-first-inout +32035 3/imm32/r32-is-first-output +32036 0/imm32/no-imm32 +32037 0/imm32/no-imm8 +32038 0/imm32/no-disp32 +32039 0/imm32/no-xm32 +32040 0/imm32/no-x32 +32041 0x11/imm32/alloc-id:fake +32042 _Primitive-convert-mem-to-xreg/imm32/next +32043 # - convert int to floating point +32044 _Primitive-convert-mem-to-xreg: # (payload primitive) +32045 0x11/imm32/alloc-id:fake:payload +32046 # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32 +32047 0x11/imm32/alloc-id:fake +32048 _string-convert/imm32/name +32049 0x11/imm32/alloc-id:fake +32050 Single-int-var-in-mem/imm32/inouts 32051 0x11/imm32/alloc-id:fake -32052 _string-truncate/imm32/name +32052 Single-float-var-in-some-register/imm32/outputs 32053 0x11/imm32/alloc-id:fake -32054 Single-float-var-in-some-register/imm32/inouts -32055 0x11/imm32/alloc-id:fake -32056 Single-int-var-in-some-register/imm32/outputs -32057 0x11/imm32/alloc-id:fake -32058 _string_f3_0f_2c_truncate_to_int/imm32/subx-name -32059 0/imm32/no-rm32 -32060 3/imm32/r32-is-first-output -32061 0/imm32/no-imm32 -32062 0/imm32/no-imm8 -32063 0/imm32/no-disp32 -32064 1/imm32/xm32-is-first-inout -32065 0/imm32/no-x32 -32066 0x11/imm32/alloc-id:fake -32067 _Primitive-reinterpret-xmem-as-reg/imm32/next -32068 # - reinterpret bytes (just for debugging) -32069 _Primitive-reinterpret-xmem-as-reg: # (payload primitive) -32070 0x11/imm32/alloc-id:fake:payload -32071 # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32 -32072 0x11/imm32/alloc-id:fake -32073 _string-reinterpret/imm32/name -32074 0x11/imm32/alloc-id:fake -32075 Single-float-var-in-mem/imm32/inouts -32076 0x11/imm32/alloc-id:fake -32077 Single-int-var-in-some-register/imm32/outputs -32078 0x11/imm32/alloc-id:fake -32079 _string_8b_->/imm32/subx-name -32080 0/imm32/no-rm32 -32081 3/imm32/r32-is-first-output -32082 0/imm32/no-imm32 -32083 0/imm32/no-imm8 -32084 0/imm32/no-disp32 -32085 1/imm32/xm32-is-first-inout -32086 0/imm32/no-x32 -32087 0x11/imm32/alloc-id:fake -32088 _Primitive-reinterpret-mem-as-xreg/imm32/next -32089 _Primitive-reinterpret-mem-as-xreg: # (payload primitive) -32090 0x11/imm32/alloc-id:fake:payload -32091 # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32 +32054 _string_f3_0f_2a_convert_to_float/imm32/subx-name +32055 1/imm32/rm32-is-first-inout +32056 0/imm32/no-r32 +32057 0/imm32/no-imm32 +32058 0/imm32/no-imm8 +32059 0/imm32/no-disp32 +32060 0/imm32/no-xm32 +32061 3/imm32/x32-is-first-output +32062 0x11/imm32/alloc-id:fake +32063 _Primitive-convert-reg-to-xreg/imm32/next +32064 _Primitive-convert-reg-to-xreg: # (payload primitive) +32065 0x11/imm32/alloc-id:fake:payload +32066 # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32 +32067 0x11/imm32/alloc-id:fake +32068 _string-convert/imm32/name +32069 0x11/imm32/alloc-id:fake +32070 Single-int-var-in-some-register/imm32/inouts +32071 0x11/imm32/alloc-id:fake +32072 Single-float-var-in-some-register/imm32/outputs +32073 0x11/imm32/alloc-id:fake +32074 _string_f3_0f_2a_convert_to_float/imm32/subx-name +32075 1/imm32/rm32-is-first-inout +32076 0/imm32/no-r32 +32077 0/imm32/no-imm32 +32078 0/imm32/no-imm8 +32079 0/imm32/no-disp32 +32080 0/imm32/no-xm32 +32081 3/imm32/x32-is-first-output +32082 0x11/imm32/alloc-id:fake +32083 _Primitive-convert-xmem-to-reg/imm32/next +32084 # - convert floating point to int +32085 _Primitive-convert-xmem-to-reg: # (payload primitive) +32086 0x11/imm32/alloc-id:fake:payload +32087 # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32 +32088 0x11/imm32/alloc-id:fake +32089 _string-convert/imm32/name +32090 0x11/imm32/alloc-id:fake +32091 Single-float-var-in-mem/imm32/inouts 32092 0x11/imm32/alloc-id:fake -32093 _string-reinterpret/imm32/name +32093 Single-int-var-in-some-register/imm32/outputs 32094 0x11/imm32/alloc-id:fake -32095 Single-int-var-in-mem/imm32/inouts -32096 0x11/imm32/alloc-id:fake -32097 Single-float-var-in-some-register/imm32/outputs -32098 0x11/imm32/alloc-id:fake -32099 _string_f3_0f_10_copy/imm32/subx-name -32100 1/imm32/rm32-is-first-inout -32101 0/imm32/no-r32 -32102 0/imm32/no-imm32 -32103 0/imm32/no-imm8 -32104 0/imm32/no-disp32 -32105 0/imm32/no-xm32 -32106 3/imm32/x32-is-first-output -32107 0x11/imm32/alloc-id:fake -32108 _Primitive-copy-xreg-to-xreg/imm32/next -32109 # - floating-point copy -32110 _Primitive-copy-xreg-to-xreg: # (payload primitive) -32111 0x11/imm32/alloc-id:fake:payload -32112 # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32 -32113 0x11/imm32/alloc-id:fake -32114 _string-copy/imm32/name -32115 0x11/imm32/alloc-id:fake -32116 Single-float-var-in-some-register/imm32/inouts -32117 0x11/imm32/alloc-id:fake -32118 Single-float-var-in-some-register/imm32/outputs -32119 0x11/imm32/alloc-id:fake -32120 _string_f3_0f_11_copy/imm32/subx-name -32121 0/imm32/no-rm32 -32122 0/imm32/no-r32 -32123 0/imm32/no-imm32 -32124 0/imm32/no-imm8 -32125 0/imm32/no-disp32 -32126 3/imm32/xm32-is-first-output -32127 1/imm32/x32-is-first-inout +32095 _string_f3_0f_2d_convert_to_int/imm32/subx-name +32096 0/imm32/no-rm32 +32097 3/imm32/r32-is-first-output +32098 0/imm32/no-imm32 +32099 0/imm32/no-imm8 +32100 0/imm32/no-disp32 +32101 1/imm32/xm32-is-first-inout +32102 0/imm32/no-x32 +32103 0x11/imm32/alloc-id:fake +32104 _Primitive-convert-xreg-to-reg/imm32/next +32105 _Primitive-convert-xreg-to-reg: # (payload primitive) +32106 0x11/imm32/alloc-id:fake:payload +32107 # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32 +32108 0x11/imm32/alloc-id:fake +32109 _string-convert/imm32/name +32110 0x11/imm32/alloc-id:fake +32111 Single-float-var-in-some-register/imm32/inouts +32112 0x11/imm32/alloc-id:fake +32113 Single-int-var-in-some-register/imm32/outputs +32114 0x11/imm32/alloc-id:fake +32115 _string_f3_0f_2d_convert_to_int/imm32/subx-name +32116 0/imm32/no-rm32 +32117 3/imm32/r32-is-first-output +32118 0/imm32/no-imm32 +32119 0/imm32/no-imm8 +32120 0/imm32/no-disp32 +32121 1/imm32/xm32-is-first-inout +32122 0/imm32/no-x32 +32123 0x11/imm32/alloc-id:fake +32124 _Primitive-truncate-xmem-to-reg/imm32/next +32125 _Primitive-truncate-xmem-to-reg: # (payload primitive) +32126 0x11/imm32/alloc-id:fake:payload +32127 # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32 32128 0x11/imm32/alloc-id:fake -32129 _Primitive-copy-xreg-to-mem/imm32/next -32130 _Primitive-copy-xreg-to-mem: # (payload primitive) -32131 0x11/imm32/alloc-id:fake:payload -32132 # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32 -32133 0x11/imm32/alloc-id:fake -32134 _string-copy-to/imm32/name -32135 0x11/imm32/alloc-id:fake -32136 Two-args-float-stack-float-reg/imm32/inouts -32137 0/imm32/no-outputs -32138 0/imm32/no-outputs -32139 0x11/imm32/alloc-id:fake -32140 _string_f3_0f_11_copy/imm32/subx-name -32141 0/imm32/no-rm32 -32142 0/imm32/no-r32 -32143 0/imm32/no-imm32 -32144 0/imm32/no-imm8 -32145 0/imm32/no-disp32 -32146 1/imm32/xm32-is-first-inout -32147 2/imm32/x32-is-second-inout +32129 _string-truncate/imm32/name +32130 0x11/imm32/alloc-id:fake +32131 Single-float-var-in-mem/imm32/inouts +32132 0x11/imm32/alloc-id:fake +32133 Single-int-var-in-some-register/imm32/outputs +32134 0x11/imm32/alloc-id:fake +32135 _string_f3_0f_2c_truncate_to_int/imm32/subx-name +32136 0/imm32/no-rm32 +32137 3/imm32/r32-is-first-output +32138 0/imm32/no-imm32 +32139 0/imm32/no-imm8 +32140 0/imm32/no-disp32 +32141 1/imm32/xm32-is-first-inout +32142 0/imm32/no-x32 +32143 0x11/imm32/alloc-id:fake +32144 _Primitive-truncate-xreg-to-reg/imm32/next +32145 _Primitive-truncate-xreg-to-reg: # (payload primitive) +32146 0x11/imm32/alloc-id:fake:payload +32147 # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32 32148 0x11/imm32/alloc-id:fake -32149 _Primitive-copy-mem-to-xreg/imm32/next -32150 _Primitive-copy-mem-to-xreg: # (payload primitive) -32151 0x11/imm32/alloc-id:fake:payload -32152 # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32 -32153 0x11/imm32/alloc-id:fake -32154 _string-copy/imm32/name -32155 0x11/imm32/alloc-id:fake -32156 Single-float-var-in-mem/imm32/inouts -32157 0x11/imm32/alloc-id:fake -32158 Single-float-var-in-some-register/imm32/outputs -32159 0x11/imm32/alloc-id:fake -32160 _string_f3_0f_10_copy/imm32/subx-name -32161 0/imm32/no-rm32 -32162 0/imm32/no-r32 -32163 0/imm32/no-imm32 -32164 0/imm32/no-imm8 -32165 0/imm32/no-disp32 -32166 1/imm32/xm32-is-first-inout -32167 3/imm32/x32-is-first-output -32168 0x11/imm32/alloc-id:fake -32169 _Primitive-address-of-xmem/imm32/next -32170 # - floating-point-address -32171 _Primitive-address-of-xmem: # (payload primitive) -32172 0x11/imm32/alloc-id:fake:payload -32173 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 -32174 0x11/imm32/alloc-id:fake -32175 _string-address/imm32/name -32176 0x11/imm32/alloc-id:fake -32177 Single-float-var-in-mem/imm32/inouts -32178 0x11/imm32/alloc-id:fake -32179 Single-addr-var-in-some-register/imm32/outputs -32180 0x11/imm32/alloc-id:fake -32181 _string_8d_copy_address/imm32/subx-name -32182 1/imm32/rm32-is-first-inout -32183 3/imm32/r32-is-first-output -32184 0/imm32/no-imm32 -32185 0/imm32/no-imm8 -32186 0/imm32/no-disp32 -32187 0/imm32/no-xm32 -32188 0/imm32/no-x32 +32149 _string-truncate/imm32/name +32150 0x11/imm32/alloc-id:fake +32151 Single-float-var-in-some-register/imm32/inouts +32152 0x11/imm32/alloc-id:fake +32153 Single-int-var-in-some-register/imm32/outputs +32154 0x11/imm32/alloc-id:fake +32155 _string_f3_0f_2c_truncate_to_int/imm32/subx-name +32156 0/imm32/no-rm32 +32157 3/imm32/r32-is-first-output +32158 0/imm32/no-imm32 +32159 0/imm32/no-imm8 +32160 0/imm32/no-disp32 +32161 1/imm32/xm32-is-first-inout +32162 0/imm32/no-x32 +32163 0x11/imm32/alloc-id:fake +32164 _Primitive-reinterpret-xmem-as-reg/imm32/next +32165 # - reinterpret bytes (just for debugging) +32166 _Primitive-reinterpret-xmem-as-reg: # (payload primitive) +32167 0x11/imm32/alloc-id:fake:payload +32168 # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32 +32169 0x11/imm32/alloc-id:fake +32170 _string-reinterpret/imm32/name +32171 0x11/imm32/alloc-id:fake +32172 Single-float-var-in-mem/imm32/inouts +32173 0x11/imm32/alloc-id:fake +32174 Single-int-var-in-some-register/imm32/outputs +32175 0x11/imm32/alloc-id:fake +32176 _string_8b_->/imm32/subx-name +32177 0/imm32/no-rm32 +32178 3/imm32/r32-is-first-output +32179 0/imm32/no-imm32 +32180 0/imm32/no-imm8 +32181 0/imm32/no-disp32 +32182 1/imm32/xm32-is-first-inout +32183 0/imm32/no-x32 +32184 0x11/imm32/alloc-id:fake +32185 _Primitive-reinterpret-mem-as-xreg/imm32/next +32186 _Primitive-reinterpret-mem-as-xreg: # (payload primitive) +32187 0x11/imm32/alloc-id:fake:payload +32188 # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32 32189 0x11/imm32/alloc-id:fake -32190 _Primitive-add-xreg-to-xreg/imm32/next -32191 # - floating-point add -32192 _Primitive-add-xreg-to-xreg: # (payload primitive) -32193 0x11/imm32/alloc-id:fake:payload -32194 # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32 +32190 _string-reinterpret/imm32/name +32191 0x11/imm32/alloc-id:fake +32192 Single-int-var-in-mem/imm32/inouts +32193 0x11/imm32/alloc-id:fake +32194 Single-float-var-in-some-register/imm32/outputs 32195 0x11/imm32/alloc-id:fake -32196 _string-add/imm32/name -32197 0x11/imm32/alloc-id:fake -32198 Single-float-var-in-some-register/imm32/inouts -32199 0x11/imm32/alloc-id:fake -32200 Single-float-var-in-some-register/imm32/outputs -32201 0x11/imm32/alloc-id:fake -32202 _string_f3_0f_58_add/imm32/subx-name -32203 0/imm32/no-rm32 -32204 0/imm32/no-r32 -32205 0/imm32/no-imm32 -32206 0/imm32/no-imm8 -32207 0/imm32/no-disp32 -32208 1/imm32/xm32-is-first-inout -32209 3/imm32/x32-is-first-output +32196 _string_f3_0f_10_copy/imm32/subx-name +32197 1/imm32/rm32-is-first-inout +32198 0/imm32/no-r32 +32199 0/imm32/no-imm32 +32200 0/imm32/no-imm8 +32201 0/imm32/no-disp32 +32202 0/imm32/no-xm32 +32203 3/imm32/x32-is-first-output +32204 0x11/imm32/alloc-id:fake +32205 _Primitive-copy-xreg-to-xreg/imm32/next +32206 # - floating-point copy +32207 _Primitive-copy-xreg-to-xreg: # (payload primitive) +32208 0x11/imm32/alloc-id:fake:payload +32209 # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32 32210 0x11/imm32/alloc-id:fake -32211 _Primitive-add-mem-to-xreg/imm32/next -32212 _Primitive-add-mem-to-xreg: # (payload primitive) -32213 0x11/imm32/alloc-id:fake:payload -32214 # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32 -32215 0x11/imm32/alloc-id:fake -32216 _string-add/imm32/name -32217 0x11/imm32/alloc-id:fake -32218 Single-float-var-in-mem/imm32/inouts -32219 0x11/imm32/alloc-id:fake -32220 Single-float-var-in-some-register/imm32/outputs -32221 0x11/imm32/alloc-id:fake -32222 _string_f3_0f_58_add/imm32/subx-name -32223 0/imm32/no-rm32 -32224 0/imm32/no-r32 -32225 0/imm32/no-imm32 -32226 0/imm32/no-imm8 -32227 0/imm32/no-disp32 -32228 1/imm32/xm32-is-first-inout -32229 3/imm32/x32-is-first-output +32211 _string-copy/imm32/name +32212 0x11/imm32/alloc-id:fake +32213 Single-float-var-in-some-register/imm32/inouts +32214 0x11/imm32/alloc-id:fake +32215 Single-float-var-in-some-register/imm32/outputs +32216 0x11/imm32/alloc-id:fake +32217 _string_f3_0f_11_copy/imm32/subx-name +32218 0/imm32/no-rm32 +32219 0/imm32/no-r32 +32220 0/imm32/no-imm32 +32221 0/imm32/no-imm8 +32222 0/imm32/no-disp32 +32223 3/imm32/xm32-is-first-output +32224 1/imm32/x32-is-first-inout +32225 0x11/imm32/alloc-id:fake +32226 _Primitive-copy-xreg-to-mem/imm32/next +32227 _Primitive-copy-xreg-to-mem: # (payload primitive) +32228 0x11/imm32/alloc-id:fake:payload +32229 # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32 32230 0x11/imm32/alloc-id:fake -32231 _Primitive-subtract-xreg-from-xreg/imm32/next -32232 # - floating-point subtract -32233 _Primitive-subtract-xreg-from-xreg: # (payload primitive) -32234 0x11/imm32/alloc-id:fake:payload -32235 # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32 +32231 _string-copy-to/imm32/name +32232 0x11/imm32/alloc-id:fake +32233 Two-args-float-stack-float-reg/imm32/inouts +32234 0/imm32/no-outputs +32235 0/imm32/no-outputs 32236 0x11/imm32/alloc-id:fake -32237 _string-subtract/imm32/name -32238 0x11/imm32/alloc-id:fake -32239 Single-float-var-in-some-register/imm32/inouts -32240 0x11/imm32/alloc-id:fake -32241 Single-float-var-in-some-register/imm32/outputs -32242 0x11/imm32/alloc-id:fake -32243 _string_f3_0f_5c_subtract/imm32/subx-name -32244 0/imm32/no-rm32 -32245 0/imm32/no-r32 -32246 0/imm32/no-imm32 -32247 0/imm32/no-imm8 -32248 0/imm32/no-disp32 -32249 1/imm32/xm32-is-first-inout -32250 3/imm32/x32-is-first-output -32251 0x11/imm32/alloc-id:fake -32252 _Primitive-subtract-mem-from-xreg/imm32/next -32253 _Primitive-subtract-mem-from-xreg: # (payload primitive) -32254 0x11/imm32/alloc-id:fake:payload -32255 # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32 +32237 _string_f3_0f_11_copy/imm32/subx-name +32238 0/imm32/no-rm32 +32239 0/imm32/no-r32 +32240 0/imm32/no-imm32 +32241 0/imm32/no-imm8 +32242 0/imm32/no-disp32 +32243 1/imm32/xm32-is-first-inout +32244 2/imm32/x32-is-second-inout +32245 0x11/imm32/alloc-id:fake +32246 _Primitive-copy-mem-to-xreg/imm32/next +32247 _Primitive-copy-mem-to-xreg: # (payload primitive) +32248 0x11/imm32/alloc-id:fake:payload +32249 # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32 +32250 0x11/imm32/alloc-id:fake +32251 _string-copy/imm32/name +32252 0x11/imm32/alloc-id:fake +32253 Single-float-var-in-mem/imm32/inouts +32254 0x11/imm32/alloc-id:fake +32255 Single-float-var-in-some-register/imm32/outputs 32256 0x11/imm32/alloc-id:fake -32257 _string-subtract/imm32/name -32258 0x11/imm32/alloc-id:fake -32259 Single-float-var-in-mem/imm32/inouts -32260 0x11/imm32/alloc-id:fake -32261 Single-float-var-in-some-register/imm32/outputs -32262 0x11/imm32/alloc-id:fake -32263 _string_f3_0f_5c_subtract/imm32/subx-name -32264 0/imm32/no-rm32 -32265 0/imm32/no-r32 -32266 0/imm32/no-imm32 -32267 0/imm32/no-imm8 -32268 0/imm32/no-disp32 -32269 1/imm32/xm32-is-first-inout -32270 3/imm32/x32-is-first-output +32257 _string_f3_0f_10_copy/imm32/subx-name +32258 0/imm32/no-rm32 +32259 0/imm32/no-r32 +32260 0/imm32/no-imm32 +32261 0/imm32/no-imm8 +32262 0/imm32/no-disp32 +32263 1/imm32/xm32-is-first-inout +32264 3/imm32/x32-is-first-output +32265 0x11/imm32/alloc-id:fake +32266 _Primitive-address-of-xmem/imm32/next +32267 # - floating-point-address +32268 _Primitive-address-of-xmem: # (payload primitive) +32269 0x11/imm32/alloc-id:fake:payload +32270 # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32 32271 0x11/imm32/alloc-id:fake -32272 _Primitive-multiply-xreg-by-xreg/imm32/next -32273 # - floating-point multiply -32274 _Primitive-multiply-xreg-by-xreg: # (payload primitive) -32275 0x11/imm32/alloc-id:fake:payload -32276 # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32 +32272 _string-address/imm32/name +32273 0x11/imm32/alloc-id:fake +32274 Single-float-var-in-mem/imm32/inouts +32275 0x11/imm32/alloc-id:fake +32276 Single-addr-var-in-some-register/imm32/outputs 32277 0x11/imm32/alloc-id:fake -32278 _string-multiply/imm32/name -32279 0x11/imm32/alloc-id:fake -32280 Single-float-var-in-some-register/imm32/inouts -32281 0x11/imm32/alloc-id:fake -32282 Single-float-var-in-some-register/imm32/outputs -32283 0x11/imm32/alloc-id:fake -32284 _string_f3_0f_59_multiply/imm32/subx-name -32285 0/imm32/no-rm32 -32286 0/imm32/no-r32 -32287 0/imm32/no-imm32 -32288 0/imm32/no-imm8 -32289 0/imm32/no-disp32 -32290 1/imm32/xm32-is-first-inout -32291 3/imm32/x32-is-first-output +32278 _string_8d_copy_address/imm32/subx-name +32279 1/imm32/rm32-is-first-inout +32280 3/imm32/r32-is-first-output +32281 0/imm32/no-imm32 +32282 0/imm32/no-imm8 +32283 0/imm32/no-disp32 +32284 0/imm32/no-xm32 +32285 0/imm32/no-x32 +32286 0x11/imm32/alloc-id:fake +32287 _Primitive-add-xreg-to-xreg/imm32/next +32288 # - floating-point add +32289 _Primitive-add-xreg-to-xreg: # (payload primitive) +32290 0x11/imm32/alloc-id:fake:payload +32291 # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32 32292 0x11/imm32/alloc-id:fake -32293 _Primitive-multiply-xreg-by-mem/imm32/next -32294 _Primitive-multiply-xreg-by-mem: # (payload primitive) -32295 0x11/imm32/alloc-id:fake:payload -32296 # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32 -32297 0x11/imm32/alloc-id:fake -32298 _string-multiply/imm32/name -32299 0x11/imm32/alloc-id:fake -32300 Single-float-var-in-mem/imm32/inouts -32301 0x11/imm32/alloc-id:fake -32302 Single-float-var-in-some-register/imm32/outputs -32303 0x11/imm32/alloc-id:fake -32304 _string_f3_0f_59_multiply/imm32/subx-name -32305 0/imm32/no-rm32 -32306 0/imm32/no-r32 -32307 0/imm32/no-imm32 -32308 0/imm32/no-imm8 -32309 0/imm32/no-disp32 -32310 1/imm32/xm32-is-first-inout -32311 3/imm32/x32-is-first-output +32293 _string-add/imm32/name +32294 0x11/imm32/alloc-id:fake +32295 Single-float-var-in-some-register/imm32/inouts +32296 0x11/imm32/alloc-id:fake +32297 Single-float-var-in-some-register/imm32/outputs +32298 0x11/imm32/alloc-id:fake +32299 _string_f3_0f_58_add/imm32/subx-name +32300 0/imm32/no-rm32 +32301 0/imm32/no-r32 +32302 0/imm32/no-imm32 +32303 0/imm32/no-imm8 +32304 0/imm32/no-disp32 +32305 1/imm32/xm32-is-first-inout +32306 3/imm32/x32-is-first-output +32307 0x11/imm32/alloc-id:fake +32308 _Primitive-add-mem-to-xreg/imm32/next +32309 _Primitive-add-mem-to-xreg: # (payload primitive) +32310 0x11/imm32/alloc-id:fake:payload +32311 # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32 32312 0x11/imm32/alloc-id:fake -32313 _Primitive-divide-xreg-by-xreg/imm32/next -32314 # - floating-point divide -32315 _Primitive-divide-xreg-by-xreg: # (payload primitive) -32316 0x11/imm32/alloc-id:fake:payload -32317 # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32 +32313 _string-add/imm32/name +32314 0x11/imm32/alloc-id:fake +32315 Single-float-var-in-mem/imm32/inouts +32316 0x11/imm32/alloc-id:fake +32317 Single-float-var-in-some-register/imm32/outputs 32318 0x11/imm32/alloc-id:fake -32319 _string-divide/imm32/name -32320 0x11/imm32/alloc-id:fake -32321 Single-float-var-in-some-register/imm32/inouts -32322 0x11/imm32/alloc-id:fake -32323 Single-float-var-in-some-register/imm32/outputs -32324 0x11/imm32/alloc-id:fake -32325 _string_f3_0f_5e_divide/imm32/subx-name -32326 0/imm32/no-rm32 -32327 0/imm32/no-r32 -32328 0/imm32/no-imm32 -32329 0/imm32/no-imm8 -32330 0/imm32/no-disp32 -32331 1/imm32/xm32-is-first-inout -32332 3/imm32/x32-is-first-output +32319 _string_f3_0f_58_add/imm32/subx-name +32320 0/imm32/no-rm32 +32321 0/imm32/no-r32 +32322 0/imm32/no-imm32 +32323 0/imm32/no-imm8 +32324 0/imm32/no-disp32 +32325 1/imm32/xm32-is-first-inout +32326 3/imm32/x32-is-first-output +32327 0x11/imm32/alloc-id:fake +32328 _Primitive-subtract-xreg-from-xreg/imm32/next +32329 # - floating-point subtract +32330 _Primitive-subtract-xreg-from-xreg: # (payload primitive) +32331 0x11/imm32/alloc-id:fake:payload +32332 # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32 32333 0x11/imm32/alloc-id:fake -32334 _Primitive-divide-xreg-by-mem/imm32/next -32335 _Primitive-divide-xreg-by-mem: # (payload primitive) -32336 0x11/imm32/alloc-id:fake:payload -32337 # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32 -32338 0x11/imm32/alloc-id:fake -32339 _string-divide/imm32/name -32340 0x11/imm32/alloc-id:fake -32341 Single-float-var-in-mem/imm32/inouts -32342 0x11/imm32/alloc-id:fake -32343 Single-float-var-in-some-register/imm32/outputs -32344 0x11/imm32/alloc-id:fake -32345 _string_f3_0f_5e_divide/imm32/subx-name -32346 0/imm32/no-rm32 -32347 0/imm32/no-r32 -32348 0/imm32/no-imm32 -32349 0/imm32/no-imm8 -32350 0/imm32/no-disp32 -32351 1/imm32/xm32-is-first-inout -32352 3/imm32/x32-is-first-output +32334 _string-subtract/imm32/name +32335 0x11/imm32/alloc-id:fake +32336 Single-float-var-in-some-register/imm32/inouts +32337 0x11/imm32/alloc-id:fake +32338 Single-float-var-in-some-register/imm32/outputs +32339 0x11/imm32/alloc-id:fake +32340 _string_f3_0f_5c_subtract/imm32/subx-name +32341 0/imm32/no-rm32 +32342 0/imm32/no-r32 +32343 0/imm32/no-imm32 +32344 0/imm32/no-imm8 +32345 0/imm32/no-disp32 +32346 1/imm32/xm32-is-first-inout +32347 3/imm32/x32-is-first-output +32348 0x11/imm32/alloc-id:fake +32349 _Primitive-subtract-mem-from-xreg/imm32/next +32350 _Primitive-subtract-mem-from-xreg: # (payload primitive) +32351 0x11/imm32/alloc-id:fake:payload +32352 # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32 32353 0x11/imm32/alloc-id:fake -32354 _Primitive-max-xreg-with-xreg/imm32/next -32355 # - floating-point maximum -32356 _Primitive-max-xreg-with-xreg: # (payload primitive) -32357 0x11/imm32/alloc-id:fake:payload -32358 # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32 +32354 _string-subtract/imm32/name +32355 0x11/imm32/alloc-id:fake +32356 Single-float-var-in-mem/imm32/inouts +32357 0x11/imm32/alloc-id:fake +32358 Single-float-var-in-some-register/imm32/outputs 32359 0x11/imm32/alloc-id:fake -32360 _string-max/imm32/name -32361 0x11/imm32/alloc-id:fake -32362 Single-float-var-in-some-register/imm32/inouts -32363 0x11/imm32/alloc-id:fake -32364 Single-float-var-in-some-register/imm32/outputs -32365 0x11/imm32/alloc-id:fake -32366 _string_f3_0f_5f_max/imm32/subx-name -32367 0/imm32/no-rm32 -32368 0/imm32/no-r32 -32369 0/imm32/no-imm32 -32370 0/imm32/no-imm8 -32371 0/imm32/no-disp32 -32372 1/imm32/xm32-is-first-inout -32373 3/imm32/x32-is-first-output +32360 _string_f3_0f_5c_subtract/imm32/subx-name +32361 0/imm32/no-rm32 +32362 0/imm32/no-r32 +32363 0/imm32/no-imm32 +32364 0/imm32/no-imm8 +32365 0/imm32/no-disp32 +32366 1/imm32/xm32-is-first-inout +32367 3/imm32/x32-is-first-output +32368 0x11/imm32/alloc-id:fake +32369 _Primitive-multiply-xreg-by-xreg/imm32/next +32370 # - floating-point multiply +32371 _Primitive-multiply-xreg-by-xreg: # (payload primitive) +32372 0x11/imm32/alloc-id:fake:payload +32373 # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32 32374 0x11/imm32/alloc-id:fake -32375 _Primitive-max-xreg-with-mem/imm32/next -32376 _Primitive-max-xreg-with-mem: # (payload primitive) -32377 0x11/imm32/alloc-id:fake:payload -32378 # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32 -32379 0x11/imm32/alloc-id:fake -32380 _string-max/imm32/name -32381 0x11/imm32/alloc-id:fake -32382 Single-float-var-in-mem/imm32/inouts -32383 0x11/imm32/alloc-id:fake -32384 Single-float-var-in-some-register/imm32/outputs -32385 0x11/imm32/alloc-id:fake -32386 _string_f3_0f_5f_max/imm32/subx-name -32387 0/imm32/no-rm32 -32388 0/imm32/no-r32 -32389 0/imm32/no-imm32 -32390 0/imm32/no-imm8 -32391 0/imm32/no-disp32 -32392 1/imm32/xm32-is-first-inout -32393 3/imm32/x32-is-first-output +32375 _string-multiply/imm32/name +32376 0x11/imm32/alloc-id:fake +32377 Single-float-var-in-some-register/imm32/inouts +32378 0x11/imm32/alloc-id:fake +32379 Single-float-var-in-some-register/imm32/outputs +32380 0x11/imm32/alloc-id:fake +32381 _string_f3_0f_59_multiply/imm32/subx-name +32382 0/imm32/no-rm32 +32383 0/imm32/no-r32 +32384 0/imm32/no-imm32 +32385 0/imm32/no-imm8 +32386 0/imm32/no-disp32 +32387 1/imm32/xm32-is-first-inout +32388 3/imm32/x32-is-first-output +32389 0x11/imm32/alloc-id:fake +32390 _Primitive-multiply-xreg-by-mem/imm32/next +32391 _Primitive-multiply-xreg-by-mem: # (payload primitive) +32392 0x11/imm32/alloc-id:fake:payload +32393 # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32 32394 0x11/imm32/alloc-id:fake -32395 _Primitive-min-xreg-with-xreg/imm32/next -32396 # - floating-point minimum -32397 _Primitive-min-xreg-with-xreg: # (payload primitive) -32398 0x11/imm32/alloc-id:fake:payload -32399 # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32 +32395 _string-multiply/imm32/name +32396 0x11/imm32/alloc-id:fake +32397 Single-float-var-in-mem/imm32/inouts +32398 0x11/imm32/alloc-id:fake +32399 Single-float-var-in-some-register/imm32/outputs 32400 0x11/imm32/alloc-id:fake -32401 _string-min/imm32/name -32402 0x11/imm32/alloc-id:fake -32403 Single-float-var-in-some-register/imm32/inouts -32404 0x11/imm32/alloc-id:fake -32405 Single-float-var-in-some-register/imm32/outputs -32406 0x11/imm32/alloc-id:fake -32407 _string_f3_0f_5d_min/imm32/subx-name -32408 0/imm32/no-rm32 -32409 0/imm32/no-r32 -32410 0/imm32/no-imm32 -32411 0/imm32/no-imm8 -32412 0/imm32/no-disp32 -32413 1/imm32/xm32-is-first-inout -32414 3/imm32/x32-is-first-output +32401 _string_f3_0f_59_multiply/imm32/subx-name +32402 0/imm32/no-rm32 +32403 0/imm32/no-r32 +32404 0/imm32/no-imm32 +32405 0/imm32/no-imm8 +32406 0/imm32/no-disp32 +32407 1/imm32/xm32-is-first-inout +32408 3/imm32/x32-is-first-output +32409 0x11/imm32/alloc-id:fake +32410 _Primitive-divide-xreg-by-xreg/imm32/next +32411 # - floating-point divide +32412 _Primitive-divide-xreg-by-xreg: # (payload primitive) +32413 0x11/imm32/alloc-id:fake:payload +32414 # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32 32415 0x11/imm32/alloc-id:fake -32416 _Primitive-min-xreg-with-mem/imm32/next -32417 _Primitive-min-xreg-with-mem: # (payload primitive) -32418 0x11/imm32/alloc-id:fake:payload -32419 # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32 -32420 0x11/imm32/alloc-id:fake -32421 _string-min/imm32/name -32422 0x11/imm32/alloc-id:fake -32423 Single-float-var-in-mem/imm32/inouts -32424 0x11/imm32/alloc-id:fake -32425 Single-float-var-in-some-register/imm32/outputs -32426 0x11/imm32/alloc-id:fake -32427 _string_f3_0f_5d_min/imm32/subx-name -32428 0/imm32/no-rm32 -32429 0/imm32/no-r32 -32430 0/imm32/no-imm32 -32431 0/imm32/no-imm8 -32432 0/imm32/no-disp32 -32433 1/imm32/xm32-is-first-inout -32434 3/imm32/x32-is-first-output +32416 _string-divide/imm32/name +32417 0x11/imm32/alloc-id:fake +32418 Single-float-var-in-some-register/imm32/inouts +32419 0x11/imm32/alloc-id:fake +32420 Single-float-var-in-some-register/imm32/outputs +32421 0x11/imm32/alloc-id:fake +32422 _string_f3_0f_5e_divide/imm32/subx-name +32423 0/imm32/no-rm32 +32424 0/imm32/no-r32 +32425 0/imm32/no-imm32 +32426 0/imm32/no-imm8 +32427 0/imm32/no-disp32 +32428 1/imm32/xm32-is-first-inout +32429 3/imm32/x32-is-first-output +32430 0x11/imm32/alloc-id:fake +32431 _Primitive-divide-xreg-by-mem/imm32/next +32432 _Primitive-divide-xreg-by-mem: # (payload primitive) +32433 0x11/imm32/alloc-id:fake:payload +32434 # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32 32435 0x11/imm32/alloc-id:fake -32436 _Primitive-reciprocal-xreg-to-xreg/imm32/next -32437 # - floating-point reciprocal -32438 _Primitive-reciprocal-xreg-to-xreg: # (payload primitive) -32439 0x11/imm32/alloc-id:fake:payload -32440 # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32 +32436 _string-divide/imm32/name +32437 0x11/imm32/alloc-id:fake +32438 Single-float-var-in-mem/imm32/inouts +32439 0x11/imm32/alloc-id:fake +32440 Single-float-var-in-some-register/imm32/outputs 32441 0x11/imm32/alloc-id:fake -32442 _string-reciprocal/imm32/name -32443 0x11/imm32/alloc-id:fake -32444 Single-float-var-in-some-register/imm32/inouts -32445 0x11/imm32/alloc-id:fake -32446 Single-float-var-in-some-register/imm32/outputs -32447 0x11/imm32/alloc-id:fake -32448 _string_f3_0f_53_reciprocal/imm32/subx-name -32449 0/imm32/no-rm32 -32450 0/imm32/no-r32 -32451 0/imm32/no-imm32 -32452 0/imm32/no-imm8 -32453 0/imm32/no-disp32 -32454 1/imm32/xm32-is-first-inout -32455 3/imm32/x32-is-first-output +32442 _string_f3_0f_5e_divide/imm32/subx-name +32443 0/imm32/no-rm32 +32444 0/imm32/no-r32 +32445 0/imm32/no-imm32 +32446 0/imm32/no-imm8 +32447 0/imm32/no-disp32 +32448 1/imm32/xm32-is-first-inout +32449 3/imm32/x32-is-first-output +32450 0x11/imm32/alloc-id:fake +32451 _Primitive-max-xreg-with-xreg/imm32/next +32452 # - floating-point maximum +32453 _Primitive-max-xreg-with-xreg: # (payload primitive) +32454 0x11/imm32/alloc-id:fake:payload +32455 # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32 32456 0x11/imm32/alloc-id:fake -32457 _Primitive-reciprocal-mem-to-xreg/imm32/next -32458 _Primitive-reciprocal-mem-to-xreg: # (payload primitive) -32459 0x11/imm32/alloc-id:fake:payload -32460 # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32 -32461 0x11/imm32/alloc-id:fake -32462 _string-reciprocal/imm32/name -32463 0x11/imm32/alloc-id:fake -32464 Single-float-var-in-mem/imm32/inouts -32465 0x11/imm32/alloc-id:fake -32466 Single-float-var-in-some-register/imm32/outputs -32467 0x11/imm32/alloc-id:fake -32468 _string_f3_0f_53_reciprocal/imm32/subx-name -32469 0/imm32/no-rm32 -32470 0/imm32/no-r32 -32471 0/imm32/no-imm32 -32472 0/imm32/no-imm8 -32473 0/imm32/no-disp32 -32474 1/imm32/xm32-is-first-inout -32475 3/imm32/x32-is-first-output +32457 _string-max/imm32/name +32458 0x11/imm32/alloc-id:fake +32459 Single-float-var-in-some-register/imm32/inouts +32460 0x11/imm32/alloc-id:fake +32461 Single-float-var-in-some-register/imm32/outputs +32462 0x11/imm32/alloc-id:fake +32463 _string_f3_0f_5f_max/imm32/subx-name +32464 0/imm32/no-rm32 +32465 0/imm32/no-r32 +32466 0/imm32/no-imm32 +32467 0/imm32/no-imm8 +32468 0/imm32/no-disp32 +32469 1/imm32/xm32-is-first-inout +32470 3/imm32/x32-is-first-output +32471 0x11/imm32/alloc-id:fake +32472 _Primitive-max-xreg-with-mem/imm32/next +32473 _Primitive-max-xreg-with-mem: # (payload primitive) +32474 0x11/imm32/alloc-id:fake:payload +32475 # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32 32476 0x11/imm32/alloc-id:fake -32477 _Primitive-square-root-xreg-to-xreg/imm32/next -32478 # - floating-point square root -32479 _Primitive-square-root-xreg-to-xreg: # (payload primitive) -32480 0x11/imm32/alloc-id:fake:payload -32481 # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32 +32477 _string-max/imm32/name +32478 0x11/imm32/alloc-id:fake +32479 Single-float-var-in-mem/imm32/inouts +32480 0x11/imm32/alloc-id:fake +32481 Single-float-var-in-some-register/imm32/outputs 32482 0x11/imm32/alloc-id:fake -32483 _string-square-root/imm32/name -32484 0x11/imm32/alloc-id:fake -32485 Single-float-var-in-some-register/imm32/inouts -32486 0x11/imm32/alloc-id:fake -32487 Single-float-var-in-some-register/imm32/outputs -32488 0x11/imm32/alloc-id:fake -32489 _string_f3_0f_51_square_root/imm32/subx-name -32490 0/imm32/no-rm32 -32491 0/imm32/no-r32 -32492 0/imm32/no-imm32 -32493 0/imm32/no-imm8 -32494 0/imm32/no-disp32 -32495 1/imm32/xm32-is-first-inout -32496 3/imm32/x32-is-first-output +32483 _string_f3_0f_5f_max/imm32/subx-name +32484 0/imm32/no-rm32 +32485 0/imm32/no-r32 +32486 0/imm32/no-imm32 +32487 0/imm32/no-imm8 +32488 0/imm32/no-disp32 +32489 1/imm32/xm32-is-first-inout +32490 3/imm32/x32-is-first-output +32491 0x11/imm32/alloc-id:fake +32492 _Primitive-min-xreg-with-xreg/imm32/next +32493 # - floating-point minimum +32494 _Primitive-min-xreg-with-xreg: # (payload primitive) +32495 0x11/imm32/alloc-id:fake:payload +32496 # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32 32497 0x11/imm32/alloc-id:fake -32498 _Primitive-square-root-mem-to-xreg/imm32/next -32499 _Primitive-square-root-mem-to-xreg: # (payload primitive) -32500 0x11/imm32/alloc-id:fake:payload -32501 # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32 -32502 0x11/imm32/alloc-id:fake -32503 _string-square-root/imm32/name -32504 0x11/imm32/alloc-id:fake -32505 Single-float-var-in-mem/imm32/inouts -32506 0x11/imm32/alloc-id:fake -32507 Single-float-var-in-some-register/imm32/outputs -32508 0x11/imm32/alloc-id:fake -32509 _string_f3_0f_51_square_root/imm32/subx-name -32510 0/imm32/no-rm32 -32511 0/imm32/no-r32 -32512 0/imm32/no-imm32 -32513 0/imm32/no-imm8 -32514 0/imm32/no-disp32 -32515 1/imm32/xm32-is-first-inout -32516 3/imm32/x32-is-first-output +32498 _string-min/imm32/name +32499 0x11/imm32/alloc-id:fake +32500 Single-float-var-in-some-register/imm32/inouts +32501 0x11/imm32/alloc-id:fake +32502 Single-float-var-in-some-register/imm32/outputs +32503 0x11/imm32/alloc-id:fake +32504 _string_f3_0f_5d_min/imm32/subx-name +32505 0/imm32/no-rm32 +32506 0/imm32/no-r32 +32507 0/imm32/no-imm32 +32508 0/imm32/no-imm8 +32509 0/imm32/no-disp32 +32510 1/imm32/xm32-is-first-inout +32511 3/imm32/x32-is-first-output +32512 0x11/imm32/alloc-id:fake +32513 _Primitive-min-xreg-with-mem/imm32/next +32514 _Primitive-min-xreg-with-mem: # (payload primitive) +32515 0x11/imm32/alloc-id:fake:payload +32516 # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32 32517 0x11/imm32/alloc-id:fake -32518 _Primitive-inverse-square-root-xreg-to-xreg/imm32/next -32519 # - floating-point inverse square root 1/sqrt(x) -32520 _Primitive-inverse-square-root-xreg-to-xreg: # (payload primitive) -32521 0x11/imm32/alloc-id:fake:payload -32522 # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32 +32518 _string-min/imm32/name +32519 0x11/imm32/alloc-id:fake +32520 Single-float-var-in-mem/imm32/inouts +32521 0x11/imm32/alloc-id:fake +32522 Single-float-var-in-some-register/imm32/outputs 32523 0x11/imm32/alloc-id:fake -32524 _string-inverse-square-root/imm32/name -32525 0x11/imm32/alloc-id:fake -32526 Single-float-var-in-some-register/imm32/inouts -32527 0x11/imm32/alloc-id:fake -32528 Single-float-var-in-some-register/imm32/outputs -32529 0x11/imm32/alloc-id:fake -32530 _string_f3_0f_52_inverse_square_root/imm32/subx-name -32531 0/imm32/no-rm32 -32532 0/imm32/no-r32 -32533 0/imm32/no-imm32 -32534 0/imm32/no-imm8 -32535 0/imm32/no-disp32 -32536 1/imm32/xm32-is-first-inout -32537 3/imm32/x32-is-first-output +32524 _string_f3_0f_5d_min/imm32/subx-name +32525 0/imm32/no-rm32 +32526 0/imm32/no-r32 +32527 0/imm32/no-imm32 +32528 0/imm32/no-imm8 +32529 0/imm32/no-disp32 +32530 1/imm32/xm32-is-first-inout +32531 3/imm32/x32-is-first-output +32532 0x11/imm32/alloc-id:fake +32533 _Primitive-reciprocal-xreg-to-xreg/imm32/next +32534 # - floating-point reciprocal +32535 _Primitive-reciprocal-xreg-to-xreg: # (payload primitive) +32536 0x11/imm32/alloc-id:fake:payload +32537 # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32 32538 0x11/imm32/alloc-id:fake -32539 _Primitive-inverse-square-root-mem-to-xreg/imm32/next -32540 _Primitive-inverse-square-root-mem-to-xreg: # (payload primitive) -32541 0x11/imm32/alloc-id:fake:payload -32542 # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32 -32543 0x11/imm32/alloc-id:fake -32544 _string-inverse-square-root/imm32/name -32545 0x11/imm32/alloc-id:fake -32546 Single-float-var-in-mem/imm32/inouts -32547 0x11/imm32/alloc-id:fake -32548 Single-float-var-in-some-register/imm32/outputs -32549 0x11/imm32/alloc-id:fake -32550 _string_f3_0f_52_inverse_square_root/imm32/subx-name -32551 0/imm32/no-rm32 -32552 0/imm32/no-r32 -32553 0/imm32/no-imm32 -32554 0/imm32/no-imm8 -32555 0/imm32/no-disp32 -32556 1/imm32/xm32-is-first-inout -32557 3/imm32/x32-is-first-output +32539 _string-reciprocal/imm32/name +32540 0x11/imm32/alloc-id:fake +32541 Single-float-var-in-some-register/imm32/inouts +32542 0x11/imm32/alloc-id:fake +32543 Single-float-var-in-some-register/imm32/outputs +32544 0x11/imm32/alloc-id:fake +32545 _string_f3_0f_53_reciprocal/imm32/subx-name +32546 0/imm32/no-rm32 +32547 0/imm32/no-r32 +32548 0/imm32/no-imm32 +32549 0/imm32/no-imm8 +32550 0/imm32/no-disp32 +32551 1/imm32/xm32-is-first-inout +32552 3/imm32/x32-is-first-output +32553 0x11/imm32/alloc-id:fake +32554 _Primitive-reciprocal-mem-to-xreg/imm32/next +32555 _Primitive-reciprocal-mem-to-xreg: # (payload primitive) +32556 0x11/imm32/alloc-id:fake:payload +32557 # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32 32558 0x11/imm32/alloc-id:fake -32559 _Primitive-compare-xreg-with-xreg/imm32/next -32560 # - floating-point compare -32561 _Primitive-compare-xreg-with-xreg: # (payload primitive) -32562 0x11/imm32/alloc-id:fake:payload -32563 # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32 +32559 _string-reciprocal/imm32/name +32560 0x11/imm32/alloc-id:fake +32561 Single-float-var-in-mem/imm32/inouts +32562 0x11/imm32/alloc-id:fake +32563 Single-float-var-in-some-register/imm32/outputs 32564 0x11/imm32/alloc-id:fake -32565 _string-compare/imm32/name -32566 0x11/imm32/alloc-id:fake -32567 Two-float-args-in-regs/imm32/inouts -32568 0/imm32/no-outputs -32569 0/imm32/no-outputs -32570 0x11/imm32/alloc-id:fake -32571 _string_0f_2f_compare/imm32/subx-name -32572 0/imm32/no-rm32 -32573 0/imm32/no-r32 -32574 0/imm32/no-imm32 -32575 0/imm32/no-imm8 -32576 0/imm32/no-disp32 -32577 2/imm32/xm32-is-second-inout -32578 1/imm32/x32-is-first-inout +32565 _string_f3_0f_53_reciprocal/imm32/subx-name +32566 0/imm32/no-rm32 +32567 0/imm32/no-r32 +32568 0/imm32/no-imm32 +32569 0/imm32/no-imm8 +32570 0/imm32/no-disp32 +32571 1/imm32/xm32-is-first-inout +32572 3/imm32/x32-is-first-output +32573 0x11/imm32/alloc-id:fake +32574 _Primitive-square-root-xreg-to-xreg/imm32/next +32575 # - floating-point square root +32576 _Primitive-square-root-xreg-to-xreg: # (payload primitive) +32577 0x11/imm32/alloc-id:fake:payload +32578 # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32 32579 0x11/imm32/alloc-id:fake -32580 _Primitive-compare-xreg-with-mem/imm32/next -32581 _Primitive-compare-xreg-with-mem: # (payload primitive) -32582 0x11/imm32/alloc-id:fake:payload -32583 # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32 -32584 0x11/imm32/alloc-id:fake -32585 _string-compare/imm32/name -32586 0x11/imm32/alloc-id:fake -32587 Two-args-float-reg-float-stack/imm32/inouts -32588 0/imm32/no-outputs -32589 0/imm32/no-outputs -32590 0x11/imm32/alloc-id:fake -32591 _string_0f_2f_compare/imm32/subx-name -32592 0/imm32/no-rm32 -32593 0/imm32/no-r32 -32594 0/imm32/no-imm32 -32595 0/imm32/no-imm8 -32596 0/imm32/no-disp32 -32597 2/imm32/xm32-is-second-inout -32598 1/imm32/x32-is-first-inout +32580 _string-square-root/imm32/name +32581 0x11/imm32/alloc-id:fake +32582 Single-float-var-in-some-register/imm32/inouts +32583 0x11/imm32/alloc-id:fake +32584 Single-float-var-in-some-register/imm32/outputs +32585 0x11/imm32/alloc-id:fake +32586 _string_f3_0f_51_square_root/imm32/subx-name +32587 0/imm32/no-rm32 +32588 0/imm32/no-r32 +32589 0/imm32/no-imm32 +32590 0/imm32/no-imm8 +32591 0/imm32/no-disp32 +32592 1/imm32/xm32-is-first-inout +32593 3/imm32/x32-is-first-output +32594 0x11/imm32/alloc-id:fake +32595 _Primitive-square-root-mem-to-xreg/imm32/next +32596 _Primitive-square-root-mem-to-xreg: # (payload primitive) +32597 0x11/imm32/alloc-id:fake:payload +32598 # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32 32599 0x11/imm32/alloc-id:fake -32600 _Primitive-break-if-addr</imm32/next -32601 # - branches -32602 _Primitive-break-if-addr<: # (payload primitive) -32603 0x11/imm32/alloc-id:fake:payload -32604 0x11/imm32/alloc-id:fake -32605 _string-break-if-addr</imm32/name -32606 0/imm32/no-inouts -32607 0/imm32/no-inouts -32608 0/imm32/no-outputs -32609 0/imm32/no-outputs -32610 0x11/imm32/alloc-id:fake -32611 _string_0f_82_jump_break/imm32/subx-name -32612 0/imm32/no-rm32 -32613 0/imm32/no-r32 -32614 0/imm32/no-imm32 -32615 0/imm32/no-imm8 -32616 0/imm32/no-disp32 -32617 0/imm32/no-xm32 -32618 0/imm32/no-x32 -32619 0x11/imm32/alloc-id:fake -32620 _Primitive-break-if-addr>=/imm32/next -32621 _Primitive-break-if-addr>=: # (payload primitive) -32622 0x11/imm32/alloc-id:fake:payload -32623 0x11/imm32/alloc-id:fake -32624 _string-break-if-addr>=/imm32/name -32625 0/imm32/no-inouts -32626 0/imm32/no-inouts -32627 0/imm32/no-outputs -32628 0/imm32/no-outputs -32629 0x11/imm32/alloc-id:fake -32630 _string_0f_83_jump_break/imm32/subx-name -32631 0/imm32/no-rm32 -32632 0/imm32/no-r32 -32633 0/imm32/no-imm32 -32634 0/imm32/no-imm8 -32635 0/imm32/no-disp32 -32636 0/imm32/no-xm32 -32637 0/imm32/no-x32 -32638 0x11/imm32/alloc-id:fake -32639 _Primitive-break-if-=/imm32/next -32640 _Primitive-break-if-=: # (payload primitive) -32641 0x11/imm32/alloc-id:fake:payload +32600 _string-square-root/imm32/name +32601 0x11/imm32/alloc-id:fake +32602 Single-float-var-in-mem/imm32/inouts +32603 0x11/imm32/alloc-id:fake +32604 Single-float-var-in-some-register/imm32/outputs +32605 0x11/imm32/alloc-id:fake +32606 _string_f3_0f_51_square_root/imm32/subx-name +32607 0/imm32/no-rm32 +32608 0/imm32/no-r32 +32609 0/imm32/no-imm32 +32610 0/imm32/no-imm8 +32611 0/imm32/no-disp32 +32612 1/imm32/xm32-is-first-inout +32613 3/imm32/x32-is-first-output +32614 0x11/imm32/alloc-id:fake +32615 _Primitive-inverse-square-root-xreg-to-xreg/imm32/next +32616 # - floating-point inverse square root 1/sqrt(x) +32617 _Primitive-inverse-square-root-xreg-to-xreg: # (payload primitive) +32618 0x11/imm32/alloc-id:fake:payload +32619 # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32 +32620 0x11/imm32/alloc-id:fake +32621 _string-inverse-square-root/imm32/name +32622 0x11/imm32/alloc-id:fake +32623 Single-float-var-in-some-register/imm32/inouts +32624 0x11/imm32/alloc-id:fake +32625 Single-float-var-in-some-register/imm32/outputs +32626 0x11/imm32/alloc-id:fake +32627 _string_f3_0f_52_inverse_square_root/imm32/subx-name +32628 0/imm32/no-rm32 +32629 0/imm32/no-r32 +32630 0/imm32/no-imm32 +32631 0/imm32/no-imm8 +32632 0/imm32/no-disp32 +32633 1/imm32/xm32-is-first-inout +32634 3/imm32/x32-is-first-output +32635 0x11/imm32/alloc-id:fake +32636 _Primitive-inverse-square-root-mem-to-xreg/imm32/next +32637 _Primitive-inverse-square-root-mem-to-xreg: # (payload primitive) +32638 0x11/imm32/alloc-id:fake:payload +32639 # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32 +32640 0x11/imm32/alloc-id:fake +32641 _string-inverse-square-root/imm32/name 32642 0x11/imm32/alloc-id:fake -32643 _string-break-if-=/imm32/name -32644 0/imm32/no-inouts -32645 0/imm32/no-inouts -32646 0/imm32/no-outputs -32647 0/imm32/no-outputs -32648 0x11/imm32/alloc-id:fake -32649 _string_0f_84_jump_break/imm32/subx-name -32650 0/imm32/no-rm32 -32651 0/imm32/no-r32 -32652 0/imm32/no-imm32 -32653 0/imm32/no-imm8 -32654 0/imm32/no-disp32 -32655 0/imm32/no-xm32 -32656 0/imm32/no-x32 -32657 0x11/imm32/alloc-id:fake -32658 _Primitive-break-if-!=/imm32/next -32659 _Primitive-break-if-!=: # (payload primitive) -32660 0x11/imm32/alloc-id:fake:payload +32643 Single-float-var-in-mem/imm32/inouts +32644 0x11/imm32/alloc-id:fake +32645 Single-float-var-in-some-register/imm32/outputs +32646 0x11/imm32/alloc-id:fake +32647 _string_f3_0f_52_inverse_square_root/imm32/subx-name +32648 0/imm32/no-rm32 +32649 0/imm32/no-r32 +32650 0/imm32/no-imm32 +32651 0/imm32/no-imm8 +32652 0/imm32/no-disp32 +32653 1/imm32/xm32-is-first-inout +32654 3/imm32/x32-is-first-output +32655 0x11/imm32/alloc-id:fake +32656 _Primitive-compare-xreg-with-xreg/imm32/next +32657 # - floating-point compare +32658 _Primitive-compare-xreg-with-xreg: # (payload primitive) +32659 0x11/imm32/alloc-id:fake:payload +32660 # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32 32661 0x11/imm32/alloc-id:fake -32662 _string-break-if-!=/imm32/name -32663 0/imm32/no-inouts -32664 0/imm32/no-inouts +32662 _string-compare/imm32/name +32663 0x11/imm32/alloc-id:fake +32664 Two-float-args-in-regs/imm32/inouts 32665 0/imm32/no-outputs 32666 0/imm32/no-outputs 32667 0x11/imm32/alloc-id:fake -32668 _string_0f_85_jump_break/imm32/subx-name +32668 _string_0f_2f_compare/imm32/subx-name 32669 0/imm32/no-rm32 32670 0/imm32/no-r32 32671 0/imm32/no-imm32 32672 0/imm32/no-imm8 32673 0/imm32/no-disp32 -32674 0/imm32/no-xm32 -32675 0/imm32/no-x32 +32674 2/imm32/xm32-is-second-inout +32675 1/imm32/x32-is-first-inout 32676 0x11/imm32/alloc-id:fake -32677 _Primitive-break-if-addr<=/imm32/next -32678 _Primitive-break-if-addr<=: # (payload primitive) +32677 _Primitive-compare-xreg-with-mem/imm32/next +32678 _Primitive-compare-xreg-with-mem: # (payload primitive) 32679 0x11/imm32/alloc-id:fake:payload -32680 0x11/imm32/alloc-id:fake -32681 _string-break-if-addr<=/imm32/name -32682 0/imm32/no-inouts -32683 0/imm32/no-inouts -32684 0/imm32/no-outputs +32680 # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32 +32681 0x11/imm32/alloc-id:fake +32682 _string-compare/imm32/name +32683 0x11/imm32/alloc-id:fake +32684 Two-args-float-reg-float-stack/imm32/inouts 32685 0/imm32/no-outputs -32686 0x11/imm32/alloc-id:fake -32687 _string_0f_86_jump_break/imm32/subx-name -32688 0/imm32/no-rm32 -32689 0/imm32/no-r32 -32690 0/imm32/no-imm32 -32691 0/imm32/no-imm8 -32692 0/imm32/no-disp32 -32693 0/imm32/no-xm32 -32694 0/imm32/no-x32 -32695 0x11/imm32/alloc-id:fake -32696 _Primitive-break-if-addr>/imm32/next -32697 _Primitive-break-if-addr>: # (payload primitive) -32698 0x11/imm32/alloc-id:fake:payload -32699 0x11/imm32/alloc-id:fake -32700 _string-break-if-addr>/imm32/name -32701 0/imm32/no-inouts -32702 0/imm32/no-inouts -32703 0/imm32/no-outputs -32704 0/imm32/no-outputs -32705 0x11/imm32/alloc-id:fake -32706 _string_0f_87_jump_break/imm32/subx-name -32707 0/imm32/no-rm32 -32708 0/imm32/no-r32 -32709 0/imm32/no-imm32 -32710 0/imm32/no-imm8 -32711 0/imm32/no-disp32 -32712 0/imm32/no-xm32 -32713 0/imm32/no-x32 -32714 0x11/imm32/alloc-id:fake -32715 _Primitive-break-if-</imm32/next -32716 _Primitive-break-if-<: # (payload primitive) -32717 0x11/imm32/alloc-id:fake:payload -32718 0x11/imm32/alloc-id:fake -32719 _string-break-if-</imm32/name -32720 0/imm32/no-inouts -32721 0/imm32/no-inouts -32722 0/imm32/no-outputs -32723 0/imm32/no-outputs -32724 0x11/imm32/alloc-id:fake -32725 _string_0f_8c_jump_break/imm32/subx-name -32726 0/imm32/no-rm32 -32727 0/imm32/no-r32 -32728 0/imm32/no-imm32 -32729 0/imm32/no-imm8 -32730 0/imm32/no-disp32 -32731 0/imm32/no-xm32 -32732 0/imm32/no-x32 -32733 0x11/imm32/alloc-id:fake -32734 _Primitive-break-if->=/imm32/next -32735 _Primitive-break-if->=: # (payload primitive) -32736 0x11/imm32/alloc-id:fake:payload -32737 0x11/imm32/alloc-id:fake -32738 _string-break-if->=/imm32/name -32739 0/imm32/no-inouts -32740 0/imm32/no-inouts -32741 0/imm32/no-outputs -32742 0/imm32/no-outputs -32743 0x11/imm32/alloc-id:fake -32744 _string_0f_8d_jump_break/imm32/subx-name -32745 0/imm32/no-rm32 -32746 0/imm32/no-r32 -32747 0/imm32/no-imm32 -32748 0/imm32/no-imm8 -32749 0/imm32/no-disp32 -32750 0/imm32/no-xm32 -32751 0/imm32/no-x32 -32752 0x11/imm32/alloc-id:fake -32753 _Primitive-break-if-<=/imm32/next -32754 _Primitive-break-if-<=: # (payload primitive) -32755 0x11/imm32/alloc-id:fake:payload -32756 0x11/imm32/alloc-id:fake -32757 _string-break-if-<=/imm32/name -32758 0/imm32/no-inouts -32759 0/imm32/no-inouts -32760 0/imm32/no-outputs -32761 0/imm32/no-outputs -32762 0x11/imm32/alloc-id:fake -32763 _string_0f_8e_jump_break/imm32/subx-name -32764 0/imm32/no-rm32 -32765 0/imm32/no-r32 -32766 0/imm32/no-imm32 -32767 0/imm32/no-imm8 -32768 0/imm32/no-disp32 -32769 0/imm32/no-xm32 -32770 0/imm32/no-x32 -32771 0x11/imm32/alloc-id:fake -32772 _Primitive-break-if->/imm32/next -32773 _Primitive-break-if->: # (payload primitive) -32774 0x11/imm32/alloc-id:fake:payload -32775 0x11/imm32/alloc-id:fake -32776 _string-break-if->/imm32/name -32777 0/imm32/no-inouts -32778 0/imm32/no-inouts -32779 0/imm32/no-outputs -32780 0/imm32/no-outputs -32781 0x11/imm32/alloc-id:fake -32782 _string_0f_8f_jump_break/imm32/subx-name -32783 0/imm32/no-rm32 -32784 0/imm32/no-r32 -32785 0/imm32/no-imm32 -32786 0/imm32/no-imm8 -32787 0/imm32/no-disp32 -32788 0/imm32/no-xm32 -32789 0/imm32/no-x32 -32790 0x11/imm32/alloc-id:fake -32791 _Primitive-break/imm32/next -32792 _Primitive-break: # (payload primitive) -32793 0x11/imm32/alloc-id:fake:payload -32794 0x11/imm32/alloc-id:fake -32795 _string-break/imm32/name -32796 0/imm32/no-inouts -32797 0/imm32/no-inouts -32798 0/imm32/no-outputs -32799 0/imm32/no-outputs -32800 0x11/imm32/alloc-id:fake -32801 _string_e9_jump_break/imm32/subx-name -32802 0/imm32/no-rm32 -32803 0/imm32/no-r32 -32804 0/imm32/no-imm32 -32805 0/imm32/no-imm8 -32806 0/imm32/no-disp32 -32807 0/imm32/no-xm32 -32808 0/imm32/no-x32 -32809 0x11/imm32/alloc-id:fake -32810 _Primitive-loop-if-addr</imm32/next -32811 _Primitive-loop-if-addr<: # (payload primitive) -32812 0x11/imm32/alloc-id:fake:payload -32813 0x11/imm32/alloc-id:fake -32814 _string-loop-if-addr</imm32/name -32815 0/imm32/no-inouts -32816 0/imm32/no-inouts -32817 0/imm32/no-outputs -32818 0/imm32/no-outputs -32819 0x11/imm32/alloc-id:fake -32820 _string_0f_82_jump_loop/imm32/subx-name -32821 0/imm32/no-rm32 -32822 0/imm32/no-r32 -32823 0/imm32/no-imm32 -32824 0/imm32/no-imm8 -32825 0/imm32/no-disp32 -32826 0/imm32/no-xm32 -32827 0/imm32/no-x32 -32828 0x11/imm32/alloc-id:fake -32829 _Primitive-loop-if-addr>=/imm32/next -32830 _Primitive-loop-if-addr>=: # (payload primitive) -32831 0x11/imm32/alloc-id:fake:payload -32832 0x11/imm32/alloc-id:fake -32833 _string-loop-if-addr>=/imm32/name -32834 0/imm32/no-inouts -32835 0/imm32/no-inouts -32836 0/imm32/no-outputs -32837 0/imm32/no-outputs -32838 0x11/imm32/alloc-id:fake -32839 _string_0f_83_jump_loop/imm32/subx-name -32840 0/imm32/no-rm32 -32841 0/imm32/no-r32 -32842 0/imm32/no-imm32 -32843 0/imm32/no-imm8 -32844 0/imm32/no-disp32 -32845 0/imm32/no-xm32 -32846 0/imm32/no-x32 -32847 0x11/imm32/alloc-id:fake -32848 _Primitive-loop-if-=/imm32/next -32849 _Primitive-loop-if-=: # (payload primitive) -32850 0x11/imm32/alloc-id:fake:payload -32851 0x11/imm32/alloc-id:fake -32852 _string-loop-if-=/imm32/name -32853 0/imm32/no-inouts -32854 0/imm32/no-inouts -32855 0/imm32/no-outputs -32856 0/imm32/no-outputs -32857 0x11/imm32/alloc-id:fake -32858 _string_0f_84_jump_loop/imm32/subx-name -32859 0/imm32/no-rm32 -32860 0/imm32/no-r32 -32861 0/imm32/no-imm32 -32862 0/imm32/no-imm8 -32863 0/imm32/no-disp32 -32864 0/imm32/no-xm32 -32865 0/imm32/no-x32 -32866 0x11/imm32/alloc-id:fake -32867 _Primitive-loop-if-!=/imm32/next -32868 _Primitive-loop-if-!=: # (payload primitive) -32869 0x11/imm32/alloc-id:fake:payload -32870 0x11/imm32/alloc-id:fake -32871 _string-loop-if-!=/imm32/name -32872 0/imm32/no-inouts -32873 0/imm32/no-inouts -32874 0/imm32/no-outputs -32875 0/imm32/no-outputs -32876 0x11/imm32/alloc-id:fake -32877 _string_0f_85_jump_loop/imm32/subx-name -32878 0/imm32/no-rm32 -32879 0/imm32/no-r32 -32880 0/imm32/no-imm32 -32881 0/imm32/no-imm8 -32882 0/imm32/no-disp32 -32883 0/imm32/no-xm32 -32884 0/imm32/no-x32 -32885 0x11/imm32/alloc-id:fake -32886 _Primitive-loop-if-addr<=/imm32/next -32887 _Primitive-loop-if-addr<=: # (payload primitive) -32888 0x11/imm32/alloc-id:fake:payload -32889 0x11/imm32/alloc-id:fake -32890 _string-loop-if-addr<=/imm32/name -32891 0/imm32/no-inouts -32892 0/imm32/no-inouts -32893 0/imm32/no-outputs -32894 0/imm32/no-outputs -32895 0x11/imm32/alloc-id:fake -32896 _string_0f_86_jump_loop/imm32/subx-name -32897 0/imm32/no-rm32 -32898 0/imm32/no-r32 -32899 0/imm32/no-imm32 -32900 0/imm32/no-imm8 -32901 0/imm32/no-disp32 -32902 0/imm32/no-xm32 -32903 0/imm32/no-x32 -32904 0x11/imm32/alloc-id:fake -32905 _Primitive-loop-if-addr>/imm32/next -32906 _Primitive-loop-if-addr>: # (payload primitive) -32907 0x11/imm32/alloc-id:fake:payload -32908 0x11/imm32/alloc-id:fake -32909 _string-loop-if-addr>/imm32/name -32910 0/imm32/no-inouts -32911 0/imm32/no-inouts -32912 0/imm32/no-outputs -32913 0/imm32/no-outputs -32914 0x11/imm32/alloc-id:fake -32915 _string_0f_87_jump_loop/imm32/subx-name -32916 0/imm32/no-rm32 -32917 0/imm32/no-r32 -32918 0/imm32/no-imm32 -32919 0/imm32/no-imm8 -32920 0/imm32/no-disp32 -32921 0/imm32/no-xm32 -32922 0/imm32/no-x32 -32923 0x11/imm32/alloc-id:fake -32924 _Primitive-loop-if-</imm32/next -32925 _Primitive-loop-if-<: # (payload primitive) -32926 0x11/imm32/alloc-id:fake:payload -32927 0x11/imm32/alloc-id:fake -32928 _string-loop-if-</imm32/name -32929 0/imm32/no-inouts -32930 0/imm32/no-inouts -32931 0/imm32/no-outputs -32932 0/imm32/no-outputs -32933 0x11/imm32/alloc-id:fake -32934 _string_0f_8c_jump_loop/imm32/subx-name -32935 0/imm32/no-rm32 -32936 0/imm32/no-r32 -32937 0/imm32/no-imm32 -32938 0/imm32/no-imm8 -32939 0/imm32/no-disp32 -32940 0/imm32/no-xm32 -32941 0/imm32/no-x32 -32942 0x11/imm32/alloc-id:fake -32943 _Primitive-loop-if->=/imm32/next -32944 _Primitive-loop-if->=: # (payload primitive) -32945 0x11/imm32/alloc-id:fake:payload -32946 0x11/imm32/alloc-id:fake -32947 _string-loop-if->=/imm32/name -32948 0/imm32/no-inouts -32949 0/imm32/no-inouts -32950 0/imm32/no-outputs -32951 0/imm32/no-outputs -32952 0x11/imm32/alloc-id:fake -32953 _string_0f_8d_jump_loop/imm32/subx-name -32954 0/imm32/no-rm32 -32955 0/imm32/no-r32 -32956 0/imm32/no-imm32 -32957 0/imm32/no-imm8 -32958 0/imm32/no-disp32 -32959 0/imm32/no-xm32 -32960 0/imm32/no-x32 -32961 0x11/imm32/alloc-id:fake -32962 _Primitive-loop-if-<=/imm32/next -32963 _Primitive-loop-if-<=: # (payload primitive) -32964 0x11/imm32/alloc-id:fake:payload -32965 0x11/imm32/alloc-id:fake -32966 _string-loop-if-<=/imm32/name -32967 0/imm32/no-inouts -32968 0/imm32/no-inouts -32969 0/imm32/no-outputs -32970 0/imm32/no-outputs -32971 0x11/imm32/alloc-id:fake -32972 _string_0f_8e_jump_loop/imm32/subx-name -32973 0/imm32/no-rm32 -32974 0/imm32/no-r32 -32975 0/imm32/no-imm32 -32976 0/imm32/no-imm8 -32977 0/imm32/no-disp32 -32978 0/imm32/no-xm32 -32979 0/imm32/no-x32 -32980 0x11/imm32/alloc-id:fake -32981 _Primitive-loop-if->/imm32/next -32982 _Primitive-loop-if->: # (payload primitive) -32983 0x11/imm32/alloc-id:fake:payload -32984 0x11/imm32/alloc-id:fake -32985 _string-loop-if->/imm32/name -32986 0/imm32/no-inouts -32987 0/imm32/no-inouts -32988 0/imm32/no-outputs -32989 0/imm32/no-outputs -32990 0x11/imm32/alloc-id:fake -32991 _string_0f_8f_jump_loop/imm32/subx-name -32992 0/imm32/no-rm32 -32993 0/imm32/no-r32 -32994 0/imm32/no-imm32 -32995 0/imm32/no-imm8 -32996 0/imm32/no-disp32 -32997 0/imm32/no-xm32 -32998 0/imm32/no-x32 -32999 0x11/imm32/alloc-id:fake -33000 _Primitive-loop/imm32/next # we probably don't need an unconditional break -33001 _Primitive-loop: # (payload primitive) -33002 0x11/imm32/alloc-id:fake:payload -33003 0x11/imm32/alloc-id:fake -33004 _string-loop/imm32/name -33005 0/imm32/no-inouts -33006 0/imm32/no-inouts -33007 0/imm32/no-outputs -33008 0/imm32/no-outputs -33009 0x11/imm32/alloc-id:fake -33010 _string_e9_jump_loop/imm32/subx-name -33011 0/imm32/no-rm32 -33012 0/imm32/no-r32 -33013 0/imm32/no-imm32 -33014 0/imm32/no-imm8 -33015 0/imm32/no-disp32 -33016 0/imm32/no-xm32 -33017 0/imm32/no-x32 -33018 0x11/imm32/alloc-id:fake -33019 _Primitive-break-if-addr<-named/imm32/next -33020 # - branches to named blocks -33021 _Primitive-break-if-addr<-named: # (payload primitive) -33022 0x11/imm32/alloc-id:fake:payload -33023 0x11/imm32/alloc-id:fake -33024 _string-break-if-addr</imm32/name -33025 0x11/imm32/alloc-id:fake -33026 Single-lit-var/imm32/inouts -33027 0/imm32/no-outputs +32686 0/imm32/no-outputs +32687 0x11/imm32/alloc-id:fake +32688 _string_0f_2f_compare/imm32/subx-name +32689 0/imm32/no-rm32 +32690 0/imm32/no-r32 +32691 0/imm32/no-imm32 +32692 0/imm32/no-imm8 +32693 0/imm32/no-disp32 +32694 2/imm32/xm32-is-second-inout +32695 1/imm32/x32-is-first-inout +32696 0x11/imm32/alloc-id:fake +32697 _Primitive-break-if-addr</imm32/next +32698 # - branches +32699 _Primitive-break-if-addr<: # (payload primitive) +32700 0x11/imm32/alloc-id:fake:payload +32701 0x11/imm32/alloc-id:fake +32702 _string-break-if-addr</imm32/name +32703 0/imm32/no-inouts +32704 0/imm32/no-inouts +32705 0/imm32/no-outputs +32706 0/imm32/no-outputs +32707 0x11/imm32/alloc-id:fake +32708 _string_0f_82_jump_break/imm32/subx-name +32709 0/imm32/no-rm32 +32710 0/imm32/no-r32 +32711 0/imm32/no-imm32 +32712 0/imm32/no-imm8 +32713 0/imm32/no-disp32 +32714 0/imm32/no-xm32 +32715 0/imm32/no-x32 +32716 0x11/imm32/alloc-id:fake +32717 _Primitive-break-if-addr>=/imm32/next +32718 _Primitive-break-if-addr>=: # (payload primitive) +32719 0x11/imm32/alloc-id:fake:payload +32720 0x11/imm32/alloc-id:fake +32721 _string-break-if-addr>=/imm32/name +32722 0/imm32/no-inouts +32723 0/imm32/no-inouts +32724 0/imm32/no-outputs +32725 0/imm32/no-outputs +32726 0x11/imm32/alloc-id:fake +32727 _string_0f_83_jump_break/imm32/subx-name +32728 0/imm32/no-rm32 +32729 0/imm32/no-r32 +32730 0/imm32/no-imm32 +32731 0/imm32/no-imm8 +32732 0/imm32/no-disp32 +32733 0/imm32/no-xm32 +32734 0/imm32/no-x32 +32735 0x11/imm32/alloc-id:fake +32736 _Primitive-break-if-=/imm32/next +32737 _Primitive-break-if-=: # (payload primitive) +32738 0x11/imm32/alloc-id:fake:payload +32739 0x11/imm32/alloc-id:fake +32740 _string-break-if-=/imm32/name +32741 0/imm32/no-inouts +32742 0/imm32/no-inouts +32743 0/imm32/no-outputs +32744 0/imm32/no-outputs +32745 0x11/imm32/alloc-id:fake +32746 _string_0f_84_jump_break/imm32/subx-name +32747 0/imm32/no-rm32 +32748 0/imm32/no-r32 +32749 0/imm32/no-imm32 +32750 0/imm32/no-imm8 +32751 0/imm32/no-disp32 +32752 0/imm32/no-xm32 +32753 0/imm32/no-x32 +32754 0x11/imm32/alloc-id:fake +32755 _Primitive-break-if-!=/imm32/next +32756 _Primitive-break-if-!=: # (payload primitive) +32757 0x11/imm32/alloc-id:fake:payload +32758 0x11/imm32/alloc-id:fake +32759 _string-break-if-!=/imm32/name +32760 0/imm32/no-inouts +32761 0/imm32/no-inouts +32762 0/imm32/no-outputs +32763 0/imm32/no-outputs +32764 0x11/imm32/alloc-id:fake +32765 _string_0f_85_jump_break/imm32/subx-name +32766 0/imm32/no-rm32 +32767 0/imm32/no-r32 +32768 0/imm32/no-imm32 +32769 0/imm32/no-imm8 +32770 0/imm32/no-disp32 +32771 0/imm32/no-xm32 +32772 0/imm32/no-x32 +32773 0x11/imm32/alloc-id:fake +32774 _Primitive-break-if-addr<=/imm32/next +32775 _Primitive-break-if-addr<=: # (payload primitive) +32776 0x11/imm32/alloc-id:fake:payload +32777 0x11/imm32/alloc-id:fake +32778 _string-break-if-addr<=/imm32/name +32779 0/imm32/no-inouts +32780 0/imm32/no-inouts +32781 0/imm32/no-outputs +32782 0/imm32/no-outputs +32783 0x11/imm32/alloc-id:fake +32784 _string_0f_86_jump_break/imm32/subx-name +32785 0/imm32/no-rm32 +32786 0/imm32/no-r32 +32787 0/imm32/no-imm32 +32788 0/imm32/no-imm8 +32789 0/imm32/no-disp32 +32790 0/imm32/no-xm32 +32791 0/imm32/no-x32 +32792 0x11/imm32/alloc-id:fake +32793 _Primitive-break-if-addr>/imm32/next +32794 _Primitive-break-if-addr>: # (payload primitive) +32795 0x11/imm32/alloc-id:fake:payload +32796 0x11/imm32/alloc-id:fake +32797 _string-break-if-addr>/imm32/name +32798 0/imm32/no-inouts +32799 0/imm32/no-inouts +32800 0/imm32/no-outputs +32801 0/imm32/no-outputs +32802 0x11/imm32/alloc-id:fake +32803 _string_0f_87_jump_break/imm32/subx-name +32804 0/imm32/no-rm32 +32805 0/imm32/no-r32 +32806 0/imm32/no-imm32 +32807 0/imm32/no-imm8 +32808 0/imm32/no-disp32 +32809 0/imm32/no-xm32 +32810 0/imm32/no-x32 +32811 0x11/imm32/alloc-id:fake +32812 _Primitive-break-if-</imm32/next +32813 _Primitive-break-if-<: # (payload primitive) +32814 0x11/imm32/alloc-id:fake:payload +32815 0x11/imm32/alloc-id:fake +32816 _string-break-if-</imm32/name +32817 0/imm32/no-inouts +32818 0/imm32/no-inouts +32819 0/imm32/no-outputs +32820 0/imm32/no-outputs +32821 0x11/imm32/alloc-id:fake +32822 _string_0f_8c_jump_break/imm32/subx-name +32823 0/imm32/no-rm32 +32824 0/imm32/no-r32 +32825 0/imm32/no-imm32 +32826 0/imm32/no-imm8 +32827 0/imm32/no-disp32 +32828 0/imm32/no-xm32 +32829 0/imm32/no-x32 +32830 0x11/imm32/alloc-id:fake +32831 _Primitive-break-if->=/imm32/next +32832 _Primitive-break-if->=: # (payload primitive) +32833 0x11/imm32/alloc-id:fake:payload +32834 0x11/imm32/alloc-id:fake +32835 _string-break-if->=/imm32/name +32836 0/imm32/no-inouts +32837 0/imm32/no-inouts +32838 0/imm32/no-outputs +32839 0/imm32/no-outputs +32840 0x11/imm32/alloc-id:fake +32841 _string_0f_8d_jump_break/imm32/subx-name +32842 0/imm32/no-rm32 +32843 0/imm32/no-r32 +32844 0/imm32/no-imm32 +32845 0/imm32/no-imm8 +32846 0/imm32/no-disp32 +32847 0/imm32/no-xm32 +32848 0/imm32/no-x32 +32849 0x11/imm32/alloc-id:fake +32850 _Primitive-break-if-<=/imm32/next +32851 _Primitive-break-if-<=: # (payload primitive) +32852 0x11/imm32/alloc-id:fake:payload +32853 0x11/imm32/alloc-id:fake +32854 _string-break-if-<=/imm32/name +32855 0/imm32/no-inouts +32856 0/imm32/no-inouts +32857 0/imm32/no-outputs +32858 0/imm32/no-outputs +32859 0x11/imm32/alloc-id:fake +32860 _string_0f_8e_jump_break/imm32/subx-name +32861 0/imm32/no-rm32 +32862 0/imm32/no-r32 +32863 0/imm32/no-imm32 +32864 0/imm32/no-imm8 +32865 0/imm32/no-disp32 +32866 0/imm32/no-xm32 +32867 0/imm32/no-x32 +32868 0x11/imm32/alloc-id:fake +32869 _Primitive-break-if->/imm32/next +32870 _Primitive-break-if->: # (payload primitive) +32871 0x11/imm32/alloc-id:fake:payload +32872 0x11/imm32/alloc-id:fake +32873 _string-break-if->/imm32/name +32874 0/imm32/no-inouts +32875 0/imm32/no-inouts +32876 0/imm32/no-outputs +32877 0/imm32/no-outputs +32878 0x11/imm32/alloc-id:fake +32879 _string_0f_8f_jump_break/imm32/subx-name +32880 0/imm32/no-rm32 +32881 0/imm32/no-r32 +32882 0/imm32/no-imm32 +32883 0/imm32/no-imm8 +32884 0/imm32/no-disp32 +32885 0/imm32/no-xm32 +32886 0/imm32/no-x32 +32887 0x11/imm32/alloc-id:fake +32888 _Primitive-break-if-carry/imm32/next +32889 _Primitive-break-if-carry: # (payload primitive) +32890 0x11/imm32/alloc-id:fake:payload +32891 0x11/imm32/alloc-id:fake +32892 _string-break-if-carry/imm32/name +32893 0/imm32/no-inouts +32894 0/imm32/no-inouts +32895 0/imm32/no-outputs +32896 0/imm32/no-outputs +32897 0x11/imm32/alloc-id:fake +32898 _string_0f_82_jump_break/imm32/subx-name +32899 0/imm32/no-rm32 +32900 0/imm32/no-r32 +32901 0/imm32/no-imm32 +32902 0/imm32/no-imm8 +32903 0/imm32/no-disp32 +32904 0/imm32/no-xm32 +32905 0/imm32/no-x32 +32906 0x11/imm32/alloc-id:fake +32907 _Primitive-break-if-not-carry/imm32/next +32908 _Primitive-break-if-not-carry: # (payload primitive) +32909 0x11/imm32/alloc-id:fake:payload +32910 0x11/imm32/alloc-id:fake +32911 _string-break-if-not-carry/imm32/name +32912 0/imm32/no-inouts +32913 0/imm32/no-inouts +32914 0/imm32/no-outputs +32915 0/imm32/no-outputs +32916 0x11/imm32/alloc-id:fake +32917 _string_0f_83_jump_break/imm32/subx-name +32918 0/imm32/no-rm32 +32919 0/imm32/no-r32 +32920 0/imm32/no-imm32 +32921 0/imm32/no-imm8 +32922 0/imm32/no-disp32 +32923 0/imm32/no-xm32 +32924 0/imm32/no-x32 +32925 0x11/imm32/alloc-id:fake +32926 _Primitive-break-if-overflow/imm32/next +32927 _Primitive-break-if-overflow: # (payload primitive) +32928 0x11/imm32/alloc-id:fake:payload +32929 0x11/imm32/alloc-id:fake +32930 _string-break-if-overflow/imm32/name +32931 0/imm32/no-inouts +32932 0/imm32/no-inouts +32933 0/imm32/no-outputs +32934 0/imm32/no-outputs +32935 0x11/imm32/alloc-id:fake +32936 _string_0f_80_jump_break/imm32/subx-name +32937 0/imm32/no-rm32 +32938 0/imm32/no-r32 +32939 0/imm32/no-imm32 +32940 0/imm32/no-imm8 +32941 0/imm32/no-disp32 +32942 0/imm32/no-xm32 +32943 0/imm32/no-x32 +32944 0x11/imm32/alloc-id:fake +32945 _Primitive-break-if-not-overflow/imm32/next +32946 _Primitive-break-if-not-overflow: # (payload primitive) +32947 0x11/imm32/alloc-id:fake:payload +32948 0x11/imm32/alloc-id:fake +32949 _string-break-if-not-overflow/imm32/name +32950 0/imm32/no-inouts +32951 0/imm32/no-inouts +32952 0/imm32/no-outputs +32953 0/imm32/no-outputs +32954 0x11/imm32/alloc-id:fake +32955 _string_0f_81_jump_break/imm32/subx-name +32956 0/imm32/no-rm32 +32957 0/imm32/no-r32 +32958 0/imm32/no-imm32 +32959 0/imm32/no-imm8 +32960 0/imm32/no-disp32 +32961 0/imm32/no-xm32 +32962 0/imm32/no-x32 +32963 0x11/imm32/alloc-id:fake +32964 _Primitive-break/imm32/next +32965 _Primitive-break: # (payload primitive) +32966 0x11/imm32/alloc-id:fake:payload +32967 0x11/imm32/alloc-id:fake +32968 _string-break/imm32/name +32969 0/imm32/no-inouts +32970 0/imm32/no-inouts +32971 0/imm32/no-outputs +32972 0/imm32/no-outputs +32973 0x11/imm32/alloc-id:fake +32974 _string_e9_jump_break/imm32/subx-name +32975 0/imm32/no-rm32 +32976 0/imm32/no-r32 +32977 0/imm32/no-imm32 +32978 0/imm32/no-imm8 +32979 0/imm32/no-disp32 +32980 0/imm32/no-xm32 +32981 0/imm32/no-x32 +32982 0x11/imm32/alloc-id:fake +32983 _Primitive-loop-if-addr</imm32/next +32984 _Primitive-loop-if-addr<: # (payload primitive) +32985 0x11/imm32/alloc-id:fake:payload +32986 0x11/imm32/alloc-id:fake +32987 _string-loop-if-addr</imm32/name +32988 0/imm32/no-inouts +32989 0/imm32/no-inouts +32990 0/imm32/no-outputs +32991 0/imm32/no-outputs +32992 0x11/imm32/alloc-id:fake +32993 _string_0f_82_jump_loop/imm32/subx-name +32994 0/imm32/no-rm32 +32995 0/imm32/no-r32 +32996 0/imm32/no-imm32 +32997 0/imm32/no-imm8 +32998 0/imm32/no-disp32 +32999 0/imm32/no-xm32 +33000 0/imm32/no-x32 +33001 0x11/imm32/alloc-id:fake +33002 _Primitive-loop-if-addr>=/imm32/next +33003 _Primitive-loop-if-addr>=: # (payload primitive) +33004 0x11/imm32/alloc-id:fake:payload +33005 0x11/imm32/alloc-id:fake +33006 _string-loop-if-addr>=/imm32/name +33007 0/imm32/no-inouts +33008 0/imm32/no-inouts +33009 0/imm32/no-outputs +33010 0/imm32/no-outputs +33011 0x11/imm32/alloc-id:fake +33012 _string_0f_83_jump_loop/imm32/subx-name +33013 0/imm32/no-rm32 +33014 0/imm32/no-r32 +33015 0/imm32/no-imm32 +33016 0/imm32/no-imm8 +33017 0/imm32/no-disp32 +33018 0/imm32/no-xm32 +33019 0/imm32/no-x32 +33020 0x11/imm32/alloc-id:fake +33021 _Primitive-loop-if-=/imm32/next +33022 _Primitive-loop-if-=: # (payload primitive) +33023 0x11/imm32/alloc-id:fake:payload +33024 0x11/imm32/alloc-id:fake +33025 _string-loop-if-=/imm32/name +33026 0/imm32/no-inouts +33027 0/imm32/no-inouts 33028 0/imm32/no-outputs -33029 0x11/imm32/alloc-id:fake -33030 _string_0f_82_jump_label/imm32/subx-name -33031 0/imm32/no-rm32 -33032 0/imm32/no-r32 -33033 0/imm32/no-imm32 -33034 0/imm32/no-imm8 -33035 1/imm32/disp32-is-first-inout -33036 0/imm32/no-xm32 -33037 0/imm32/no-x32 -33038 0x11/imm32/alloc-id:fake -33039 _Primitive-break-if-addr>=-named/imm32/next -33040 _Primitive-break-if-addr>=-named: # (payload primitive) -33041 0x11/imm32/alloc-id:fake:payload -33042 0x11/imm32/alloc-id:fake -33043 _string-break-if-addr>=/imm32/name -33044 0x11/imm32/alloc-id:fake -33045 Single-lit-var/imm32/inouts -33046 0/imm32/no-outputs +33029 0/imm32/no-outputs +33030 0x11/imm32/alloc-id:fake +33031 _string_0f_84_jump_loop/imm32/subx-name +33032 0/imm32/no-rm32 +33033 0/imm32/no-r32 +33034 0/imm32/no-imm32 +33035 0/imm32/no-imm8 +33036 0/imm32/no-disp32 +33037 0/imm32/no-xm32 +33038 0/imm32/no-x32 +33039 0x11/imm32/alloc-id:fake +33040 _Primitive-loop-if-!=/imm32/next +33041 _Primitive-loop-if-!=: # (payload primitive) +33042 0x11/imm32/alloc-id:fake:payload +33043 0x11/imm32/alloc-id:fake +33044 _string-loop-if-!=/imm32/name +33045 0/imm32/no-inouts +33046 0/imm32/no-inouts 33047 0/imm32/no-outputs -33048 0x11/imm32/alloc-id:fake -33049 _string_0f_83_jump_label/imm32/subx-name -33050 0/imm32/no-rm32 -33051 0/imm32/no-r32 -33052 0/imm32/no-imm32 -33053 0/imm32/no-imm8 -33054 1/imm32/disp32-is-first-inout -33055 0/imm32/no-xm32 -33056 0/imm32/no-x32 -33057 0x11/imm32/alloc-id:fake -33058 _Primitive-break-if-=-named/imm32/next -33059 _Primitive-break-if-=-named: # (payload primitive) -33060 0x11/imm32/alloc-id:fake:payload -33061 0x11/imm32/alloc-id:fake -33062 _string-break-if-=/imm32/name -33063 0x11/imm32/alloc-id:fake -33064 Single-lit-var/imm32/inouts -33065 0/imm32/no-outputs +33048 0/imm32/no-outputs +33049 0x11/imm32/alloc-id:fake +33050 _string_0f_85_jump_loop/imm32/subx-name +33051 0/imm32/no-rm32 +33052 0/imm32/no-r32 +33053 0/imm32/no-imm32 +33054 0/imm32/no-imm8 +33055 0/imm32/no-disp32 +33056 0/imm32/no-xm32 +33057 0/imm32/no-x32 +33058 0x11/imm32/alloc-id:fake +33059 _Primitive-loop-if-addr<=/imm32/next +33060 _Primitive-loop-if-addr<=: # (payload primitive) +33061 0x11/imm32/alloc-id:fake:payload +33062 0x11/imm32/alloc-id:fake +33063 _string-loop-if-addr<=/imm32/name +33064 0/imm32/no-inouts +33065 0/imm32/no-inouts 33066 0/imm32/no-outputs -33067 0x11/imm32/alloc-id:fake -33068 _string_0f_84_jump_label/imm32/subx-name -33069 0/imm32/no-rm32 -33070 0/imm32/no-r32 -33071 0/imm32/no-imm32 -33072 0/imm32/no-imm8 -33073 1/imm32/disp32-is-first-inout -33074 0/imm32/no-xm32 -33075 0/imm32/no-x32 -33076 0x11/imm32/alloc-id:fake -33077 _Primitive-break-if-!=-named/imm32/next -33078 _Primitive-break-if-!=-named: # (payload primitive) -33079 0x11/imm32/alloc-id:fake:payload -33080 0x11/imm32/alloc-id:fake -33081 _string-break-if-!=/imm32/name -33082 0x11/imm32/alloc-id:fake -33083 Single-lit-var/imm32/inouts -33084 0/imm32/no-outputs +33067 0/imm32/no-outputs +33068 0x11/imm32/alloc-id:fake +33069 _string_0f_86_jump_loop/imm32/subx-name +33070 0/imm32/no-rm32 +33071 0/imm32/no-r32 +33072 0/imm32/no-imm32 +33073 0/imm32/no-imm8 +33074 0/imm32/no-disp32 +33075 0/imm32/no-xm32 +33076 0/imm32/no-x32 +33077 0x11/imm32/alloc-id:fake +33078 _Primitive-loop-if-addr>/imm32/next +33079 _Primitive-loop-if-addr>: # (payload primitive) +33080 0x11/imm32/alloc-id:fake:payload +33081 0x11/imm32/alloc-id:fake +33082 _string-loop-if-addr>/imm32/name +33083 0/imm32/no-inouts +33084 0/imm32/no-inouts 33085 0/imm32/no-outputs -33086 0x11/imm32/alloc-id:fake -33087 _string_0f_85_jump_label/imm32/subx-name -33088 0/imm32/no-rm32 -33089 0/imm32/no-r32 -33090 0/imm32/no-imm32 -33091 0/imm32/no-imm8 -33092 1/imm32/disp32-is-first-inout -33093 0/imm32/no-xm32 -33094 0/imm32/no-x32 -33095 0x11/imm32/alloc-id:fake -33096 _Primitive-break-if-addr<=-named/imm32/next -33097 _Primitive-break-if-addr<=-named: # (payload primitive) -33098 0x11/imm32/alloc-id:fake:payload -33099 0x11/imm32/alloc-id:fake -33100 _string-break-if-addr<=/imm32/name -33101 0x11/imm32/alloc-id:fake -33102 Single-lit-var/imm32/inouts -33103 0/imm32/no-outputs +33086 0/imm32/no-outputs +33087 0x11/imm32/alloc-id:fake +33088 _string_0f_87_jump_loop/imm32/subx-name +33089 0/imm32/no-rm32 +33090 0/imm32/no-r32 +33091 0/imm32/no-imm32 +33092 0/imm32/no-imm8 +33093 0/imm32/no-disp32 +33094 0/imm32/no-xm32 +33095 0/imm32/no-x32 +33096 0x11/imm32/alloc-id:fake +33097 _Primitive-loop-if-</imm32/next +33098 _Primitive-loop-if-<: # (payload primitive) +33099 0x11/imm32/alloc-id:fake:payload +33100 0x11/imm32/alloc-id:fake +33101 _string-loop-if-</imm32/name +33102 0/imm32/no-inouts +33103 0/imm32/no-inouts 33104 0/imm32/no-outputs -33105 0x11/imm32/alloc-id:fake -33106 _string_0f_86_jump_label/imm32/subx-name -33107 0/imm32/no-rm32 -33108 0/imm32/no-r32 -33109 0/imm32/no-imm32 -33110 0/imm32/no-imm8 -33111 1/imm32/disp32-is-first-inout -33112 0/imm32/no-xm32 -33113 0/imm32/no-x32 -33114 0x11/imm32/alloc-id:fake -33115 _Primitive-break-if-addr>-named/imm32/next -33116 _Primitive-break-if-addr>-named: # (payload primitive) -33117 0x11/imm32/alloc-id:fake:payload -33118 0x11/imm32/alloc-id:fake -33119 _string-break-if-addr>/imm32/name -33120 0x11/imm32/alloc-id:fake -33121 Single-lit-var/imm32/inouts -33122 0/imm32/no-outputs +33105 0/imm32/no-outputs +33106 0x11/imm32/alloc-id:fake +33107 _string_0f_8c_jump_loop/imm32/subx-name +33108 0/imm32/no-rm32 +33109 0/imm32/no-r32 +33110 0/imm32/no-imm32 +33111 0/imm32/no-imm8 +33112 0/imm32/no-disp32 +33113 0/imm32/no-xm32 +33114 0/imm32/no-x32 +33115 0x11/imm32/alloc-id:fake +33116 _Primitive-loop-if->=/imm32/next +33117 _Primitive-loop-if->=: # (payload primitive) +33118 0x11/imm32/alloc-id:fake:payload +33119 0x11/imm32/alloc-id:fake +33120 _string-loop-if->=/imm32/name +33121 0/imm32/no-inouts +33122 0/imm32/no-inouts 33123 0/imm32/no-outputs -33124 0x11/imm32/alloc-id:fake -33125 _string_0f_87_jump_label/imm32/subx-name -33126 0/imm32/no-rm32 -33127 0/imm32/no-r32 -33128 0/imm32/no-imm32 -33129 0/imm32/no-imm8 -33130 1/imm32/disp32-is-first-inout -33131 0/imm32/no-xm32 -33132 0/imm32/no-x32 -33133 0x11/imm32/alloc-id:fake -33134 _Primitive-break-if-<-named/imm32/next -33135 _Primitive-break-if-<-named: # (payload primitive) -33136 0x11/imm32/alloc-id:fake:payload -33137 0x11/imm32/alloc-id:fake -33138 _string-break-if-</imm32/name -33139 0x11/imm32/alloc-id:fake -33140 Single-lit-var/imm32/inouts -33141 0/imm32/no-outputs +33124 0/imm32/no-outputs +33125 0x11/imm32/alloc-id:fake +33126 _string_0f_8d_jump_loop/imm32/subx-name +33127 0/imm32/no-rm32 +33128 0/imm32/no-r32 +33129 0/imm32/no-imm32 +33130 0/imm32/no-imm8 +33131 0/imm32/no-disp32 +33132 0/imm32/no-xm32 +33133 0/imm32/no-x32 +33134 0x11/imm32/alloc-id:fake +33135 _Primitive-loop-if-<=/imm32/next +33136 _Primitive-loop-if-<=: # (payload primitive) +33137 0x11/imm32/alloc-id:fake:payload +33138 0x11/imm32/alloc-id:fake +33139 _string-loop-if-<=/imm32/name +33140 0/imm32/no-inouts +33141 0/imm32/no-inouts 33142 0/imm32/no-outputs -33143 0x11/imm32/alloc-id:fake -33144 _string_0f_8c_jump_label/imm32/subx-name -33145 0/imm32/no-rm32 -33146 0/imm32/no-r32 -33147 0/imm32/no-imm32 -33148 0/imm32/no-imm8 -33149 1/imm32/disp32-is-first-inout -33150 0/imm32/no-xm32 -33151 0/imm32/no-x32 -33152 0x11/imm32/alloc-id:fake -33153 _Primitive-break-if->=-named/imm32/next -33154 _Primitive-break-if->=-named: # (payload primitive) -33155 0x11/imm32/alloc-id:fake:payload -33156 0x11/imm32/alloc-id:fake -33157 _string-break-if->=/imm32/name -33158 0x11/imm32/alloc-id:fake -33159 Single-lit-var/imm32/inouts -33160 0/imm32/no-outputs +33143 0/imm32/no-outputs +33144 0x11/imm32/alloc-id:fake +33145 _string_0f_8e_jump_loop/imm32/subx-name +33146 0/imm32/no-rm32 +33147 0/imm32/no-r32 +33148 0/imm32/no-imm32 +33149 0/imm32/no-imm8 +33150 0/imm32/no-disp32 +33151 0/imm32/no-xm32 +33152 0/imm32/no-x32 +33153 0x11/imm32/alloc-id:fake +33154 _Primitive-loop-if->/imm32/next +33155 _Primitive-loop-if->: # (payload primitive) +33156 0x11/imm32/alloc-id:fake:payload +33157 0x11/imm32/alloc-id:fake +33158 _string-loop-if->/imm32/name +33159 0/imm32/no-inouts +33160 0/imm32/no-inouts 33161 0/imm32/no-outputs -33162 0x11/imm32/alloc-id:fake -33163 _string_0f_8d_jump_label/imm32/subx-name -33164 0/imm32/no-rm32 -33165 0/imm32/no-r32 -33166 0/imm32/no-imm32 -33167 0/imm32/no-imm8 -33168 1/imm32/disp32-is-first-inout -33169 0/imm32/no-xm32 -33170 0/imm32/no-x32 -33171 0x11/imm32/alloc-id:fake -33172 _Primitive-break-if-<=-named/imm32/next -33173 _Primitive-break-if-<=-named: # (payload primitive) -33174 0x11/imm32/alloc-id:fake:payload -33175 0x11/imm32/alloc-id:fake -33176 _string-break-if-<=/imm32/name -33177 0x11/imm32/alloc-id:fake -33178 Single-lit-var/imm32/inouts -33179 0/imm32/no-outputs +33162 0/imm32/no-outputs +33163 0x11/imm32/alloc-id:fake +33164 _string_0f_8f_jump_loop/imm32/subx-name +33165 0/imm32/no-rm32 +33166 0/imm32/no-r32 +33167 0/imm32/no-imm32 +33168 0/imm32/no-imm8 +33169 0/imm32/no-disp32 +33170 0/imm32/no-xm32 +33171 0/imm32/no-x32 +33172 0x11/imm32/alloc-id:fake +33173 _Primitive-loop-if-carry/imm32/next +33174 _Primitive-loop-if-carry: # (payload primitive) +33175 0x11/imm32/alloc-id:fake:payload +33176 0x11/imm32/alloc-id:fake +33177 _string-loop-if-carry/imm32/name +33178 0/imm32/no-inouts +33179 0/imm32/no-inouts 33180 0/imm32/no-outputs -33181 0x11/imm32/alloc-id:fake -33182 _string_0f_8e_jump_label/imm32/subx-name -33183 0/imm32/no-rm32 -33184 0/imm32/no-r32 -33185 0/imm32/no-imm32 -33186 0/imm32/no-imm8 -33187 1/imm32/disp32-is-first-inout -33188 0/imm32/no-xm32 -33189 0/imm32/no-x32 -33190 0x11/imm32/alloc-id:fake -33191 _Primitive-break-if->-named/imm32/next -33192 _Primitive-break-if->-named: # (payload primitive) -33193 0x11/imm32/alloc-id:fake:payload -33194 0x11/imm32/alloc-id:fake -33195 _string-break-if->/imm32/name -33196 0x11/imm32/alloc-id:fake -33197 Single-lit-var/imm32/inouts -33198 0/imm32/no-outputs +33181 0/imm32/no-outputs +33182 0x11/imm32/alloc-id:fake +33183 _string_0f_82_jump_loop/imm32/subx-name +33184 0/imm32/no-rm32 +33185 0/imm32/no-r32 +33186 0/imm32/no-imm32 +33187 0/imm32/no-imm8 +33188 0/imm32/no-disp32 +33189 0/imm32/no-xm32 +33190 0/imm32/no-x32 +33191 0x11/imm32/alloc-id:fake +33192 _Primitive-loop-if-not-carry/imm32/next +33193 _Primitive-loop-if-not-carry: # (payload primitive) +33194 0x11/imm32/alloc-id:fake:payload +33195 0x11/imm32/alloc-id:fake +33196 _string-loop-if-not-carry/imm32/name +33197 0/imm32/no-inouts +33198 0/imm32/no-inouts 33199 0/imm32/no-outputs -33200 0x11/imm32/alloc-id:fake -33201 _string_0f_8f_jump_label/imm32/subx-name -33202 0/imm32/no-rm32 -33203 0/imm32/no-r32 -33204 0/imm32/no-imm32 -33205 0/imm32/no-imm8 -33206 1/imm32/disp32-is-first-inout -33207 0/imm32/no-xm32 -33208 0/imm32/no-x32 -33209 0x11/imm32/alloc-id:fake -33210 _Primitive-break-named/imm32/next -33211 _Primitive-break-named: # (payload primitive) -33212 0x11/imm32/alloc-id:fake:payload -33213 0x11/imm32/alloc-id:fake -33214 _string-break/imm32/name -33215 0x11/imm32/alloc-id:fake -33216 Single-lit-var/imm32/inouts -33217 0/imm32/no-outputs +33200 0/imm32/no-outputs +33201 0x11/imm32/alloc-id:fake +33202 _string_0f_83_jump_loop/imm32/subx-name +33203 0/imm32/no-rm32 +33204 0/imm32/no-r32 +33205 0/imm32/no-imm32 +33206 0/imm32/no-imm8 +33207 0/imm32/no-disp32 +33208 0/imm32/no-xm32 +33209 0/imm32/no-x32 +33210 0x11/imm32/alloc-id:fake +33211 _Primitive-loop-if-overflow/imm32/next +33212 _Primitive-loop-if-overflow: # (payload primitive) +33213 0x11/imm32/alloc-id:fake:payload +33214 0x11/imm32/alloc-id:fake +33215 _string-loop-if-overflow/imm32/name +33216 0/imm32/no-inouts +33217 0/imm32/no-inouts 33218 0/imm32/no-outputs -33219 0x11/imm32/alloc-id:fake -33220 _string_e9_jump_label/imm32/subx-name -33221 0/imm32/no-rm32 -33222 0/imm32/no-r32 -33223 0/imm32/no-imm32 -33224 0/imm32/no-imm8 -33225 1/imm32/disp32-is-first-inout -33226 0/imm32/no-xm32 -33227 0/imm32/no-x32 -33228 0x11/imm32/alloc-id:fake -33229 _Primitive-loop-if-addr<-named/imm32/next -33230 _Primitive-loop-if-addr<-named: # (payload primitive) -33231 0x11/imm32/alloc-id:fake:payload -33232 0x11/imm32/alloc-id:fake -33233 _string-loop-if-addr</imm32/name -33234 0x11/imm32/alloc-id:fake -33235 Single-lit-var/imm32/inouts -33236 0/imm32/no-outputs +33219 0/imm32/no-outputs +33220 0x11/imm32/alloc-id:fake +33221 _string_0f_80_jump_loop/imm32/subx-name +33222 0/imm32/no-rm32 +33223 0/imm32/no-r32 +33224 0/imm32/no-imm32 +33225 0/imm32/no-imm8 +33226 0/imm32/no-disp32 +33227 0/imm32/no-xm32 +33228 0/imm32/no-x32 +33229 0x11/imm32/alloc-id:fake +33230 _Primitive-loop-if-not-overflow/imm32/next +33231 _Primitive-loop-if-not-overflow: # (payload primitive) +33232 0x11/imm32/alloc-id:fake:payload +33233 0x11/imm32/alloc-id:fake +33234 _string-loop-if-not-overflow/imm32/name +33235 0/imm32/no-inouts +33236 0/imm32/no-inouts 33237 0/imm32/no-outputs -33238 0x11/imm32/alloc-id:fake -33239 _string_0f_82_jump_label/imm32/subx-name -33240 0/imm32/no-rm32 -33241 0/imm32/no-r32 -33242 0/imm32/no-imm32 -33243 0/imm32/no-imm8 -33244 1/imm32/disp32-is-first-inout -33245 0/imm32/no-xm32 -33246 0/imm32/no-x32 -33247 0x11/imm32/alloc-id:fake -33248 _Primitive-loop-if-addr>=-named/imm32/next -33249 _Primitive-loop-if-addr>=-named: # (payload primitive) -33250 0x11/imm32/alloc-id:fake:payload -33251 0x11/imm32/alloc-id:fake -33252 _string-loop-if-addr>=/imm32/name -33253 0x11/imm32/alloc-id:fake -33254 Single-lit-var/imm32/inouts -33255 0/imm32/no-outputs +33238 0/imm32/no-outputs +33239 0x11/imm32/alloc-id:fake +33240 _string_0f_81_jump_loop/imm32/subx-name +33241 0/imm32/no-rm32 +33242 0/imm32/no-r32 +33243 0/imm32/no-imm32 +33244 0/imm32/no-imm8 +33245 0/imm32/no-disp32 +33246 0/imm32/no-xm32 +33247 0/imm32/no-x32 +33248 0x11/imm32/alloc-id:fake +33249 _Primitive-loop/imm32/next # we probably don't need an unconditional break +33250 _Primitive-loop: # (payload primitive) +33251 0x11/imm32/alloc-id:fake:payload +33252 0x11/imm32/alloc-id:fake +33253 _string-loop/imm32/name +33254 0/imm32/no-inouts +33255 0/imm32/no-inouts 33256 0/imm32/no-outputs -33257 0x11/imm32/alloc-id:fake -33258 _string_0f_83_jump_label/imm32/subx-name -33259 0/imm32/no-rm32 -33260 0/imm32/no-r32 -33261 0/imm32/no-imm32 -33262 0/imm32/no-imm8 -33263 1/imm32/disp32-is-first-inout -33264 0/imm32/no-xm32 -33265 0/imm32/no-x32 -33266 0x11/imm32/alloc-id:fake -33267 _Primitive-loop-if-=-named/imm32/next -33268 _Primitive-loop-if-=-named: # (payload primitive) -33269 0x11/imm32/alloc-id:fake:payload -33270 0x11/imm32/alloc-id:fake -33271 _string-loop-if-=/imm32/name +33257 0/imm32/no-outputs +33258 0x11/imm32/alloc-id:fake +33259 _string_e9_jump_loop/imm32/subx-name +33260 0/imm32/no-rm32 +33261 0/imm32/no-r32 +33262 0/imm32/no-imm32 +33263 0/imm32/no-imm8 +33264 0/imm32/no-disp32 +33265 0/imm32/no-xm32 +33266 0/imm32/no-x32 +33267 0x11/imm32/alloc-id:fake +33268 _Primitive-break-if-addr<-named/imm32/next +33269 # - branches to named blocks +33270 _Primitive-break-if-addr<-named: # (payload primitive) +33271 0x11/imm32/alloc-id:fake:payload 33272 0x11/imm32/alloc-id:fake -33273 Single-lit-var/imm32/inouts -33274 0/imm32/no-outputs -33275 0/imm32/no-outputs -33276 0x11/imm32/alloc-id:fake -33277 _string_0f_84_jump_label/imm32/subx-name -33278 0/imm32/no-rm32 -33279 0/imm32/no-r32 -33280 0/imm32/no-imm32 -33281 0/imm32/no-imm8 -33282 1/imm32/disp32-is-first-inout -33283 0/imm32/no-xm32 -33284 0/imm32/no-x32 -33285 0x11/imm32/alloc-id:fake -33286 _Primitive-loop-if-!=-named/imm32/next -33287 _Primitive-loop-if-!=-named: # (payload primitive) -33288 0x11/imm32/alloc-id:fake:payload -33289 0x11/imm32/alloc-id:fake -33290 _string-loop-if-!=/imm32/name +33273 _string-break-if-addr</imm32/name +33274 0x11/imm32/alloc-id:fake +33275 Single-lit-var/imm32/inouts +33276 0/imm32/no-outputs +33277 0/imm32/no-outputs +33278 0x11/imm32/alloc-id:fake +33279 _string_0f_82_jump_label/imm32/subx-name +33280 0/imm32/no-rm32 +33281 0/imm32/no-r32 +33282 0/imm32/no-imm32 +33283 0/imm32/no-imm8 +33284 1/imm32/disp32-is-first-inout +33285 0/imm32/no-xm32 +33286 0/imm32/no-x32 +33287 0x11/imm32/alloc-id:fake +33288 _Primitive-break-if-addr>=-named/imm32/next +33289 _Primitive-break-if-addr>=-named: # (payload primitive) +33290 0x11/imm32/alloc-id:fake:payload 33291 0x11/imm32/alloc-id:fake -33292 Single-lit-var/imm32/inouts -33293 0/imm32/no-outputs -33294 0/imm32/no-outputs -33295 0x11/imm32/alloc-id:fake -33296 _string_0f_85_jump_label/imm32/subx-name -33297 0/imm32/no-rm32 -33298 0/imm32/no-r32 -33299 0/imm32/no-imm32 -33300 0/imm32/no-imm8 -33301 1/imm32/disp32-is-first-inout -33302 0/imm32/no-xm32 -33303 0/imm32/no-x32 -33304 0x11/imm32/alloc-id:fake -33305 _Primitive-loop-if-addr<=-named/imm32/next -33306 _Primitive-loop-if-addr<=-named: # (payload primitive) -33307 0x11/imm32/alloc-id:fake:payload -33308 0x11/imm32/alloc-id:fake -33309 _string-loop-if-addr<=/imm32/name +33292 _string-break-if-addr>=/imm32/name +33293 0x11/imm32/alloc-id:fake +33294 Single-lit-var/imm32/inouts +33295 0/imm32/no-outputs +33296 0/imm32/no-outputs +33297 0x11/imm32/alloc-id:fake +33298 _string_0f_83_jump_label/imm32/subx-name +33299 0/imm32/no-rm32 +33300 0/imm32/no-r32 +33301 0/imm32/no-imm32 +33302 0/imm32/no-imm8 +33303 1/imm32/disp32-is-first-inout +33304 0/imm32/no-xm32 +33305 0/imm32/no-x32 +33306 0x11/imm32/alloc-id:fake +33307 _Primitive-break-if-=-named/imm32/next +33308 _Primitive-break-if-=-named: # (payload primitive) +33309 0x11/imm32/alloc-id:fake:payload 33310 0x11/imm32/alloc-id:fake -33311 Single-lit-var/imm32/inouts -33312 0/imm32/no-outputs -33313 0/imm32/no-outputs -33314 0x11/imm32/alloc-id:fake -33315 _string_0f_86_jump_label/imm32/subx-name -33316 0/imm32/no-rm32 -33317 0/imm32/no-r32 -33318 0/imm32/no-imm32 -33319 0/imm32/no-imm8 -33320 1/imm32/disp32-is-first-inout -33321 0/imm32/no-xm32 -33322 0/imm32/no-x32 -33323 0x11/imm32/alloc-id:fake -33324 _Primitive-loop-if-addr>-named/imm32/next -33325 _Primitive-loop-if-addr>-named: # (payload primitive) -33326 0x11/imm32/alloc-id:fake:payload -33327 0x11/imm32/alloc-id:fake -33328 _string-loop-if-addr>/imm32/name +33311 _string-break-if-=/imm32/name +33312 0x11/imm32/alloc-id:fake +33313 Single-lit-var/imm32/inouts +33314 0/imm32/no-outputs +33315 0/imm32/no-outputs +33316 0x11/imm32/alloc-id:fake +33317 _string_0f_84_jump_label/imm32/subx-name +33318 0/imm32/no-rm32 +33319 0/imm32/no-r32 +33320 0/imm32/no-imm32 +33321 0/imm32/no-imm8 +33322 1/imm32/disp32-is-first-inout +33323 0/imm32/no-xm32 +33324 0/imm32/no-x32 +33325 0x11/imm32/alloc-id:fake +33326 _Primitive-break-if-!=-named/imm32/next +33327 _Primitive-break-if-!=-named: # (payload primitive) +33328 0x11/imm32/alloc-id:fake:payload 33329 0x11/imm32/alloc-id:fake -33330 Single-lit-var/imm32/inouts -33331 0/imm32/no-outputs -33332 0/imm32/no-outputs -33333 0x11/imm32/alloc-id:fake -33334 _string_0f_87_jump_label/imm32/subx-name -33335 0/imm32/no-rm32 -33336 0/imm32/no-r32 -33337 0/imm32/no-imm32 -33338 0/imm32/no-imm8 -33339 1/imm32/disp32-is-first-inout -33340 0/imm32/no-xm32 -33341 0/imm32/no-x32 -33342 0x11/imm32/alloc-id:fake -33343 _Primitive-loop-if-<-named/imm32/next -33344 _Primitive-loop-if-<-named: # (payload primitive) -33345 0x11/imm32/alloc-id:fake:payload -33346 0x11/imm32/alloc-id:fake -33347 _string-loop-if-</imm32/name +33330 _string-break-if-!=/imm32/name +33331 0x11/imm32/alloc-id:fake +33332 Single-lit-var/imm32/inouts +33333 0/imm32/no-outputs +33334 0/imm32/no-outputs +33335 0x11/imm32/alloc-id:fake +33336 _string_0f_85_jump_label/imm32/subx-name +33337 0/imm32/no-rm32 +33338 0/imm32/no-r32 +33339 0/imm32/no-imm32 +33340 0/imm32/no-imm8 +33341 1/imm32/disp32-is-first-inout +33342 0/imm32/no-xm32 +33343 0/imm32/no-x32 +33344 0x11/imm32/alloc-id:fake +33345 _Primitive-break-if-addr<=-named/imm32/next +33346 _Primitive-break-if-addr<=-named: # (payload primitive) +33347 0x11/imm32/alloc-id:fake:payload 33348 0x11/imm32/alloc-id:fake -33349 Single-lit-var/imm32/inouts -33350 0/imm32/no-outputs -33351 0/imm32/no-outputs -33352 0x11/imm32/alloc-id:fake -33353 _string_0f_8c_jump_label/imm32/subx-name -33354 0/imm32/no-rm32 -33355 0/imm32/no-r32 -33356 0/imm32/no-imm32 -33357 0/imm32/no-imm8 -33358 1/imm32/disp32-is-first-inout -33359 0/imm32/no-xm32 -33360 0/imm32/no-x32 -33361 0x11/imm32/alloc-id:fake -33362 _Primitive-loop-if->=-named/imm32/next -33363 _Primitive-loop-if->=-named: # (payload primitive) -33364 0x11/imm32/alloc-id:fake:payload -33365 0x11/imm32/alloc-id:fake -33366 _string-loop-if->=/imm32/name +33349 _string-break-if-addr<=/imm32/name +33350 0x11/imm32/alloc-id:fake +33351 Single-lit-var/imm32/inouts +33352 0/imm32/no-outputs +33353 0/imm32/no-outputs +33354 0x11/imm32/alloc-id:fake +33355 _string_0f_86_jump_label/imm32/subx-name +33356 0/imm32/no-rm32 +33357 0/imm32/no-r32 +33358 0/imm32/no-imm32 +33359 0/imm32/no-imm8 +33360 1/imm32/disp32-is-first-inout +33361 0/imm32/no-xm32 +33362 0/imm32/no-x32 +33363 0x11/imm32/alloc-id:fake +33364 _Primitive-break-if-addr>-named/imm32/next +33365 _Primitive-break-if-addr>-named: # (payload primitive) +33366 0x11/imm32/alloc-id:fake:payload 33367 0x11/imm32/alloc-id:fake -33368 Single-lit-var/imm32/inouts -33369 0/imm32/no-outputs -33370 0/imm32/no-outputs -33371 0x11/imm32/alloc-id:fake -33372 _string_0f_8d_jump_label/imm32/subx-name -33373 0/imm32/no-rm32 -33374 0/imm32/no-r32 -33375 0/imm32/no-imm32 -33376 0/imm32/no-imm8 -33377 1/imm32/disp32-is-first-inout -33378 0/imm32/no-xm32 -33379 0/imm32/no-x32 -33380 0x11/imm32/alloc-id:fake -33381 _Primitive-loop-if-<=-named/imm32/next -33382 _Primitive-loop-if-<=-named: # (payload primitive) -33383 0x11/imm32/alloc-id:fake:payload -33384 0x11/imm32/alloc-id:fake -33385 _string-loop-if-<=/imm32/name +33368 _string-break-if-addr>/imm32/name +33369 0x11/imm32/alloc-id:fake +33370 Single-lit-var/imm32/inouts +33371 0/imm32/no-outputs +33372 0/imm32/no-outputs +33373 0x11/imm32/alloc-id:fake +33374 _string_0f_87_jump_label/imm32/subx-name +33375 0/imm32/no-rm32 +33376 0/imm32/no-r32 +33377 0/imm32/no-imm32 +33378 0/imm32/no-imm8 +33379 1/imm32/disp32-is-first-inout +33380 0/imm32/no-xm32 +33381 0/imm32/no-x32 +33382 0x11/imm32/alloc-id:fake +33383 _Primitive-break-if-<-named/imm32/next +33384 _Primitive-break-if-<-named: # (payload primitive) +33385 0x11/imm32/alloc-id:fake:payload 33386 0x11/imm32/alloc-id:fake -33387 Single-lit-var/imm32/inouts -33388 0/imm32/no-outputs -33389 0/imm32/no-outputs -33390 0x11/imm32/alloc-id:fake -33391 _string_0f_8e_jump_label/imm32/subx-name -33392 0/imm32/no-rm32 -33393 0/imm32/no-r32 -33394 0/imm32/no-imm32 -33395 0/imm32/no-imm8 -33396 1/imm32/disp32-is-first-inout -33397 0/imm32/no-xm32 -33398 0/imm32/no-x32 -33399 0x11/imm32/alloc-id:fake -33400 _Primitive-loop-if->-named/imm32/next -33401 _Primitive-loop-if->-named: # (payload primitive) -33402 0x11/imm32/alloc-id:fake:payload -33403 0x11/imm32/alloc-id:fake -33404 _string-loop-if->/imm32/name +33387 _string-break-if-</imm32/name +33388 0x11/imm32/alloc-id:fake +33389 Single-lit-var/imm32/inouts +33390 0/imm32/no-outputs +33391 0/imm32/no-outputs +33392 0x11/imm32/alloc-id:fake +33393 _string_0f_8c_jump_label/imm32/subx-name +33394 0/imm32/no-rm32 +33395 0/imm32/no-r32 +33396 0/imm32/no-imm32 +33397 0/imm32/no-imm8 +33398 1/imm32/disp32-is-first-inout +33399 0/imm32/no-xm32 +33400 0/imm32/no-x32 +33401 0x11/imm32/alloc-id:fake +33402 _Primitive-break-if->=-named/imm32/next +33403 _Primitive-break-if->=-named: # (payload primitive) +33404 0x11/imm32/alloc-id:fake:payload 33405 0x11/imm32/alloc-id:fake -33406 Single-lit-var/imm32/inouts -33407 0/imm32/no-outputs -33408 0/imm32/no-outputs -33409 0x11/imm32/alloc-id:fake -33410 _string_0f_8f_jump_label/imm32/subx-name -33411 0/imm32/no-rm32 -33412 0/imm32/no-r32 -33413 0/imm32/no-imm32 -33414 0/imm32/no-imm8 -33415 1/imm32/disp32-is-first-inout -33416 0/imm32/no-xm32 -33417 0/imm32/no-x32 -33418 0x11/imm32/alloc-id:fake -33419 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -33420 _Primitive-loop-named: # (payload primitive) -33421 0x11/imm32/alloc-id:fake:payload -33422 0x11/imm32/alloc-id:fake -33423 _string-loop/imm32/name +33406 _string-break-if->=/imm32/name +33407 0x11/imm32/alloc-id:fake +33408 Single-lit-var/imm32/inouts +33409 0/imm32/no-outputs +33410 0/imm32/no-outputs +33411 0x11/imm32/alloc-id:fake +33412 _string_0f_8d_jump_label/imm32/subx-name +33413 0/imm32/no-rm32 +33414 0/imm32/no-r32 +33415 0/imm32/no-imm32 +33416 0/imm32/no-imm8 +33417 1/imm32/disp32-is-first-inout +33418 0/imm32/no-xm32 +33419 0/imm32/no-x32 +33420 0x11/imm32/alloc-id:fake +33421 _Primitive-break-if-<=-named/imm32/next +33422 _Primitive-break-if-<=-named: # (payload primitive) +33423 0x11/imm32/alloc-id:fake:payload 33424 0x11/imm32/alloc-id:fake -33425 Single-lit-var/imm32/inouts -33426 0/imm32/no-outputs -33427 0/imm32/no-outputs -33428 0x11/imm32/alloc-id:fake -33429 _string_e9_jump_label/imm32/subx-name -33430 0/imm32/no-rm32 -33431 0/imm32/no-r32 -33432 0/imm32/no-imm32 -33433 0/imm32/no-imm8 -33434 1/imm32/disp32-is-first-inout -33435 0/imm32/no-xm32 -33436 0/imm32/no-x32 -33437 0x11/imm32/alloc-id:fake -33438 _Primitive-break-if-float</imm32/next -33439 # - branches based on floating-point comparisons -33440 _Primitive-break-if-float<: # (payload primitive) -33441 0x11/imm32/alloc-id:fake:payload -33442 0x11/imm32/alloc-id:fake -33443 _string-break-if-float</imm32/name -33444 0/imm32/no-inouts -33445 0/imm32/no-inouts -33446 0/imm32/no-outputs +33425 _string-break-if-<=/imm32/name +33426 0x11/imm32/alloc-id:fake +33427 Single-lit-var/imm32/inouts +33428 0/imm32/no-outputs +33429 0/imm32/no-outputs +33430 0x11/imm32/alloc-id:fake +33431 _string_0f_8e_jump_label/imm32/subx-name +33432 0/imm32/no-rm32 +33433 0/imm32/no-r32 +33434 0/imm32/no-imm32 +33435 0/imm32/no-imm8 +33436 1/imm32/disp32-is-first-inout +33437 0/imm32/no-xm32 +33438 0/imm32/no-x32 +33439 0x11/imm32/alloc-id:fake +33440 _Primitive-break-if->-named/imm32/next +33441 _Primitive-break-if->-named: # (payload primitive) +33442 0x11/imm32/alloc-id:fake:payload +33443 0x11/imm32/alloc-id:fake +33444 _string-break-if->/imm32/name +33445 0x11/imm32/alloc-id:fake +33446 Single-lit-var/imm32/inouts 33447 0/imm32/no-outputs -33448 0x11/imm32/alloc-id:fake -33449 _string_0f_82_jump_break/imm32/subx-name -33450 0/imm32/no-rm32 -33451 0/imm32/no-r32 -33452 0/imm32/no-imm32 -33453 0/imm32/no-imm8 -33454 0/imm32/no-disp32 -33455 0/imm32/no-xm32 -33456 0/imm32/no-x32 -33457 0x11/imm32/alloc-id:fake -33458 _Primitive-break-if-float>=/imm32/next -33459 _Primitive-break-if-float>=: # (payload primitive) -33460 0x11/imm32/alloc-id:fake:payload -33461 0x11/imm32/alloc-id:fake -33462 _string-break-if-float>=/imm32/name -33463 0/imm32/no-inouts -33464 0/imm32/no-inouts -33465 0/imm32/no-outputs +33448 0/imm32/no-outputs +33449 0x11/imm32/alloc-id:fake +33450 _string_0f_8f_jump_label/imm32/subx-name +33451 0/imm32/no-rm32 +33452 0/imm32/no-r32 +33453 0/imm32/no-imm32 +33454 0/imm32/no-imm8 +33455 1/imm32/disp32-is-first-inout +33456 0/imm32/no-xm32 +33457 0/imm32/no-x32 +33458 0x11/imm32/alloc-id:fake +33459 _Primitive-break-named/imm32/next +33460 _Primitive-break-named: # (payload primitive) +33461 0x11/imm32/alloc-id:fake:payload +33462 0x11/imm32/alloc-id:fake +33463 _string-break/imm32/name +33464 0x11/imm32/alloc-id:fake +33465 Single-lit-var/imm32/inouts 33466 0/imm32/no-outputs -33467 0x11/imm32/alloc-id:fake -33468 _string_0f_83_jump_break/imm32/subx-name -33469 0/imm32/no-rm32 -33470 0/imm32/no-r32 -33471 0/imm32/no-imm32 -33472 0/imm32/no-imm8 -33473 0/imm32/no-disp32 -33474 0/imm32/no-xm32 -33475 0/imm32/no-x32 -33476 0x11/imm32/alloc-id:fake -33477 _Primitive-break-if-float<=/imm32/next -33478 _Primitive-break-if-float<=: # (payload primitive) -33479 0x11/imm32/alloc-id:fake:payload -33480 0x11/imm32/alloc-id:fake -33481 _string-break-if-float<=/imm32/name -33482 0/imm32/no-inouts -33483 0/imm32/no-inouts -33484 0/imm32/no-outputs +33467 0/imm32/no-outputs +33468 0x11/imm32/alloc-id:fake +33469 _string_e9_jump_label/imm32/subx-name +33470 0/imm32/no-rm32 +33471 0/imm32/no-r32 +33472 0/imm32/no-imm32 +33473 0/imm32/no-imm8 +33474 1/imm32/disp32-is-first-inout +33475 0/imm32/no-xm32 +33476 0/imm32/no-x32 +33477 0x11/imm32/alloc-id:fake +33478 _Primitive-loop-if-addr<-named/imm32/next +33479 _Primitive-loop-if-addr<-named: # (payload primitive) +33480 0x11/imm32/alloc-id:fake:payload +33481 0x11/imm32/alloc-id:fake +33482 _string-loop-if-addr</imm32/name +33483 0x11/imm32/alloc-id:fake +33484 Single-lit-var/imm32/inouts 33485 0/imm32/no-outputs -33486 0x11/imm32/alloc-id:fake -33487 _string_0f_86_jump_break/imm32/subx-name -33488 0/imm32/no-rm32 -33489 0/imm32/no-r32 -33490 0/imm32/no-imm32 -33491 0/imm32/no-imm8 -33492 0/imm32/no-disp32 -33493 0/imm32/no-xm32 -33494 0/imm32/no-x32 -33495 0x11/imm32/alloc-id:fake -33496 _Primitive-break-if-float>/imm32/next -33497 _Primitive-break-if-float>: # (payload primitive) -33498 0x11/imm32/alloc-id:fake:payload -33499 0x11/imm32/alloc-id:fake -33500 _string-break-if-float>/imm32/name -33501 0/imm32/no-inouts -33502 0/imm32/no-inouts -33503 0/imm32/no-outputs +33486 0/imm32/no-outputs +33487 0x11/imm32/alloc-id:fake +33488 _string_0f_82_jump_label/imm32/subx-name +33489 0/imm32/no-rm32 +33490 0/imm32/no-r32 +33491 0/imm32/no-imm32 +33492 0/imm32/no-imm8 +33493 1/imm32/disp32-is-first-inout +33494 0/imm32/no-xm32 +33495 0/imm32/no-x32 +33496 0x11/imm32/alloc-id:fake +33497 _Primitive-loop-if-addr>=-named/imm32/next +33498 _Primitive-loop-if-addr>=-named: # (payload primitive) +33499 0x11/imm32/alloc-id:fake:payload +33500 0x11/imm32/alloc-id:fake +33501 _string-loop-if-addr>=/imm32/name +33502 0x11/imm32/alloc-id:fake +33503 Single-lit-var/imm32/inouts 33504 0/imm32/no-outputs -33505 0x11/imm32/alloc-id:fake -33506 _string_0f_87_jump_break/imm32/subx-name -33507 0/imm32/no-rm32 -33508 0/imm32/no-r32 -33509 0/imm32/no-imm32 -33510 0/imm32/no-imm8 -33511 0/imm32/no-disp32 -33512 0/imm32/no-xm32 -33513 0/imm32/no-x32 -33514 0x11/imm32/alloc-id:fake -33515 _Primitive-loop-if-float</imm32/next -33516 _Primitive-loop-if-float<: # (payload primitive) -33517 0x11/imm32/alloc-id:fake:payload -33518 0x11/imm32/alloc-id:fake -33519 _string-loop-if-float</imm32/name -33520 0/imm32/no-inouts -33521 0/imm32/no-inouts -33522 0/imm32/no-outputs +33505 0/imm32/no-outputs +33506 0x11/imm32/alloc-id:fake +33507 _string_0f_83_jump_label/imm32/subx-name +33508 0/imm32/no-rm32 +33509 0/imm32/no-r32 +33510 0/imm32/no-imm32 +33511 0/imm32/no-imm8 +33512 1/imm32/disp32-is-first-inout +33513 0/imm32/no-xm32 +33514 0/imm32/no-x32 +33515 0x11/imm32/alloc-id:fake +33516 _Primitive-loop-if-=-named/imm32/next +33517 _Primitive-loop-if-=-named: # (payload primitive) +33518 0x11/imm32/alloc-id:fake:payload +33519 0x11/imm32/alloc-id:fake +33520 _string-loop-if-=/imm32/name +33521 0x11/imm32/alloc-id:fake +33522 Single-lit-var/imm32/inouts 33523 0/imm32/no-outputs -33524 0x11/imm32/alloc-id:fake -33525 _string_0f_82_jump_loop/imm32/subx-name -33526 0/imm32/no-rm32 -33527 0/imm32/no-r32 -33528 0/imm32/no-imm32 -33529 0/imm32/no-imm8 -33530 0/imm32/no-disp32 -33531 0/imm32/no-xm32 -33532 0/imm32/no-x32 -33533 0x11/imm32/alloc-id:fake -33534 _Primitive-loop-if-float>=/imm32/next -33535 _Primitive-loop-if-float>=: # (payload primitive) -33536 0x11/imm32/alloc-id:fake:payload -33537 0x11/imm32/alloc-id:fake -33538 _string-loop-if-float>=/imm32/name -33539 0/imm32/no-inouts -33540 0/imm32/no-inouts -33541 0/imm32/no-outputs +33524 0/imm32/no-outputs +33525 0x11/imm32/alloc-id:fake +33526 _string_0f_84_jump_label/imm32/subx-name +33527 0/imm32/no-rm32 +33528 0/imm32/no-r32 +33529 0/imm32/no-imm32 +33530 0/imm32/no-imm8 +33531 1/imm32/disp32-is-first-inout +33532 0/imm32/no-xm32 +33533 0/imm32/no-x32 +33534 0x11/imm32/alloc-id:fake +33535 _Primitive-loop-if-!=-named/imm32/next +33536 _Primitive-loop-if-!=-named: # (payload primitive) +33537 0x11/imm32/alloc-id:fake:payload +33538 0x11/imm32/alloc-id:fake +33539 _string-loop-if-!=/imm32/name +33540 0x11/imm32/alloc-id:fake +33541 Single-lit-var/imm32/inouts 33542 0/imm32/no-outputs -33543 0x11/imm32/alloc-id:fake -33544 _string_0f_83_jump_loop/imm32/subx-name -33545 0/imm32/no-rm32 -33546 0/imm32/no-r32 -33547 0/imm32/no-imm32 -33548 0/imm32/no-imm8 -33549 0/imm32/no-disp32 -33550 0/imm32/no-xm32 -33551 0/imm32/no-x32 -33552 0x11/imm32/alloc-id:fake -33553 _Primitive-loop-if-float<=/imm32/next -33554 _Primitive-loop-if-float<=: # (payload primitive) -33555 0x11/imm32/alloc-id:fake:payload -33556 0x11/imm32/alloc-id:fake -33557 _string-loop-if-float<=/imm32/name -33558 0/imm32/no-inouts -33559 0/imm32/no-inouts -33560 0/imm32/no-outputs +33543 0/imm32/no-outputs +33544 0x11/imm32/alloc-id:fake +33545 _string_0f_85_jump_label/imm32/subx-name +33546 0/imm32/no-rm32 +33547 0/imm32/no-r32 +33548 0/imm32/no-imm32 +33549 0/imm32/no-imm8 +33550 1/imm32/disp32-is-first-inout +33551 0/imm32/no-xm32 +33552 0/imm32/no-x32 +33553 0x11/imm32/alloc-id:fake +33554 _Primitive-loop-if-addr<=-named/imm32/next +33555 _Primitive-loop-if-addr<=-named: # (payload primitive) +33556 0x11/imm32/alloc-id:fake:payload +33557 0x11/imm32/alloc-id:fake +33558 _string-loop-if-addr<=/imm32/name +33559 0x11/imm32/alloc-id:fake +33560 Single-lit-var/imm32/inouts 33561 0/imm32/no-outputs -33562 0x11/imm32/alloc-id:fake -33563 _string_0f_86_jump_loop/imm32/subx-name -33564 0/imm32/no-rm32 -33565 0/imm32/no-r32 -33566 0/imm32/no-imm32 -33567 0/imm32/no-imm8 -33568 0/imm32/no-disp32 -33569 0/imm32/no-xm32 -33570 0/imm32/no-x32 -33571 0x11/imm32/alloc-id:fake -33572 _Primitive-loop-if-float>/imm32/next -33573 _Primitive-loop-if-float>: # (payload primitive) -33574 0x11/imm32/alloc-id:fake:payload -33575 0x11/imm32/alloc-id:fake -33576 _string-loop-if-float>/imm32/name -33577 0/imm32/no-inouts -33578 0/imm32/no-inouts -33579 0/imm32/no-outputs +33562 0/imm32/no-outputs +33563 0x11/imm32/alloc-id:fake +33564 _string_0f_86_jump_label/imm32/subx-name +33565 0/imm32/no-rm32 +33566 0/imm32/no-r32 +33567 0/imm32/no-imm32 +33568 0/imm32/no-imm8 +33569 1/imm32/disp32-is-first-inout +33570 0/imm32/no-xm32 +33571 0/imm32/no-x32 +33572 0x11/imm32/alloc-id:fake +33573 _Primitive-loop-if-addr>-named/imm32/next +33574 _Primitive-loop-if-addr>-named: # (payload primitive) +33575 0x11/imm32/alloc-id:fake:payload +33576 0x11/imm32/alloc-id:fake +33577 _string-loop-if-addr>/imm32/name +33578 0x11/imm32/alloc-id:fake +33579 Single-lit-var/imm32/inouts 33580 0/imm32/no-outputs -33581 0x11/imm32/alloc-id:fake -33582 _string_0f_87_jump_loop/imm32/subx-name -33583 0/imm32/no-rm32 -33584 0/imm32/no-r32 -33585 0/imm32/no-imm32 -33586 0/imm32/no-imm8 -33587 0/imm32/no-disp32 -33588 0/imm32/no-xm32 -33589 0/imm32/no-x32 -33590 0x11/imm32/alloc-id:fake -33591 _Primitive-break-if-float<-named/imm32/next -33592 _Primitive-break-if-float<-named: # (payload primitive) -33593 0x11/imm32/alloc-id:fake:payload -33594 0x11/imm32/alloc-id:fake -33595 _string-break-if-float</imm32/name -33596 0x11/imm32/alloc-id:fake -33597 Single-lit-var/imm32/inouts -33598 0/imm32/no-outputs +33581 0/imm32/no-outputs +33582 0x11/imm32/alloc-id:fake +33583 _string_0f_87_jump_label/imm32/subx-name +33584 0/imm32/no-rm32 +33585 0/imm32/no-r32 +33586 0/imm32/no-imm32 +33587 0/imm32/no-imm8 +33588 1/imm32/disp32-is-first-inout +33589 0/imm32/no-xm32 +33590 0/imm32/no-x32 +33591 0x11/imm32/alloc-id:fake +33592 _Primitive-loop-if-<-named/imm32/next +33593 _Primitive-loop-if-<-named: # (payload primitive) +33594 0x11/imm32/alloc-id:fake:payload +33595 0x11/imm32/alloc-id:fake +33596 _string-loop-if-</imm32/name +33597 0x11/imm32/alloc-id:fake +33598 Single-lit-var/imm32/inouts 33599 0/imm32/no-outputs -33600 0x11/imm32/alloc-id:fake -33601 _string_0f_82_jump_label/imm32/subx-name -33602 0/imm32/no-rm32 -33603 0/imm32/no-r32 -33604 0/imm32/no-imm32 -33605 0/imm32/no-imm8 -33606 1/imm32/disp32-is-first-inout -33607 0/imm32/no-xm32 -33608 0/imm32/no-x32 -33609 0x11/imm32/alloc-id:fake -33610 _Primitive-break-if-float>=-named/imm32/next -33611 _Primitive-break-if-float>=-named: # (payload primitive) -33612 0x11/imm32/alloc-id:fake:payload -33613 0x11/imm32/alloc-id:fake -33614 _string-break-if-float>=/imm32/name -33615 0x11/imm32/alloc-id:fake -33616 Single-lit-var/imm32/inouts -33617 0/imm32/no-outputs +33600 0/imm32/no-outputs +33601 0x11/imm32/alloc-id:fake +33602 _string_0f_8c_jump_label/imm32/subx-name +33603 0/imm32/no-rm32 +33604 0/imm32/no-r32 +33605 0/imm32/no-imm32 +33606 0/imm32/no-imm8 +33607 1/imm32/disp32-is-first-inout +33608 0/imm32/no-xm32 +33609 0/imm32/no-x32 +33610 0x11/imm32/alloc-id:fake +33611 _Primitive-loop-if->=-named/imm32/next +33612 _Primitive-loop-if->=-named: # (payload primitive) +33613 0x11/imm32/alloc-id:fake:payload +33614 0x11/imm32/alloc-id:fake +33615 _string-loop-if->=/imm32/name +33616 0x11/imm32/alloc-id:fake +33617 Single-lit-var/imm32/inouts 33618 0/imm32/no-outputs -33619 0x11/imm32/alloc-id:fake -33620 _string_0f_83_jump_label/imm32/subx-name -33621 0/imm32/no-rm32 -33622 0/imm32/no-r32 -33623 0/imm32/no-imm32 -33624 0/imm32/no-imm8 -33625 1/imm32/disp32-is-first-inout -33626 0/imm32/no-xm32 -33627 0/imm32/no-x32 -33628 0x11/imm32/alloc-id:fake -33629 _Primitive-break-if-float<=-named/imm32/next -33630 _Primitive-break-if-float<=-named: # (payload primitive) -33631 0x11/imm32/alloc-id:fake:payload -33632 0x11/imm32/alloc-id:fake -33633 _string-break-if-float<=/imm32/name -33634 0x11/imm32/alloc-id:fake -33635 Single-lit-var/imm32/inouts -33636 0/imm32/no-outputs +33619 0/imm32/no-outputs +33620 0x11/imm32/alloc-id:fake +33621 _string_0f_8d_jump_label/imm32/subx-name +33622 0/imm32/no-rm32 +33623 0/imm32/no-r32 +33624 0/imm32/no-imm32 +33625 0/imm32/no-imm8 +33626 1/imm32/disp32-is-first-inout +33627 0/imm32/no-xm32 +33628 0/imm32/no-x32 +33629 0x11/imm32/alloc-id:fake +33630 _Primitive-loop-if-<=-named/imm32/next +33631 _Primitive-loop-if-<=-named: # (payload primitive) +33632 0x11/imm32/alloc-id:fake:payload +33633 0x11/imm32/alloc-id:fake +33634 _string-loop-if-<=/imm32/name +33635 0x11/imm32/alloc-id:fake +33636 Single-lit-var/imm32/inouts 33637 0/imm32/no-outputs -33638 0x11/imm32/alloc-id:fake -33639 _string_0f_86_jump_label/imm32/subx-name -33640 0/imm32/no-rm32 -33641 0/imm32/no-r32 -33642 0/imm32/no-imm32 -33643 0/imm32/no-imm8 -33644 1/imm32/disp32-is-first-inout -33645 0/imm32/no-xm32 -33646 0/imm32/no-x32 -33647 0x11/imm32/alloc-id:fake -33648 _Primitive-break-if-float>-named/imm32/next -33649 _Primitive-break-if-float>-named: # (payload primitive) -33650 0x11/imm32/alloc-id:fake:payload -33651 0x11/imm32/alloc-id:fake -33652 _string-break-if-float>/imm32/name -33653 0x11/imm32/alloc-id:fake -33654 Single-lit-var/imm32/inouts -33655 0/imm32/no-outputs +33638 0/imm32/no-outputs +33639 0x11/imm32/alloc-id:fake +33640 _string_0f_8e_jump_label/imm32/subx-name +33641 0/imm32/no-rm32 +33642 0/imm32/no-r32 +33643 0/imm32/no-imm32 +33644 0/imm32/no-imm8 +33645 1/imm32/disp32-is-first-inout +33646 0/imm32/no-xm32 +33647 0/imm32/no-x32 +33648 0x11/imm32/alloc-id:fake +33649 _Primitive-loop-if->-named/imm32/next +33650 _Primitive-loop-if->-named: # (payload primitive) +33651 0x11/imm32/alloc-id:fake:payload +33652 0x11/imm32/alloc-id:fake +33653 _string-loop-if->/imm32/name +33654 0x11/imm32/alloc-id:fake +33655 Single-lit-var/imm32/inouts 33656 0/imm32/no-outputs -33657 0x11/imm32/alloc-id:fake -33658 _string_0f_87_jump_label/imm32/subx-name -33659 0/imm32/no-rm32 -33660 0/imm32/no-r32 -33661 0/imm32/no-imm32 -33662 0/imm32/no-imm8 -33663 1/imm32/disp32-is-first-inout -33664 0/imm32/no-xm32 -33665 0/imm32/no-x32 -33666 0x11/imm32/alloc-id:fake -33667 _Primitive-loop-if-float<-named/imm32/next -33668 _Primitive-loop-if-float<-named: # (payload primitive) -33669 0x11/imm32/alloc-id:fake:payload -33670 0x11/imm32/alloc-id:fake -33671 _string-loop-if-float</imm32/name -33672 0x11/imm32/alloc-id:fake -33673 Single-lit-var/imm32/inouts -33674 0/imm32/no-outputs +33657 0/imm32/no-outputs +33658 0x11/imm32/alloc-id:fake +33659 _string_0f_8f_jump_label/imm32/subx-name +33660 0/imm32/no-rm32 +33661 0/imm32/no-r32 +33662 0/imm32/no-imm32 +33663 0/imm32/no-imm8 +33664 1/imm32/disp32-is-first-inout +33665 0/imm32/no-xm32 +33666 0/imm32/no-x32 +33667 0x11/imm32/alloc-id:fake +33668 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break +33669 _Primitive-loop-named: # (payload primitive) +33670 0x11/imm32/alloc-id:fake:payload +33671 0x11/imm32/alloc-id:fake +33672 _string-loop/imm32/name +33673 0x11/imm32/alloc-id:fake +33674 Single-lit-var/imm32/inouts 33675 0/imm32/no-outputs -33676 0x11/imm32/alloc-id:fake -33677 _string_0f_82_jump_label/imm32/subx-name -33678 0/imm32/no-rm32 -33679 0/imm32/no-r32 -33680 0/imm32/no-imm32 -33681 0/imm32/no-imm8 -33682 1/imm32/disp32-is-first-inout -33683 0/imm32/no-xm32 -33684 0/imm32/no-x32 -33685 0x11/imm32/alloc-id:fake -33686 _Primitive-loop-if-float>=-named/imm32/next -33687 _Primitive-loop-if-float>=-named: # (payload primitive) -33688 0x11/imm32/alloc-id:fake:payload -33689 0x11/imm32/alloc-id:fake -33690 _string-loop-if-float>=/imm32/name +33676 0/imm32/no-outputs +33677 0x11/imm32/alloc-id:fake +33678 _string_e9_jump_label/imm32/subx-name +33679 0/imm32/no-rm32 +33680 0/imm32/no-r32 +33681 0/imm32/no-imm32 +33682 0/imm32/no-imm8 +33683 1/imm32/disp32-is-first-inout +33684 0/imm32/no-xm32 +33685 0/imm32/no-x32 +33686 0x11/imm32/alloc-id:fake +33687 _Primitive-break-if-float</imm32/next +33688 # - branches based on floating-point comparisons +33689 _Primitive-break-if-float<: # (payload primitive) +33690 0x11/imm32/alloc-id:fake:payload 33691 0x11/imm32/alloc-id:fake -33692 Single-lit-var/imm32/inouts -33693 0/imm32/no-outputs -33694 0/imm32/no-outputs -33695 0x11/imm32/alloc-id:fake -33696 _string_0f_83_jump_label/imm32/subx-name -33697 0/imm32/no-rm32 -33698 0/imm32/no-r32 -33699 0/imm32/no-imm32 -33700 0/imm32/no-imm8 -33701 1/imm32/disp32-is-first-inout -33702 0/imm32/no-xm32 -33703 0/imm32/no-x32 -33704 0x11/imm32/alloc-id:fake -33705 _Primitive-loop-if-float<=-named/imm32/next -33706 _Primitive-loop-if-float<=-named: # (payload primitive) -33707 0x11/imm32/alloc-id:fake:payload -33708 0x11/imm32/alloc-id:fake -33709 _string-loop-if-float<=/imm32/name +33692 _string-break-if-float</imm32/name +33693 0/imm32/no-inouts +33694 0/imm32/no-inouts +33695 0/imm32/no-outputs +33696 0/imm32/no-outputs +33697 0x11/imm32/alloc-id:fake +33698 _string_0f_82_jump_break/imm32/subx-name +33699 0/imm32/no-rm32 +33700 0/imm32/no-r32 +33701 0/imm32/no-imm32 +33702 0/imm32/no-imm8 +33703 0/imm32/no-disp32 +33704 0/imm32/no-xm32 +33705 0/imm32/no-x32 +33706 0x11/imm32/alloc-id:fake +33707 _Primitive-break-if-float>=/imm32/next +33708 _Primitive-break-if-float>=: # (payload primitive) +33709 0x11/imm32/alloc-id:fake:payload 33710 0x11/imm32/alloc-id:fake -33711 Single-lit-var/imm32/inouts -33712 0/imm32/no-outputs -33713 0/imm32/no-outputs -33714 0x11/imm32/alloc-id:fake -33715 _string_0f_86_jump_label/imm32/subx-name -33716 0/imm32/no-rm32 -33717 0/imm32/no-r32 -33718 0/imm32/no-imm32 -33719 0/imm32/no-imm8 -33720 1/imm32/disp32-is-first-inout -33721 0/imm32/no-xm32 -33722 0/imm32/no-x32 -33723 0x11/imm32/alloc-id:fake -33724 _Primitive-loop-if-float>-named/imm32/next -33725 _Primitive-loop-if-float>-named: # (payload primitive) -33726 0x11/imm32/alloc-id:fake:payload -33727 0x11/imm32/alloc-id:fake -33728 _string-loop-if-float>/imm32/name +33711 _string-break-if-float>=/imm32/name +33712 0/imm32/no-inouts +33713 0/imm32/no-inouts +33714 0/imm32/no-outputs +33715 0/imm32/no-outputs +33716 0x11/imm32/alloc-id:fake +33717 _string_0f_83_jump_break/imm32/subx-name +33718 0/imm32/no-rm32 +33719 0/imm32/no-r32 +33720 0/imm32/no-imm32 +33721 0/imm32/no-imm8 +33722 0/imm32/no-disp32 +33723 0/imm32/no-xm32 +33724 0/imm32/no-x32 +33725 0x11/imm32/alloc-id:fake +33726 _Primitive-break-if-float<=/imm32/next +33727 _Primitive-break-if-float<=: # (payload primitive) +33728 0x11/imm32/alloc-id:fake:payload 33729 0x11/imm32/alloc-id:fake -33730 Single-lit-var/imm32/inouts -33731 0/imm32/no-outputs -33732 0/imm32/no-outputs -33733 0x11/imm32/alloc-id:fake -33734 _string_0f_87_jump_label/imm32/subx-name -33735 0/imm32/no-rm32 -33736 0/imm32/no-r32 -33737 0/imm32/no-imm32 -33738 0/imm32/no-imm8 -33739 1/imm32/disp32-is-first-inout -33740 0/imm32/no-xm32 -33741 0/imm32/no-x32 -33742 0/imm32/next -33743 0/imm32/next -33744 -33745 # string literals for Mu instructions -33746 _string-add: # (payload array byte) +33730 _string-break-if-float<=/imm32/name +33731 0/imm32/no-inouts +33732 0/imm32/no-inouts +33733 0/imm32/no-outputs +33734 0/imm32/no-outputs +33735 0x11/imm32/alloc-id:fake +33736 _string_0f_86_jump_break/imm32/subx-name +33737 0/imm32/no-rm32 +33738 0/imm32/no-r32 +33739 0/imm32/no-imm32 +33740 0/imm32/no-imm8 +33741 0/imm32/no-disp32 +33742 0/imm32/no-xm32 +33743 0/imm32/no-x32 +33744 0x11/imm32/alloc-id:fake +33745 _Primitive-break-if-float>/imm32/next +33746 _Primitive-break-if-float>: # (payload primitive) 33747 0x11/imm32/alloc-id:fake:payload -33748 # "add" -33749 0x3/imm32/size -33750 0x61/a 0x64/d 0x64/d -33751 _string-address: # (payload array byte) -33752 0x11/imm32/alloc-id:fake:payload -33753 # "address" -33754 0x7/imm32/size -33755 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s -33756 _string-add-to: # (payload array byte) -33757 0x11/imm32/alloc-id:fake:payload -33758 # "add-to" -33759 0x6/imm32/size -33760 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o -33761 _string-and: # (payload array byte) -33762 0x11/imm32/alloc-id:fake:payload -33763 # "and" -33764 0x3/imm32/size -33765 0x61/a 0x6e/n 0x64/d -33766 _string-and-with: # (payload array byte) -33767 0x11/imm32/alloc-id:fake:payload -33768 # "and-with" -33769 0x8/imm32/size -33770 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -33771 _string-break: # (payload array byte) -33772 0x11/imm32/alloc-id:fake:payload -33773 # "break" -33774 0x5/imm32/size -33775 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k -33776 _string-break-if-<: # (payload array byte) -33777 0x11/imm32/alloc-id:fake:payload -33778 # "break-if-<" -33779 0xa/imm32/size -33780 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< -33781 _string-break-if-<=: # (payload array byte) -33782 0x11/imm32/alloc-id:fake:payload -33783 # "break-if-<=" -33784 0xb/imm32/size -33785 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= -33786 _string-break-if-=: # (payload array byte) -33787 0x11/imm32/alloc-id:fake:payload -33788 # "break-if-=" -33789 0xa/imm32/size -33790 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= -33791 _string-break-if->: # (payload array byte) -33792 0x11/imm32/alloc-id:fake:payload -33793 # "break-if->" -33794 0xa/imm32/size -33795 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> -33796 _string-break-if->=: # (payload array byte) -33797 0x11/imm32/alloc-id:fake:payload -33798 # "break-if->=" -33799 0xb/imm32/size -33800 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= -33801 _string-break-if-!=: # (payload array byte) -33802 0x11/imm32/alloc-id:fake:payload -33803 # "break-if-!=" -33804 0xb/imm32/size -33805 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= -33806 _string-break-if-addr<: # (payload array byte) -33807 0x11/imm32/alloc-id:fake:payload -33808 # "break-if-addr<" -33809 0xe/imm32/size -33810 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< -33811 _string-break-if-addr<=: # (payload array byte) -33812 0x11/imm32/alloc-id:fake:payload -33813 # "break-if-addr<=" -33814 0xf/imm32/size -33815 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= -33816 _string-break-if-addr>: # (payload array byte) -33817 0x11/imm32/alloc-id:fake:payload -33818 # "break-if-addr>" -33819 0xe/imm32/size -33820 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> -33821 _string-break-if-addr>=: # (payload array byte) -33822 0x11/imm32/alloc-id:fake:payload -33823 # "break-if-addr>=" -33824 0xf/imm32/size -33825 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= -33826 _string-break-if-float<: # (payload array byte) -33827 0x11/imm32/alloc-id:fake:payload -33828 # "break-if-float<" -33829 0xf/imm32/size -33830 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< -33831 _string-break-if-float<=: # (payload array byte) -33832 0x11/imm32/alloc-id:fake:payload -33833 # "break-if-float<=" -33834 0x10/imm32/size -33835 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/= -33836 _string-break-if-float>: # (payload array byte) -33837 0x11/imm32/alloc-id:fake:payload -33838 # "break-if-float>" -33839 0xf/imm32/size -33840 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> -33841 _string-break-if-float>=: # (payload array byte) +33748 0x11/imm32/alloc-id:fake +33749 _string-break-if-float>/imm32/name +33750 0/imm32/no-inouts +33751 0/imm32/no-inouts +33752 0/imm32/no-outputs +33753 0/imm32/no-outputs +33754 0x11/imm32/alloc-id:fake +33755 _string_0f_87_jump_break/imm32/subx-name +33756 0/imm32/no-rm32 +33757 0/imm32/no-r32 +33758 0/imm32/no-imm32 +33759 0/imm32/no-imm8 +33760 0/imm32/no-disp32 +33761 0/imm32/no-xm32 +33762 0/imm32/no-x32 +33763 0x11/imm32/alloc-id:fake +33764 _Primitive-loop-if-float</imm32/next +33765 _Primitive-loop-if-float<: # (payload primitive) +33766 0x11/imm32/alloc-id:fake:payload +33767 0x11/imm32/alloc-id:fake +33768 _string-loop-if-float</imm32/name +33769 0/imm32/no-inouts +33770 0/imm32/no-inouts +33771 0/imm32/no-outputs +33772 0/imm32/no-outputs +33773 0x11/imm32/alloc-id:fake +33774 _string_0f_82_jump_loop/imm32/subx-name +33775 0/imm32/no-rm32 +33776 0/imm32/no-r32 +33777 0/imm32/no-imm32 +33778 0/imm32/no-imm8 +33779 0/imm32/no-disp32 +33780 0/imm32/no-xm32 +33781 0/imm32/no-x32 +33782 0x11/imm32/alloc-id:fake +33783 _Primitive-loop-if-float>=/imm32/next +33784 _Primitive-loop-if-float>=: # (payload primitive) +33785 0x11/imm32/alloc-id:fake:payload +33786 0x11/imm32/alloc-id:fake +33787 _string-loop-if-float>=/imm32/name +33788 0/imm32/no-inouts +33789 0/imm32/no-inouts +33790 0/imm32/no-outputs +33791 0/imm32/no-outputs +33792 0x11/imm32/alloc-id:fake +33793 _string_0f_83_jump_loop/imm32/subx-name +33794 0/imm32/no-rm32 +33795 0/imm32/no-r32 +33796 0/imm32/no-imm32 +33797 0/imm32/no-imm8 +33798 0/imm32/no-disp32 +33799 0/imm32/no-xm32 +33800 0/imm32/no-x32 +33801 0x11/imm32/alloc-id:fake +33802 _Primitive-loop-if-float<=/imm32/next +33803 _Primitive-loop-if-float<=: # (payload primitive) +33804 0x11/imm32/alloc-id:fake:payload +33805 0x11/imm32/alloc-id:fake +33806 _string-loop-if-float<=/imm32/name +33807 0/imm32/no-inouts +33808 0/imm32/no-inouts +33809 0/imm32/no-outputs +33810 0/imm32/no-outputs +33811 0x11/imm32/alloc-id:fake +33812 _string_0f_86_jump_loop/imm32/subx-name +33813 0/imm32/no-rm32 +33814 0/imm32/no-r32 +33815 0/imm32/no-imm32 +33816 0/imm32/no-imm8 +33817 0/imm32/no-disp32 +33818 0/imm32/no-xm32 +33819 0/imm32/no-x32 +33820 0x11/imm32/alloc-id:fake +33821 _Primitive-loop-if-float>/imm32/next +33822 _Primitive-loop-if-float>: # (payload primitive) +33823 0x11/imm32/alloc-id:fake:payload +33824 0x11/imm32/alloc-id:fake +33825 _string-loop-if-float>/imm32/name +33826 0/imm32/no-inouts +33827 0/imm32/no-inouts +33828 0/imm32/no-outputs +33829 0/imm32/no-outputs +33830 0x11/imm32/alloc-id:fake +33831 _string_0f_87_jump_loop/imm32/subx-name +33832 0/imm32/no-rm32 +33833 0/imm32/no-r32 +33834 0/imm32/no-imm32 +33835 0/imm32/no-imm8 +33836 0/imm32/no-disp32 +33837 0/imm32/no-xm32 +33838 0/imm32/no-x32 +33839 0x11/imm32/alloc-id:fake +33840 _Primitive-break-if-float<-named/imm32/next +33841 _Primitive-break-if-float<-named: # (payload primitive) 33842 0x11/imm32/alloc-id:fake:payload -33843 # "break-if-float>=" -33844 0x10/imm32/size -33845 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/= -33846 _string-compare: # (payload array byte) -33847 0x11/imm32/alloc-id:fake:payload -33848 # "compare" -33849 0x7/imm32/size -33850 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e -33851 _string-copy: # (payload array byte) -33852 0x11/imm32/alloc-id:fake:payload -33853 # "copy" -33854 0x4/imm32/size -33855 0x63/c 0x6f/o 0x70/p 0x79/y -33856 _string-copy-to: # (payload array byte) -33857 0x11/imm32/alloc-id:fake:payload -33858 # "copy-to" -33859 0x7/imm32/size -33860 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o -33861 _string-copy-byte: -33862 0x11/imm32/alloc-id:fake:payload -33863 # "copy-byte" -33864 0x9/imm32/size -33865 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e -33866 _string-copy-byte-to: -33867 0x11/imm32/alloc-id:fake:payload -33868 # "copy-byte-to" -33869 0xc/imm32/size -33870 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o -33871 _string-decrement: # (payload array byte) -33872 0x11/imm32/alloc-id:fake:payload -33873 # "decrement" -33874 0x9/imm32/size -33875 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t -33876 _string-increment: # (payload array byte) -33877 0x11/imm32/alloc-id:fake:payload -33878 # "increment" -33879 0x9/imm32/size -33880 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t -33881 _string-loop: # (payload array byte) -33882 0x11/imm32/alloc-id:fake:payload -33883 # "loop" -33884 0x4/imm32/size -33885 0x6c/l 0x6f/o 0x6f/o 0x70/p -33886 _string-loop-if-<: # (payload array byte) -33887 0x11/imm32/alloc-id:fake:payload -33888 # "loop-if-<" -33889 0x9/imm32/size -33890 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< -33891 _string-loop-if-<=: # (payload array byte) -33892 0x11/imm32/alloc-id:fake:payload -33893 # "loop-if-<=" -33894 0xa/imm32/size -33895 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= -33896 _string-loop-if-=: # (payload array byte) -33897 0x11/imm32/alloc-id:fake:payload -33898 # "loop-if-=" -33899 0x9/imm32/size -33900 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= -33901 _string-loop-if->: # (payload array byte) -33902 0x11/imm32/alloc-id:fake:payload -33903 # "loop-if->" -33904 0x9/imm32/size -33905 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> -33906 _string-loop-if->=: # (payload array byte) -33907 0x11/imm32/alloc-id:fake:payload -33908 # "loop-if->=" -33909 0xa/imm32/size -33910 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= -33911 _string-loop-if-!=: # (payload array byte) -33912 0x11/imm32/alloc-id:fake:payload -33913 # "loop-if-!=" -33914 0xa/imm32/size -33915 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= -33916 _string-loop-if-addr<: # (payload array byte) -33917 0x11/imm32/alloc-id:fake:payload -33918 # "loop-if-addr<" -33919 0xd/imm32/size -33920 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< -33921 _string-loop-if-addr<=: # (payload array byte) -33922 0x11/imm32/alloc-id:fake:payload -33923 # "loop-if-addr<=" -33924 0xe/imm32/size -33925 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= -33926 _string-loop-if-addr>: # (payload array byte) -33927 0x11/imm32/alloc-id:fake:payload -33928 # "loop-if-addr>" -33929 0xd/imm32/size -33930 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> -33931 _string-loop-if-addr>=: # (payload array byte) -33932 0x11/imm32/alloc-id:fake:payload -33933 # "loop-if-addr>=" -33934 0xe/imm32/size -33935 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= -33936 _string-loop-if-float<: # (payload array byte) +33843 0x11/imm32/alloc-id:fake +33844 _string-break-if-float</imm32/name +33845 0x11/imm32/alloc-id:fake +33846 Single-lit-var/imm32/inouts +33847 0/imm32/no-outputs +33848 0/imm32/no-outputs +33849 0x11/imm32/alloc-id:fake +33850 _string_0f_82_jump_label/imm32/subx-name +33851 0/imm32/no-rm32 +33852 0/imm32/no-r32 +33853 0/imm32/no-imm32 +33854 0/imm32/no-imm8 +33855 1/imm32/disp32-is-first-inout +33856 0/imm32/no-xm32 +33857 0/imm32/no-x32 +33858 0x11/imm32/alloc-id:fake +33859 _Primitive-break-if-float>=-named/imm32/next +33860 _Primitive-break-if-float>=-named: # (payload primitive) +33861 0x11/imm32/alloc-id:fake:payload +33862 0x11/imm32/alloc-id:fake +33863 _string-break-if-float>=/imm32/name +33864 0x11/imm32/alloc-id:fake +33865 Single-lit-var/imm32/inouts +33866 0/imm32/no-outputs +33867 0/imm32/no-outputs +33868 0x11/imm32/alloc-id:fake +33869 _string_0f_83_jump_label/imm32/subx-name +33870 0/imm32/no-rm32 +33871 0/imm32/no-r32 +33872 0/imm32/no-imm32 +33873 0/imm32/no-imm8 +33874 1/imm32/disp32-is-first-inout +33875 0/imm32/no-xm32 +33876 0/imm32/no-x32 +33877 0x11/imm32/alloc-id:fake +33878 _Primitive-break-if-float<=-named/imm32/next +33879 _Primitive-break-if-float<=-named: # (payload primitive) +33880 0x11/imm32/alloc-id:fake:payload +33881 0x11/imm32/alloc-id:fake +33882 _string-break-if-float<=/imm32/name +33883 0x11/imm32/alloc-id:fake +33884 Single-lit-var/imm32/inouts +33885 0/imm32/no-outputs +33886 0/imm32/no-outputs +33887 0x11/imm32/alloc-id:fake +33888 _string_0f_86_jump_label/imm32/subx-name +33889 0/imm32/no-rm32 +33890 0/imm32/no-r32 +33891 0/imm32/no-imm32 +33892 0/imm32/no-imm8 +33893 1/imm32/disp32-is-first-inout +33894 0/imm32/no-xm32 +33895 0/imm32/no-x32 +33896 0x11/imm32/alloc-id:fake +33897 _Primitive-break-if-float>-named/imm32/next +33898 _Primitive-break-if-float>-named: # (payload primitive) +33899 0x11/imm32/alloc-id:fake:payload +33900 0x11/imm32/alloc-id:fake +33901 _string-break-if-float>/imm32/name +33902 0x11/imm32/alloc-id:fake +33903 Single-lit-var/imm32/inouts +33904 0/imm32/no-outputs +33905 0/imm32/no-outputs +33906 0x11/imm32/alloc-id:fake +33907 _string_0f_87_jump_label/imm32/subx-name +33908 0/imm32/no-rm32 +33909 0/imm32/no-r32 +33910 0/imm32/no-imm32 +33911 0/imm32/no-imm8 +33912 1/imm32/disp32-is-first-inout +33913 0/imm32/no-xm32 +33914 0/imm32/no-x32 +33915 0x11/imm32/alloc-id:fake +33916 _Primitive-loop-if-float<-named/imm32/next +33917 _Primitive-loop-if-float<-named: # (payload primitive) +33918 0x11/imm32/alloc-id:fake:payload +33919 0x11/imm32/alloc-id:fake +33920 _string-loop-if-float</imm32/name +33921 0x11/imm32/alloc-id:fake +33922 Single-lit-var/imm32/inouts +33923 0/imm32/no-outputs +33924 0/imm32/no-outputs +33925 0x11/imm32/alloc-id:fake +33926 _string_0f_82_jump_label/imm32/subx-name +33927 0/imm32/no-rm32 +33928 0/imm32/no-r32 +33929 0/imm32/no-imm32 +33930 0/imm32/no-imm8 +33931 1/imm32/disp32-is-first-inout +33932 0/imm32/no-xm32 +33933 0/imm32/no-x32 +33934 0x11/imm32/alloc-id:fake +33935 _Primitive-loop-if-float>=-named/imm32/next +33936 _Primitive-loop-if-float>=-named: # (payload primitive) 33937 0x11/imm32/alloc-id:fake:payload -33938 # "loop-if-float<" -33939 0xe/imm32/size -33940 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< -33941 _string-loop-if-float<=: # (payload array byte) -33942 0x11/imm32/alloc-id:fake:payload -33943 # "loop-if-float<=" -33944 0xf/imm32/size -33945 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/= -33946 _string-loop-if-float>: # (payload array byte) -33947 0x11/imm32/alloc-id:fake:payload -33948 # "loop-if-float>" -33949 0xe/imm32/size -33950 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> -33951 _string-loop-if-float>=: # (payload array byte) -33952 0x11/imm32/alloc-id:fake:payload -33953 # "loop-if-float>=" -33954 0xf/imm32/size -33955 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/= -33956 _string-multiply: # (payload array byte) -33957 0x11/imm32/alloc-id:fake:payload -33958 # "multiply" -33959 0x8/imm32/size -33960 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y -33961 _string-convert: # (payload array byte) -33962 0x11/imm32/alloc-id:fake:payload -33963 # "convert" -33964 0x7/imm32/size -33965 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t -33966 _string-truncate: # (payload array byte) -33967 0x11/imm32/alloc-id:fake:payload -33968 # "truncate" -33969 0x8/imm32/size -33970 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e -33971 _string-reinterpret: # (payload array byte) -33972 0x11/imm32/alloc-id:fake:payload -33973 # "reinterpret" -33974 0xb/imm32/size -33975 0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t -33976 _string-divide: -33977 0x11/imm32/alloc-id:fake:payload -33978 # "divide" -33979 0x6/imm32/size -33980 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e -33981 _string-max: -33982 0x11/imm32/alloc-id:fake:payload -33983 # "max" -33984 0x3/imm32/size -33985 0x6d/m 0x61/a 0x78/x -33986 _string-min: -33987 0x11/imm32/alloc-id:fake:payload -33988 # "min" -33989 0x3/imm32/size -33990 0x6d/m 0x69/i 0x6e/n -33991 _string-reciprocal: -33992 0x11/imm32/alloc-id:fake:payload -33993 # "reciprocal" -33994 0xa/imm32/size -33995 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l -33996 _string-square-root: -33997 0x11/imm32/alloc-id:fake:payload -33998 # "square-root" -33999 0xb/imm32/size -34000 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t -34001 _string-inverse-square-root: -34002 0x11/imm32/alloc-id:fake:payload -34003 # "inverse-square-root" -34004 0x13/imm32/size -34005 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t -34006 _string-negate: # (payload array byte) -34007 0x11/imm32/alloc-id:fake:payload -34008 # "negate" -34009 0x6/imm32/size -34010 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e -34011 _string-or: # (payload array byte) -34012 0x11/imm32/alloc-id:fake:payload -34013 # "or" -34014 0x2/imm32/size -34015 0x6f/o 0x72/r -34016 _string-or-with: # (payload array byte) -34017 0x11/imm32/alloc-id:fake:payload -34018 # "or-with" -34019 0x7/imm32/size -34020 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -34021 _string-subtract: # (payload array byte) -34022 0x11/imm32/alloc-id:fake:payload -34023 # "subtract" -34024 0x8/imm32/size -34025 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t -34026 _string-subtract-from: # (payload array byte) -34027 0x11/imm32/alloc-id:fake:payload -34028 # "subtract-from" -34029 0xd/imm32/size -34030 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m -34031 _string-xor: # (payload array byte) -34032 0x11/imm32/alloc-id:fake:payload -34033 # "xor" -34034 0x3/imm32/size -34035 0x78/x 0x6f/o 0x72/r -34036 _string-xor-with: # (payload array byte) -34037 0x11/imm32/alloc-id:fake:payload -34038 # "xor-with" -34039 0x8/imm32/size -34040 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -34041 _string-shift-left: # (payload array byte) -34042 0x11/imm32/alloc-id:fake:payload -34043 # "shift-left" -34044 0xa/imm32/size -34045 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t -34046 _string-shift-right: # (payload array byte) -34047 0x11/imm32/alloc-id:fake:payload -34048 # "shift-right" -34049 0xb/imm32/size -34050 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t -34051 _string-shift-right-signed: # (payload array byte) -34052 0x11/imm32/alloc-id:fake:payload -34053 # "shift-right-signed" -34054 0x12/imm32/size -34055 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n 0x65/e 0x64/d -34056 -34057 # string literals for SubX instructions -34058 _string_01_add_to: # (payload array byte) -34059 0x11/imm32/alloc-id:fake:payload -34060 # "01/add-to" -34061 0x9/imm32/size -34062 0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o -34063 _string_03_add: # (payload array byte) -34064 0x11/imm32/alloc-id:fake:payload -34065 # "03/add" -34066 0x6/imm32/size -34067 0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d -34068 _string_05_add_to_eax: # (payload array byte) -34069 0x11/imm32/alloc-id:fake:payload -34070 # "05/add-to-eax" -34071 0xd/imm32/size -34072 0x30/0 0x35/5 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x -34073 _string_09_or_with: # (payload array byte) -34074 0x11/imm32/alloc-id:fake:payload -34075 # "09/or-with" -34076 0xa/imm32/size -34077 0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -34078 _string_0b_or: # (payload array byte) -34079 0x11/imm32/alloc-id:fake:payload -34080 # "0b/or" -34081 0x5/imm32/size -34082 0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r -34083 _string_0d_or_with_eax: # (payload array byte) -34084 0x11/imm32/alloc-id:fake:payload -34085 # "0d/or-with-eax" -34086 0xe/imm32/size -34087 0x30/0 0x64/d 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x -34088 _string_0f_82_jump_label: # (payload array byte) -34089 0x11/imm32/alloc-id:fake:payload -34090 # "0f 82/jump-if-addr<" -34091 0x13/imm32/size -34092 0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< -34093 _string_0f_82_jump_break: # (payload array byte) -34094 0x11/imm32/alloc-id:fake:payload -34095 # "0f 82/jump-if-addr< break/disp32" -34096 0x20/imm32/size -34097 0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34098 _string_0f_82_jump_loop: # (payload array byte) -34099 0x11/imm32/alloc-id:fake:payload -34100 # "0f 82/jump-if-addr< loop/disp32" -34101 0x1f/imm32/size -34102 0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34103 _string_0f_83_jump_label: # (payload array byte) -34104 0x11/imm32/alloc-id:fake:payload -34105 # "0f 83/jump-if-addr>=" -34106 0x14/imm32/size -34107 0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= -34108 _string_0f_83_jump_break: # (payload array byte) -34109 0x11/imm32/alloc-id:fake:payload -34110 # "0f 83/jump-if-addr>= break/disp32" -34111 0x21/imm32/size -34112 0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34113 _string_0f_83_jump_loop: # (payload array byte) -34114 0x11/imm32/alloc-id:fake:payload -34115 # "0f 83/jump-if-addr>= loop/disp32" -34116 0x20/imm32/size -34117 0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34118 _string_0f_84_jump_label: # (payload array byte) -34119 0x11/imm32/alloc-id:fake:payload -34120 # "0f 84/jump-if-=" -34121 0xf/imm32/size -34122 0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= -34123 _string_0f_84_jump_break: # (payload array byte) -34124 0x11/imm32/alloc-id:fake:payload -34125 # "0f 84/jump-if-= break/disp32" -34126 0x1c/imm32/size -34127 0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34128 _string_0f_84_jump_loop: # (payload array byte) -34129 0x11/imm32/alloc-id:fake:payload -34130 # "0f 84/jump-if-= loop/disp32" -34131 0x1b/imm32/size -34132 0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34133 _string_0f_85_jump_label: # (payload array byte) -34134 0x11/imm32/alloc-id:fake:payload -34135 # "0f 85/jump-if-!=" -34136 0x10/imm32/size -34137 0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= -34138 _string_0f_85_jump_break: # (payload array byte) -34139 0x11/imm32/alloc-id:fake:payload -34140 # "0f 85/jump-if-!= break/disp32" -34141 0x1d/imm32/size -34142 0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34143 _string_0f_85_jump_loop: # (payload array byte) -34144 0x11/imm32/alloc-id:fake:payload -34145 # "0f 85/jump-if-!= loop/disp32" -34146 0x1c/imm32/size -34147 0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34148 _string_0f_86_jump_label: # (payload array byte) -34149 0x11/imm32/alloc-id:fake:payload -34150 # "0f 86/jump-if-addr<=" -34151 0x14/imm32/size -34152 0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= -34153 _string_0f_86_jump_break: # (payload array byte) -34154 0x11/imm32/alloc-id:fake:payload -34155 # "0f 86/jump-if-addr<= break/disp32" -34156 0x21/imm32/size -34157 0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34158 _string_0f_86_jump_loop: # (payload array byte) -34159 0x11/imm32/alloc-id:fake:payload -34160 # "0f 86/jump-if-addr<= loop/disp32" -34161 0x20/imm32/size -34162 0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34163 _string_0f_87_jump_label: # (payload array byte) -34164 0x11/imm32/alloc-id:fake:payload -34165 # "0f 87/jump-if-addr>" -34166 0x13/imm32/size -34167 0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> -34168 _string_0f_87_jump_break: # (payload array byte) -34169 0x11/imm32/alloc-id:fake:payload -34170 # "0f 87/jump-if-addr> break/disp32" -34171 0x20/imm32/size -34172 0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34173 _string_0f_87_jump_loop: # (payload array byte) -34174 0x11/imm32/alloc-id:fake:payload -34175 # "0f 87/jump-if-addr> loop/disp32" -34176 0x1f/imm32/size -34177 0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34178 _string_0f_8c_jump_label: # (payload array byte) -34179 0x11/imm32/alloc-id:fake:payload -34180 # "0f 8c/jump-if-<" -34181 0xf/imm32/size -34182 0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< -34183 _string_0f_8c_jump_break: # (payload array byte) -34184 0x11/imm32/alloc-id:fake:payload -34185 # "0f 8c/jump-if-< break/disp32" -34186 0x1c/imm32/size -34187 0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34188 _string_0f_8c_jump_loop: # (payload array byte) -34189 0x11/imm32/alloc-id:fake:payload -34190 # "0f 8c/jump-if-< loop/disp32" -34191 0x1b/imm32/size -34192 0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34193 _string_0f_8d_jump_label: # (payload array byte) -34194 0x11/imm32/alloc-id:fake:payload -34195 # "0f 8d/jump-if->=" -34196 0x10/imm32/size -34197 0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= -34198 _string_0f_8d_jump_break: # (payload array byte) -34199 0x11/imm32/alloc-id:fake:payload -34200 # "0f 8d/jump-if->= break/disp32" -34201 0x1d/imm32/size -34202 0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34203 _string_0f_8d_jump_loop: # (payload array byte) -34204 0x11/imm32/alloc-id:fake:payload -34205 # "0f 8d/jump-if->= loop/disp32" -34206 0x1c/imm32/size -34207 0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34208 _string_0f_8e_jump_label: # (payload array byte) -34209 0x11/imm32/alloc-id:fake:payload -34210 # "0f 8e/jump-if-<=" -34211 0x10/imm32/size -34212 0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= -34213 _string_0f_8e_jump_break: # (payload array byte) -34214 0x11/imm32/alloc-id:fake:payload -34215 # "0f 8e/jump-if-<= break/disp32" -34216 0x1d/imm32/size -34217 0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34218 _string_0f_8e_jump_loop: # (payload array byte) -34219 0x11/imm32/alloc-id:fake:payload -34220 # "0f 8e/jump-if-<= loop/disp32" -34221 0x1c/imm32/size -34222 0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34223 _string_0f_8f_jump_label: # (payload array byte) -34224 0x11/imm32/alloc-id:fake:payload -34225 # "0f 8f/jump-if->" -34226 0xf/imm32/size -34227 0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> -34228 _string_0f_8f_jump_break: # (payload array byte) -34229 0x11/imm32/alloc-id:fake:payload -34230 # "0f 8f/jump-if-> break/disp32" -34231 0x1c/imm32/size -34232 0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34233 _string_0f_8f_jump_loop: # (payload array byte) -34234 0x11/imm32/alloc-id:fake:payload -34235 # "0f 8f/jump-if-> loop/disp32" -34236 0x1b/imm32/size -34237 0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34238 _string_0f_af_multiply: # (payload array byte) -34239 0x11/imm32/alloc-id:fake:payload -34240 # "0f af/multiply" -34241 0xe/imm32/size -34242 0x30/0 0x66/f 0x20/space 0x61/a 0x66/f 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y -34243 _string_f3_0f_2a_convert_to_float: -34244 0x11/imm32/alloc-id:fake:payload -34245 # "f3 0f 2a/convert-to-float" -34246 0x19/imm32/size -34247 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t -34248 _string_f3_0f_2d_convert_to_int: -34249 0x11/imm32/alloc-id:fake:payload -34250 # "f3 0f 2d/convert-to-int" -34251 0x17/imm32/size -34252 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t -34253 _string_f3_0f_2c_truncate_to_int: -34254 0x11/imm32/alloc-id:fake:payload -34255 # "f3 0f 2c/truncate-to-int" -34256 0x18/imm32/size -34257 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x63/c 0x2f/slash 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t -34258 _string_f3_0f_58_add: -34259 0x11/imm32/alloc-id:fake:payload -34260 # "f3 0f 58/add" -34261 0xc/imm32/size -34262 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d -34263 _string_f3_0f_5c_subtract: -34264 0x11/imm32/alloc-id:fake:payload -34265 # "f3 0f 5c/subtract" -34266 0x11/imm32/size -34267 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x63/c 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t -34268 _string_f3_0f_59_multiply: -34269 0x11/imm32/alloc-id:fake:payload -34270 # "f3 0f 59/multiply" -34271 0x11/imm32/size -34272 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x39/9 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y -34273 _string_f3_0f_5e_divide: -34274 0x11/imm32/alloc-id:fake:payload -34275 # "f3 0f 5e/divide" -34276 0xf/imm32/size -34277 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x65/e 0x2f/slash 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e -34278 _string_f3_0f_53_reciprocal: -34279 0x11/imm32/alloc-id:fake:payload -34280 # "f3 0f 53/reciprocal" -34281 0x13/imm32/size -34282 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x33/3 0x2f/slash 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l -34283 _string_f3_0f_51_square_root: -34284 0x11/imm32/alloc-id:fake:payload -34285 # "f3 0f 51/square-root" -34286 0x14/imm32/size -34287 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x31/1 0x2f/slash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t -34288 _string_f3_0f_52_inverse_square_root: -34289 0x11/imm32/alloc-id:fake:payload -34290 # "f3 0f 52/inverse-square-root" -34291 0x1c/imm32/size -34292 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t -34293 _string_f3_0f_5d_min: -34294 0x11/imm32/alloc-id:fake:payload -34295 # "f3 0f 5d/min" -34296 0xc/imm32/size -34297 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n -34298 _string_f3_0f_5f_max: -34299 0x11/imm32/alloc-id:fake:payload -34300 # "f3 0f 5f/max" -34301 0xc/imm32/size -34302 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x -34303 _string_f3_0f_10_copy: -34304 0x11/imm32/alloc-id:fake:payload -34305 # "f3 0f 10/copy" -34306 0xd/imm32/size -34307 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x30/0 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y -34308 _string_f3_0f_11_copy: -34309 0x11/imm32/alloc-id:fake:payload -34310 # "f3 0f 11/copy" -34311 0xd/imm32/size -34312 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x31/1 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y -34313 _string_0f_2f_compare: -34314 0x11/imm32/alloc-id:fake:payload -34315 # "0f 2f/compare" -34316 0xd/imm32/size -34317 0x30/0 0x66/f 0x20/space 0x32/2 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e -34318 _string_21_and_with: # (payload array byte) -34319 0x11/imm32/alloc-id:fake:payload -34320 # "21/and-with" -34321 0xb/imm32/size -34322 0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -34323 _string_23_and: # (payload array byte) -34324 0x11/imm32/alloc-id:fake:payload -34325 # "23/and" -34326 0x6/imm32/size -34327 0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d -34328 _string_25_and_with_eax: # (payload array byte) -34329 0x11/imm32/alloc-id:fake:payload -34330 # "25/and-with-eax" -34331 0xf/imm32/size -34332 0x32/2 0x35/5 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x -34333 _string_29_subtract_from: # (payload array byte) -34334 0x11/imm32/alloc-id:fake:payload -34335 # "29/subtract-from" -34336 0x10/imm32/size -34337 0x32/2 0x39/9 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m -34338 _string_2b_subtract: # (payload array byte) -34339 0x11/imm32/alloc-id:fake:payload -34340 # "2b/subtract" -34341 0xb/imm32/size -34342 0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t -34343 _string_2d_subtract_from_eax: # (payload array byte) -34344 0x11/imm32/alloc-id:fake:payload -34345 # "2d/subtract-from-eax" -34346 0x14/imm32/size -34347 0x32/2 0x64/d 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m 0x2d/dash 0x65/e 0x61/a 0x78/x -34348 _string_31_xor_with: # (payload array byte) -34349 0x11/imm32/alloc-id:fake:payload -34350 # "31/xor-with" -34351 0xb/imm32/size -34352 0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -34353 _string_33_xor: # (payload array byte) -34354 0x11/imm32/alloc-id:fake:payload -34355 # "33/xor" -34356 0x6/imm32/size -34357 0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r -34358 _string_35_xor_with_eax: # (payload array byte) -34359 0x11/imm32/alloc-id:fake:payload -34360 # "35/xor-with-eax" -34361 0xf/imm32/size -34362 0x33/3 0x35/5 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x -34363 _string_39_compare->: # (payload array byte) -34364 0x11/imm32/alloc-id:fake:payload -34365 # "39/compare->" -34366 0xc/imm32/size -34367 0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/> -34368 _string_3b_compare<-: # (payload array byte) -34369 0x11/imm32/alloc-id:fake:payload -34370 # "3b/compare<-" -34371 0xc/imm32/size -34372 0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash -34373 _string_3d_compare_eax_with: # (payload array byte) -34374 0x11/imm32/alloc-id:fake:payload -34375 # "3d/compare-eax-with" -34376 0x13/imm32/size -34377 0x33/3 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x65/e 0x61/a 0x78/x 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h -34378 _string_40_increment_eax: # (payload array byte) -34379 0x11/imm32/alloc-id:fake:payload -34380 # "40/increment-eax" -34381 0x10/imm32/size -34382 0x34/4 0x30/0 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x -34383 _string_41_increment_ecx: # (payload array byte) -34384 0x11/imm32/alloc-id:fake:payload -34385 # "41/increment-ecx" -34386 0x10/imm32/size -34387 0x34/4 0x31/1 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x -34388 _string_42_increment_edx: # (payload array byte) -34389 0x11/imm32/alloc-id:fake:payload -34390 # "42/increment-edx" -34391 0x10/imm32/size -34392 0x34/4 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x -34393 _string_43_increment_ebx: # (payload array byte) -34394 0x11/imm32/alloc-id:fake:payload -34395 # "43/increment-ebx" -34396 0x10/imm32/size -34397 0x34/4 0x33/3 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x -34398 _string_46_increment_esi: # (payload array byte) -34399 0x11/imm32/alloc-id:fake:payload -34400 # "46/increment-esi" -34401 0x10/imm32/size -34402 0x34/4 0x36/6 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i -34403 _string_47_increment_edi: # (payload array byte) -34404 0x11/imm32/alloc-id:fake:payload -34405 # "47/increment-edi" -34406 0x10/imm32/size -34407 0x34/4 0x37/7 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i -34408 _string_48_decrement_eax: # (payload array byte) -34409 0x11/imm32/alloc-id:fake:payload -34410 # "48/decrement-eax" -34411 0x10/imm32/size -34412 0x34/4 0x38/8 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x -34413 _string_49_decrement_ecx: # (payload array byte) -34414 0x11/imm32/alloc-id:fake:payload -34415 # "49/decrement-ecx" -34416 0x10/imm32/size -34417 0x34/4 0x39/9 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x -34418 _string_4a_decrement_edx: # (payload array byte) -34419 0x11/imm32/alloc-id:fake:payload -34420 # "4a/decrement-edx" -34421 0x10/imm32/size -34422 0x34/4 0x61/a 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x -34423 _string_4b_decrement_ebx: # (payload array byte) -34424 0x11/imm32/alloc-id:fake:payload -34425 # "4b/decrement-ebx" -34426 0x10/imm32/size -34427 0x34/4 0x62/b 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x -34428 _string_4e_decrement_esi: # (payload array byte) -34429 0x11/imm32/alloc-id:fake:payload -34430 # "4e/decrement-esi" -34431 0x10/imm32/size -34432 0x34/4 0x65/e 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i -34433 _string_4f_decrement_edi: # (payload array byte) -34434 0x11/imm32/alloc-id:fake:payload -34435 # "4f/decrement-edi" -34436 0x10/imm32/size -34437 0x34/4 0x66/f 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i -34438 _string_81_subop_add: # (payload array byte) -34439 0x11/imm32/alloc-id:fake:payload -34440 # "81 0/subop/add" -34441 0xe/imm32/size -34442 0x38/8 0x31/1 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x64/d 0x64/d -34443 _string_81_subop_or: # (payload array byte) -34444 0x11/imm32/alloc-id:fake:payload -34445 # "81 1/subop/or" -34446 0xd/imm32/size -34447 0x38/8 0x31/1 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6f/o 0x72/r -34448 _string_81_subop_and: # (payload array byte) -34449 0x11/imm32/alloc-id:fake:payload -34450 # "81 4/subop/and" -34451 0xe/imm32/size -34452 0x38/8 0x31/1 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x6e/n 0x64/d -34453 _string_81_subop_subtract: # (payload array byte) -34454 0x11/imm32/alloc-id:fake:payload -34455 # "81 5/subop/subtract" -34456 0x13/imm32/size -34457 0x38/8 0x31/1 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t -34458 _string_81_subop_xor: # (payload array byte) -34459 0x11/imm32/alloc-id:fake:payload -34460 # "81 6/subop/xor" -34461 0xe/imm32/size -34462 0x38/8 0x31/1 0x20/space 0x36/6 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x78/x 0x6f/o 0x72/r -34463 _string_81_subop_compare: # (payload array byte) -34464 0x11/imm32/alloc-id:fake:payload -34465 # "81 7/subop/compare" -34466 0x12/imm32/size -34467 0x38/8 0x31/1 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e -34468 _string_89_<-: # (payload array byte) -34469 0x11/imm32/alloc-id:fake:payload -34470 # "89/<-" -34471 0x5/imm32/size -34472 0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash -34473 _string_8b_->: # (payload array byte) -34474 0x11/imm32/alloc-id:fake:payload -34475 # "8b/->" -34476 0x5/imm32/size -34477 0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/> -34478 _string_8a_copy_byte: -34479 0x11/imm32/alloc-id:fake:payload -34480 # "8a/byte->" -34481 0x9/imm32/size -34482 0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/> -34483 _string_88_copy_byte: -34484 0x11/imm32/alloc-id:fake:payload -34485 # "88/byte<-" -34486 0x9/imm32/size -34487 0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/- -34488 _string_8d_copy_address: # (payload array byte) -34489 0x11/imm32/alloc-id:fake:payload -34490 # "8d/copy-address" -34491 0xf/imm32/size -34492 0x38/8 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s -34493 _string_b8_copy_to_eax: # (payload array byte) -34494 0x11/imm32/alloc-id:fake:payload -34495 # "b8/copy-to-eax" -34496 0xe/imm32/size -34497 0x62/b 0x38/8 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x -34498 _string_b9_copy_to_ecx: # (payload array byte) -34499 0x11/imm32/alloc-id:fake:payload -34500 # "b9/copy-to-ecx" -34501 0xe/imm32/size -34502 0x62/b 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x63/c 0x78/x -34503 _string_ba_copy_to_edx: # (payload array byte) -34504 0x11/imm32/alloc-id:fake:payload -34505 # "ba/copy-to-edx" -34506 0xe/imm32/size -34507 0x62/b 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x78/x -34508 _string_bb_copy_to_ebx: # (payload array byte) -34509 0x11/imm32/alloc-id:fake:payload -34510 # "bb/copy-to-ebx" -34511 0xe/imm32/size -34512 0x62/b 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x62/b 0x78/x -34513 _string_be_copy_to_esi: # (payload array byte) -34514 0x11/imm32/alloc-id:fake:payload -34515 # "be/copy-to-esi" -34516 0xe/imm32/size -34517 0x62/b 0x65/e 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x73/s 0x69/i -34518 _string_bf_copy_to_edi: # (payload array byte) -34519 0x11/imm32/alloc-id:fake:payload -34520 # "bf/copy-to-edi" -34521 0xe/imm32/size -34522 0x62/b 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x69/i -34523 _string_c7_subop_copy: # (payload array byte) -34524 0x11/imm32/alloc-id:fake:payload -34525 # "c7 0/subop/copy" -34526 0xf/imm32/size -34527 0x63/c 0x37/7 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y -34528 _string_e9_jump_label: # (payload array byte) -34529 0x11/imm32/alloc-id:fake:payload -34530 # "e9/jump" -34531 0x7/imm32/size -34532 0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p -34533 _string_e9_jump_break: # (payload array byte) -34534 0x11/imm32/alloc-id:fake:payload -34535 # "e9/jump break/disp32" -34536 0x14/imm32/size -34537 0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34538 _string_e9_jump_loop: # (payload array byte) -34539 0x11/imm32/alloc-id:fake:payload -34540 # "e9/jump loop/disp32" -34541 0x13/imm32/size -34542 0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 -34543 _string_f7_subop_negate: -34544 0x11/imm32/alloc-id:fake:payload -34545 # "f7 3/subop/negate" -34546 0x11/imm32/size -34547 0x66/f 0x37/7 0x20/space 0x33/3 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e -34548 _string_ff_subop_increment: # (payload array byte) -34549 0x11/imm32/alloc-id:fake:payload -34550 # "ff 0/subop/increment" -34551 0x14/imm32/size -34552 0x66/f 0x66/f 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t -34553 _string_ff_subop_decrement: # (payload array byte) -34554 0x11/imm32/alloc-id:fake:payload -34555 # "ff 1/subop/decrement" -34556 0x14/imm32/size -34557 0x66/f 0x66/f 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t -34558 _string_c1_subop_shift_left: # (payload array byte) -34559 0x11/imm32/alloc-id:fake:payload -34560 # "c1/shift 4/subop/left" -34561 0x15/imm32/size -34562 0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6c/l 0x65/e 0x66/f 0x74/t -34563 _string_c1_subop_shift_right_padding_zeroes: # (payload array byte) -34564 0x11/imm32/alloc-id:fake:payload -34565 # "c1/shift 5/subop/right-padding-zeroes" -34566 0x25/imm32/size -34567 0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x61/a 0x64/d 0x64/d 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x7a/z 0x65/e 0x72/r 0x6f/o 0x65/e 0x73/s -34568 _string_c1_subop_shift_right_preserving_sign: # (payload array byte) -34569 0x11/imm32/alloc-id:fake:payload -34570 # "c1/shift 7/subop/right-preserving-sign" -34571 0x26/imm32/size -34572 0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x72/r 0x65/e 0x73/s 0x65/e 0x72/r 0x76/v 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n -34573 -34574 Single-int-var-in-mem: # (payload list var) -34575 0x11/imm32/alloc-id:fake:payload -34576 0x11/imm32/alloc-id:fake -34577 Int-var-in-mem/imm32 -34578 0/imm32/next -34579 0/imm32/next -34580 -34581 Int-var-in-mem: # (payload var) -34582 0x11/imm32/alloc-id:fake:payload -34583 0/imm32/name -34584 0/imm32/name -34585 0x11/imm32/alloc-id:fake -34586 Type-int/imm32 -34587 1/imm32/some-block-depth -34588 1/imm32/some-stack-offset -34589 0/imm32/no-register -34590 0/imm32/no-register -34591 -34592 # Not really legal, but closest we can currently represent a dereference of an (addr byte) -34593 Single-byte-var-in-mem: # (payload list var) -34594 0x11/imm32/alloc-id:fake:payload -34595 0x11/imm32/alloc-id:fake -34596 Byte-var-in-mem/imm32 -34597 0/imm32/next -34598 0/imm32/next -34599 -34600 # Not really legal, but closest we can currently represent a dereference of an (addr byte) -34601 Byte-var-in-mem: # (payload var) -34602 0x11/imm32/alloc-id:fake:payload -34603 0/imm32/name -34604 0/imm32/name -34605 0x11/imm32/alloc-id:fake -34606 Type-byte/imm32 -34607 1/imm32/some-block-depth -34608 1/imm32/some-stack-offset -34609 0/imm32/no-register -34610 0/imm32/no-register -34611 -34612 Two-args-int-stack-int-reg: # (payload list var) +33938 0x11/imm32/alloc-id:fake +33939 _string-loop-if-float>=/imm32/name +33940 0x11/imm32/alloc-id:fake +33941 Single-lit-var/imm32/inouts +33942 0/imm32/no-outputs +33943 0/imm32/no-outputs +33944 0x11/imm32/alloc-id:fake +33945 _string_0f_83_jump_label/imm32/subx-name +33946 0/imm32/no-rm32 +33947 0/imm32/no-r32 +33948 0/imm32/no-imm32 +33949 0/imm32/no-imm8 +33950 1/imm32/disp32-is-first-inout +33951 0/imm32/no-xm32 +33952 0/imm32/no-x32 +33953 0x11/imm32/alloc-id:fake +33954 _Primitive-loop-if-float<=-named/imm32/next +33955 _Primitive-loop-if-float<=-named: # (payload primitive) +33956 0x11/imm32/alloc-id:fake:payload +33957 0x11/imm32/alloc-id:fake +33958 _string-loop-if-float<=/imm32/name +33959 0x11/imm32/alloc-id:fake +33960 Single-lit-var/imm32/inouts +33961 0/imm32/no-outputs +33962 0/imm32/no-outputs +33963 0x11/imm32/alloc-id:fake +33964 _string_0f_86_jump_label/imm32/subx-name +33965 0/imm32/no-rm32 +33966 0/imm32/no-r32 +33967 0/imm32/no-imm32 +33968 0/imm32/no-imm8 +33969 1/imm32/disp32-is-first-inout +33970 0/imm32/no-xm32 +33971 0/imm32/no-x32 +33972 0x11/imm32/alloc-id:fake +33973 _Primitive-loop-if-float>-named/imm32/next +33974 _Primitive-loop-if-float>-named: # (payload primitive) +33975 0x11/imm32/alloc-id:fake:payload +33976 0x11/imm32/alloc-id:fake +33977 _string-loop-if-float>/imm32/name +33978 0x11/imm32/alloc-id:fake +33979 Single-lit-var/imm32/inouts +33980 0/imm32/no-outputs +33981 0/imm32/no-outputs +33982 0x11/imm32/alloc-id:fake +33983 _string_0f_87_jump_label/imm32/subx-name +33984 0/imm32/no-rm32 +33985 0/imm32/no-r32 +33986 0/imm32/no-imm32 +33987 0/imm32/no-imm8 +33988 1/imm32/disp32-is-first-inout +33989 0/imm32/no-xm32 +33990 0/imm32/no-x32 +33991 0/imm32/next +33992 0/imm32/next +33993 +33994 # string literals for Mu instructions +33995 _string-add: # (payload array byte) +33996 0x11/imm32/alloc-id:fake:payload +33997 # "add" +33998 0x3/imm32/size +33999 0x61/a 0x64/d 0x64/d +34000 _string-address: # (payload array byte) +34001 0x11/imm32/alloc-id:fake:payload +34002 # "address" +34003 0x7/imm32/size +34004 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s +34005 _string-add-to: # (payload array byte) +34006 0x11/imm32/alloc-id:fake:payload +34007 # "add-to" +34008 0x6/imm32/size +34009 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o +34010 _string-and: # (payload array byte) +34011 0x11/imm32/alloc-id:fake:payload +34012 # "and" +34013 0x3/imm32/size +34014 0x61/a 0x6e/n 0x64/d +34015 _string-and-with: # (payload array byte) +34016 0x11/imm32/alloc-id:fake:payload +34017 # "and-with" +34018 0x8/imm32/size +34019 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34020 _string-break: # (payload array byte) +34021 0x11/imm32/alloc-id:fake:payload +34022 # "break" +34023 0x5/imm32/size +34024 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k +34025 _string-break-if-<: # (payload array byte) +34026 0x11/imm32/alloc-id:fake:payload +34027 # "break-if-<" +34028 0xa/imm32/size +34029 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< +34030 _string-break-if-<=: # (payload array byte) +34031 0x11/imm32/alloc-id:fake:payload +34032 # "break-if-<=" +34033 0xb/imm32/size +34034 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= +34035 _string-break-if-=: # (payload array byte) +34036 0x11/imm32/alloc-id:fake:payload +34037 # "break-if-=" +34038 0xa/imm32/size +34039 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= +34040 _string-break-if->: # (payload array byte) +34041 0x11/imm32/alloc-id:fake:payload +34042 # "break-if->" +34043 0xa/imm32/size +34044 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> +34045 _string-break-if->=: # (payload array byte) +34046 0x11/imm32/alloc-id:fake:payload +34047 # "break-if->=" +34048 0xb/imm32/size +34049 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= +34050 _string-break-if-!=: # (payload array byte) +34051 0x11/imm32/alloc-id:fake:payload +34052 # "break-if-!=" +34053 0xb/imm32/size +34054 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= +34055 _string-break-if-addr<: # (payload array byte) +34056 0x11/imm32/alloc-id:fake:payload +34057 # "break-if-addr<" +34058 0xe/imm32/size +34059 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< +34060 _string-break-if-addr<=: # (payload array byte) +34061 0x11/imm32/alloc-id:fake:payload +34062 # "break-if-addr<=" +34063 0xf/imm32/size +34064 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= +34065 _string-break-if-addr>: # (payload array byte) +34066 0x11/imm32/alloc-id:fake:payload +34067 # "break-if-addr>" +34068 0xe/imm32/size +34069 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> +34070 _string-break-if-addr>=: # (payload array byte) +34071 0x11/imm32/alloc-id:fake:payload +34072 # "break-if-addr>=" +34073 0xf/imm32/size +34074 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= +34075 _string-break-if-float<: # (payload array byte) +34076 0x11/imm32/alloc-id:fake:payload +34077 # "break-if-float<" +34078 0xf/imm32/size +34079 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< +34080 _string-break-if-float<=: # (payload array byte) +34081 0x11/imm32/alloc-id:fake:payload +34082 # "break-if-float<=" +34083 0x10/imm32/size +34084 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/= +34085 _string-break-if-float>: # (payload array byte) +34086 0x11/imm32/alloc-id:fake:payload +34087 # "break-if-float>" +34088 0xf/imm32/size +34089 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> +34090 _string-break-if-float>=: # (payload array byte) +34091 0x11/imm32/alloc-id:fake:payload +34092 # "break-if-float>=" +34093 0x10/imm32/size +34094 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/= +34095 _string-break-if-carry: # (payload array byte) +34096 0x11/imm32/alloc-id:fake:payload +34097 # "break-if-carry" +34098 0xe/imm32/size +34099 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y +34100 _string-break-if-not-carry: # (payload array byte) +34101 0x11/imm32/alloc-id:fake:payload +34102 # "break-if-not-carry" +34103 0x12/imm32/size +34104 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y +34105 _string-break-if-overflow: # (payload array byte) +34106 0x11/imm32/alloc-id:fake:payload +34107 # "break-if-overflow" +34108 0x11/imm32/size +34109 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w +34110 _string-break-if-not-overflow: # (payload array byte) +34111 0x11/imm32/alloc-id:fake:payload +34112 # "break-if-not-overflow" +34113 0x15/imm32/size +34114 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w +34115 _string-compare: # (payload array byte) +34116 0x11/imm32/alloc-id:fake:payload +34117 # "compare" +34118 0x7/imm32/size +34119 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e +34120 _string-copy: # (payload array byte) +34121 0x11/imm32/alloc-id:fake:payload +34122 # "copy" +34123 0x4/imm32/size +34124 0x63/c 0x6f/o 0x70/p 0x79/y +34125 _string-copy-to: # (payload array byte) +34126 0x11/imm32/alloc-id:fake:payload +34127 # "copy-to" +34128 0x7/imm32/size +34129 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o +34130 _string-copy-byte: +34131 0x11/imm32/alloc-id:fake:payload +34132 # "copy-byte" +34133 0x9/imm32/size +34134 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e +34135 _string-copy-byte-to: +34136 0x11/imm32/alloc-id:fake:payload +34137 # "copy-byte-to" +34138 0xc/imm32/size +34139 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o +34140 _string-decrement: # (payload array byte) +34141 0x11/imm32/alloc-id:fake:payload +34142 # "decrement" +34143 0x9/imm32/size +34144 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t +34145 _string-increment: # (payload array byte) +34146 0x11/imm32/alloc-id:fake:payload +34147 # "increment" +34148 0x9/imm32/size +34149 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t +34150 _string-loop: # (payload array byte) +34151 0x11/imm32/alloc-id:fake:payload +34152 # "loop" +34153 0x4/imm32/size +34154 0x6c/l 0x6f/o 0x6f/o 0x70/p +34155 _string-loop-if-<: # (payload array byte) +34156 0x11/imm32/alloc-id:fake:payload +34157 # "loop-if-<" +34158 0x9/imm32/size +34159 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< +34160 _string-loop-if-<=: # (payload array byte) +34161 0x11/imm32/alloc-id:fake:payload +34162 # "loop-if-<=" +34163 0xa/imm32/size +34164 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= +34165 _string-loop-if-=: # (payload array byte) +34166 0x11/imm32/alloc-id:fake:payload +34167 # "loop-if-=" +34168 0x9/imm32/size +34169 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= +34170 _string-loop-if->: # (payload array byte) +34171 0x11/imm32/alloc-id:fake:payload +34172 # "loop-if->" +34173 0x9/imm32/size +34174 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> +34175 _string-loop-if->=: # (payload array byte) +34176 0x11/imm32/alloc-id:fake:payload +34177 # "loop-if->=" +34178 0xa/imm32/size +34179 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= +34180 _string-loop-if-!=: # (payload array byte) +34181 0x11/imm32/alloc-id:fake:payload +34182 # "loop-if-!=" +34183 0xa/imm32/size +34184 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= +34185 _string-loop-if-addr<: # (payload array byte) +34186 0x11/imm32/alloc-id:fake:payload +34187 # "loop-if-addr<" +34188 0xd/imm32/size +34189 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< +34190 _string-loop-if-addr<=: # (payload array byte) +34191 0x11/imm32/alloc-id:fake:payload +34192 # "loop-if-addr<=" +34193 0xe/imm32/size +34194 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= +34195 _string-loop-if-addr>: # (payload array byte) +34196 0x11/imm32/alloc-id:fake:payload +34197 # "loop-if-addr>" +34198 0xd/imm32/size +34199 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> +34200 _string-loop-if-addr>=: # (payload array byte) +34201 0x11/imm32/alloc-id:fake:payload +34202 # "loop-if-addr>=" +34203 0xe/imm32/size +34204 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= +34205 _string-loop-if-float<: # (payload array byte) +34206 0x11/imm32/alloc-id:fake:payload +34207 # "loop-if-float<" +34208 0xe/imm32/size +34209 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< +34210 _string-loop-if-float<=: # (payload array byte) +34211 0x11/imm32/alloc-id:fake:payload +34212 # "loop-if-float<=" +34213 0xf/imm32/size +34214 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/= +34215 _string-loop-if-float>: # (payload array byte) +34216 0x11/imm32/alloc-id:fake:payload +34217 # "loop-if-float>" +34218 0xe/imm32/size +34219 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> +34220 _string-loop-if-float>=: # (payload array byte) +34221 0x11/imm32/alloc-id:fake:payload +34222 # "loop-if-float>=" +34223 0xf/imm32/size +34224 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/= +34225 _string-loop-if-carry: # (payload array byte) +34226 0x11/imm32/alloc-id:fake:payload +34227 # "loop-if-carry" +34228 0xd/imm32/size +34229 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y +34230 _string-loop-if-not-carry: # (payload array byte) +34231 0x11/imm32/alloc-id:fake:payload +34232 # "loop-if-not-carry" +34233 0x11/imm32/size +34234 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y +34235 _string-loop-if-overflow: # (payload array byte) +34236 0x11/imm32/alloc-id:fake:payload +34237 # "loop-if-overflow" +34238 0x10/imm32/size +34239 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w +34240 _string-loop-if-not-overflow: # (payload array byte) +34241 0x11/imm32/alloc-id:fake:payload +34242 # "loop-if-not-overflow" +34243 0x14/imm32/size +34244 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w +34245 _string-multiply: # (payload array byte) +34246 0x11/imm32/alloc-id:fake:payload +34247 # "multiply" +34248 0x8/imm32/size +34249 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y +34250 _string-convert: # (payload array byte) +34251 0x11/imm32/alloc-id:fake:payload +34252 # "convert" +34253 0x7/imm32/size +34254 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t +34255 _string-truncate: # (payload array byte) +34256 0x11/imm32/alloc-id:fake:payload +34257 # "truncate" +34258 0x8/imm32/size +34259 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e +34260 _string-reinterpret: # (payload array byte) +34261 0x11/imm32/alloc-id:fake:payload +34262 # "reinterpret" +34263 0xb/imm32/size +34264 0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t +34265 _string-divide: +34266 0x11/imm32/alloc-id:fake:payload +34267 # "divide" +34268 0x6/imm32/size +34269 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e +34270 _string-max: +34271 0x11/imm32/alloc-id:fake:payload +34272 # "max" +34273 0x3/imm32/size +34274 0x6d/m 0x61/a 0x78/x +34275 _string-min: +34276 0x11/imm32/alloc-id:fake:payload +34277 # "min" +34278 0x3/imm32/size +34279 0x6d/m 0x69/i 0x6e/n +34280 _string-reciprocal: +34281 0x11/imm32/alloc-id:fake:payload +34282 # "reciprocal" +34283 0xa/imm32/size +34284 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l +34285 _string-square-root: +34286 0x11/imm32/alloc-id:fake:payload +34287 # "square-root" +34288 0xb/imm32/size +34289 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t +34290 _string-inverse-square-root: +34291 0x11/imm32/alloc-id:fake:payload +34292 # "inverse-square-root" +34293 0x13/imm32/size +34294 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t +34295 _string-negate: # (payload array byte) +34296 0x11/imm32/alloc-id:fake:payload +34297 # "negate" +34298 0x6/imm32/size +34299 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e +34300 _string-not: # (payload array byte) +34301 0x11/imm32/alloc-id:fake:payload +34302 # "not" +34303 0x3/imm32/size +34304 0x6e/n 0x6f/o 0x74/t +34305 _string-or: # (payload array byte) +34306 0x11/imm32/alloc-id:fake:payload +34307 # "or" +34308 0x2/imm32/size +34309 0x6f/o 0x72/r +34310 _string-or-with: # (payload array byte) +34311 0x11/imm32/alloc-id:fake:payload +34312 # "or-with" +34313 0x7/imm32/size +34314 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34315 _string-subtract: # (payload array byte) +34316 0x11/imm32/alloc-id:fake:payload +34317 # "subtract" +34318 0x8/imm32/size +34319 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t +34320 _string-subtract-from: # (payload array byte) +34321 0x11/imm32/alloc-id:fake:payload +34322 # "subtract-from" +34323 0xd/imm32/size +34324 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m +34325 _string-xor: # (payload array byte) +34326 0x11/imm32/alloc-id:fake:payload +34327 # "xor" +34328 0x3/imm32/size +34329 0x78/x 0x6f/o 0x72/r +34330 _string-xor-with: # (payload array byte) +34331 0x11/imm32/alloc-id:fake:payload +34332 # "xor-with" +34333 0x8/imm32/size +34334 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34335 _string-shift-left: # (payload array byte) +34336 0x11/imm32/alloc-id:fake:payload +34337 # "shift-left" +34338 0xa/imm32/size +34339 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t +34340 _string-shift-right: # (payload array byte) +34341 0x11/imm32/alloc-id:fake:payload +34342 # "shift-right" +34343 0xb/imm32/size +34344 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t +34345 _string-shift-right-signed: # (payload array byte) +34346 0x11/imm32/alloc-id:fake:payload +34347 # "shift-right-signed" +34348 0x12/imm32/size +34349 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n 0x65/e 0x64/d +34350 +34351 # string literals for SubX instructions +34352 _string_01_add_to: # (payload array byte) +34353 0x11/imm32/alloc-id:fake:payload +34354 # "01/add-to" +34355 0x9/imm32/size +34356 0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o +34357 _string_03_add: # (payload array byte) +34358 0x11/imm32/alloc-id:fake:payload +34359 # "03/add" +34360 0x6/imm32/size +34361 0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d +34362 _string_05_add_to_eax: # (payload array byte) +34363 0x11/imm32/alloc-id:fake:payload +34364 # "05/add-to-eax" +34365 0xd/imm32/size +34366 0x30/0 0x35/5 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x +34367 _string_09_or_with: # (payload array byte) +34368 0x11/imm32/alloc-id:fake:payload +34369 # "09/or-with" +34370 0xa/imm32/size +34371 0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34372 _string_0b_or: # (payload array byte) +34373 0x11/imm32/alloc-id:fake:payload +34374 # "0b/or" +34375 0x5/imm32/size +34376 0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r +34377 _string_0d_or_with_eax: # (payload array byte) +34378 0x11/imm32/alloc-id:fake:payload +34379 # "0d/or-with-eax" +34380 0xe/imm32/size +34381 0x30/0 0x64/d 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x +34382 _string_0f_80_jump_label: # (payload array byte) +34383 0x11/imm32/alloc-id:fake:payload +34384 # "0f 80/jump-if-overflow" +34385 0x16/imm32/size +34386 0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w +34387 _string_0f_80_jump_break: # (payload array byte) +34388 0x11/imm32/alloc-id:fake:payload +34389 # "0f 80/jump-if-overflow break/disp32" +34390 0x23/imm32/size +34391 0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34392 _string_0f_80_jump_loop: # (payload array byte) +34393 0x11/imm32/alloc-id:fake:payload +34394 # "0f 80/jump-if-overflow loop/disp32" +34395 0x22/imm32/size +34396 0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34397 _string_0f_81_jump_label: # (payload array byte) +34398 0x11/imm32/alloc-id:fake:payload +34399 # "0f 81/jump-if-not-overflow" +34400 0x1a/imm32/size +34401 0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w +34402 _string_0f_81_jump_break: # (payload array byte) +34403 0x11/imm32/alloc-id:fake:payload +34404 # "0f 81/jump-if-not-overflow break/disp32" +34405 0x27/imm32/size +34406 0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34407 _string_0f_81_jump_loop: # (payload array byte) +34408 0x11/imm32/alloc-id:fake:payload +34409 # "0f 81/jump-if-not-overflow loop/disp32" +34410 0x26/imm32/size +34411 0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34412 _string_0f_82_jump_label: # (payload array byte) +34413 0x11/imm32/alloc-id:fake:payload +34414 # "0f 82/jump-if-addr<" +34415 0x13/imm32/size +34416 0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< +34417 _string_0f_82_jump_break: # (payload array byte) +34418 0x11/imm32/alloc-id:fake:payload +34419 # "0f 82/jump-if-addr< break/disp32" +34420 0x20/imm32/size +34421 0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34422 _string_0f_82_jump_loop: # (payload array byte) +34423 0x11/imm32/alloc-id:fake:payload +34424 # "0f 82/jump-if-addr< loop/disp32" +34425 0x1f/imm32/size +34426 0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34427 _string_0f_83_jump_label: # (payload array byte) +34428 0x11/imm32/alloc-id:fake:payload +34429 # "0f 83/jump-if-addr>=" +34430 0x14/imm32/size +34431 0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= +34432 _string_0f_83_jump_break: # (payload array byte) +34433 0x11/imm32/alloc-id:fake:payload +34434 # "0f 83/jump-if-addr>= break/disp32" +34435 0x21/imm32/size +34436 0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34437 _string_0f_83_jump_loop: # (payload array byte) +34438 0x11/imm32/alloc-id:fake:payload +34439 # "0f 83/jump-if-addr>= loop/disp32" +34440 0x20/imm32/size +34441 0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34442 _string_0f_84_jump_label: # (payload array byte) +34443 0x11/imm32/alloc-id:fake:payload +34444 # "0f 84/jump-if-=" +34445 0xf/imm32/size +34446 0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= +34447 _string_0f_84_jump_break: # (payload array byte) +34448 0x11/imm32/alloc-id:fake:payload +34449 # "0f 84/jump-if-= break/disp32" +34450 0x1c/imm32/size +34451 0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34452 _string_0f_84_jump_loop: # (payload array byte) +34453 0x11/imm32/alloc-id:fake:payload +34454 # "0f 84/jump-if-= loop/disp32" +34455 0x1a/imm32/size +34456 0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34457 _string_0f_85_jump_label: # (payload array byte) +34458 0x11/imm32/alloc-id:fake:payload +34459 # "0f 85/jump-if-!=" +34460 0x10/imm32/size +34461 0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= +34462 _string_0f_85_jump_break: # (payload array byte) +34463 0x11/imm32/alloc-id:fake:payload +34464 # "0f 85/jump-if-!= break/disp32" +34465 0x1d/imm32/size +34466 0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34467 _string_0f_85_jump_loop: # (payload array byte) +34468 0x11/imm32/alloc-id:fake:payload +34469 # "0f 85/jump-if-!= loop/disp32" +34470 0x1c/imm32/size +34471 0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34472 _string_0f_86_jump_label: # (payload array byte) +34473 0x11/imm32/alloc-id:fake:payload +34474 # "0f 86/jump-if-addr<=" +34475 0x14/imm32/size +34476 0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= +34477 _string_0f_86_jump_break: # (payload array byte) +34478 0x11/imm32/alloc-id:fake:payload +34479 # "0f 86/jump-if-addr<= break/disp32" +34480 0x21/imm32/size +34481 0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34482 _string_0f_86_jump_loop: # (payload array byte) +34483 0x11/imm32/alloc-id:fake:payload +34484 # "0f 86/jump-if-addr<= loop/disp32" +34485 0x20/imm32/size +34486 0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34487 _string_0f_87_jump_label: # (payload array byte) +34488 0x11/imm32/alloc-id:fake:payload +34489 # "0f 87/jump-if-addr>" +34490 0x13/imm32/size +34491 0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> +34492 _string_0f_87_jump_break: # (payload array byte) +34493 0x11/imm32/alloc-id:fake:payload +34494 # "0f 87/jump-if-addr> break/disp32" +34495 0x20/imm32/size +34496 0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34497 _string_0f_87_jump_loop: # (payload array byte) +34498 0x11/imm32/alloc-id:fake:payload +34499 # "0f 87/jump-if-addr> loop/disp32" +34500 0x1f/imm32/size +34501 0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34502 _string_0f_8c_jump_label: # (payload array byte) +34503 0x11/imm32/alloc-id:fake:payload +34504 # "0f 8c/jump-if-<" +34505 0xf/imm32/size +34506 0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< +34507 _string_0f_8c_jump_break: # (payload array byte) +34508 0x11/imm32/alloc-id:fake:payload +34509 # "0f 8c/jump-if-< break/disp32" +34510 0x1c/imm32/size +34511 0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34512 _string_0f_8c_jump_loop: # (payload array byte) +34513 0x11/imm32/alloc-id:fake:payload +34514 # "0f 8c/jump-if-< loop/disp32" +34515 0x1b/imm32/size +34516 0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34517 _string_0f_8d_jump_label: # (payload array byte) +34518 0x11/imm32/alloc-id:fake:payload +34519 # "0f 8d/jump-if->=" +34520 0x10/imm32/size +34521 0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= +34522 _string_0f_8d_jump_break: # (payload array byte) +34523 0x11/imm32/alloc-id:fake:payload +34524 # "0f 8d/jump-if->= break/disp32" +34525 0x1d/imm32/size +34526 0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34527 _string_0f_8d_jump_loop: # (payload array byte) +34528 0x11/imm32/alloc-id:fake:payload +34529 # "0f 8d/jump-if->= loop/disp32" +34530 0x1c/imm32/size +34531 0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34532 _string_0f_8e_jump_label: # (payload array byte) +34533 0x11/imm32/alloc-id:fake:payload +34534 # "0f 8e/jump-if-<=" +34535 0x10/imm32/size +34536 0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= +34537 _string_0f_8e_jump_break: # (payload array byte) +34538 0x11/imm32/alloc-id:fake:payload +34539 # "0f 8e/jump-if-<= break/disp32" +34540 0x1d/imm32/size +34541 0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34542 _string_0f_8e_jump_loop: # (payload array byte) +34543 0x11/imm32/alloc-id:fake:payload +34544 # "0f 8e/jump-if-<= loop/disp32" +34545 0x1c/imm32/size +34546 0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34547 _string_0f_8f_jump_label: # (payload array byte) +34548 0x11/imm32/alloc-id:fake:payload +34549 # "0f 8f/jump-if->" +34550 0xf/imm32/size +34551 0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> +34552 _string_0f_8f_jump_break: # (payload array byte) +34553 0x11/imm32/alloc-id:fake:payload +34554 # "0f 8f/jump-if-> break/disp32" +34555 0x1c/imm32/size +34556 0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34557 _string_0f_8f_jump_loop: # (payload array byte) +34558 0x11/imm32/alloc-id:fake:payload +34559 # "0f 8f/jump-if-> loop/disp32" +34560 0x1b/imm32/size +34561 0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34562 _string_0f_af_multiply: # (payload array byte) +34563 0x11/imm32/alloc-id:fake:payload +34564 # "0f af/multiply" +34565 0xe/imm32/size +34566 0x30/0 0x66/f 0x20/space 0x61/a 0x66/f 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y +34567 _string_f3_0f_2a_convert_to_float: +34568 0x11/imm32/alloc-id:fake:payload +34569 # "f3 0f 2a/convert-to-float" +34570 0x19/imm32/size +34571 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t +34572 _string_f3_0f_2d_convert_to_int: +34573 0x11/imm32/alloc-id:fake:payload +34574 # "f3 0f 2d/convert-to-int" +34575 0x17/imm32/size +34576 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t +34577 _string_f3_0f_2c_truncate_to_int: +34578 0x11/imm32/alloc-id:fake:payload +34579 # "f3 0f 2c/truncate-to-int" +34580 0x18/imm32/size +34581 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x63/c 0x2f/slash 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t +34582 _string_f3_0f_58_add: +34583 0x11/imm32/alloc-id:fake:payload +34584 # "f3 0f 58/add" +34585 0xc/imm32/size +34586 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d +34587 _string_f3_0f_5c_subtract: +34588 0x11/imm32/alloc-id:fake:payload +34589 # "f3 0f 5c/subtract" +34590 0x11/imm32/size +34591 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x63/c 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t +34592 _string_f3_0f_59_multiply: +34593 0x11/imm32/alloc-id:fake:payload +34594 # "f3 0f 59/multiply" +34595 0x11/imm32/size +34596 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x39/9 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y +34597 _string_f3_0f_5e_divide: +34598 0x11/imm32/alloc-id:fake:payload +34599 # "f3 0f 5e/divide" +34600 0xf/imm32/size +34601 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x65/e 0x2f/slash 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e +34602 _string_f3_0f_53_reciprocal: +34603 0x11/imm32/alloc-id:fake:payload +34604 # "f3 0f 53/reciprocal" +34605 0x13/imm32/size +34606 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x33/3 0x2f/slash 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l +34607 _string_f3_0f_51_square_root: +34608 0x11/imm32/alloc-id:fake:payload +34609 # "f3 0f 51/square-root" +34610 0x14/imm32/size +34611 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x31/1 0x2f/slash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t +34612 _string_f3_0f_52_inverse_square_root: 34613 0x11/imm32/alloc-id:fake:payload -34614 0x11/imm32/alloc-id:fake -34615 Int-var-in-mem/imm32 -34616 0x11/imm32/alloc-id:fake -34617 Single-int-var-in-some-register/imm32/next -34618 -34619 Two-int-args-in-regs: # (payload list var) -34620 0x11/imm32/alloc-id:fake:payload -34621 0x11/imm32/alloc-id:fake -34622 Int-var-in-some-register/imm32 -34623 0x11/imm32/alloc-id:fake -34624 Single-int-var-in-some-register/imm32/next -34625 -34626 # Not really legal, but closest we can currently represent a dereference of an (addr byte) -34627 Two-args-byte-stack-byte-reg: # (payload list var) +34614 # "f3 0f 52/inverse-square-root" +34615 0x1c/imm32/size +34616 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t +34617 _string_f3_0f_5d_min: +34618 0x11/imm32/alloc-id:fake:payload +34619 # "f3 0f 5d/min" +34620 0xc/imm32/size +34621 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n +34622 _string_f3_0f_5f_max: +34623 0x11/imm32/alloc-id:fake:payload +34624 # "f3 0f 5f/max" +34625 0xc/imm32/size +34626 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x +34627 _string_f3_0f_10_copy: 34628 0x11/imm32/alloc-id:fake:payload -34629 0x11/imm32/alloc-id:fake -34630 Byte-var-in-mem/imm32 -34631 0x11/imm32/alloc-id:fake -34632 Single-byte-var-in-some-register/imm32/next -34633 -34634 Two-args-int-reg-int-stack: # (payload list var) -34635 0x11/imm32/alloc-id:fake:payload -34636 0x11/imm32/alloc-id:fake -34637 Int-var-in-some-register/imm32 -34638 0x11/imm32/alloc-id:fake -34639 Single-int-var-in-mem/imm32/next -34640 -34641 Two-args-int-eax-int-literal: # (payload list var) -34642 0x11/imm32/alloc-id:fake:payload -34643 0x11/imm32/alloc-id:fake -34644 Int-var-in-eax/imm32 -34645 0x11/imm32/alloc-id:fake -34646 Single-lit-var/imm32/next -34647 -34648 Int-var-and-literal: # (payload list var) -34649 0x11/imm32/alloc-id:fake:payload -34650 0x11/imm32/alloc-id:fake -34651 Int-var-in-mem/imm32 -34652 0x11/imm32/alloc-id:fake -34653 Single-lit-var/imm32/next -34654 -34655 Int-var-in-register-and-literal: # (payload list var) -34656 0x11/imm32/alloc-id:fake:payload -34657 0x11/imm32/alloc-id:fake -34658 Int-var-in-some-register/imm32 -34659 0x11/imm32/alloc-id:fake -34660 Single-lit-var/imm32/next -34661 -34662 Two-float-args-in-regs: # (payload list var) +34629 # "f3 0f 10/copy" +34630 0xd/imm32/size +34631 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x30/0 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y +34632 _string_f3_0f_11_copy: +34633 0x11/imm32/alloc-id:fake:payload +34634 # "f3 0f 11/copy" +34635 0xd/imm32/size +34636 0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x31/1 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y +34637 _string_0f_2f_compare: +34638 0x11/imm32/alloc-id:fake:payload +34639 # "0f 2f/compare" +34640 0xd/imm32/size +34641 0x30/0 0x66/f 0x20/space 0x32/2 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e +34642 _string_21_and_with: # (payload array byte) +34643 0x11/imm32/alloc-id:fake:payload +34644 # "21/and-with" +34645 0xb/imm32/size +34646 0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34647 _string_23_and: # (payload array byte) +34648 0x11/imm32/alloc-id:fake:payload +34649 # "23/and" +34650 0x6/imm32/size +34651 0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d +34652 _string_25_and_with_eax: # (payload array byte) +34653 0x11/imm32/alloc-id:fake:payload +34654 # "25/and-with-eax" +34655 0xf/imm32/size +34656 0x32/2 0x35/5 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x +34657 _string_29_subtract_from: # (payload array byte) +34658 0x11/imm32/alloc-id:fake:payload +34659 # "29/subtract-from" +34660 0x10/imm32/size +34661 0x32/2 0x39/9 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m +34662 _string_2b_subtract: # (payload array byte) 34663 0x11/imm32/alloc-id:fake:payload -34664 0x11/imm32/alloc-id:fake -34665 Float-var-in-some-register/imm32 -34666 0x11/imm32/alloc-id:fake -34667 Single-float-var-in-some-register/imm32/next -34668 -34669 Two-args-float-reg-float-stack: # (payload list var) -34670 0x11/imm32/alloc-id:fake:payload -34671 0x11/imm32/alloc-id:fake -34672 Float-var-in-some-register/imm32 -34673 0x11/imm32/alloc-id:fake -34674 Single-float-var-in-mem/imm32/next -34675 -34676 Two-args-float-stack-float-reg: # (payload list var) -34677 0x11/imm32/alloc-id:fake:payload -34678 0x11/imm32/alloc-id:fake -34679 Float-var-in-mem/imm32 -34680 0x11/imm32/alloc-id:fake -34681 Single-float-var-in-some-register/imm32/next -34682 -34683 Single-int-var-in-some-register: # (payload list var) -34684 0x11/imm32/alloc-id:fake:payload -34685 0x11/imm32/alloc-id:fake -34686 Int-var-in-some-register/imm32 -34687 0/imm32/next -34688 0/imm32/next -34689 -34690 Single-addr-var-in-some-register: # (payload list var) -34691 0x11/imm32/alloc-id:fake:payload -34692 0x11/imm32/alloc-id:fake -34693 Addr-var-in-some-register/imm32 -34694 0/imm32/next -34695 0/imm32/next -34696 -34697 Single-byte-var-in-some-register: # (payload list var) +34664 # "2b/subtract" +34665 0xb/imm32/size +34666 0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t +34667 _string_2d_subtract_from_eax: # (payload array byte) +34668 0x11/imm32/alloc-id:fake:payload +34669 # "2d/subtract-from-eax" +34670 0x14/imm32/size +34671 0x32/2 0x64/d 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m 0x2d/dash 0x65/e 0x61/a 0x78/x +34672 _string_31_xor_with: # (payload array byte) +34673 0x11/imm32/alloc-id:fake:payload +34674 # "31/xor-with" +34675 0xb/imm32/size +34676 0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34677 _string_33_xor: # (payload array byte) +34678 0x11/imm32/alloc-id:fake:payload +34679 # "33/xor" +34680 0x6/imm32/size +34681 0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r +34682 _string_35_xor_with_eax: # (payload array byte) +34683 0x11/imm32/alloc-id:fake:payload +34684 # "35/xor-with-eax" +34685 0xf/imm32/size +34686 0x33/3 0x35/5 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x +34687 _string_39_compare->: # (payload array byte) +34688 0x11/imm32/alloc-id:fake:payload +34689 # "39/compare->" +34690 0xc/imm32/size +34691 0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/> +34692 _string_3b_compare<-: # (payload array byte) +34693 0x11/imm32/alloc-id:fake:payload +34694 # "3b/compare<-" +34695 0xc/imm32/size +34696 0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash +34697 _string_3d_compare_eax_with: # (payload array byte) 34698 0x11/imm32/alloc-id:fake:payload -34699 0x11/imm32/alloc-id:fake -34700 Byte-var-in-some-register/imm32 -34701 0/imm32/next -34702 0/imm32/next -34703 -34704 Int-var-in-some-register: # (payload var) -34705 0x11/imm32/alloc-id:fake:payload -34706 0/imm32/name -34707 0/imm32/name -34708 0x11/imm32/alloc-id:fake -34709 Type-int/imm32 -34710 1/imm32/some-block-depth -34711 0/imm32/no-stack-offset -34712 0x11/imm32/alloc-id:fake -34713 Any-register/imm32 -34714 -34715 Any-register: # (payload array byte) -34716 0x11/imm32/alloc-id:fake:payload -34717 1/imm32/size -34718 # data -34719 2a/asterisk -34720 -34721 Addr-var-in-some-register: # (payload var) -34722 0x11/imm32/alloc-id:fake:payload -34723 0/imm32/name -34724 0/imm32/name -34725 0x11/imm32/alloc-id:fake -34726 Type-addr/imm32 -34727 1/imm32/some-block-depth -34728 0/imm32/no-stack-offset -34729 0x11/imm32/alloc-id:fake -34730 Any-register/imm32 -34731 -34732 Byte-var-in-some-register: # (payload var) +34699 # "3d/compare-eax-with" +34700 0x13/imm32/size +34701 0x33/3 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x65/e 0x61/a 0x78/x 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h +34702 _string_40_increment_eax: # (payload array byte) +34703 0x11/imm32/alloc-id:fake:payload +34704 # "40/increment-eax" +34705 0x10/imm32/size +34706 0x34/4 0x30/0 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x +34707 _string_41_increment_ecx: # (payload array byte) +34708 0x11/imm32/alloc-id:fake:payload +34709 # "41/increment-ecx" +34710 0x10/imm32/size +34711 0x34/4 0x31/1 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x +34712 _string_42_increment_edx: # (payload array byte) +34713 0x11/imm32/alloc-id:fake:payload +34714 # "42/increment-edx" +34715 0x10/imm32/size +34716 0x34/4 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x +34717 _string_43_increment_ebx: # (payload array byte) +34718 0x11/imm32/alloc-id:fake:payload +34719 # "43/increment-ebx" +34720 0x10/imm32/size +34721 0x34/4 0x33/3 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x +34722 _string_46_increment_esi: # (payload array byte) +34723 0x11/imm32/alloc-id:fake:payload +34724 # "46/increment-esi" +34725 0x10/imm32/size +34726 0x34/4 0x36/6 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i +34727 _string_47_increment_edi: # (payload array byte) +34728 0x11/imm32/alloc-id:fake:payload +34729 # "47/increment-edi" +34730 0x10/imm32/size +34731 0x34/4 0x37/7 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i +34732 _string_48_decrement_eax: # (payload array byte) 34733 0x11/imm32/alloc-id:fake:payload -34734 0/imm32/name -34735 0/imm32/name -34736 0x11/imm32/alloc-id:fake -34737 Type-byte/imm32 -34738 1/imm32/some-block-depth -34739 0/imm32/no-stack-offset -34740 0x11/imm32/alloc-id:fake -34741 Any-register/imm32 -34742 -34743 Single-int-var-in-eax: # (payload list var) -34744 0x11/imm32/alloc-id:fake:payload -34745 0x11/imm32/alloc-id:fake -34746 Int-var-in-eax/imm32 -34747 0/imm32/next -34748 0/imm32/next -34749 -34750 Int-var-in-eax: -34751 0x11/imm32/alloc-id:fake:payload -34752 0/imm32/name -34753 0/imm32/name -34754 0x11/imm32/alloc-id:fake -34755 Type-int/imm32 -34756 1/imm32/some-block-depth -34757 0/imm32/no-stack-offset -34758 0x11/imm32/alloc-id:fake -34759 $Mu-register-eax/imm32 # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO) -34760 -34761 Single-int-var-in-ecx: # (payload list var) -34762 0x11/imm32/alloc-id:fake:payload -34763 0x11/imm32/alloc-id:fake -34764 Int-var-in-ecx/imm32 -34765 0/imm32/next -34766 0/imm32/next -34767 -34768 Int-var-in-ecx: -34769 0x11/imm32/alloc-id:fake:payload -34770 0/imm32/name -34771 0/imm32/name -34772 0x11/imm32/alloc-id:fake -34773 Type-int/imm32 -34774 1/imm32/some-block-depth -34775 0/imm32/no-stack-offset -34776 0x11/imm32/alloc-id:fake -34777 $Register-ecx/imm32/register -34778 -34779 Single-int-var-in-edx: # (payload list var) -34780 0x11/imm32/alloc-id:fake:payload -34781 0x11/imm32/alloc-id:fake -34782 Int-var-in-edx/imm32 -34783 0/imm32/next -34784 0/imm32/next -34785 -34786 Int-var-in-edx: # (payload list var) -34787 0x11/imm32/alloc-id:fake:payload -34788 0/imm32/name -34789 0/imm32/name -34790 0x11/imm32/alloc-id:fake -34791 Type-int/imm32 -34792 1/imm32/some-block-depth -34793 0/imm32/no-stack-offset -34794 0x11/imm32/alloc-id:fake -34795 $Register-edx/imm32/register -34796 -34797 Single-int-var-in-ebx: # (payload list var) +34734 # "48/decrement-eax" +34735 0x10/imm32/size +34736 0x34/4 0x38/8 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x +34737 _string_49_decrement_ecx: # (payload array byte) +34738 0x11/imm32/alloc-id:fake:payload +34739 # "49/decrement-ecx" +34740 0x10/imm32/size +34741 0x34/4 0x39/9 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x +34742 _string_4a_decrement_edx: # (payload array byte) +34743 0x11/imm32/alloc-id:fake:payload +34744 # "4a/decrement-edx" +34745 0x10/imm32/size +34746 0x34/4 0x61/a 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x +34747 _string_4b_decrement_ebx: # (payload array byte) +34748 0x11/imm32/alloc-id:fake:payload +34749 # "4b/decrement-ebx" +34750 0x10/imm32/size +34751 0x34/4 0x62/b 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x +34752 _string_4e_decrement_esi: # (payload array byte) +34753 0x11/imm32/alloc-id:fake:payload +34754 # "4e/decrement-esi" +34755 0x10/imm32/size +34756 0x34/4 0x65/e 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i +34757 _string_4f_decrement_edi: # (payload array byte) +34758 0x11/imm32/alloc-id:fake:payload +34759 # "4f/decrement-edi" +34760 0x10/imm32/size +34761 0x34/4 0x66/f 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i +34762 _string_81_subop_add: # (payload array byte) +34763 0x11/imm32/alloc-id:fake:payload +34764 # "81 0/subop/add" +34765 0xe/imm32/size +34766 0x38/8 0x31/1 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x64/d 0x64/d +34767 _string_81_subop_or: # (payload array byte) +34768 0x11/imm32/alloc-id:fake:payload +34769 # "81 1/subop/or" +34770 0xd/imm32/size +34771 0x38/8 0x31/1 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6f/o 0x72/r +34772 _string_81_subop_and: # (payload array byte) +34773 0x11/imm32/alloc-id:fake:payload +34774 # "81 4/subop/and" +34775 0xe/imm32/size +34776 0x38/8 0x31/1 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x6e/n 0x64/d +34777 _string_81_subop_subtract: # (payload array byte) +34778 0x11/imm32/alloc-id:fake:payload +34779 # "81 5/subop/subtract" +34780 0x13/imm32/size +34781 0x38/8 0x31/1 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t +34782 _string_81_subop_xor: # (payload array byte) +34783 0x11/imm32/alloc-id:fake:payload +34784 # "81 6/subop/xor" +34785 0xe/imm32/size +34786 0x38/8 0x31/1 0x20/space 0x36/6 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x78/x 0x6f/o 0x72/r +34787 _string_81_subop_compare: # (payload array byte) +34788 0x11/imm32/alloc-id:fake:payload +34789 # "81 7/subop/compare" +34790 0x12/imm32/size +34791 0x38/8 0x31/1 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e +34792 _string_89_<-: # (payload array byte) +34793 0x11/imm32/alloc-id:fake:payload +34794 # "89/<-" +34795 0x5/imm32/size +34796 0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash +34797 _string_8b_->: # (payload array byte) 34798 0x11/imm32/alloc-id:fake:payload -34799 0x11/imm32/alloc-id:fake -34800 Int-var-in-ebx/imm32 -34801 0/imm32/next -34802 0/imm32/next -34803 -34804 Int-var-in-ebx: # (payload list var) -34805 0x11/imm32/alloc-id:fake:payload -34806 0/imm32/name -34807 0/imm32/name -34808 0x11/imm32/alloc-id:fake -34809 Type-int/imm32 -34810 1/imm32/some-block-depth -34811 0/imm32/no-stack-offset -34812 0x11/imm32/alloc-id:fake -34813 $Register-ebx/imm32/register -34814 -34815 Single-int-var-in-esi: # (payload list var) -34816 0x11/imm32/alloc-id:fake:payload -34817 0x11/imm32/alloc-id:fake -34818 Int-var-in-esi/imm32 -34819 0/imm32/next -34820 0/imm32/next -34821 -34822 Int-var-in-esi: # (payload list var) +34799 # "8b/->" +34800 0x5/imm32/size +34801 0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/> +34802 _string_8a_copy_byte: +34803 0x11/imm32/alloc-id:fake:payload +34804 # "8a/byte->" +34805 0x9/imm32/size +34806 0x38/8 0x61/a 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x3e/> +34807 _string_88_copy_byte: +34808 0x11/imm32/alloc-id:fake:payload +34809 # "88/byte<-" +34810 0x9/imm32/size +34811 0x38/8 0x38/8 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/- +34812 _string_8d_copy_address: # (payload array byte) +34813 0x11/imm32/alloc-id:fake:payload +34814 # "8d/copy-address" +34815 0xf/imm32/size +34816 0x38/8 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s +34817 _string_b8_copy_to_eax: # (payload array byte) +34818 0x11/imm32/alloc-id:fake:payload +34819 # "b8/copy-to-eax" +34820 0xe/imm32/size +34821 0x62/b 0x38/8 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x +34822 _string_b9_copy_to_ecx: # (payload array byte) 34823 0x11/imm32/alloc-id:fake:payload -34824 0/imm32/name -34825 0/imm32/name -34826 0x11/imm32/alloc-id:fake -34827 Type-int/imm32 -34828 1/imm32/some-block-depth -34829 0/imm32/no-stack-offset -34830 0x11/imm32/alloc-id:fake -34831 $Register-esi/imm32/register -34832 -34833 Single-int-var-in-edi: # (payload list var) -34834 0x11/imm32/alloc-id:fake:payload -34835 0x11/imm32/alloc-id:fake -34836 Int-var-in-edi/imm32 -34837 0/imm32/next -34838 0/imm32/next -34839 -34840 Int-var-in-edi: # (payload list var) -34841 0x11/imm32/alloc-id:fake:payload -34842 0/imm32/name -34843 0/imm32/name -34844 0x11/imm32/alloc-id:fake -34845 Type-int/imm32 -34846 1/imm32/some-block-depth -34847 0/imm32/no-stack-offset -34848 0x11/imm32/alloc-id:fake -34849 $Register-edi/imm32/register -34850 -34851 Single-lit-var: # (payload list var) -34852 0x11/imm32/alloc-id:fake:payload -34853 0x11/imm32/alloc-id:fake -34854 Lit-var/imm32 -34855 0/imm32/next -34856 0/imm32/next -34857 -34858 Lit-var: # (payload var) -34859 0x11/imm32/alloc-id:fake:payload -34860 0/imm32/name -34861 0/imm32/name -34862 0x11/imm32/alloc-id:fake -34863 Type-literal/imm32 -34864 1/imm32/some-block-depth -34865 0/imm32/no-stack-offset -34866 0/imm32/no-register -34867 0/imm32/no-register -34868 -34869 Single-float-var-in-mem: # (payload list var) -34870 0x11/imm32/alloc-id:fake:payload -34871 0x11/imm32/alloc-id:fake -34872 Float-var-in-mem/imm32 -34873 0/imm32/next -34874 0/imm32/next -34875 -34876 Float-var-in-mem: # (payload var) -34877 0x11/imm32/alloc-id:fake:payload -34878 0/imm32/name -34879 0/imm32/name -34880 0x11/imm32/alloc-id:fake -34881 Type-float/imm32 -34882 1/imm32/some-block-depth -34883 1/imm32/some-stack-offset -34884 0/imm32/no-register -34885 0/imm32/no-register -34886 -34887 Single-float-var-in-some-register: # (payload list var) +34824 # "b9/copy-to-ecx" +34825 0xe/imm32/size +34826 0x62/b 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x63/c 0x78/x +34827 _string_ba_copy_to_edx: # (payload array byte) +34828 0x11/imm32/alloc-id:fake:payload +34829 # "ba/copy-to-edx" +34830 0xe/imm32/size +34831 0x62/b 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x78/x +34832 _string_bb_copy_to_ebx: # (payload array byte) +34833 0x11/imm32/alloc-id:fake:payload +34834 # "bb/copy-to-ebx" +34835 0xe/imm32/size +34836 0x62/b 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x62/b 0x78/x +34837 _string_be_copy_to_esi: # (payload array byte) +34838 0x11/imm32/alloc-id:fake:payload +34839 # "be/copy-to-esi" +34840 0xe/imm32/size +34841 0x62/b 0x65/e 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x73/s 0x69/i +34842 _string_bf_copy_to_edi: # (payload array byte) +34843 0x11/imm32/alloc-id:fake:payload +34844 # "bf/copy-to-edi" +34845 0xe/imm32/size +34846 0x62/b 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x69/i +34847 _string_c7_subop_copy: # (payload array byte) +34848 0x11/imm32/alloc-id:fake:payload +34849 # "c7 0/subop/copy" +34850 0xf/imm32/size +34851 0x63/c 0x37/7 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y +34852 _string_e9_jump_label: # (payload array byte) +34853 0x11/imm32/alloc-id:fake:payload +34854 # "e9/jump" +34855 0x7/imm32/size +34856 0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p +34857 _string_e9_jump_break: # (payload array byte) +34858 0x11/imm32/alloc-id:fake:payload +34859 # "e9/jump break/disp32" +34860 0x14/imm32/size +34861 0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34862 _string_e9_jump_loop: # (payload array byte) +34863 0x11/imm32/alloc-id:fake:payload +34864 # "e9/jump loop/disp32" +34865 0x13/imm32/size +34866 0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2 +34867 _string_f7_subop_negate: +34868 0x11/imm32/alloc-id:fake:payload +34869 # "f7 3/subop/negate" +34870 0x11/imm32/size +34871 0x66/f 0x37/7 0x20/space 0x33/3 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e +34872 _string_f7_subop_not: +34873 0x11/imm32/alloc-id:fake:payload +34874 # "f7 2/subop/not" +34875 0xe/imm32/size +34876 0x66/f 0x37/7 0x20/space 0x32/2 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x6f/o 0x74/t +34877 _string_ff_subop_increment: # (payload array byte) +34878 0x11/imm32/alloc-id:fake:payload +34879 # "ff 0/subop/increment" +34880 0x14/imm32/size +34881 0x66/f 0x66/f 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t +34882 _string_ff_subop_decrement: # (payload array byte) +34883 0x11/imm32/alloc-id:fake:payload +34884 # "ff 1/subop/decrement" +34885 0x14/imm32/size +34886 0x66/f 0x66/f 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t +34887 _string_c1_subop_shift_left: # (payload array byte) 34888 0x11/imm32/alloc-id:fake:payload -34889 0x11/imm32/alloc-id:fake -34890 Float-var-in-some-register/imm32 -34891 0/imm32/next -34892 0/imm32/next -34893 -34894 Float-var-in-some-register: # (payload var) -34895 0x11/imm32/alloc-id:fake:payload -34896 0/imm32/name -34897 0/imm32/name -34898 0x11/imm32/alloc-id:fake -34899 Type-float/imm32 -34900 1/imm32/some-block-depth -34901 0/imm32/no-stack-offset -34902 0x11/imm32/alloc-id:fake -34903 Any-register/imm32 -34904 -34905 Type-int: # (payload type-tree) -34906 0x11/imm32/alloc-id:fake:payload -34907 1/imm32/is-atom -34908 1/imm32/value:int -34909 0/imm32/left:unused -34910 0/imm32/right:null -34911 0/imm32/right:null -34912 -34913 Type-literal: # (payload type-tree) -34914 0x11/imm32/alloc-id:fake:payload -34915 1/imm32/is-atom -34916 0/imm32/value:literal -34917 0/imm32/left:unused -34918 0/imm32/right:null -34919 0/imm32/right:null +34889 # "c1/shift 4/subop/left" +34890 0x15/imm32/size +34891 0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6c/l 0x65/e 0x66/f 0x74/t +34892 _string_c1_subop_shift_right_padding_zeroes: # (payload array byte) +34893 0x11/imm32/alloc-id:fake:payload +34894 # "c1/shift 5/subop/right-padding-zeroes" +34895 0x25/imm32/size +34896 0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x61/a 0x64/d 0x64/d 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x7a/z 0x65/e 0x72/r 0x6f/o 0x65/e 0x73/s +34897 _string_c1_subop_shift_right_preserving_sign: # (payload array byte) +34898 0x11/imm32/alloc-id:fake:payload +34899 # "c1/shift 7/subop/right-preserving-sign" +34900 0x26/imm32/size +34901 0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x72/r 0x65/e 0x73/s 0x65/e 0x72/r 0x76/v 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n +34902 +34903 Single-int-var-in-mem: # (payload list var) +34904 0x11/imm32/alloc-id:fake:payload +34905 0x11/imm32/alloc-id:fake +34906 Int-var-in-mem/imm32 +34907 0/imm32/next +34908 0/imm32/next +34909 +34910 Int-var-in-mem: # (payload var) +34911 0x11/imm32/alloc-id:fake:payload +34912 0/imm32/name +34913 0/imm32/name +34914 0x11/imm32/alloc-id:fake +34915 Type-int/imm32 +34916 1/imm32/some-block-depth +34917 1/imm32/some-stack-offset +34918 0/imm32/no-register +34919 0/imm32/no-register 34920 -34921 Type-addr: # (payload type-tree) -34922 0x11/imm32/alloc-id:fake:payload -34923 1/imm32/is-atom -34924 2/imm32/value:addr -34925 0/imm32/left:unused -34926 0/imm32/right:null -34927 0/imm32/right:null +34921 # Not really legal, but closest we can currently represent a dereference of an (addr byte) +34922 Single-byte-var-in-mem: # (payload list var) +34923 0x11/imm32/alloc-id:fake:payload +34924 0x11/imm32/alloc-id:fake +34925 Byte-var-in-mem/imm32 +34926 0/imm32/next +34927 0/imm32/next 34928 -34929 Type-byte: # (payload type-tree) -34930 0x11/imm32/alloc-id:fake:payload -34931 1/imm32/is-atom -34932 8/imm32/value:byte -34933 0/imm32/left:unused -34934 0/imm32/right:null -34935 0/imm32/right:null -34936 -34937 Type-float: # (payload type-tree) -34938 0x11/imm32/alloc-id:fake:payload -34939 1/imm32/is-atom -34940 0xf/imm32/value:float -34941 0/imm32/left:unused -34942 0/imm32/right:null -34943 0/imm32/right:null -34944 -34945 == code -34946 emit-subx-primitive: # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor) -34947 # . prologue -34948 55/push-ebp -34949 89/<- %ebp 4/r32/esp -34950 # . save registers -34951 50/push-eax -34952 51/push-ecx -34953 # ecx = primitive -34954 8b/-> *(ebp+0x10) 1/r32/ecx -34955 # emit primitive name -34956 (emit-indent *(ebp+8) *Curr-block-depth) -34957 (lookup *(ecx+0x18) *(ecx+0x1c)) # Primitive-subx-name Primitive-subx-name => eax -34958 (write-buffered *(ebp+8) %eax) -34959 # emit rm32 if necessary -34960 (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # Primitive-subx-rm32 -34961 # emit xm32 if necessary -34962 (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # Primitive-subx-xm32 -34963 # emit r32 if necessary -34964 (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc)) # Primitive-subx-r32 -34965 # emit x32 if necessary -34966 (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc)) # Primitive-subx-x32 -34967 # emit imm32 if necessary -34968 (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc)) # Primitive-subx-imm32 -34969 # emit imm8 if necessary -34970 (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc)) # Primitive-subx-imm8 -34971 # emit disp32 if necessary -34972 (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # Primitive-subx-disp32 -34973 (write-buffered *(ebp+8) Newline) -34974 $emit-subx-primitive:end: -34975 # . restore registers -34976 59/pop-to-ecx -34977 58/pop-to-eax -34978 # . epilogue -34979 89/<- %esp 5/r32/ebp -34980 5d/pop-to-ebp -34981 c3/return -34982 -34983 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -34984 # . prologue -34985 55/push-ebp -34986 89/<- %ebp 4/r32/esp -34987 # . save registers -34988 50/push-eax -34989 # if (l == 0) return -34990 81 7/subop/compare *(ebp+0xc) 0/imm32 -34991 74/jump-if-= $emit-subx-rm32:end/disp8 -34992 # var v/eax: (addr stmt-var) -34993 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # => eax -34994 (emit-subx-var-as-rm32 *(ebp+8) %eax) -34995 $emit-subx-rm32:end: -34996 # . restore registers -34997 58/pop-to-eax -34998 # . epilogue -34999 89/<- %esp 5/r32/ebp -35000 5d/pop-to-ebp -35001 c3/return -35002 -35003 get-stmt-operand-from-arg-location: # stmt: (addr stmt), l: arg-location, err: (addr buffered-file), ed: (addr exit-descriptor) -> var/eax: (addr stmt-var) -35004 # . prologue -35005 55/push-ebp -35006 89/<- %ebp 4/r32/esp -35007 # . save registers -35008 51/push-ecx -35009 # eax = l -35010 8b/-> *(ebp+0xc) 0/r32/eax -35011 # ecx = stmt -35012 8b/-> *(ebp+8) 1/r32/ecx -35013 # if (l == 1) return stmt->inouts -35014 { -35015 3d/compare-eax-and 1/imm32 -35016 75/jump-if-!= break/disp8 -35017 $get-stmt-operand-from-arg-location:1: -35018 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -35019 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -35020 } -35021 # if (l == 2) return stmt->inouts->next -35022 { -35023 3d/compare-eax-and 2/imm32 -35024 75/jump-if-!= break/disp8 -35025 $get-stmt-operand-from-arg-location:2: -35026 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -35027 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -35028 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -35029 } -35030 # if (l == 3) return stmt->outputs -35031 { -35032 3d/compare-eax-and 3/imm32 -35033 75/jump-if-!= break/disp8 -35034 $get-stmt-operand-from-arg-location:3: -35035 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax -35036 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -35037 } -35038 # abort -35039 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -35040 $get-stmt-operand-from-arg-location:end: -35041 # . restore registers -35042 59/pop-to-ecx -35043 # . epilogue -35044 89/<- %esp 5/r32/ebp -35045 5d/pop-to-ebp -35046 c3/return -35047 -35048 $get-stmt-operand-from-arg-location:abort: -35049 # error("invalid arg-location " eax) -35050 (write-buffered *(ebp+0x10) "invalid arg-location ") -35051 (write-int32-hex-buffered *(ebp+0x10) %eax) -35052 (write-buffered *(ebp+0x10) Newline) -35053 (flush *(ebp+0x10)) -35054 (stop *(ebp+0x14) 1) -35055 # never gets here -35056 -35057 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) -35058 # . prologue -35059 55/push-ebp -35060 89/<- %ebp 4/r32/esp -35061 # . save registers -35062 50/push-eax -35063 51/push-ecx -35064 # if (l == 0) return -35065 81 7/subop/compare *(ebp+0xc) 0/imm32 -35066 0f 84/jump-if-= $emit-subx-r32:end/disp32 -35067 # var v/eax: (addr stmt-var) -35068 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -35069 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -35070 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -35071 #? (write-buffered Stderr "looking up ") -35072 #? (write-buffered Stderr %eax) -35073 #? (write-buffered Stderr Newline) -35074 #? (flush Stderr) -35075 (maybe-get Mu-registers %eax 0xc) # => eax: (addr register-index) -35076 (write-buffered *(ebp+8) Space) -35077 (write-int32-hex-buffered *(ebp+8) *eax) -35078 (write-buffered *(ebp+8) "/r32") -35079 $emit-subx-r32:end: -35080 # . restore registers -35081 59/pop-to-ecx -35082 58/pop-to-eax -35083 # . epilogue -35084 89/<- %esp 5/r32/ebp -35085 5d/pop-to-ebp -35086 c3/return -35087 -35088 emit-subx-x32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) -35089 # . prologue -35090 55/push-ebp -35091 89/<- %ebp 4/r32/esp -35092 # . save registers -35093 50/push-eax -35094 51/push-ecx -35095 # if (l == 0) return -35096 81 7/subop/compare *(ebp+0xc) 0/imm32 -35097 0f 84/jump-if-= $emit-subx-x32:end/disp32 -35098 # var v/eax: (addr stmt-var) -35099 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -35100 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -35101 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax -35102 #? (write-buffered Stderr "looking up ") -35103 #? (write-buffered Stderr %eax) -35104 #? (write-buffered Stderr Newline) -35105 #? (flush Stderr) -35106 (maybe-get Mu-registers %eax 0xc) # => eax: (addr register-index) -35107 (write-buffered *(ebp+8) Space) -35108 (write-int32-hex-buffered *(ebp+8) *eax) -35109 (write-buffered *(ebp+8) "/x32") -35110 $emit-subx-x32:end: -35111 # . restore registers -35112 59/pop-to-ecx -35113 58/pop-to-eax -35114 # . epilogue -35115 89/<- %esp 5/r32/ebp -35116 5d/pop-to-ebp -35117 c3/return -35118 -35119 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) -35120 # . prologue -35121 55/push-ebp -35122 89/<- %ebp 4/r32/esp -35123 # . save registers -35124 50/push-eax -35125 51/push-ecx -35126 # if (l == 0) return -35127 81 7/subop/compare *(ebp+0xc) 0/imm32 -35128 0f 84/jump-if-= $emit-subx-imm32:end/disp32 -35129 # var v/eax: (handle var) -35130 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -35131 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -35132 (lookup *eax *(eax+4)) # Var-name Var-name => eax -35133 (write-buffered *(ebp+8) Space) -35134 (write-buffered *(ebp+8) %eax) -35135 (write-buffered *(ebp+8) "/imm32") -35136 $emit-subx-imm32:end: -35137 # . restore registers -35138 59/pop-to-ecx -35139 58/pop-to-eax -35140 # . epilogue -35141 89/<- %esp 5/r32/ebp -35142 5d/pop-to-ebp -35143 c3/return -35144 -35145 emit-subx-imm8: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) -35146 # . prologue -35147 55/push-ebp -35148 89/<- %ebp 4/r32/esp -35149 # . save registers -35150 50/push-eax -35151 51/push-ecx -35152 # if (l == 0) return -35153 81 7/subop/compare *(ebp+0xc) 0/imm32 -35154 0f 84/jump-if-= $emit-subx-imm32:end/disp32 -35155 # var v/eax: (handle var) -35156 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -35157 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -35158 (lookup *eax *(eax+4)) # Var-name Var-name => eax -35159 (write-buffered *(ebp+8) Space) -35160 (write-buffered *(ebp+8) %eax) -35161 (write-buffered *(ebp+8) "/imm8") -35162 $emit-subx-imm8:end: -35163 # . restore registers -35164 59/pop-to-ecx -35165 58/pop-to-eax -35166 # . epilogue -35167 89/<- %esp 5/r32/ebp -35168 5d/pop-to-ebp -35169 c3/return -35170 -35171 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) -35172 # . prologue -35173 55/push-ebp -35174 89/<- %ebp 4/r32/esp -35175 # . save registers -35176 50/push-eax -35177 51/push-ecx -35178 # if (location == 0) return -35179 81 7/subop/compare *(ebp+0xc) 0/imm32 -35180 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -35181 # var v/eax: (addr stmt-var) -35182 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # => eax -35183 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax -35184 (lookup *eax *(eax+4)) # Var-name Var-name => eax -35185 (write-buffered *(ebp+8) Space) -35186 (write-buffered *(ebp+8) %eax) -35187 # hack: if instruction operation starts with "break", emit ":break" -35188 # var name/ecx: (addr array byte) = lookup(stmt->operation) -35189 8b/-> *(ebp+0x10) 0/r32/eax -35190 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -35191 89/<- %ecx 0/r32/eax -35192 { -35193 (string-starts-with? %ecx "break") # => eax -35194 3d/compare-eax-and 0/imm32/false -35195 74/jump-if-= break/disp8 -35196 (write-buffered *(ebp+8) ":break") -35197 } -35198 # hack: if instruction operation starts with "loop", emit ":loop" -35199 { -35200 (string-starts-with? %ecx "loop") # => eax -35201 3d/compare-eax-and 0/imm32/false -35202 74/jump-if-= break/disp8 -35203 (write-buffered *(ebp+8) ":loop") -35204 } -35205 (write-buffered *(ebp+8) "/disp32") -35206 $emit-subx-disp32:end: -35207 # . restore registers -35208 59/pop-to-ecx -35209 58/pop-to-eax -35210 # . epilogue -35211 89/<- %esp 5/r32/ebp -35212 5d/pop-to-ebp -35213 c3/return -35214 -35215 emit-call: # out: (addr buffered-file), stmt: (addr stmt) -35216 # . prologue -35217 55/push-ebp -35218 89/<- %ebp 4/r32/esp -35219 # . save registers -35220 50/push-eax -35221 51/push-ecx -35222 # -35223 (emit-indent *(ebp+8) *Curr-block-depth) -35224 (write-buffered *(ebp+8) "(") -35225 # ecx = stmt -35226 8b/-> *(ebp+0xc) 1/r32/ecx -35227 # - emit function name -35228 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax -35229 (write-buffered *(ebp+8) %eax) -35230 # - emit arguments -35231 # var curr/eax: (addr stmt-var) = lookup(stmt->inouts) -35232 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -35233 { -35234 # if (curr == null) break -35235 3d/compare-eax-and 0/imm32 -35236 74/jump-if-= break/disp8 -35237 # -35238 (emit-subx-call-operand *(ebp+8) %eax) -35239 # curr = lookup(curr->next) -35240 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax -35241 eb/jump loop/disp8 -35242 } -35243 # -35244 (write-buffered *(ebp+8) ")\n") -35245 $emit-call:end: -35246 # . restore registers -35247 59/pop-to-ecx -35248 58/pop-to-eax -35249 # . epilogue -35250 89/<- %esp 5/r32/ebp -35251 5d/pop-to-ebp -35252 c3/return -35253 -35254 emit-subx-call-operand: # out: (addr buffered-file), s: (addr stmt-var) -35255 # shares code with emit-subx-var-as-rm32 -35256 # . prologue -35257 55/push-ebp -35258 89/<- %ebp 4/r32/esp -35259 # . save registers -35260 50/push-eax -35261 51/push-ecx -35262 56/push-esi -35263 # ecx = s -35264 8b/-> *(ebp+0xc) 1/r32/ecx -35265 # var operand/esi: (addr var) = lookup(s->value) -35266 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -35267 89/<- %esi 0/r32/eax -35268 # if (operand->register && !s->is-deref?) emit "%__" -35269 { -35270 $emit-subx-call-operand:check-for-register-direct: -35271 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register -35272 74/jump-if-= break/disp8 -35273 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35274 75/jump-if-!= break/disp8 -35275 $emit-subx-call-operand:register-direct: -35276 (write-buffered *(ebp+8) " %") -35277 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax -35278 (write-buffered *(ebp+8) %eax) -35279 e9/jump $emit-subx-call-operand:end/disp32 -35280 } -35281 # else if (operand->register && s->is-deref?) emit "*__" -35282 { -35283 $emit-subx-call-operand:check-for-register-indirect: -35284 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register -35285 74/jump-if-= break/disp8 -35286 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35287 74/jump-if-= break/disp8 -35288 $emit-subx-call-operand:register-indirect: -35289 (emit-subx-call-operand-register-indirect *(ebp+8) %esi) -35290 e9/jump $emit-subx-call-operand:end/disp32 -35291 } -35292 # else if (operand->stack-offset) emit "*(ebp+__)" -35293 { -35294 81 7/subop/compare *(esi+0x14) 0/imm32 # Var-offset -35295 74/jump-if-= break/disp8 -35296 $emit-subx-call-operand:stack: -35297 (emit-subx-call-operand-stack *(ebp+8) %esi) -35298 e9/jump $emit-subx-call-operand:end/disp32 -35299 } -35300 # else if (operand->type == literal) emit "__" -35301 { -35302 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax -35303 81 7/subop/compare *(eax+4) 0/imm32 # Type-tree-value -35304 75/jump-if-!= break/disp8 -35305 $emit-subx-call-operand:literal: -35306 (write-buffered *(ebp+8) Space) -35307 (lookup *esi *(esi+4)) # Var-name Var-name => eax -35308 (write-buffered *(ebp+8) %eax) -35309 e9/jump $emit-subx-call-operand:end/disp32 -35310 } -35311 # else if (operand->type == literal-string) emit "__" -35312 { -35313 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax -35314 81 7/subop/compare *(eax+4) 0x10/imm32 # Type-tree-value -35315 75/jump-if-!= break/disp8 -35316 $emit-subx-call-operand:literal-string: -35317 (write-buffered *(ebp+8) Space) -35318 (lookup *esi *(esi+4)) # Var-name Var-name => eax -35319 (write-buffered *(ebp+8) %eax) -35320 } -35321 $emit-subx-call-operand:end: -35322 # . restore registers -35323 5e/pop-to-esi -35324 59/pop-to-ecx -35325 58/pop-to-eax -35326 # . epilogue -35327 89/<- %esp 5/r32/ebp -35328 5d/pop-to-ebp -35329 c3/return -35330 -35331 emit-subx-call-operand-register-indirect: # out: (addr buffered-file), v: (addr var) -35332 # . prologue -35333 55/push-ebp -35334 89/<- %ebp 4/r32/esp -35335 # . save registers -35336 50/push-eax +34929 # Not really legal, but closest we can currently represent a dereference of an (addr byte) +34930 Byte-var-in-mem: # (payload var) +34931 0x11/imm32/alloc-id:fake:payload +34932 0/imm32/name +34933 0/imm32/name +34934 0x11/imm32/alloc-id:fake +34935 Type-byte/imm32 +34936 1/imm32/some-block-depth +34937 1/imm32/some-stack-offset +34938 0/imm32/no-register +34939 0/imm32/no-register +34940 +34941 Two-args-int-stack-int-reg: # (payload list var) +34942 0x11/imm32/alloc-id:fake:payload +34943 0x11/imm32/alloc-id:fake +34944 Int-var-in-mem/imm32 +34945 0x11/imm32/alloc-id:fake +34946 Single-int-var-in-some-register/imm32/next +34947 +34948 Two-int-args-in-regs: # (payload list var) +34949 0x11/imm32/alloc-id:fake:payload +34950 0x11/imm32/alloc-id:fake +34951 Int-var-in-some-register/imm32 +34952 0x11/imm32/alloc-id:fake +34953 Single-int-var-in-some-register/imm32/next +34954 +34955 # Not really legal, but closest we can currently represent a dereference of an (addr byte) +34956 Two-args-byte-stack-byte-reg: # (payload list var) +34957 0x11/imm32/alloc-id:fake:payload +34958 0x11/imm32/alloc-id:fake +34959 Byte-var-in-mem/imm32 +34960 0x11/imm32/alloc-id:fake +34961 Single-byte-var-in-some-register/imm32/next +34962 +34963 Two-args-int-reg-int-stack: # (payload list var) +34964 0x11/imm32/alloc-id:fake:payload +34965 0x11/imm32/alloc-id:fake +34966 Int-var-in-some-register/imm32 +34967 0x11/imm32/alloc-id:fake +34968 Single-int-var-in-mem/imm32/next +34969 +34970 Two-args-int-eax-int-literal: # (payload list var) +34971 0x11/imm32/alloc-id:fake:payload +34972 0x11/imm32/alloc-id:fake +34973 Int-var-in-eax/imm32 +34974 0x11/imm32/alloc-id:fake +34975 Single-lit-var/imm32/next +34976 +34977 Int-var-and-literal: # (payload list var) +34978 0x11/imm32/alloc-id:fake:payload +34979 0x11/imm32/alloc-id:fake +34980 Int-var-in-mem/imm32 +34981 0x11/imm32/alloc-id:fake +34982 Single-lit-var/imm32/next +34983 +34984 Int-var-in-register-and-literal: # (payload list var) +34985 0x11/imm32/alloc-id:fake:payload +34986 0x11/imm32/alloc-id:fake +34987 Int-var-in-some-register/imm32 +34988 0x11/imm32/alloc-id:fake +34989 Single-lit-var/imm32/next +34990 +34991 Two-float-args-in-regs: # (payload list var) +34992 0x11/imm32/alloc-id:fake:payload +34993 0x11/imm32/alloc-id:fake +34994 Float-var-in-some-register/imm32 +34995 0x11/imm32/alloc-id:fake +34996 Single-float-var-in-some-register/imm32/next +34997 +34998 Two-args-float-reg-float-stack: # (payload list var) +34999 0x11/imm32/alloc-id:fake:payload +35000 0x11/imm32/alloc-id:fake +35001 Float-var-in-some-register/imm32 +35002 0x11/imm32/alloc-id:fake +35003 Single-float-var-in-mem/imm32/next +35004 +35005 Two-args-float-stack-float-reg: # (payload list var) +35006 0x11/imm32/alloc-id:fake:payload +35007 0x11/imm32/alloc-id:fake +35008 Float-var-in-mem/imm32 +35009 0x11/imm32/alloc-id:fake +35010 Single-float-var-in-some-register/imm32/next +35011 +35012 Single-int-var-in-some-register: # (payload list var) +35013 0x11/imm32/alloc-id:fake:payload +35014 0x11/imm32/alloc-id:fake +35015 Int-var-in-some-register/imm32 +35016 0/imm32/next +35017 0/imm32/next +35018 +35019 Single-addr-var-in-some-register: # (payload list var) +35020 0x11/imm32/alloc-id:fake:payload +35021 0x11/imm32/alloc-id:fake +35022 Addr-var-in-some-register/imm32 +35023 0/imm32/next +35024 0/imm32/next +35025 +35026 Single-byte-var-in-some-register: # (payload list var) +35027 0x11/imm32/alloc-id:fake:payload +35028 0x11/imm32/alloc-id:fake +35029 Byte-var-in-some-register/imm32 +35030 0/imm32/next +35031 0/imm32/next +35032 +35033 Int-var-in-some-register: # (payload var) +35034 0x11/imm32/alloc-id:fake:payload +35035 0/imm32/name +35036 0/imm32/name +35037 0x11/imm32/alloc-id:fake +35038 Type-int/imm32 +35039 1/imm32/some-block-depth +35040 0/imm32/no-stack-offset +35041 0x11/imm32/alloc-id:fake +35042 Any-register/imm32 +35043 +35044 Any-register: # (payload array byte) +35045 0x11/imm32/alloc-id:fake:payload +35046 1/imm32/size +35047 # data +35048 2a/asterisk +35049 +35050 Addr-var-in-some-register: # (payload var) +35051 0x11/imm32/alloc-id:fake:payload +35052 0/imm32/name +35053 0/imm32/name +35054 0x11/imm32/alloc-id:fake +35055 Type-addr/imm32 +35056 1/imm32/some-block-depth +35057 0/imm32/no-stack-offset +35058 0x11/imm32/alloc-id:fake +35059 Any-register/imm32 +35060 +35061 Byte-var-in-some-register: # (payload var) +35062 0x11/imm32/alloc-id:fake:payload +35063 0/imm32/name +35064 0/imm32/name +35065 0x11/imm32/alloc-id:fake +35066 Type-byte/imm32 +35067 1/imm32/some-block-depth +35068 0/imm32/no-stack-offset +35069 0x11/imm32/alloc-id:fake +35070 Any-register/imm32 +35071 +35072 Single-int-var-in-eax: # (payload list var) +35073 0x11/imm32/alloc-id:fake:payload +35074 0x11/imm32/alloc-id:fake +35075 Int-var-in-eax/imm32 +35076 0/imm32/next +35077 0/imm32/next +35078 +35079 Int-var-in-eax: +35080 0x11/imm32/alloc-id:fake:payload +35081 0/imm32/name +35082 0/imm32/name +35083 0x11/imm32/alloc-id:fake +35084 Type-int/imm32 +35085 1/imm32/some-block-depth +35086 0/imm32/no-stack-offset +35087 0x11/imm32/alloc-id:fake +35088 $Mu-register-eax/imm32 # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO) +35089 +35090 Single-int-var-in-ecx: # (payload list var) +35091 0x11/imm32/alloc-id:fake:payload +35092 0x11/imm32/alloc-id:fake +35093 Int-var-in-ecx/imm32 +35094 0/imm32/next +35095 0/imm32/next +35096 +35097 Int-var-in-ecx: +35098 0x11/imm32/alloc-id:fake:payload +35099 0/imm32/name +35100 0/imm32/name +35101 0x11/imm32/alloc-id:fake +35102 Type-int/imm32 +35103 1/imm32/some-block-depth +35104 0/imm32/no-stack-offset +35105 0x11/imm32/alloc-id:fake +35106 $Register-ecx/imm32/register +35107 +35108 Single-int-var-in-edx: # (payload list var) +35109 0x11/imm32/alloc-id:fake:payload +35110 0x11/imm32/alloc-id:fake +35111 Int-var-in-edx/imm32 +35112 0/imm32/next +35113 0/imm32/next +35114 +35115 Int-var-in-edx: # (payload list var) +35116 0x11/imm32/alloc-id:fake:payload +35117 0/imm32/name +35118 0/imm32/name +35119 0x11/imm32/alloc-id:fake +35120 Type-int/imm32 +35121 1/imm32/some-block-depth +35122 0/imm32/no-stack-offset +35123 0x11/imm32/alloc-id:fake +35124 $Register-edx/imm32/register +35125 +35126 Single-int-var-in-ebx: # (payload list var) +35127 0x11/imm32/alloc-id:fake:payload +35128 0x11/imm32/alloc-id:fake +35129 Int-var-in-ebx/imm32 +35130 0/imm32/next +35131 0/imm32/next +35132 +35133 Int-var-in-ebx: # (payload list var) +35134 0x11/imm32/alloc-id:fake:payload +35135 0/imm32/name +35136 0/imm32/name +35137 0x11/imm32/alloc-id:fake +35138 Type-int/imm32 +35139 1/imm32/some-block-depth +35140 0/imm32/no-stack-offset +35141 0x11/imm32/alloc-id:fake +35142 $Register-ebx/imm32/register +35143 +35144 Single-int-var-in-esi: # (payload list var) +35145 0x11/imm32/alloc-id:fake:payload +35146 0x11/imm32/alloc-id:fake +35147 Int-var-in-esi/imm32 +35148 0/imm32/next +35149 0/imm32/next +35150 +35151 Int-var-in-esi: # (payload list var) +35152 0x11/imm32/alloc-id:fake:payload +35153 0/imm32/name +35154 0/imm32/name +35155 0x11/imm32/alloc-id:fake +35156 Type-int/imm32 +35157 1/imm32/some-block-depth +35158 0/imm32/no-stack-offset +35159 0x11/imm32/alloc-id:fake +35160 $Register-esi/imm32/register +35161 +35162 Single-int-var-in-edi: # (payload list var) +35163 0x11/imm32/alloc-id:fake:payload +35164 0x11/imm32/alloc-id:fake +35165 Int-var-in-edi/imm32 +35166 0/imm32/next +35167 0/imm32/next +35168 +35169 Int-var-in-edi: # (payload list var) +35170 0x11/imm32/alloc-id:fake:payload +35171 0/imm32/name +35172 0/imm32/name +35173 0x11/imm32/alloc-id:fake +35174 Type-int/imm32 +35175 1/imm32/some-block-depth +35176 0/imm32/no-stack-offset +35177 0x11/imm32/alloc-id:fake +35178 $Register-edi/imm32/register +35179 +35180 Single-lit-var: # (payload list var) +35181 0x11/imm32/alloc-id:fake:payload +35182 0x11/imm32/alloc-id:fake +35183 Lit-var/imm32 +35184 0/imm32/next +35185 0/imm32/next +35186 +35187 Lit-var: # (payload var) +35188 0x11/imm32/alloc-id:fake:payload +35189 0/imm32/name +35190 0/imm32/name +35191 0x11/imm32/alloc-id:fake +35192 Type-literal/imm32 +35193 1/imm32/some-block-depth +35194 0/imm32/no-stack-offset +35195 0/imm32/no-register +35196 0/imm32/no-register +35197 +35198 Single-float-var-in-mem: # (payload list var) +35199 0x11/imm32/alloc-id:fake:payload +35200 0x11/imm32/alloc-id:fake +35201 Float-var-in-mem/imm32 +35202 0/imm32/next +35203 0/imm32/next +35204 +35205 Float-var-in-mem: # (payload var) +35206 0x11/imm32/alloc-id:fake:payload +35207 0/imm32/name +35208 0/imm32/name +35209 0x11/imm32/alloc-id:fake +35210 Type-float/imm32 +35211 1/imm32/some-block-depth +35212 1/imm32/some-stack-offset +35213 0/imm32/no-register +35214 0/imm32/no-register +35215 +35216 Single-float-var-in-some-register: # (payload list var) +35217 0x11/imm32/alloc-id:fake:payload +35218 0x11/imm32/alloc-id:fake +35219 Float-var-in-some-register/imm32 +35220 0/imm32/next +35221 0/imm32/next +35222 +35223 Float-var-in-some-register: # (payload var) +35224 0x11/imm32/alloc-id:fake:payload +35225 0/imm32/name +35226 0/imm32/name +35227 0x11/imm32/alloc-id:fake +35228 Type-float/imm32 +35229 1/imm32/some-block-depth +35230 0/imm32/no-stack-offset +35231 0x11/imm32/alloc-id:fake +35232 Any-register/imm32 +35233 +35234 Type-int: # (payload type-tree) +35235 0x11/imm32/alloc-id:fake:payload +35236 1/imm32/is-atom +35237 1/imm32/value:int +35238 0/imm32/left:unused +35239 0/imm32/right:null +35240 0/imm32/right:null +35241 +35242 Type-literal: # (payload type-tree) +35243 0x11/imm32/alloc-id:fake:payload +35244 1/imm32/is-atom +35245 0/imm32/value:literal +35246 0/imm32/left:unused +35247 0/imm32/right:null +35248 0/imm32/right:null +35249 +35250 Type-addr: # (payload type-tree) +35251 0x11/imm32/alloc-id:fake:payload +35252 1/imm32/is-atom +35253 2/imm32/value:addr +35254 0/imm32/left:unused +35255 0/imm32/right:null +35256 0/imm32/right:null +35257 +35258 Type-byte: # (payload type-tree) +35259 0x11/imm32/alloc-id:fake:payload +35260 1/imm32/is-atom +35261 8/imm32/value:byte +35262 0/imm32/left:unused +35263 0/imm32/right:null +35264 0/imm32/right:null +35265 +35266 Type-float: # (payload type-tree) +35267 0x11/imm32/alloc-id:fake:payload +35268 1/imm32/is-atom +35269 0xf/imm32/value:float +35270 0/imm32/left:unused +35271 0/imm32/right:null +35272 0/imm32/right:null +35273 +35274 == code +35275 emit-subx-primitive: # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor) +35276 # . prologue +35277 55/push-ebp +35278 89/<- %ebp 4/r32/esp +35279 # . save registers +35280 50/push-eax +35281 51/push-ecx +35282 # ecx = primitive +35283 8b/-> *(ebp+0x10) 1/r32/ecx +35284 # emit primitive name +35285 (emit-indent *(ebp+8) *Curr-block-depth) +35286 (lookup *(ecx+0x18) *(ecx+0x1c)) # Primitive-subx-name Primitive-subx-name => eax +35287 (write-buffered *(ebp+8) %eax) +35288 # emit rm32 if necessary +35289 (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # Primitive-subx-rm32 +35290 # emit xm32 if necessary +35291 (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # Primitive-subx-xm32 +35292 # emit r32 if necessary +35293 (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc)) # Primitive-subx-r32 +35294 # emit x32 if necessary +35295 (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc)) # Primitive-subx-x32 +35296 # emit imm32 if necessary +35297 (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc)) # Primitive-subx-imm32 +35298 # emit imm8 if necessary +35299 (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc)) # Primitive-subx-imm8 +35300 # emit disp32 if necessary +35301 (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # Primitive-subx-disp32 +35302 (write-buffered *(ebp+8) Newline) +35303 $emit-subx-primitive:end: +35304 # . restore registers +35305 59/pop-to-ecx +35306 58/pop-to-eax +35307 # . epilogue +35308 89/<- %esp 5/r32/ebp +35309 5d/pop-to-ebp +35310 c3/return +35311 +35312 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +35313 # . prologue +35314 55/push-ebp +35315 89/<- %ebp 4/r32/esp +35316 # . save registers +35317 50/push-eax +35318 # if (l == 0) return +35319 81 7/subop/compare *(ebp+0xc) 0/imm32 +35320 74/jump-if-= $emit-subx-rm32:end/disp8 +35321 # var v/eax: (addr stmt-var) +35322 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # => eax +35323 (emit-subx-var-as-rm32 *(ebp+8) %eax) +35324 $emit-subx-rm32:end: +35325 # . restore registers +35326 58/pop-to-eax +35327 # . epilogue +35328 89/<- %esp 5/r32/ebp +35329 5d/pop-to-ebp +35330 c3/return +35331 +35332 get-stmt-operand-from-arg-location: # stmt: (addr stmt), l: arg-location, err: (addr buffered-file), ed: (addr exit-descriptor) -> var/eax: (addr stmt-var) +35333 # . prologue +35334 55/push-ebp +35335 89/<- %ebp 4/r32/esp +35336 # . save registers 35337 51/push-ecx -35338 56/push-esi -35339 # esi = v -35340 8b/-> *(ebp+0xc) 6/r32/esi -35341 # var size/ecx: int = size-of-deref(v) -35342 (size-of-deref %esi) # => eax -35343 89/<- %ecx 0/r32/eax -35344 # var reg-name/esi: (addr array byte) = lookup(v->register) -35345 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax -35346 89/<- %esi 0/r32/eax -35347 # TODO: assert size is a multiple of 4 -35348 # var i/eax: int = 0 -35349 b8/copy-to-eax 0/imm32 -35350 { -35351 $emit-subx-call-operand-register-indirect:loop: -35352 # if (i >= size) break -35353 39/compare %eax 1/r32/ecx -35354 7d/jump-if->= break/disp8 -35355 # emit " *(" v->register "+" i ")" -35356 (write-buffered *(ebp+8) " *(") -35357 (write-buffered *(ebp+8) %esi) -35358 (write-buffered *(ebp+8) "+") -35359 (write-int32-hex-buffered *(ebp+8) %eax) -35360 (write-buffered *(ebp+8) ")") -35361 # i += 4 -35362 05/add-to-eax 4/imm32 -35363 # -35364 eb/jump loop/disp8 -35365 } -35366 $emit-subx-call-operand-register-indirect:end: -35367 # . restore registers -35368 5e/pop-to-esi -35369 59/pop-to-ecx -35370 58/pop-to-eax -35371 # . epilogue -35372 89/<- %esp 5/r32/ebp -35373 5d/pop-to-ebp -35374 c3/return -35375 -35376 emit-subx-call-operand-stack: # out: (addr buffered-file), v: (addr var) -35377 # . prologue -35378 55/push-ebp -35379 89/<- %ebp 4/r32/esp -35380 # . save registers -35381 50/push-eax -35382 51/push-ecx -35383 56/push-esi -35384 # esi = v -35385 8b/-> *(ebp+0xc) 6/r32/esi -35386 # var curr/ecx: int = v->offset -35387 8b/-> *(esi+0x14) 1/r32/ecx # Var-offset -35388 # var max/eax: int = v->offset + size-of(v) -35389 (size-of %esi) # => eax -35390 # TODO: assert size is a multiple of 4 -35391 01/add-to %eax 1/r32/ecx -35392 { -35393 $emit-subx-call-operand-stack:loop: -35394 # if (curr >= max) break -35395 39/compare %ecx 0/r32/eax -35396 7d/jump-if->= break/disp8 -35397 # emit " *(ebp+" curr ")" -35398 (write-buffered *(ebp+8) " *(ebp+") -35399 (write-int32-hex-buffered *(ebp+8) %ecx) -35400 (write-buffered *(ebp+8) ")") -35401 # i += 4 -35402 81 0/subop/add %ecx 4/imm32 -35403 # -35404 eb/jump loop/disp8 -35405 } -35406 $emit-subx-call-operand-stack:end: -35407 # . restore registers -35408 5e/pop-to-esi -35409 59/pop-to-ecx -35410 58/pop-to-eax -35411 # . epilogue -35412 89/<- %esp 5/r32/ebp -35413 5d/pop-to-ebp -35414 c3/return -35415 -35416 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (addr stmt-var) -35417 # . prologue -35418 55/push-ebp -35419 89/<- %ebp 4/r32/esp -35420 # . save registers -35421 50/push-eax -35422 51/push-ecx -35423 56/push-esi -35424 # ecx = s -35425 8b/-> *(ebp+0xc) 1/r32/ecx -35426 # var operand/esi: (addr var) = lookup(s->value) -35427 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -35428 89/<- %esi 0/r32/eax -35429 # if (operand->register && s->is-deref?) emit "*__" -35430 { -35431 $emit-subx-var-as-rm32:check-for-register-indirect: -35432 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register -35433 74/jump-if-= break/disp8 -35434 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35435 74/jump-if-= break/disp8 -35436 $emit-subx-var-as-rm32:register-indirect: -35437 (write-buffered *(ebp+8) " *") -35438 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax -35439 (write-buffered *(ebp+8) %eax) -35440 e9/jump $emit-subx-var-as-rm32:end/disp32 -35441 } -35442 # if (operand->register && !s->is-deref?) emit "%__" -35443 { -35444 $emit-subx-var-as-rm32:check-for-register-direct: -35445 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register -35446 74/jump-if-= break/disp8 -35447 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35448 75/jump-if-!= break/disp8 -35449 $emit-subx-var-as-rm32:register-direct: -35450 (write-buffered *(ebp+8) " %") -35451 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax -35452 (write-buffered *(ebp+8) %eax) -35453 e9/jump $emit-subx-var-as-rm32:end/disp32 -35454 } -35455 # else if (operand->stack-offset) emit "*(ebp+__)" -35456 { -35457 81 7/subop/compare *(esi+0x14) 0/imm32 # Var-offset -35458 74/jump-if-= break/disp8 -35459 $emit-subx-var-as-rm32:stack: -35460 (write-buffered *(ebp+8) Space) -35461 (write-buffered *(ebp+8) "*(ebp+") -35462 (write-int32-hex-buffered *(ebp+8) *(esi+0x14)) # Var-offset -35463 (write-buffered *(ebp+8) ")") -35464 } -35465 $emit-subx-var-as-rm32:end: +35338 # eax = l +35339 8b/-> *(ebp+0xc) 0/r32/eax +35340 # ecx = stmt +35341 8b/-> *(ebp+8) 1/r32/ecx +35342 # if (l == 1) return stmt->inouts +35343 { +35344 3d/compare-eax-and 1/imm32 +35345 75/jump-if-!= break/disp8 +35346 $get-stmt-operand-from-arg-location:1: +35347 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +35348 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +35349 } +35350 # if (l == 2) return stmt->inouts->next +35351 { +35352 3d/compare-eax-and 2/imm32 +35353 75/jump-if-!= break/disp8 +35354 $get-stmt-operand-from-arg-location:2: +35355 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +35356 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +35357 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +35358 } +35359 # if (l == 3) return stmt->outputs +35360 { +35361 3d/compare-eax-and 3/imm32 +35362 75/jump-if-!= break/disp8 +35363 $get-stmt-operand-from-arg-location:3: +35364 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax +35365 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +35366 } +35367 # abort +35368 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +35369 $get-stmt-operand-from-arg-location:end: +35370 # . restore registers +35371 59/pop-to-ecx +35372 # . epilogue +35373 89/<- %esp 5/r32/ebp +35374 5d/pop-to-ebp +35375 c3/return +35376 +35377 $get-stmt-operand-from-arg-location:abort: +35378 # error("invalid arg-location " eax) +35379 (write-buffered *(ebp+0x10) "invalid arg-location ") +35380 (write-int32-hex-buffered *(ebp+0x10) %eax) +35381 (write-buffered *(ebp+0x10) Newline) +35382 (flush *(ebp+0x10)) +35383 (stop *(ebp+0x14) 1) +35384 # never gets here +35385 +35386 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) +35387 # . prologue +35388 55/push-ebp +35389 89/<- %ebp 4/r32/esp +35390 # . save registers +35391 50/push-eax +35392 51/push-ecx +35393 # if (l == 0) return +35394 81 7/subop/compare *(ebp+0xc) 0/imm32 +35395 0f 84/jump-if-= $emit-subx-r32:end/disp32 +35396 # var v/eax: (addr stmt-var) +35397 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +35398 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +35399 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +35400 #? (write-buffered Stderr "looking up ") +35401 #? (write-buffered Stderr %eax) +35402 #? (write-buffered Stderr Newline) +35403 #? (flush Stderr) +35404 (maybe-get Mu-registers %eax 0xc) # => eax: (addr register-index) +35405 (write-buffered *(ebp+8) Space) +35406 (write-int32-hex-buffered *(ebp+8) *eax) +35407 (write-buffered *(ebp+8) "/r32") +35408 $emit-subx-r32:end: +35409 # . restore registers +35410 59/pop-to-ecx +35411 58/pop-to-eax +35412 # . epilogue +35413 89/<- %esp 5/r32/ebp +35414 5d/pop-to-ebp +35415 c3/return +35416 +35417 emit-subx-x32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) +35418 # . prologue +35419 55/push-ebp +35420 89/<- %ebp 4/r32/esp +35421 # . save registers +35422 50/push-eax +35423 51/push-ecx +35424 # if (l == 0) return +35425 81 7/subop/compare *(ebp+0xc) 0/imm32 +35426 0f 84/jump-if-= $emit-subx-x32:end/disp32 +35427 # var v/eax: (addr stmt-var) +35428 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +35429 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +35430 (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax +35431 #? (write-buffered Stderr "looking up ") +35432 #? (write-buffered Stderr %eax) +35433 #? (write-buffered Stderr Newline) +35434 #? (flush Stderr) +35435 (maybe-get Mu-registers %eax 0xc) # => eax: (addr register-index) +35436 (write-buffered *(ebp+8) Space) +35437 (write-int32-hex-buffered *(ebp+8) *eax) +35438 (write-buffered *(ebp+8) "/x32") +35439 $emit-subx-x32:end: +35440 # . restore registers +35441 59/pop-to-ecx +35442 58/pop-to-eax +35443 # . epilogue +35444 89/<- %esp 5/r32/ebp +35445 5d/pop-to-ebp +35446 c3/return +35447 +35448 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) +35449 # . prologue +35450 55/push-ebp +35451 89/<- %ebp 4/r32/esp +35452 # . save registers +35453 50/push-eax +35454 51/push-ecx +35455 # if (l == 0) return +35456 81 7/subop/compare *(ebp+0xc) 0/imm32 +35457 0f 84/jump-if-= $emit-subx-imm32:end/disp32 +35458 # var v/eax: (handle var) +35459 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +35460 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +35461 (lookup *eax *(eax+4)) # Var-name Var-name => eax +35462 (write-buffered *(ebp+8) Space) +35463 (write-buffered *(ebp+8) %eax) +35464 (write-buffered *(ebp+8) "/imm32") +35465 $emit-subx-imm32:end: 35466 # . restore registers -35467 5e/pop-to-esi -35468 59/pop-to-ecx -35469 58/pop-to-eax -35470 # . epilogue -35471 89/<- %esp 5/r32/ebp -35472 5d/pop-to-ebp -35473 c3/return -35474 -35475 find-matching-primitive: # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive) -35476 # . prologue -35477 55/push-ebp -35478 89/<- %ebp 4/r32/esp -35479 # . save registers +35467 59/pop-to-ecx +35468 58/pop-to-eax +35469 # . epilogue +35470 89/<- %esp 5/r32/ebp +35471 5d/pop-to-ebp +35472 c3/return +35473 +35474 emit-subx-imm8: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt) +35475 # . prologue +35476 55/push-ebp +35477 89/<- %ebp 4/r32/esp +35478 # . save registers +35479 50/push-eax 35480 51/push-ecx -35481 # var curr/ecx: (addr primitive) = primitives -35482 8b/-> *(ebp+8) 1/r32/ecx -35483 { -35484 $find-matching-primitive:loop: -35485 # if (curr == null) break -35486 81 7/subop/compare %ecx 0/imm32 -35487 74/jump-if-= break/disp8 -35488 # if match(curr, stmt) return curr -35489 { -35490 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -35491 3d/compare-eax-and 0/imm32/false -35492 74/jump-if-= break/disp8 -35493 89/<- %eax 1/r32/ecx -35494 eb/jump $find-matching-primitive:end/disp8 -35495 } -35496 $find-matching-primitive:next-primitive: -35497 # curr = curr->next -35498 (lookup *(ecx+0x3c) *(ecx+0x40)) # Primitive-next Primitive-next => eax -35499 89/<- %ecx 0/r32/eax -35500 # -35501 e9/jump loop/disp32 -35502 } -35503 # return null -35504 b8/copy-to-eax 0/imm32 -35505 $find-matching-primitive:end: -35506 # . restore registers -35507 59/pop-to-ecx -35508 # . epilogue -35509 89/<- %esp 5/r32/ebp -35510 5d/pop-to-ebp -35511 c3/return -35512 -35513 mu-stmt-matches-primitive?: # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean -35514 # A mu stmt matches a primitive if the name matches, all the inout vars -35515 # match, and all the output vars match. -35516 # Vars match if types match and registers match. -35517 # In addition, a stmt output matches a primitive's output if types match -35518 # and the primitive has a wildcard register. -35519 # . prologue -35520 55/push-ebp -35521 89/<- %ebp 4/r32/esp -35522 # . save registers -35523 51/push-ecx -35524 52/push-edx -35525 53/push-ebx -35526 56/push-esi -35527 57/push-edi -35528 # ecx = stmt -35529 8b/-> *(ebp+8) 1/r32/ecx -35530 # edx = primitive -35531 8b/-> *(ebp+0xc) 2/r32/edx -35532 { -35533 $mu-stmt-matches-primitive?:check-name: -35534 # if (primitive->name != stmt->operation) return false -35535 # . var esi: (addr array byte) = lookup(stmt->operation) -35536 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax -35537 89/<- %esi 0/r32/eax -35538 # . var edi: (addr array byte) = lookup(primitive->name) -35539 (lookup *edx *(edx+4)) # Primitive-name Primitive-name => eax -35540 #? (write-buffered Stderr %eax) -35541 #? (write-buffered Stderr Newline) -35542 #? (flush Stderr) -35543 89/<- %edi 0/r32/eax -35544 (string-equal? %esi %edi) # => eax -35545 3d/compare-eax-and 0/imm32/false -35546 75/jump-if-!= break/disp8 -35547 b8/copy-to-eax 0/imm32 -35548 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35549 } -35550 # var curr/esi: (addr stmt-var) = lookup(stmt->inouts) -35551 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax -35552 89/<- %esi 0/r32/eax -35553 # var curr2/edi: (addr list var) = lookup(primitive->inouts) -35554 (lookup *(edx+8) *(edx+0xc)) # Primitive-inouts Primitive-inouts => eax -35555 89/<- %edi 0/r32/eax -35556 { -35557 $mu-stmt-matches-primitive?:inouts-loop: -35558 # if (curr == 0 && curr2 == 0) move on to check outputs -35559 { -35560 $mu-stmt-matches-primitive?:check-both-inouts-null: -35561 81 7/subop/compare %esi 0/imm32 -35562 75/jump-if-!= break/disp8 -35563 $mu-stmt-matches-primitive?:stmt-inout-null: -35564 81 7/subop/compare %edi 0/imm32 -35565 0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32 -35566 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null: -35567 # return false -35568 b8/copy-to-eax 0/imm32/false -35569 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35570 } -35571 # if (curr2 == 0) return false -35572 { -35573 $mu-stmt-matches-primitive?:check-prim-inout-null: -35574 81 7/subop/compare %edi 0/imm32 -35575 75/jump-if-!= break/disp8 -35576 $mu-stmt-matches-primitive?:prim-inout-null: -35577 b8/copy-to-eax 0/imm32/false -35578 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35579 } -35580 # if (curr != curr2) return false -35581 { -35582 $mu-stmt-matches-primitive?:check-inouts-match: -35583 (lookup *edi *(edi+4)) # List-value List-value => eax -35584 (operand-matches-primitive? %esi %eax) # => eax -35585 3d/compare-eax-and 0/imm32/false -35586 75/jump-if-!= break/disp8 -35587 $mu-stmt-matches-primitive?:inouts-match: -35588 b8/copy-to-eax 0/imm32/false -35589 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35590 } -35591 $mu-stmt-matches-primitive?:next-inout: -35592 # curr = lookup(curr->next) -35593 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -35594 89/<- %esi 0/r32/eax -35595 # curr2 = lookup(curr2->next) -35596 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax -35597 89/<- %edi 0/r32/eax -35598 # -35599 e9/jump loop/disp32 -35600 } -35601 $mu-stmt-matches-primitive?:check-outputs: -35602 # var curr/esi: (addr stmt-var) = lookup(stmt->outputs) -35603 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax -35604 89/<- %esi 0/r32/eax -35605 # var curr2/edi: (addr list var) = lookup(primitive->outputs) -35606 (lookup *(edx+0x10) *(edx+0x14)) # Primitive-outputs Primitive-outputs => eax -35607 89/<- %edi 0/r32/eax -35608 { -35609 $mu-stmt-matches-primitive?:outputs-loop: -35610 # if (curr == 0) return (curr2 == 0) -35611 { -35612 $mu-stmt-matches-primitive?:check-both-outputs-null: -35613 81 7/subop/compare %esi 0/imm32 -35614 75/jump-if-!= break/disp8 -35615 { -35616 $mu-stmt-matches-primitive?:stmt-output-null: -35617 81 7/subop/compare %edi 0/imm32 -35618 75/jump-if-!= break/disp8 -35619 $mu-stmt-matches-primitive?:both-outputs-null: -35620 # return true -35621 b8/copy-to-eax 1/imm32 -35622 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35623 } -35624 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null: -35625 # return false -35626 b8/copy-to-eax 0/imm32 -35627 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35628 } -35629 # if (curr2 == 0) return false -35630 { -35631 $mu-stmt-matches-primitive?:check-prim-output-null: -35632 81 7/subop/compare %edi 0/imm32 -35633 75/jump-if-!= break/disp8 -35634 $mu-stmt-matches-primitive?:prim-output-is-null: -35635 b8/copy-to-eax 0/imm32 -35636 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35637 } -35638 # if (curr != curr2) return false -35639 { -35640 $mu-stmt-matches-primitive?:check-outputs-match: -35641 (lookup *edi *(edi+4)) # List-value List-value => eax -35642 (operand-matches-primitive? %esi %eax) # => eax -35643 3d/compare-eax-and 0/imm32/false -35644 75/jump-if-!= break/disp8 -35645 $mu-stmt-matches-primitive?:outputs-match: -35646 b8/copy-to-eax 0/imm32 -35647 e9/jump $mu-stmt-matches-primitive?:end/disp32 -35648 } -35649 $mu-stmt-matches-primitive?:next-output: -35650 # curr = lookup(curr->next) -35651 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax -35652 89/<- %esi 0/r32/eax -35653 # curr2 = lookup(curr2->next) -35654 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax -35655 89/<- %edi 0/r32/eax -35656 # -35657 e9/jump loop/disp32 -35658 } -35659 $mu-stmt-matches-primitive?:return-true: -35660 b8/copy-to-eax 1/imm32 -35661 $mu-stmt-matches-primitive?:end: -35662 # . restore registers -35663 5f/pop-to-edi -35664 5e/pop-to-esi -35665 5b/pop-to-ebx -35666 5a/pop-to-edx -35667 59/pop-to-ecx -35668 # . epilogue -35669 89/<- %esp 5/r32/ebp -35670 5d/pop-to-ebp -35671 c3/return -35672 -35673 operand-matches-primitive?: # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean -35674 # . prologue -35675 55/push-ebp -35676 89/<- %ebp 4/r32/esp -35677 # . save registers -35678 51/push-ecx -35679 52/push-edx -35680 53/push-ebx -35681 56/push-esi -35682 57/push-edi -35683 # ecx = s -35684 8b/-> *(ebp+8) 1/r32/ecx -35685 # var var/esi: (addr var) = lookup(s->value) -35686 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax -35687 89/<- %esi 0/r32/eax -35688 # edi = prim-var -35689 8b/-> *(ebp+0xc) 7/r32/edi -35690 $operand-matches-primitive?:check-type: -35691 # if !category-match?(var->type, prim-var->type) return false -35692 # . var vtype/ebx: (addr type-tree) = lookup(var->type) -35693 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax -35694 89/<- %ebx 0/r32/eax -35695 # . if s is deref, vtype = vtype->right -35696 { -35697 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35698 74/jump-if-= break/disp8 -35699 $operand-matches-primitive?:is-deref: -35700 # . var t/eax: (addr type) -35701 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax -35702 # . if !t->is-atom? t = t->left -35703 81 7/subop/compare *eax 0/imm32/false -35704 { -35705 75/jump-if-!= break/disp8 -35706 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -35707 } -35708 # . -35709 89/<- %ebx 0/r32/eax -35710 } -35711 # . var ptype/eax: (addr type-tree) = lookup(prim-var->type) -35712 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax -35713 (subx-type-category-match? %ebx %eax) # => eax -35714 3d/compare-eax-and 0/imm32/false -35715 0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32 -35716 { -35717 $operand-matches-primitive?:check-register: -35718 # if prim-var is in memory and var is in register but dereference, match -35719 { -35720 81 7/subop/compare *(edi+0x18) 0/imm32 # Var-register -35721 0f 85/jump-if-!= break/disp32 -35722 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register -35723 74/jump-if-= break/disp8 -35724 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35725 74/jump-if-= break/disp8 -35726 $operand-matches-primitive?:var-deref-match: -35727 e9/jump $operand-matches-primitive?:return-true/disp32 -35728 } -35729 # if prim-var is in register and var is in register but dereference, no match -35730 { -35731 81 7/subop/compare *(edi+0x18) 0/imm32 # Var-register -35732 0f 84/jump-if-= break/disp32 -35733 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register -35734 0f 84/jump-if-= break/disp32 -35735 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref -35736 74/jump-if-= break/disp8 -35737 $operand-matches-primitive?:var-deref-no-match: -35738 e9/jump $operand-matches-primitive?:return-false/disp32 -35739 } -35740 # return false if var->register doesn't match prim-var->register -35741 { -35742 # if register addresses are equal, it's a match -35743 # var vreg/ebx: (addr array byte) = lookup(var->register) -35744 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax -35745 89/<- %ebx 0/r32/eax -35746 # var preg/ecx: (addr array byte) = lookup(prim-var->register) -35747 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax -35748 89/<- %ecx 0/r32/eax -35749 # if (vreg == preg) break -35750 39/compare %ecx 3/r32/ebx -35751 74/jump-if-= break/disp8 -35752 $operand-matches-primitive?:var-register-no-match: -35753 # if either address is 0, return false -35754 81 7/subop/compare %ebx 0/imm32 -35755 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -35756 81 7/subop/compare %ecx 0/imm32 -35757 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -35758 # if prim-var->register is wildcard, it's a match -35759 (string-equal? %ecx "*") # Any-register => eax -35760 3d/compare-eax-and 0/imm32/false -35761 75/jump-if-!= break/disp8 -35762 $operand-matches-primitive?:wildcard-no-match: -35763 # if string contents aren't equal, return false -35764 (string-equal? %ecx %ebx) # => eax -35765 3d/compare-eax-and 0/imm32/false -35766 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -35767 } -35768 } -35769 $operand-matches-primitive?:return-true: -35770 b8/copy-to-eax 1/imm32/true -35771 eb/jump $operand-matches-primitive?:end/disp8 -35772 $operand-matches-primitive?:return-false: -35773 b8/copy-to-eax 0/imm32/false -35774 $operand-matches-primitive?:end: -35775 # . restore registers -35776 5f/pop-to-edi -35777 5e/pop-to-esi -35778 5b/pop-to-ebx -35779 5a/pop-to-edx -35780 59/pop-to-ecx -35781 # . epilogue -35782 89/<- %esp 5/r32/ebp -35783 5d/pop-to-ebp -35784 c3/return -35785 -35786 find-matching-function: # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function) -35787 # . prologue -35788 55/push-ebp -35789 89/<- %ebp 4/r32/esp -35790 # . save registers -35791 51/push-ecx -35792 # var curr/ecx: (handle function) = functions -35793 8b/-> *(ebp+8) 1/r32/ecx -35794 { -35795 # if (curr == null) break -35796 81 7/subop/compare %ecx 0/imm32 -35797 74/jump-if-= break/disp8 -35798 #? (write-buffered Stderr "iter\n") -35799 #? (flush Stderr) -35800 # if match(stmt, curr) return curr -35801 { -35802 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -35803 3d/compare-eax-and 0/imm32/false -35804 74/jump-if-= break/disp8 -35805 89/<- %eax 1/r32/ecx -35806 eb/jump $find-matching-function:end/disp8 -35807 } -35808 # curr = curr->next -35809 (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax -35810 89/<- %ecx 0/r32/eax -35811 # -35812 eb/jump loop/disp8 -35813 } -35814 # return null -35815 b8/copy-to-eax 0/imm32 -35816 $find-matching-function:end: -35817 # . restore registers -35818 59/pop-to-ecx -35819 # . epilogue -35820 89/<- %esp 5/r32/ebp -35821 5d/pop-to-ebp -35822 c3/return -35823 -35824 # Just compare names; user-defined functions don't support overloading yet. -35825 mu-stmt-matches-function?: # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean -35826 # . prologue -35827 55/push-ebp -35828 89/<- %ebp 4/r32/esp -35829 # . save registers -35830 51/push-ecx -35831 # return function->name == stmt->operation -35832 # ecx = lookup(stmt->operation) -35833 8b/-> *(ebp+8) 0/r32/eax -35834 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax -35835 89/<- %ecx 0/r32/eax -35836 # eax = lookup(function->name) -35837 8b/-> *(ebp+0xc) 0/r32/eax -35838 (lookup *eax *(eax+4)) # Function-name Function-name => eax -35839 (string-equal? %eax %ecx) # => eax -35840 $mu-stmt-matches-function?:end: -35841 # . restore registers -35842 59/pop-to-ecx -35843 # . epilogue -35844 89/<- %esp 5/r32/ebp -35845 5d/pop-to-ebp -35846 c3/return -35847 -35848 # Type-checking happens elsewhere. This method is for selecting between -35849 # primitives. -35850 subx-type-category-match?: # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean -35851 # . prologue -35852 55/push-ebp -35853 89/<- %ebp 4/r32/esp -35854 # . save registers -35855 51/push-ecx -35856 # var cata/ecx: int = type-category(a) -35857 (type-category *(ebp+8)) # => eax -35858 89/<- %ecx 0/r32/eax -35859 # var catb/eax: int = type-category(b) -35860 (type-category *(ebp+0xc)) # => eax -35861 # return cata == catb -35862 39/compare %eax 1/r32/ecx -35863 0f 94/set-byte-if-= %al -35864 81 4/subop/and %eax 0xff/imm32 -35865 $subx-type-category-match?:end: -35866 # . restore registers -35867 59/pop-to-ecx -35868 # . epilogue -35869 89/<- %esp 5/r32/ebp -35870 5d/pop-to-ebp -35871 c3/return -35872 -35873 type-category: # a: (addr type-tree) -> result/eax: int -35874 # . prologue -35875 55/push-ebp -35876 89/<- %ebp 4/r32/esp -35877 # . save registers -35878 51/push-ecx -35879 # var lit?/ecx: boolean = literal-type?(a) -35880 (simple-mu-type? *(ebp+8) 0) # literal => eax -35881 89/<- %ecx 0/r32/eax -35882 # var float?/eax: int = float?(a) -35883 (simple-mu-type? *(ebp+8) 0xf) # => eax -35884 # set bits for lit? and float? -35885 c1/shift 4/subop/left %ecx 1/imm8 -35886 09/or %eax 1/r32/ecx -35887 $type-category:end: -35888 # . restore registers -35889 59/pop-to-ecx -35890 # . epilogue -35891 89/<- %esp 5/r32/ebp -35892 5d/pop-to-ebp -35893 c3/return -35894 -35895 simple-mu-type?: # a: (addr type-tree), n: type-id -> result/eax: boolean -35896 # . prologue -35897 55/push-ebp -35898 89/<- %ebp 4/r32/esp -35899 # . save registers -35900 51/push-ecx -35901 # ecx = n -35902 8b/-> *(ebp+0xc) 1/r32/ecx -35903 # return (a->value == n) -35904 8b/-> *(ebp+8) 0/r32/eax -35905 39/compare *(eax+4) 1/r32/ecx # Type-tree-value -35906 0f 94/set-byte-if-= %al -35907 81 4/subop/and %eax 0xff/imm32 -35908 $simple-mu-type?:end: -35909 # . restore registers -35910 59/pop-to-ecx -35911 # . epilogue -35912 89/<- %esp 5/r32/ebp -35913 5d/pop-to-ebp -35914 c3/return -35915 -35916 mu-addr-type?: # a: (addr type-tree) -> result/eax: boolean -35917 # . prologue -35918 55/push-ebp -35919 89/<- %ebp 4/r32/esp -35920 # eax = a -35921 8b/-> *(ebp+8) 0/r32/eax -35922 # if (!a->is-atom?) a = a->left -35923 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -35924 { -35925 75/jump-if-!= break/disp8 -35926 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -35927 } -35928 # return (a->value == addr) -35929 81 7/subop/compare *(eax+4) 2/imm32/addr # Type-tree-value -35930 0f 94/set-byte-if-= %al -35931 81 4/subop/and %eax 0xff/imm32 -35932 $mu-addr-type?:end: -35933 # . epilogue -35934 89/<- %esp 5/r32/ebp -35935 5d/pop-to-ebp -35936 c3/return -35937 -35938 mu-array-type?: # a: (addr type-tree) -> result/eax: boolean -35939 # . prologue -35940 55/push-ebp -35941 89/<- %ebp 4/r32/esp -35942 # eax = a -35943 8b/-> *(ebp+8) 0/r32/eax -35944 # if (!a->is-atom?) a = a->left -35945 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -35946 { -35947 75/jump-if-!= break/disp8 -35948 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -35949 } -35950 # return (a->value == array) -35951 81 7/subop/compare *(eax+4) 3/imm32/array # Type-tree-value -35952 0f 94/set-byte-if-= %al -35953 81 4/subop/and %eax 0xff/imm32 -35954 $mu-array-type?:end: -35955 # . epilogue -35956 89/<- %esp 5/r32/ebp -35957 5d/pop-to-ebp -35958 c3/return -35959 -35960 mu-string-type?: # a: (addr type-tree) -> result/eax: boolean -35961 # . prologue -35962 55/push-ebp -35963 89/<- %ebp 4/r32/esp -35964 # . save registers -35965 56/push-esi -35966 # esi = a -35967 8b/-> *(ebp+8) 6/r32/esi -35968 # if (a->is-atom?) return false -35969 81 7/subop/compare *esi 0/imm32/false # Type-tree-is-atom -35970 0f 85/jump-if-!= $mu-string-type?:return-false/disp32 -35971 # if a is not an addr, return false -35972 (mu-addr-type? %esi) # => eax -35973 3d/compare-eax-with 0/imm32/false -35974 0f 84/jump-if-= $mu-string-type?:end/disp32 # eax changes var -35975 # if a is not an array, return false -35976 (lookup *(esi+0xc) *(esi+0x10)) # Type-tree-right Type-tree-right => eax -35977 (mu-array-type? %eax) # => eax -35978 3d/compare-eax-with 0/imm32/false -35979 74/jump-if-= $mu-string-type?:end/disp8 # eax changes var -35980 # var p/eax: (addr type-tree) = payload of a -35981 (lookup *(esi+0xc) *(esi+0x10)) # Type-tree-right Type-tree-right => eax -35982 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax -35983 # if p is an atom, return false -35984 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -35985 75/jump-if-!= $mu-string-type?:return-false/disp8 -35986 # return (p == byte) -35987 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -35988 (simple-mu-type? %eax 8) # byte => eax -35989 eb/jump $mu-string-type?:end/disp8 -35990 $mu-string-type?:return-false: -35991 b8/copy-to-eax 0/imm32/false -35992 $mu-string-type?:end: -35993 # . restore registers -35994 5e/pop-to-esi -35995 # . epilogue -35996 89/<- %esp 5/r32/ebp -35997 5d/pop-to-ebp -35998 c3/return -35999 -36000 mu-stream-type?: # a: (addr type-tree) -> result/eax: boolean -36001 # . prologue -36002 55/push-ebp -36003 89/<- %ebp 4/r32/esp -36004 # eax = a -36005 8b/-> *(ebp+8) 0/r32/eax -36006 # if (!a->is-atom?) a = a->left -36007 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom -36008 { -36009 75/jump-if-!= break/disp8 -36010 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax -36011 } -36012 # return (a->value == stream) -36013 81 7/subop/compare *(eax+4) 0xb/imm32/stream # Type-tree-value -36014 0f 94/set-byte-if-= %al -36015 81 4/subop/and %eax 0xff/imm32 -36016 $mu-stream-type?:end: -36017 # . epilogue -36018 89/<- %esp 5/r32/ebp -36019 5d/pop-to-ebp -36020 c3/return -36021 -36022 test-emit-subx-stmt-primitive: -36023 # Primitive operation on a variable on the stack. -36024 # increment foo -36025 # => -36026 # ff 0/subop/increment *(ebp-8) -36027 # -36028 # There's a variable on the var stack as follows: -36029 # name: 'foo' -36030 # type: int -36031 # stack-offset: -8 -36032 # -36033 # There's a primitive with this info: -36034 # name: 'increment' -36035 # inouts: int/mem -36036 # value: 'ff 0/subop/increment' -36037 # -36038 # . prologue -36039 55/push-ebp -36040 89/<- %ebp 4/r32/esp -36041 # setup -36042 (clear-stream _test-output-stream) -36043 (clear-stream $_test-output-buffered-file->buffer) -36044 # simulate allocated payloads starting with an initial fake alloc-id (0x11) -36045 $test-emit-subx-stmt-primitive:initialize-type: -36046 # var type/ecx: (payload type-tree) = int -36047 68/push 0/imm32/right:null -36048 68/push 0/imm32/right:null -36049 68/push 0/imm32/left:unused -36050 68/push 1/imm32/value:int -36051 68/push 1/imm32/is-atom?:true -36052 68/push 0x11/imm32/alloc-id:fake:payload -36053 89/<- %ecx 4/r32/esp -36054 $test-emit-subx-stmt-primitive:initialize-var: -36055 # var var-foo/ecx: (payload var) = var(type) -36056 68/push 0/imm32/no-register -36057 68/push 0/imm32/no-register -36058 68/push -8/imm32/stack-offset -36059 68/push 1/imm32/block-depth -36060 51/push-ecx/type -36061 68/push 0x11/imm32/alloc-id:fake -36062 68/push 0/imm32/name -36063 68/push 0/imm32/name -36064 68/push 0x11/imm32/alloc-id:fake:payload -36065 89/<- %ecx 4/r32/esp -36066 $test-emit-subx-stmt-primitive:initialize-var-name: -36067 # var-foo->name = "foo" -36068 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36069 (copy-array Heap "foo" %eax) -36070 $test-emit-subx-stmt-primitive:initialize-stmt-var: -36071 # var operand/ebx: (payload stmt-var) = stmt-var(var-foo) -36072 68/push 0/imm32/is-deref:false -36073 68/push 0/imm32/next -36074 68/push 0/imm32/next -36075 51/push-ecx/var-foo -36076 68/push 0x11/imm32/alloc-id:fake -36077 68/push 0x11/imm32/alloc-id:fake:payload -36078 89/<- %ebx 4/r32/esp -36079 $test-emit-subx-stmt-primitive:initialize-stmt: -36080 # var stmt/esi: (addr statement) -36081 68/push 0/imm32/no-outputs -36082 68/push 0/imm32/no-outputs -36083 53/push-ebx/inouts -36084 68/push 0x11/imm32/alloc-id:fake -36085 68/push 0/imm32/operation -36086 68/push 0/imm32/operation -36087 68/push 1/imm32/tag -36088 89/<- %esi 4/r32/esp -36089 $test-emit-subx-stmt-primitive:initialize-stmt-operation: -36090 # stmt->operation = "increment" -36091 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36092 (copy-array Heap "increment" %eax) -36093 $test-emit-subx-stmt-primitive:initialize-primitive: -36094 # var primitives/ebx: (addr primitive) -36095 68/push 0/imm32/next -36096 68/push 0/imm32/next -36097 68/push 0/imm32/no-x32 -36098 68/push 0/imm32/no-xm32 -36099 68/push 0/imm32/no-disp32 -36100 68/push 0/imm32/no-imm8 -36101 68/push 0/imm32/no-imm32 -36102 68/push 0/imm32/no-r32 -36103 68/push 1/imm32/rm32-is-first-inout -36104 68/push 0/imm32/subx-name -36105 68/push 0/imm32/subx-name -36106 68/push 0/imm32/no-outputs -36107 68/push 0/imm32/no-outputs -36108 53/push-ebx/inouts # hack: reuse stmt-var from call stmt as (list var) in function declaration -36109 68/push 0x11/imm32/alloc-id:fake -36110 68/push 0/imm32/name -36111 68/push 0/imm32/name -36112 89/<- %ebx 4/r32/esp -36113 $test-emit-subx-stmt-primitive:initialize-primitive-name: -36114 # primitives->name = "increment" -36115 (copy-array Heap "increment" %ebx) # Primitive-name -36116 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name: -36117 # primitives->subx-name = "ff 0/subop/increment" -36118 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name -36119 (copy-array Heap "ff 0/subop/increment" %eax) -36120 # convert -36121 c7 0/subop/copy *Curr-block-depth 0/imm32 -36122 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) -36123 (flush _test-output-buffered-file) -36124 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36130 # check output -36131 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") -36132 # . epilogue -36133 89/<- %esp 5/r32/ebp -36134 5d/pop-to-ebp -36135 c3/return -36136 -36137 test-emit-subx-stmt-primitive-register: -36138 # Primitive operation on a variable in a register. -36139 # foo <- increment -36140 # => -36141 # ff 0/subop/increment %eax # sub-optimal, but should suffice -36142 # -36143 # There's a variable on the var stack as follows: -36144 # name: 'foo' -36145 # type: int -36146 # register: 'eax' -36147 # -36148 # There's a primitive with this info: -36149 # name: 'increment' -36150 # out: int/reg -36151 # value: 'ff 0/subop/increment' -36152 # -36153 # . prologue -36154 55/push-ebp -36155 89/<- %ebp 4/r32/esp -36156 # setup -36157 (clear-stream _test-output-stream) -36158 (clear-stream $_test-output-buffered-file->buffer) -36159 $test-emit-subx-stmt-primitive-register:initialize-type: -36160 # var type/ecx: (payload type-tree) = int -36161 68/push 0/imm32/right:null -36162 68/push 0/imm32/right:null -36163 68/push 0/imm32/left:unused -36164 68/push 1/imm32/value:int -36165 68/push 1/imm32/is-atom?:true -36166 68/push 0x11/imm32/alloc-id:fake:payload -36167 89/<- %ecx 4/r32/esp -36168 $test-emit-subx-stmt-primitive-register:initialize-var: -36169 # var var-foo/ecx: (payload var) -36170 68/push 0/imm32/register -36171 68/push 0/imm32/register -36172 68/push 0/imm32/no-stack-offset -36173 68/push 1/imm32/block-depth -36174 51/push-ecx -36175 68/push 0x11/imm32/alloc-id:fake -36176 68/push 0/imm32/name -36177 68/push 0/imm32/name -36178 68/push 0x11/imm32/alloc-id:fake:payload -36179 89/<- %ecx 4/r32/esp -36180 $test-emit-subx-stmt-primitive-register:initialize-var-name: -36181 # var-foo->name = "foo" -36182 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36183 (copy-array Heap "foo" %eax) -36184 $test-emit-subx-stmt-primitive-register:initialize-var-register: -36185 # var-foo->register = "eax" -36186 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -36187 (copy-array Heap "eax" %eax) -36188 $test-emit-subx-stmt-primitive-register:initialize-stmt-var: -36189 # var operand/ebx: (payload stmt-var) -36190 68/push 0/imm32/is-deref:false -36191 68/push 0/imm32/next -36192 68/push 0/imm32/next -36193 51/push-ecx/var-foo -36194 68/push 0x11/imm32/alloc-id:fake -36195 68/push 0x11/imm32/alloc-id:fake:payload -36196 89/<- %ebx 4/r32/esp -36197 $test-emit-subx-stmt-primitive-register:initialize-stmt: -36198 # var stmt/esi: (addr statement) -36199 53/push-ebx/outputs -36200 68/push 0x11/imm32/alloc-id:fake -36201 68/push 0/imm32/no-inouts -36202 68/push 0/imm32/no-inouts -36203 68/push 0/imm32/operation -36204 68/push 0/imm32/operation -36205 68/push 1/imm32 -36206 89/<- %esi 4/r32/esp -36207 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation: -36208 # stmt->operation = "increment" -36209 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36210 (copy-array Heap "increment" %eax) -36211 $test-emit-subx-stmt-primitive-register:initialize-formal-var: -36212 # var formal-var/ebx: (payload var) -36213 68/push 0/imm32/register -36214 68/push 0/imm32/register -36215 68/push 0/imm32/no-stack-offset -36216 68/push 1/imm32/block-depth -36217 ff 6/subop/push *(ecx+0x10) # Var-type + payload alloc id + handle alloc id -36218 68/push 0x11/imm32/alloc-id:fake -36219 68/push 0/imm32/name -36220 68/push 0/imm32/name -36221 68/push 0x11/imm32/alloc-id:fake:payload -36222 89/<- %ebx 4/r32/esp -36223 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name: -36224 # formal-var->name = "dummy" -36225 8d/copy-address *(ebx+4) 0/r32/eax # Var-name + 4 -36226 (copy-array Heap "dummy" %eax) -36227 $test-emit-subx-stmt-primitive-register:initialize-formal-register: -36228 # formal-var->register = "*" -36229 8d/copy-address *(ebx+0x1c) 0/r32/eax # Var-register + 4 -36230 (copy-array Heap "*" %eax) # Any-register -36231 $test-emit-subx-stmt-primitive-register:initialize-var-list: -36232 # var formal-outputs/ebx: (payload list var) -36233 68/push 0/imm32/next -36234 68/push 0/imm32/next -36235 53/push-ebx/formal-var -36236 68/push 0x11/imm32/alloc-id:fake -36237 68/push 0x11/imm32/alloc-id:fake:payload -36238 89/<- %ebx 4/r32/esp -36239 $test-emit-subx-stmt-primitive-register:initialize-primitive: -36240 # var primitives/ebx: (addr primitive) -36241 68/push 0/imm32/next -36242 68/push 0/imm32/next -36243 68/push 0/imm32/no-x32 -36244 68/push 0/imm32/no-xm32 -36245 68/push 0/imm32/no-disp32 -36246 68/push 0/imm32/no-imm8 -36247 68/push 0/imm32/no-imm32 -36248 68/push 0/imm32/no-r32 -36249 68/push 3/imm32/rm32-is-first-output -36250 68/push 0/imm32/subx-name -36251 68/push 0/imm32/subx-name -36252 53/push-ebx/outputs -36253 68/push 0x11/imm32/alloc-id:fake -36254 68/push 0/imm32/no-inouts -36255 68/push 0/imm32/no-inouts -36256 68/push 0/imm32/name -36257 68/push 0/imm32/name -36258 89/<- %ebx 4/r32/esp -36259 $test-emit-subx-stmt-primitive-register:initialize-primitive-name: -36260 # primitives->name = "increment" -36261 (copy-array Heap "increment" %ebx) # Primitive-name -36262 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name: -36263 # primitives->subx-name = "ff 0/subop/increment" -36264 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name -36265 (copy-array Heap "ff 0/subop/increment" %eax) -36266 # convert -36267 c7 0/subop/copy *Curr-block-depth 0/imm32 -36268 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) -36269 (flush _test-output-buffered-file) -36270 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36276 # check output -36277 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") -36278 # . epilogue -36279 89/<- %esp 5/r32/ebp -36280 5d/pop-to-ebp -36281 c3/return -36282 -36283 test-emit-subx-stmt-select-primitive: -36284 # Select the right primitive between overloads. -36285 # foo <- increment -36286 # => -36287 # ff 0/subop/increment %eax # sub-optimal, but should suffice -36288 # -36289 # There's a variable on the var stack as follows: -36290 # name: 'foo' -36291 # type: int -36292 # register: 'eax' -36293 # -36294 # There's two primitives, as follows: -36295 # - name: 'increment' -36296 # out: int/reg -36297 # value: 'ff 0/subop/increment' -36298 # - name: 'increment' -36299 # inout: int/mem -36300 # value: 'ff 0/subop/increment' -36301 # -36302 # . prologue -36303 55/push-ebp -36304 89/<- %ebp 4/r32/esp -36305 # setup -36306 (clear-stream _test-output-stream) -36307 (clear-stream $_test-output-buffered-file->buffer) -36308 $test-emit-subx-stmt-select-primitive:initialize-type: -36309 # var type/ecx: (payload type-tree) = int -36310 68/push 0/imm32/right:null -36311 68/push 0/imm32/right:null -36312 68/push 0/imm32/left:unused -36313 68/push 1/imm32/value:int -36314 68/push 1/imm32/is-atom?:true -36315 68/push 0x11/imm32/alloc-id:fake:payload -36316 89/<- %ecx 4/r32/esp -36317 $test-emit-subx-stmt-select-primitive:initialize-var: -36318 # var var-foo/ecx: (payload var) -36319 68/push 0/imm32/register -36320 68/push 0/imm32/register -36321 68/push 0/imm32/no-stack-offset -36322 68/push 1/imm32/block-depth -36323 51/push-ecx -36324 68/push 0x11/imm32/alloc-id:fake -36325 68/push 0/imm32/name -36326 68/push 0/imm32/name -36327 68/push 0x11/imm32/alloc-id:fake:payload -36328 89/<- %ecx 4/r32/esp -36329 $test-emit-subx-stmt-select-primitive:initialize-var-name: -36330 # var-foo->name = "foo" -36331 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36332 (copy-array Heap "foo" %eax) -36333 $test-emit-subx-stmt-select-primitive:initialize-var-register: -36334 # var-foo->register = "eax" -36335 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -36336 (copy-array Heap "eax" %eax) -36337 $test-emit-subx-stmt-select-primitive:initialize-stmt-var: -36338 # var operand/ebx: (payload stmt-var) -36339 68/push 0/imm32/is-deref:false -36340 68/push 0/imm32/next -36341 68/push 0/imm32/next -36342 51/push-ecx/var-foo -36343 68/push 0x11/imm32/alloc-id:fake -36344 68/push 0x11/imm32/alloc-id:fake:payload -36345 89/<- %ebx 4/r32/esp -36346 $test-emit-subx-stmt-select-primitive:initialize-stmt: -36347 # var stmt/esi: (addr statement) -36348 53/push-ebx/outputs -36349 68/push 0x11/imm32/alloc-id:fake -36350 68/push 0/imm32/no-inouts -36351 68/push 0/imm32/no-inouts -36352 68/push 0/imm32/operation -36353 68/push 0/imm32/operation -36354 68/push 1/imm32 -36355 89/<- %esi 4/r32/esp -36356 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation: -36357 # stmt->operation = "increment" -36358 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36359 (copy-array Heap "increment" %eax) -36360 $test-emit-subx-stmt-select-primitive:initialize-formal-var: -36361 # var formal-var/ebx: (payload var) -36362 68/push 0/imm32/register -36363 68/push 0/imm32/register -36364 68/push 0/imm32/no-stack-offset -36365 68/push 1/imm32/block-depth -36366 ff 6/subop/push *(ecx+0x10) # Var-type + payload alloc id + handle alloc id -36367 68/push 0x11/imm32/alloc-id:fake -36368 68/push 0/imm32/name -36369 68/push 0/imm32/name -36370 68/push 0x11/imm32/alloc-id:fake:payload -36371 89/<- %ebx 4/r32/esp -36372 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name: -36373 # formal-var->name = "dummy" -36374 8d/copy-address *(ebx+4) 0/r32/eax # Var-name + 4 -36375 (copy-array Heap "dummy" %eax) -36376 $test-emit-subx-stmt-select-primitive:initialize-formal-register: -36377 # formal-var->register = "*" -36378 8d/copy-address *(ebx+0x1c) 0/r32/eax # Var-register + 4 -36379 (copy-array Heap "*" %eax) # Any-register -36380 $test-emit-subx-stmt-select-primitive:initialize-var-list: -36381 # var formal-outputs/ebx: (payload list var) -36382 68/push 0/imm32/next -36383 68/push 0/imm32/next -36384 53/push-ebx/formal-var -36385 68/push 0x11/imm32/alloc-id:fake -36386 68/push 0x11/imm32/alloc-id:fake:payload -36387 89/<- %ebx 4/r32/esp -36388 $test-emit-subx-stmt-select-primitive:initialize-primitive2: -36389 # var primitive2/edi: (payload primitive) -36390 68/push 0/imm32/next -36391 68/push 0/imm32/next -36392 68/push 0/imm32/no-x32 -36393 68/push 0/imm32/no-xm32 -36394 68/push 0/imm32/no-disp32 -36395 68/push 0/imm32/no-imm8 -36396 68/push 0/imm32/no-imm32 -36397 68/push 0/imm32/no-r32 -36398 68/push 3/imm32/rm32-is-first-output -36399 68/push 0/imm32/subx-name -36400 68/push 0/imm32/subx-name -36401 53/push-ebx/outputs -36402 68/push 0x11/imm32/alloc-id:fake -36403 68/push 0/imm32/no-inouts -36404 68/push 0/imm32/no-inouts -36405 68/push 0/imm32/name -36406 68/push 0/imm32/name -36407 68/push 0x11/imm32/alloc-id:fake:payload -36408 89/<- %edi 4/r32/esp -36409 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name: -36410 # primitives->name = "increment" -36411 8d/copy-address *(edi+4) 0/r32/eax # Primitive-name + 4 -36412 (copy-array Heap "increment" %eax) -36413 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name: -36414 # primitives->subx-name = "ff 0/subop/increment" -36415 8d/copy-address *(edi+0x1c) 0/r32/eax # Primitive-subx-name + 4 -36416 (copy-array Heap "ff 0/subop/increment" %eax) -36417 $test-emit-subx-stmt-select-primitive:initialize-primitive: -36418 # var primitives/ebx: (addr primitive) -36419 57/push-edi -36420 68/push 0x11/imm32/alloc-id:fake -36421 68/push 0/imm32/no-x32 -36422 68/push 0/imm32/no-xm32 -36423 68/push 0/imm32/no-disp32 -36424 68/push 0/imm32/no-imm8 -36425 68/push 0/imm32/no-imm32 -36426 68/push 0/imm32/no-r32 -36427 68/push 1/imm32/rm32-is-first-inout -36428 68/push 0/imm32/subx-name -36429 68/push 0/imm32/subx-name -36430 68/push 0/imm32/no-outputs -36431 68/push 0/imm32/no-outputs -36432 53/push-ebx/inouts # hack: reuse stmt-var from call stmt as (list var) in function declaration -36433 68/push 0x11/imm32/alloc-id:fake -36434 68/push 0/imm32/name -36435 68/push 0/imm32/name -36436 89/<- %ebx 4/r32/esp -36437 $test-emit-subx-stmt-select-primitive:initialize-primitive-name: -36438 # primitives->name = "increment" -36439 (copy-array Heap "increment" %ebx) # Primitive-name -36440 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name: -36441 # primitives->subx-name = "ff 0/subop/increment" -36442 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name -36443 (copy-array Heap "ff 0/subop/increment" %eax) -36444 # convert -36445 c7 0/subop/copy *Curr-block-depth 0/imm32 -36446 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) -36447 (flush _test-output-buffered-file) -36448 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36454 # check output -36455 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") -36456 # . epilogue -36457 89/<- %esp 5/r32/ebp -36458 5d/pop-to-ebp -36459 c3/return -36460 -36461 test-emit-subx-stmt-select-primitive-2: -36462 # Select the right primitive between overloads. -36463 # increment foo -36464 # => -36465 # ff 0/subop/increment %eax # sub-optimal, but should suffice -36466 # -36467 # There's a variable on the var stack as follows: -36468 # name: 'foo' -36469 # type: int -36470 # register: 'eax' +35481 # if (l == 0) return +35482 81 7/subop/compare *(ebp+0xc) 0/imm32 +35483 0f 84/jump-if-= $emit-subx-imm32:end/disp32 +35484 # var v/eax: (handle var) +35485 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +35486 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +35487 (lookup *eax *(eax+4)) # Var-name Var-name => eax +35488 (write-buffered *(ebp+8) Space) +35489 (write-buffered *(ebp+8) %eax) +35490 (write-buffered *(ebp+8) "/imm8") +35491 $emit-subx-imm8:end: +35492 # . restore registers +35493 59/pop-to-ecx +35494 58/pop-to-eax +35495 # . epilogue +35496 89/<- %esp 5/r32/ebp +35497 5d/pop-to-ebp +35498 c3/return +35499 +35500 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor) +35501 # . prologue +35502 55/push-ebp +35503 89/<- %ebp 4/r32/esp +35504 # . save registers +35505 50/push-eax +35506 51/push-ecx +35507 # if (location == 0) return +35508 81 7/subop/compare *(ebp+0xc) 0/imm32 +35509 0f 84/jump-if-= $emit-subx-disp32:end/disp32 +35510 # var v/eax: (addr stmt-var) +35511 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18)) # => eax +35512 (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax +35513 (lookup *eax *(eax+4)) # Var-name Var-name => eax +35514 (write-buffered *(ebp+8) Space) +35515 (write-buffered *(ebp+8) %eax) +35516 # hack: if instruction operation starts with "break", emit ":break" +35517 # var name/ecx: (addr array byte) = lookup(stmt->operation) +35518 8b/-> *(ebp+0x10) 0/r32/eax +35519 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +35520 89/<- %ecx 0/r32/eax +35521 { +35522 (string-starts-with? %ecx "break") # => eax +35523 3d/compare-eax-and 0/imm32/false +35524 74/jump-if-= break/disp8 +35525 (write-buffered *(ebp+8) ":break") +35526 } +35527 # hack: if instruction operation starts with "loop", emit ":loop" +35528 { +35529 (string-starts-with? %ecx "loop") # => eax +35530 3d/compare-eax-and 0/imm32/false +35531 74/jump-if-= break/disp8 +35532 (write-buffered *(ebp+8) ":loop") +35533 } +35534 (write-buffered *(ebp+8) "/disp32") +35535 $emit-subx-disp32:end: +35536 # . restore registers +35537 59/pop-to-ecx +35538 58/pop-to-eax +35539 # . epilogue +35540 89/<- %esp 5/r32/ebp +35541 5d/pop-to-ebp +35542 c3/return +35543 +35544 emit-call: # out: (addr buffered-file), stmt: (addr stmt) +35545 # . prologue +35546 55/push-ebp +35547 89/<- %ebp 4/r32/esp +35548 # . save registers +35549 50/push-eax +35550 51/push-ecx +35551 # +35552 (emit-indent *(ebp+8) *Curr-block-depth) +35553 (write-buffered *(ebp+8) "(") +35554 # ecx = stmt +35555 8b/-> *(ebp+0xc) 1/r32/ecx +35556 # - emit function name +35557 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax +35558 (write-buffered *(ebp+8) %eax) +35559 # - emit arguments +35560 # var curr/eax: (addr stmt-var) = lookup(stmt->inouts) +35561 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +35562 { +35563 # if (curr == null) break +35564 3d/compare-eax-and 0/imm32 +35565 74/jump-if-= break/disp8 +35566 # +35567 (emit-subx-call-operand *(ebp+8) %eax) +35568 # curr = lookup(curr->next) +35569 (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax +35570 eb/jump loop/disp8 +35571 } +35572 # +35573 (write-buffered *(ebp+8) ")\n") +35574 $emit-call:end: +35575 # . restore registers +35576 59/pop-to-ecx +35577 58/pop-to-eax +35578 # . epilogue +35579 89/<- %esp 5/r32/ebp +35580 5d/pop-to-ebp +35581 c3/return +35582 +35583 emit-subx-call-operand: # out: (addr buffered-file), s: (addr stmt-var) +35584 # shares code with emit-subx-var-as-rm32 +35585 # . prologue +35586 55/push-ebp +35587 89/<- %ebp 4/r32/esp +35588 # . save registers +35589 50/push-eax +35590 51/push-ecx +35591 56/push-esi +35592 # ecx = s +35593 8b/-> *(ebp+0xc) 1/r32/ecx +35594 # var operand/esi: (addr var) = lookup(s->value) +35595 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +35596 89/<- %esi 0/r32/eax +35597 # if (operand->register && !s->is-deref?) emit "%__" +35598 { +35599 $emit-subx-call-operand:check-for-register-direct: +35600 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register +35601 74/jump-if-= break/disp8 +35602 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +35603 75/jump-if-!= break/disp8 +35604 $emit-subx-call-operand:register-direct: +35605 (write-buffered *(ebp+8) " %") +35606 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax +35607 (write-buffered *(ebp+8) %eax) +35608 e9/jump $emit-subx-call-operand:end/disp32 +35609 } +35610 # else if (operand->register && s->is-deref?) emit "*__" +35611 { +35612 $emit-subx-call-operand:check-for-register-indirect: +35613 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register +35614 74/jump-if-= break/disp8 +35615 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +35616 74/jump-if-= break/disp8 +35617 $emit-subx-call-operand:register-indirect: +35618 (emit-subx-call-operand-register-indirect *(ebp+8) %esi) +35619 e9/jump $emit-subx-call-operand:end/disp32 +35620 } +35621 # else if (operand->stack-offset) emit "*(ebp+__)" +35622 { +35623 81 7/subop/compare *(esi+0x14) 0/imm32 # Var-offset +35624 74/jump-if-= break/disp8 +35625 $emit-subx-call-operand:stack: +35626 (emit-subx-call-operand-stack *(ebp+8) %esi) +35627 e9/jump $emit-subx-call-operand:end/disp32 +35628 } +35629 # else if (operand->type == literal) emit "__" +35630 { +35631 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax +35632 81 7/subop/compare *(eax+4) 0/imm32 # Type-tree-value +35633 75/jump-if-!= break/disp8 +35634 $emit-subx-call-operand:literal: +35635 (write-buffered *(ebp+8) Space) +35636 (lookup *esi *(esi+4)) # Var-name Var-name => eax +35637 (write-buffered *(ebp+8) %eax) +35638 e9/jump $emit-subx-call-operand:end/disp32 +35639 } +35640 # else if (operand->type == literal-string) emit "__" +35641 { +35642 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax +35643 81 7/subop/compare *(eax+4) 0x10/imm32 # Type-tree-value +35644 75/jump-if-!= break/disp8 +35645 $emit-subx-call-operand:literal-string: +35646 (write-buffered *(ebp+8) Space) +35647 (lookup *esi *(esi+4)) # Var-name Var-name => eax +35648 (write-buffered *(ebp+8) %eax) +35649 } +35650 $emit-subx-call-operand:end: +35651 # . restore registers +35652 5e/pop-to-esi +35653 59/pop-to-ecx +35654 58/pop-to-eax +35655 # . epilogue +35656 89/<- %esp 5/r32/ebp +35657 5d/pop-to-ebp +35658 c3/return +35659 +35660 emit-subx-call-operand-register-indirect: # out: (addr buffered-file), v: (addr var) +35661 # . prologue +35662 55/push-ebp +35663 89/<- %ebp 4/r32/esp +35664 # . save registers +35665 50/push-eax +35666 51/push-ecx +35667 56/push-esi +35668 # esi = v +35669 8b/-> *(ebp+0xc) 6/r32/esi +35670 # var size/ecx: int = size-of-deref(v) +35671 (size-of-deref %esi) # => eax +35672 89/<- %ecx 0/r32/eax +35673 # var reg-name/esi: (addr array byte) = lookup(v->register) +35674 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax +35675 89/<- %esi 0/r32/eax +35676 # TODO: assert size is a multiple of 4 +35677 # var i/eax: int = 0 +35678 b8/copy-to-eax 0/imm32 +35679 { +35680 $emit-subx-call-operand-register-indirect:loop: +35681 # if (i >= size) break +35682 39/compare %eax 1/r32/ecx +35683 7d/jump-if->= break/disp8 +35684 # emit " *(" v->register "+" i ")" +35685 (write-buffered *(ebp+8) " *(") +35686 (write-buffered *(ebp+8) %esi) +35687 (write-buffered *(ebp+8) "+") +35688 (write-int32-hex-buffered *(ebp+8) %eax) +35689 (write-buffered *(ebp+8) ")") +35690 # i += 4 +35691 05/add-to-eax 4/imm32 +35692 # +35693 eb/jump loop/disp8 +35694 } +35695 $emit-subx-call-operand-register-indirect:end: +35696 # . restore registers +35697 5e/pop-to-esi +35698 59/pop-to-ecx +35699 58/pop-to-eax +35700 # . epilogue +35701 89/<- %esp 5/r32/ebp +35702 5d/pop-to-ebp +35703 c3/return +35704 +35705 emit-subx-call-operand-stack: # out: (addr buffered-file), v: (addr var) +35706 # . prologue +35707 55/push-ebp +35708 89/<- %ebp 4/r32/esp +35709 # . save registers +35710 50/push-eax +35711 51/push-ecx +35712 56/push-esi +35713 # esi = v +35714 8b/-> *(ebp+0xc) 6/r32/esi +35715 # var curr/ecx: int = v->offset +35716 8b/-> *(esi+0x14) 1/r32/ecx # Var-offset +35717 # var max/eax: int = v->offset + size-of(v) +35718 (size-of %esi) # => eax +35719 # TODO: assert size is a multiple of 4 +35720 01/add-to %eax 1/r32/ecx +35721 { +35722 $emit-subx-call-operand-stack:loop: +35723 # if (curr >= max) break +35724 39/compare %ecx 0/r32/eax +35725 7d/jump-if->= break/disp8 +35726 # emit " *(ebp+" curr ")" +35727 (write-buffered *(ebp+8) " *(ebp+") +35728 (write-int32-hex-buffered *(ebp+8) %ecx) +35729 (write-buffered *(ebp+8) ")") +35730 # i += 4 +35731 81 0/subop/add %ecx 4/imm32 +35732 # +35733 eb/jump loop/disp8 +35734 } +35735 $emit-subx-call-operand-stack:end: +35736 # . restore registers +35737 5e/pop-to-esi +35738 59/pop-to-ecx +35739 58/pop-to-eax +35740 # . epilogue +35741 89/<- %esp 5/r32/ebp +35742 5d/pop-to-ebp +35743 c3/return +35744 +35745 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (addr stmt-var) +35746 # . prologue +35747 55/push-ebp +35748 89/<- %ebp 4/r32/esp +35749 # . save registers +35750 50/push-eax +35751 51/push-ecx +35752 56/push-esi +35753 # ecx = s +35754 8b/-> *(ebp+0xc) 1/r32/ecx +35755 # var operand/esi: (addr var) = lookup(s->value) +35756 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +35757 89/<- %esi 0/r32/eax +35758 # if (operand->register && s->is-deref?) emit "*__" +35759 { +35760 $emit-subx-var-as-rm32:check-for-register-indirect: +35761 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register +35762 74/jump-if-= break/disp8 +35763 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +35764 74/jump-if-= break/disp8 +35765 $emit-subx-var-as-rm32:register-indirect: +35766 (write-buffered *(ebp+8) " *") +35767 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax +35768 (write-buffered *(ebp+8) %eax) +35769 e9/jump $emit-subx-var-as-rm32:end/disp32 +35770 } +35771 # if (operand->register && !s->is-deref?) emit "%__" +35772 { +35773 $emit-subx-var-as-rm32:check-for-register-direct: +35774 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register +35775 74/jump-if-= break/disp8 +35776 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +35777 75/jump-if-!= break/disp8 +35778 $emit-subx-var-as-rm32:register-direct: +35779 (write-buffered *(ebp+8) " %") +35780 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax +35781 (write-buffered *(ebp+8) %eax) +35782 e9/jump $emit-subx-var-as-rm32:end/disp32 +35783 } +35784 # else if (operand->stack-offset) emit "*(ebp+__)" +35785 { +35786 81 7/subop/compare *(esi+0x14) 0/imm32 # Var-offset +35787 74/jump-if-= break/disp8 +35788 $emit-subx-var-as-rm32:stack: +35789 (write-buffered *(ebp+8) Space) +35790 (write-buffered *(ebp+8) "*(ebp+") +35791 (write-int32-hex-buffered *(ebp+8) *(esi+0x14)) # Var-offset +35792 (write-buffered *(ebp+8) ")") +35793 } +35794 $emit-subx-var-as-rm32:end: +35795 # . restore registers +35796 5e/pop-to-esi +35797 59/pop-to-ecx +35798 58/pop-to-eax +35799 # . epilogue +35800 89/<- %esp 5/r32/ebp +35801 5d/pop-to-ebp +35802 c3/return +35803 +35804 find-matching-primitive: # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive) +35805 # . prologue +35806 55/push-ebp +35807 89/<- %ebp 4/r32/esp +35808 # . save registers +35809 51/push-ecx +35810 # var curr/ecx: (addr primitive) = primitives +35811 8b/-> *(ebp+8) 1/r32/ecx +35812 { +35813 $find-matching-primitive:loop: +35814 # if (curr == null) break +35815 81 7/subop/compare %ecx 0/imm32 +35816 74/jump-if-= break/disp8 +35817 # if match(curr, stmt) return curr +35818 { +35819 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +35820 3d/compare-eax-and 0/imm32/false +35821 74/jump-if-= break/disp8 +35822 89/<- %eax 1/r32/ecx +35823 eb/jump $find-matching-primitive:end/disp8 +35824 } +35825 $find-matching-primitive:next-primitive: +35826 # curr = curr->next +35827 (lookup *(ecx+0x3c) *(ecx+0x40)) # Primitive-next Primitive-next => eax +35828 89/<- %ecx 0/r32/eax +35829 # +35830 e9/jump loop/disp32 +35831 } +35832 # return null +35833 b8/copy-to-eax 0/imm32 +35834 $find-matching-primitive:end: +35835 # . restore registers +35836 59/pop-to-ecx +35837 # . epilogue +35838 89/<- %esp 5/r32/ebp +35839 5d/pop-to-ebp +35840 c3/return +35841 +35842 mu-stmt-matches-primitive?: # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean +35843 # A mu stmt matches a primitive if the name matches, all the inout vars +35844 # match, and all the output vars match. +35845 # Vars match if types match and registers match. +35846 # In addition, a stmt output matches a primitive's output if types match +35847 # and the primitive has a wildcard register. +35848 # . prologue +35849 55/push-ebp +35850 89/<- %ebp 4/r32/esp +35851 # . save registers +35852 51/push-ecx +35853 52/push-edx +35854 53/push-ebx +35855 56/push-esi +35856 57/push-edi +35857 # ecx = stmt +35858 8b/-> *(ebp+8) 1/r32/ecx +35859 # edx = primitive +35860 8b/-> *(ebp+0xc) 2/r32/edx +35861 { +35862 $mu-stmt-matches-primitive?:check-name: +35863 # if (primitive->name != stmt->operation) return false +35864 # . var esi: (addr array byte) = lookup(stmt->operation) +35865 (lookup *(ecx+4) *(ecx+8)) # Stmt1-operation Stmt1-operation => eax +35866 89/<- %esi 0/r32/eax +35867 # . var edi: (addr array byte) = lookup(primitive->name) +35868 (lookup *edx *(edx+4)) # Primitive-name Primitive-name => eax +35869 #? (write-buffered Stderr %eax) +35870 #? (write-buffered Stderr Newline) +35871 #? (flush Stderr) +35872 89/<- %edi 0/r32/eax +35873 (string-equal? %esi %edi) # => eax +35874 3d/compare-eax-and 0/imm32/false +35875 75/jump-if-!= break/disp8 +35876 b8/copy-to-eax 0/imm32 +35877 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35878 } +35879 # var curr/esi: (addr stmt-var) = lookup(stmt->inouts) +35880 (lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax +35881 89/<- %esi 0/r32/eax +35882 # var curr2/edi: (addr list var) = lookup(primitive->inouts) +35883 (lookup *(edx+8) *(edx+0xc)) # Primitive-inouts Primitive-inouts => eax +35884 89/<- %edi 0/r32/eax +35885 { +35886 $mu-stmt-matches-primitive?:inouts-loop: +35887 # if (curr == 0 && curr2 == 0) move on to check outputs +35888 { +35889 $mu-stmt-matches-primitive?:check-both-inouts-null: +35890 81 7/subop/compare %esi 0/imm32 +35891 75/jump-if-!= break/disp8 +35892 $mu-stmt-matches-primitive?:stmt-inout-null: +35893 81 7/subop/compare %edi 0/imm32 +35894 0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32 +35895 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null: +35896 # return false +35897 b8/copy-to-eax 0/imm32/false +35898 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35899 } +35900 # if (curr2 == 0) return false +35901 { +35902 $mu-stmt-matches-primitive?:check-prim-inout-null: +35903 81 7/subop/compare %edi 0/imm32 +35904 75/jump-if-!= break/disp8 +35905 $mu-stmt-matches-primitive?:prim-inout-null: +35906 b8/copy-to-eax 0/imm32/false +35907 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35908 } +35909 # if (curr != curr2) return false +35910 { +35911 $mu-stmt-matches-primitive?:check-inouts-match: +35912 (lookup *edi *(edi+4)) # List-value List-value => eax +35913 (operand-matches-primitive? %esi %eax) # => eax +35914 3d/compare-eax-and 0/imm32/false +35915 75/jump-if-!= break/disp8 +35916 $mu-stmt-matches-primitive?:inouts-match: +35917 b8/copy-to-eax 0/imm32/false +35918 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35919 } +35920 $mu-stmt-matches-primitive?:next-inout: +35921 # curr = lookup(curr->next) +35922 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +35923 89/<- %esi 0/r32/eax +35924 # curr2 = lookup(curr2->next) +35925 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax +35926 89/<- %edi 0/r32/eax +35927 # +35928 e9/jump loop/disp32 +35929 } +35930 $mu-stmt-matches-primitive?:check-outputs: +35931 # var curr/esi: (addr stmt-var) = lookup(stmt->outputs) +35932 (lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax +35933 89/<- %esi 0/r32/eax +35934 # var curr2/edi: (addr list var) = lookup(primitive->outputs) +35935 (lookup *(edx+0x10) *(edx+0x14)) # Primitive-outputs Primitive-outputs => eax +35936 89/<- %edi 0/r32/eax +35937 { +35938 $mu-stmt-matches-primitive?:outputs-loop: +35939 # if (curr == 0) return (curr2 == 0) +35940 { +35941 $mu-stmt-matches-primitive?:check-both-outputs-null: +35942 81 7/subop/compare %esi 0/imm32 +35943 75/jump-if-!= break/disp8 +35944 { +35945 $mu-stmt-matches-primitive?:stmt-output-null: +35946 81 7/subop/compare %edi 0/imm32 +35947 75/jump-if-!= break/disp8 +35948 $mu-stmt-matches-primitive?:both-outputs-null: +35949 # return true +35950 b8/copy-to-eax 1/imm32 +35951 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35952 } +35953 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null: +35954 # return false +35955 b8/copy-to-eax 0/imm32 +35956 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35957 } +35958 # if (curr2 == 0) return false +35959 { +35960 $mu-stmt-matches-primitive?:check-prim-output-null: +35961 81 7/subop/compare %edi 0/imm32 +35962 75/jump-if-!= break/disp8 +35963 $mu-stmt-matches-primitive?:prim-output-is-null: +35964 b8/copy-to-eax 0/imm32 +35965 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35966 } +35967 # if (curr != curr2) return false +35968 { +35969 $mu-stmt-matches-primitive?:check-outputs-match: +35970 (lookup *edi *(edi+4)) # List-value List-value => eax +35971 (operand-matches-primitive? %esi %eax) # => eax +35972 3d/compare-eax-and 0/imm32/false +35973 75/jump-if-!= break/disp8 +35974 $mu-stmt-matches-primitive?:outputs-match: +35975 b8/copy-to-eax 0/imm32 +35976 e9/jump $mu-stmt-matches-primitive?:end/disp32 +35977 } +35978 $mu-stmt-matches-primitive?:next-output: +35979 # curr = lookup(curr->next) +35980 (lookup *(esi+8) *(esi+0xc)) # Stmt-var-next Stmt-var-next => eax +35981 89/<- %esi 0/r32/eax +35982 # curr2 = lookup(curr2->next) +35983 (lookup *(edi+8) *(edi+0xc)) # List-next List-next => eax +35984 89/<- %edi 0/r32/eax +35985 # +35986 e9/jump loop/disp32 +35987 } +35988 $mu-stmt-matches-primitive?:return-true: +35989 b8/copy-to-eax 1/imm32 +35990 $mu-stmt-matches-primitive?:end: +35991 # . restore registers +35992 5f/pop-to-edi +35993 5e/pop-to-esi +35994 5b/pop-to-ebx +35995 5a/pop-to-edx +35996 59/pop-to-ecx +35997 # . epilogue +35998 89/<- %esp 5/r32/ebp +35999 5d/pop-to-ebp +36000 c3/return +36001 +36002 operand-matches-primitive?: # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean +36003 # . prologue +36004 55/push-ebp +36005 89/<- %ebp 4/r32/esp +36006 # . save registers +36007 51/push-ecx +36008 52/push-edx +36009 53/push-ebx +36010 56/push-esi +36011 57/push-edi +36012 # ecx = s +36013 8b/-> *(ebp+8) 1/r32/ecx +36014 # var var/esi: (addr var) = lookup(s->value) +36015 (lookup *ecx *(ecx+4)) # Stmt-var-value Stmt-var-value => eax +36016 89/<- %esi 0/r32/eax +36017 # edi = prim-var +36018 8b/-> *(ebp+0xc) 7/r32/edi +36019 $operand-matches-primitive?:check-type: +36020 # if !category-match?(var->type, prim-var->type) return false +36021 # . var vtype/ebx: (addr type-tree) = lookup(var->type) +36022 (lookup *(esi+8) *(esi+0xc)) # Var-type Var-type => eax +36023 89/<- %ebx 0/r32/eax +36024 # . if s is deref, vtype = vtype->right +36025 { +36026 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +36027 74/jump-if-= break/disp8 +36028 $operand-matches-primitive?:is-deref: +36029 # . var t/eax: (addr type) +36030 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +36031 # . if !t->is-atom? t = t->left +36032 81 7/subop/compare *eax 0/imm32/false +36033 { +36034 75/jump-if-!= break/disp8 +36035 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +36036 } +36037 # . +36038 89/<- %ebx 0/r32/eax +36039 } +36040 # . var ptype/eax: (addr type-tree) = lookup(prim-var->type) +36041 (lookup *(edi+8) *(edi+0xc)) # Var-type Var-type => eax +36042 (subx-type-category-match? %ebx %eax) # => eax +36043 3d/compare-eax-and 0/imm32/false +36044 0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32 +36045 { +36046 $operand-matches-primitive?:check-register: +36047 # if prim-var is in memory and var is in register but dereference, match +36048 { +36049 81 7/subop/compare *(edi+0x18) 0/imm32 # Var-register +36050 0f 85/jump-if-!= break/disp32 +36051 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register +36052 74/jump-if-= break/disp8 +36053 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +36054 74/jump-if-= break/disp8 +36055 $operand-matches-primitive?:var-deref-match: +36056 e9/jump $operand-matches-primitive?:return-true/disp32 +36057 } +36058 # if prim-var is in register and var is in register but dereference, no match +36059 { +36060 81 7/subop/compare *(edi+0x18) 0/imm32 # Var-register +36061 0f 84/jump-if-= break/disp32 +36062 81 7/subop/compare *(esi+0x18) 0/imm32 # Var-register +36063 0f 84/jump-if-= break/disp32 +36064 81 7/subop/compare *(ecx+0x10) 0/imm32/false # Stmt-var-is-deref +36065 74/jump-if-= break/disp8 +36066 $operand-matches-primitive?:var-deref-no-match: +36067 e9/jump $operand-matches-primitive?:return-false/disp32 +36068 } +36069 # return false if var->register doesn't match prim-var->register +36070 { +36071 # if register addresses are equal, it's a match +36072 # var vreg/ebx: (addr array byte) = lookup(var->register) +36073 (lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax +36074 89/<- %ebx 0/r32/eax +36075 # var preg/ecx: (addr array byte) = lookup(prim-var->register) +36076 (lookup *(edi+0x18) *(edi+0x1c)) # Var-register Var-register => eax +36077 89/<- %ecx 0/r32/eax +36078 # if (vreg == preg) break +36079 39/compare %ecx 3/r32/ebx +36080 74/jump-if-= break/disp8 +36081 $operand-matches-primitive?:var-register-no-match: +36082 # if either address is 0, return false +36083 81 7/subop/compare %ebx 0/imm32 +36084 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +36085 81 7/subop/compare %ecx 0/imm32 +36086 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +36087 # if prim-var->register is wildcard, it's a match +36088 (string-equal? %ecx "*") # Any-register => eax +36089 3d/compare-eax-and 0/imm32/false +36090 75/jump-if-!= break/disp8 +36091 $operand-matches-primitive?:wildcard-no-match: +36092 # if string contents aren't equal, return false +36093 (string-equal? %ecx %ebx) # => eax +36094 3d/compare-eax-and 0/imm32/false +36095 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +36096 } +36097 } +36098 $operand-matches-primitive?:return-true: +36099 b8/copy-to-eax 1/imm32/true +36100 eb/jump $operand-matches-primitive?:end/disp8 +36101 $operand-matches-primitive?:return-false: +36102 b8/copy-to-eax 0/imm32/false +36103 $operand-matches-primitive?:end: +36104 # . restore registers +36105 5f/pop-to-edi +36106 5e/pop-to-esi +36107 5b/pop-to-ebx +36108 5a/pop-to-edx +36109 59/pop-to-ecx +36110 # . epilogue +36111 89/<- %esp 5/r32/ebp +36112 5d/pop-to-ebp +36113 c3/return +36114 +36115 find-matching-function: # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function) +36116 # . prologue +36117 55/push-ebp +36118 89/<- %ebp 4/r32/esp +36119 # . save registers +36120 51/push-ecx +36121 # var curr/ecx: (handle function) = functions +36122 8b/-> *(ebp+8) 1/r32/ecx +36123 { +36124 # if (curr == null) break +36125 81 7/subop/compare %ecx 0/imm32 +36126 74/jump-if-= break/disp8 +36127 #? (write-buffered Stderr "iter\n") +36128 #? (flush Stderr) +36129 # if match(stmt, curr) return curr +36130 { +36131 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +36132 3d/compare-eax-and 0/imm32/false +36133 74/jump-if-= break/disp8 +36134 89/<- %eax 1/r32/ecx +36135 eb/jump $find-matching-function:end/disp8 +36136 } +36137 # curr = curr->next +36138 (lookup *(ecx+0x20) *(ecx+0x24)) # Function-next Function-next => eax +36139 89/<- %ecx 0/r32/eax +36140 # +36141 eb/jump loop/disp8 +36142 } +36143 # return null +36144 b8/copy-to-eax 0/imm32 +36145 $find-matching-function:end: +36146 # . restore registers +36147 59/pop-to-ecx +36148 # . epilogue +36149 89/<- %esp 5/r32/ebp +36150 5d/pop-to-ebp +36151 c3/return +36152 +36153 # Just compare names; user-defined functions don't support overloading yet. +36154 mu-stmt-matches-function?: # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean +36155 # . prologue +36156 55/push-ebp +36157 89/<- %ebp 4/r32/esp +36158 # . save registers +36159 51/push-ecx +36160 # return function->name == stmt->operation +36161 # ecx = lookup(stmt->operation) +36162 8b/-> *(ebp+8) 0/r32/eax +36163 (lookup *(eax+4) *(eax+8)) # Stmt1-operation Stmt1-operation => eax +36164 89/<- %ecx 0/r32/eax +36165 # eax = lookup(function->name) +36166 8b/-> *(ebp+0xc) 0/r32/eax +36167 (lookup *eax *(eax+4)) # Function-name Function-name => eax +36168 (string-equal? %eax %ecx) # => eax +36169 $mu-stmt-matches-function?:end: +36170 # . restore registers +36171 59/pop-to-ecx +36172 # . epilogue +36173 89/<- %esp 5/r32/ebp +36174 5d/pop-to-ebp +36175 c3/return +36176 +36177 # Type-checking happens elsewhere. This method is for selecting between +36178 # primitives. +36179 subx-type-category-match?: # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean +36180 # . prologue +36181 55/push-ebp +36182 89/<- %ebp 4/r32/esp +36183 # . save registers +36184 51/push-ecx +36185 # var cata/ecx: int = type-category(a) +36186 (type-category *(ebp+8)) # => eax +36187 89/<- %ecx 0/r32/eax +36188 # var catb/eax: int = type-category(b) +36189 (type-category *(ebp+0xc)) # => eax +36190 # return cata == catb +36191 39/compare %eax 1/r32/ecx +36192 0f 94/set-byte-if-= %al +36193 25/and-eax-with 0xff/imm32 +36194 $subx-type-category-match?:end: +36195 # . restore registers +36196 59/pop-to-ecx +36197 # . epilogue +36198 89/<- %esp 5/r32/ebp +36199 5d/pop-to-ebp +36200 c3/return +36201 +36202 type-category: # a: (addr type-tree) -> result/eax: int +36203 # . prologue +36204 55/push-ebp +36205 89/<- %ebp 4/r32/esp +36206 # . save registers +36207 51/push-ecx +36208 # var lit?/ecx: boolean = literal-type?(a) +36209 (simple-mu-type? *(ebp+8) 0) # literal => eax +36210 89/<- %ecx 0/r32/eax +36211 # var float?/eax: int = float?(a) +36212 (simple-mu-type? *(ebp+8) 0xf) # => eax +36213 # set bits for lit? and float? +36214 c1/shift 4/subop/left %ecx 1/imm8 +36215 09/or %eax 1/r32/ecx +36216 $type-category:end: +36217 # . restore registers +36218 59/pop-to-ecx +36219 # . epilogue +36220 89/<- %esp 5/r32/ebp +36221 5d/pop-to-ebp +36222 c3/return +36223 +36224 simple-mu-type?: # a: (addr type-tree), n: type-id -> result/eax: boolean +36225 # . prologue +36226 55/push-ebp +36227 89/<- %ebp 4/r32/esp +36228 # . save registers +36229 51/push-ecx +36230 # ecx = n +36231 8b/-> *(ebp+0xc) 1/r32/ecx +36232 # return (a->value == n) +36233 8b/-> *(ebp+8) 0/r32/eax +36234 39/compare *(eax+4) 1/r32/ecx # Type-tree-value +36235 0f 94/set-byte-if-= %al +36236 25/and-eax-with 0xff/imm32 +36237 $simple-mu-type?:end: +36238 # . restore registers +36239 59/pop-to-ecx +36240 # . epilogue +36241 89/<- %esp 5/r32/ebp +36242 5d/pop-to-ebp +36243 c3/return +36244 +36245 mu-addr-type?: # a: (addr type-tree) -> result/eax: boolean +36246 # . prologue +36247 55/push-ebp +36248 89/<- %ebp 4/r32/esp +36249 # eax = a +36250 8b/-> *(ebp+8) 0/r32/eax +36251 # if (!a->is-atom?) a = a->left +36252 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +36253 { +36254 75/jump-if-!= break/disp8 +36255 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +36256 } +36257 # return (a->value == addr) +36258 81 7/subop/compare *(eax+4) 2/imm32/addr # Type-tree-value +36259 0f 94/set-byte-if-= %al +36260 25/and-eax-with 0xff/imm32 +36261 $mu-addr-type?:end: +36262 # . epilogue +36263 89/<- %esp 5/r32/ebp +36264 5d/pop-to-ebp +36265 c3/return +36266 +36267 mu-array-type?: # a: (addr type-tree) -> result/eax: boolean +36268 # . prologue +36269 55/push-ebp +36270 89/<- %ebp 4/r32/esp +36271 # eax = a +36272 8b/-> *(ebp+8) 0/r32/eax +36273 # if (!a->is-atom?) a = a->left +36274 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +36275 { +36276 75/jump-if-!= break/disp8 +36277 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +36278 } +36279 # return (a->value == array) +36280 81 7/subop/compare *(eax+4) 3/imm32/array # Type-tree-value +36281 0f 94/set-byte-if-= %al +36282 25/and-eax-with 0xff/imm32 +36283 $mu-array-type?:end: +36284 # . epilogue +36285 89/<- %esp 5/r32/ebp +36286 5d/pop-to-ebp +36287 c3/return +36288 +36289 mu-string-type?: # a: (addr type-tree) -> result/eax: boolean +36290 # . prologue +36291 55/push-ebp +36292 89/<- %ebp 4/r32/esp +36293 # . save registers +36294 56/push-esi +36295 # esi = a +36296 8b/-> *(ebp+8) 6/r32/esi +36297 # if (a->is-atom?) return false +36298 81 7/subop/compare *esi 0/imm32/false # Type-tree-is-atom +36299 0f 85/jump-if-!= $mu-string-type?:return-false/disp32 +36300 # if a is not an addr, return false +36301 (mu-addr-type? %esi) # => eax +36302 3d/compare-eax-with 0/imm32/false +36303 0f 84/jump-if-= $mu-string-type?:end/disp32 # eax changes var +36304 # if a is not an array, return false +36305 (lookup *(esi+0xc) *(esi+0x10)) # Type-tree-right Type-tree-right => eax +36306 (mu-array-type? %eax) # => eax +36307 3d/compare-eax-with 0/imm32/false +36308 74/jump-if-= $mu-string-type?:end/disp8 # eax changes var +36309 # var p/eax: (addr type-tree) = payload of a +36310 (lookup *(esi+0xc) *(esi+0x10)) # Type-tree-right Type-tree-right => eax +36311 (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax +36312 # if p is an atom, return false +36313 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +36314 75/jump-if-!= $mu-string-type?:return-false/disp8 +36315 # return (p == byte) +36316 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +36317 (simple-mu-type? %eax 8) # byte => eax +36318 eb/jump $mu-string-type?:end/disp8 +36319 $mu-string-type?:return-false: +36320 b8/copy-to-eax 0/imm32/false +36321 $mu-string-type?:end: +36322 # . restore registers +36323 5e/pop-to-esi +36324 # . epilogue +36325 89/<- %esp 5/r32/ebp +36326 5d/pop-to-ebp +36327 c3/return +36328 +36329 mu-stream-type?: # a: (addr type-tree) -> result/eax: boolean +36330 # . prologue +36331 55/push-ebp +36332 89/<- %ebp 4/r32/esp +36333 # eax = a +36334 8b/-> *(ebp+8) 0/r32/eax +36335 # if (!a->is-atom?) a = a->left +36336 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +36337 { +36338 75/jump-if-!= break/disp8 +36339 (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax +36340 } +36341 # return (a->value == stream) +36342 81 7/subop/compare *(eax+4) 0xb/imm32/stream # Type-tree-value +36343 0f 94/set-byte-if-= %al +36344 25/and-eax-with 0xff/imm32 +36345 $mu-stream-type?:end: +36346 # . epilogue +36347 89/<- %esp 5/r32/ebp +36348 5d/pop-to-ebp +36349 c3/return +36350 +36351 test-emit-subx-stmt-primitive: +36352 # Primitive operation on a variable on the stack. +36353 # increment foo +36354 # => +36355 # ff 0/subop/increment *(ebp-8) +36356 # +36357 # There's a variable on the var stack as follows: +36358 # name: 'foo' +36359 # type: int +36360 # stack-offset: -8 +36361 # +36362 # There's a primitive with this info: +36363 # name: 'increment' +36364 # inouts: int/mem +36365 # value: 'ff 0/subop/increment' +36366 # +36367 # . prologue +36368 55/push-ebp +36369 89/<- %ebp 4/r32/esp +36370 # setup +36371 (clear-stream _test-output-stream) +36372 (clear-stream $_test-output-buffered-file->buffer) +36373 # simulate allocated payloads starting with an initial fake alloc-id (0x11) +36374 $test-emit-subx-stmt-primitive:initialize-type: +36375 # var type/ecx: (payload type-tree) = int +36376 68/push 0/imm32/right:null +36377 68/push 0/imm32/right:null +36378 68/push 0/imm32/left:unused +36379 68/push 1/imm32/value:int +36380 68/push 1/imm32/is-atom?:true +36381 68/push 0x11/imm32/alloc-id:fake:payload +36382 89/<- %ecx 4/r32/esp +36383 $test-emit-subx-stmt-primitive:initialize-var: +36384 # var var-foo/ecx: (payload var) = var(type) +36385 68/push 0/imm32/no-register +36386 68/push 0/imm32/no-register +36387 68/push -8/imm32/stack-offset +36388 68/push 1/imm32/block-depth +36389 51/push-ecx/type +36390 68/push 0x11/imm32/alloc-id:fake +36391 68/push 0/imm32/name +36392 68/push 0/imm32/name +36393 68/push 0x11/imm32/alloc-id:fake:payload +36394 89/<- %ecx 4/r32/esp +36395 $test-emit-subx-stmt-primitive:initialize-var-name: +36396 # var-foo->name = "foo" +36397 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +36398 (copy-array Heap "foo" %eax) +36399 $test-emit-subx-stmt-primitive:initialize-stmt-var: +36400 # var operand/ebx: (payload stmt-var) = stmt-var(var-foo) +36401 68/push 0/imm32/is-deref:false +36402 68/push 0/imm32/next +36403 68/push 0/imm32/next +36404 51/push-ecx/var-foo +36405 68/push 0x11/imm32/alloc-id:fake +36406 68/push 0x11/imm32/alloc-id:fake:payload +36407 89/<- %ebx 4/r32/esp +36408 $test-emit-subx-stmt-primitive:initialize-stmt: +36409 # var stmt/esi: (addr statement) +36410 68/push 0/imm32/no-outputs +36411 68/push 0/imm32/no-outputs +36412 53/push-ebx/inouts +36413 68/push 0x11/imm32/alloc-id:fake +36414 68/push 0/imm32/operation +36415 68/push 0/imm32/operation +36416 68/push 1/imm32/tag +36417 89/<- %esi 4/r32/esp +36418 $test-emit-subx-stmt-primitive:initialize-stmt-operation: +36419 # stmt->operation = "increment" +36420 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +36421 (copy-array Heap "increment" %eax) +36422 $test-emit-subx-stmt-primitive:initialize-primitive: +36423 # var primitives/ebx: (addr primitive) +36424 68/push 0/imm32/next +36425 68/push 0/imm32/next +36426 68/push 0/imm32/no-x32 +36427 68/push 0/imm32/no-xm32 +36428 68/push 0/imm32/no-disp32 +36429 68/push 0/imm32/no-imm8 +36430 68/push 0/imm32/no-imm32 +36431 68/push 0/imm32/no-r32 +36432 68/push 1/imm32/rm32-is-first-inout +36433 68/push 0/imm32/subx-name +36434 68/push 0/imm32/subx-name +36435 68/push 0/imm32/no-outputs +36436 68/push 0/imm32/no-outputs +36437 53/push-ebx/inouts # hack: reuse stmt-var from call stmt as (list var) in function declaration +36438 68/push 0x11/imm32/alloc-id:fake +36439 68/push 0/imm32/name +36440 68/push 0/imm32/name +36441 89/<- %ebx 4/r32/esp +36442 $test-emit-subx-stmt-primitive:initialize-primitive-name: +36443 # primitives->name = "increment" +36444 (copy-array Heap "increment" %ebx) # Primitive-name +36445 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name: +36446 # primitives->subx-name = "ff 0/subop/increment" +36447 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name +36448 (copy-array Heap "ff 0/subop/increment" %eax) +36449 # convert +36450 c7 0/subop/copy *Curr-block-depth 0/imm32 +36451 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) +36452 (flush _test-output-buffered-file) +36453 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +36459 # check output +36460 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive") +36461 # . epilogue +36462 89/<- %esp 5/r32/ebp +36463 5d/pop-to-ebp +36464 c3/return +36465 +36466 test-emit-subx-stmt-primitive-register: +36467 # Primitive operation on a variable in a register. +36468 # foo <- increment +36469 # => +36470 # ff 0/subop/increment %eax # sub-optimal, but should suffice 36471 # -36472 # There's two primitives, as follows: -36473 # - name: 'increment' -36474 # out: int/reg -36475 # value: 'ff 0/subop/increment' -36476 # - name: 'increment' -36477 # inout: int/mem -36478 # value: 'ff 0/subop/increment' -36479 # -36480 # . prologue -36481 55/push-ebp -36482 89/<- %ebp 4/r32/esp -36483 # setup -36484 (clear-stream _test-output-stream) -36485 (clear-stream $_test-output-buffered-file->buffer) -36486 $test-emit-subx-stmt-select-primitive-2:initialize-type: -36487 # var type/ecx: (payload type-tree) = int -36488 68/push 0/imm32/right:null -36489 68/push 0/imm32/right:null -36490 68/push 0/imm32/left:unused -36491 68/push 1/imm32/value:int -36492 68/push 1/imm32/is-atom?:true -36493 68/push 0x11/imm32/alloc-id:fake:payload -36494 89/<- %ecx 4/r32/esp -36495 $test-emit-subx-stmt-select-primitive-2:initialize-var: -36496 # var var-foo/ecx: (payload var) -36497 68/push 0/imm32/register -36498 68/push 0/imm32/register -36499 68/push 0/imm32/no-stack-offset -36500 68/push 1/imm32/block-depth -36501 51/push-ecx -36502 68/push 0x11/imm32/alloc-id:fake -36503 68/push 0/imm32/name -36504 68/push 0/imm32/name -36505 68/push 0x11/imm32/alloc-id:fake:payload -36506 89/<- %ecx 4/r32/esp -36507 $test-emit-subx-stmt-select-primitive-2:initialize-var-name: -36508 # var-foo->name = "foo" -36509 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36510 (copy-array Heap "foo" %eax) -36511 $test-emit-subx-stmt-select-primitive-2:initialize-var-register: -36512 # var-foo->register = "eax" -36513 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -36514 (copy-array Heap "eax" %eax) -36515 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var: -36516 # var operand/ebx: (payload stmt-var) -36517 68/push 0/imm32/is-deref:false -36518 68/push 0/imm32/next -36519 68/push 0/imm32/next -36520 51/push-ecx/var-foo -36521 68/push 0x11/imm32/alloc-id:fake -36522 68/push 0x11/imm32/alloc-id:fake:payload -36523 89/<- %ebx 4/r32/esp -36524 $test-emit-subx-stmt-select-primitive-2:initialize-stmt: -36525 # var stmt/esi: (addr statement) -36526 68/push 0/imm32/no-outputs -36527 68/push 0/imm32/no-outputs -36528 53/push-ebx/inouts +36472 # There's a variable on the var stack as follows: +36473 # name: 'foo' +36474 # type: int +36475 # register: 'eax' +36476 # +36477 # There's a primitive with this info: +36478 # name: 'increment' +36479 # out: int/reg +36480 # value: 'ff 0/subop/increment' +36481 # +36482 # . prologue +36483 55/push-ebp +36484 89/<- %ebp 4/r32/esp +36485 # setup +36486 (clear-stream _test-output-stream) +36487 (clear-stream $_test-output-buffered-file->buffer) +36488 $test-emit-subx-stmt-primitive-register:initialize-type: +36489 # var type/ecx: (payload type-tree) = int +36490 68/push 0/imm32/right:null +36491 68/push 0/imm32/right:null +36492 68/push 0/imm32/left:unused +36493 68/push 1/imm32/value:int +36494 68/push 1/imm32/is-atom?:true +36495 68/push 0x11/imm32/alloc-id:fake:payload +36496 89/<- %ecx 4/r32/esp +36497 $test-emit-subx-stmt-primitive-register:initialize-var: +36498 # var var-foo/ecx: (payload var) +36499 68/push 0/imm32/register +36500 68/push 0/imm32/register +36501 68/push 0/imm32/no-stack-offset +36502 68/push 1/imm32/block-depth +36503 51/push-ecx +36504 68/push 0x11/imm32/alloc-id:fake +36505 68/push 0/imm32/name +36506 68/push 0/imm32/name +36507 68/push 0x11/imm32/alloc-id:fake:payload +36508 89/<- %ecx 4/r32/esp +36509 $test-emit-subx-stmt-primitive-register:initialize-var-name: +36510 # var-foo->name = "foo" +36511 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +36512 (copy-array Heap "foo" %eax) +36513 $test-emit-subx-stmt-primitive-register:initialize-var-register: +36514 # var-foo->register = "eax" +36515 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +36516 (copy-array Heap "eax" %eax) +36517 $test-emit-subx-stmt-primitive-register:initialize-stmt-var: +36518 # var operand/ebx: (payload stmt-var) +36519 68/push 0/imm32/is-deref:false +36520 68/push 0/imm32/next +36521 68/push 0/imm32/next +36522 51/push-ecx/var-foo +36523 68/push 0x11/imm32/alloc-id:fake +36524 68/push 0x11/imm32/alloc-id:fake:payload +36525 89/<- %ebx 4/r32/esp +36526 $test-emit-subx-stmt-primitive-register:initialize-stmt: +36527 # var stmt/esi: (addr statement) +36528 53/push-ebx/outputs 36529 68/push 0x11/imm32/alloc-id:fake -36530 68/push 0/imm32/operation -36531 68/push 0/imm32/operation -36532 68/push 1/imm32 -36533 89/<- %esi 4/r32/esp -36534 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation: -36535 # stmt->operation = "increment" -36536 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36537 (copy-array Heap "increment" %eax) -36538 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var: -36539 # var formal-var/ebx: (payload var) -36540 68/push 0/imm32/register -36541 68/push 0/imm32/register -36542 68/push 0/imm32/no-stack-offset -36543 68/push 1/imm32/block-depth -36544 ff 6/subop/push *(ecx+0x10) # Var-type + payload alloc id + handle alloc id -36545 68/push 0x11/imm32/alloc-id:fake -36546 68/push 0/imm32/name -36547 68/push 0/imm32/name -36548 68/push 0x11/imm32/alloc-id:fake:payload -36549 89/<- %ebx 4/r32/esp -36550 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name: -36551 # formal-var->name = "dummy" -36552 8d/copy-address *(ebx+4) 0/r32/eax # Var-name + 4 -36553 (copy-array Heap "dummy" %eax) -36554 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register: -36555 # formal-var->register = "*" -36556 8d/copy-address *(ebx+0x1c) 0/r32/eax # Var-register + 4 -36557 (copy-array Heap "*" %eax) # Any-register -36558 $test-emit-subx-stmt-select-primitive-2:initialize-var-list: -36559 # var formal-outputs/ebx: (payload list stmt-var) -36560 68/push 0/imm32/next -36561 68/push 0/imm32/next -36562 53/push-ebx/formal-var -36563 68/push 0x11/imm32/alloc-id:fake -36564 68/push 0x11/imm32/alloc-id:fake:payload -36565 89/<- %ebx 4/r32/esp -36566 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2: -36567 # var primitive2/edi: (payload primitive) -36568 68/push 0/imm32/next -36569 68/push 0/imm32/next -36570 68/push 0/imm32/no-x32 -36571 68/push 0/imm32/no-xm32 -36572 68/push 0/imm32/no-disp32 -36573 68/push 0/imm32/no-imm8 -36574 68/push 0/imm32/no-imm32 -36575 68/push 0/imm32/no-r32 -36576 68/push 3/imm32/rm32-is-first-output -36577 68/push 0/imm32/subx-name -36578 68/push 0/imm32/subx-name -36579 53/push-ebx/outputs -36580 68/push 0x11/imm32/alloc-id:fake -36581 68/push 0/imm32/no-inouts -36582 68/push 0/imm32/no-inouts -36583 68/push 0/imm32/name -36584 68/push 0/imm32/name -36585 68/push 0x11/imm32/alloc-id:fake:payload -36586 89/<- %edi 4/r32/esp -36587 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name: -36588 # primitives->name = "increment" -36589 8d/copy-address *(edi+4) 0/r32/eax # Primitive-name + 4 -36590 (copy-array Heap "increment" %eax) -36591 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name: +36530 68/push 0/imm32/no-inouts +36531 68/push 0/imm32/no-inouts +36532 68/push 0/imm32/operation +36533 68/push 0/imm32/operation +36534 68/push 1/imm32 +36535 89/<- %esi 4/r32/esp +36536 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation: +36537 # stmt->operation = "increment" +36538 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +36539 (copy-array Heap "increment" %eax) +36540 $test-emit-subx-stmt-primitive-register:initialize-formal-var: +36541 # var formal-var/ebx: (payload var) +36542 68/push 0/imm32/register +36543 68/push 0/imm32/register +36544 68/push 0/imm32/no-stack-offset +36545 68/push 1/imm32/block-depth +36546 ff 6/subop/push *(ecx+0x10) # Var-type + payload alloc id + handle alloc id +36547 68/push 0x11/imm32/alloc-id:fake +36548 68/push 0/imm32/name +36549 68/push 0/imm32/name +36550 68/push 0x11/imm32/alloc-id:fake:payload +36551 89/<- %ebx 4/r32/esp +36552 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name: +36553 # formal-var->name = "dummy" +36554 8d/copy-address *(ebx+4) 0/r32/eax # Var-name + 4 +36555 (copy-array Heap "dummy" %eax) +36556 $test-emit-subx-stmt-primitive-register:initialize-formal-register: +36557 # formal-var->register = "*" +36558 8d/copy-address *(ebx+0x1c) 0/r32/eax # Var-register + 4 +36559 (copy-array Heap "*" %eax) # Any-register +36560 $test-emit-subx-stmt-primitive-register:initialize-var-list: +36561 # var formal-outputs/ebx: (payload list var) +36562 68/push 0/imm32/next +36563 68/push 0/imm32/next +36564 53/push-ebx/formal-var +36565 68/push 0x11/imm32/alloc-id:fake +36566 68/push 0x11/imm32/alloc-id:fake:payload +36567 89/<- %ebx 4/r32/esp +36568 $test-emit-subx-stmt-primitive-register:initialize-primitive: +36569 # var primitives/ebx: (addr primitive) +36570 68/push 0/imm32/next +36571 68/push 0/imm32/next +36572 68/push 0/imm32/no-x32 +36573 68/push 0/imm32/no-xm32 +36574 68/push 0/imm32/no-disp32 +36575 68/push 0/imm32/no-imm8 +36576 68/push 0/imm32/no-imm32 +36577 68/push 0/imm32/no-r32 +36578 68/push 3/imm32/rm32-is-first-output +36579 68/push 0/imm32/subx-name +36580 68/push 0/imm32/subx-name +36581 53/push-ebx/outputs +36582 68/push 0x11/imm32/alloc-id:fake +36583 68/push 0/imm32/no-inouts +36584 68/push 0/imm32/no-inouts +36585 68/push 0/imm32/name +36586 68/push 0/imm32/name +36587 89/<- %ebx 4/r32/esp +36588 $test-emit-subx-stmt-primitive-register:initialize-primitive-name: +36589 # primitives->name = "increment" +36590 (copy-array Heap "increment" %ebx) # Primitive-name +36591 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name: 36592 # primitives->subx-name = "ff 0/subop/increment" -36593 8d/copy-address *(edi+0x1c) 0/r32/eax # Primitive-subx-name + 4 +36593 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name 36594 (copy-array Heap "ff 0/subop/increment" %eax) -36595 $test-emit-subx-stmt-select-primitive-2:initialize-primitive: -36596 # var primitives/ebx: (addr primitive) -36597 57/push-edi -36598 68/push 0x11/imm32/alloc-id:fake -36599 68/push 0/imm32/no-x32 -36600 68/push 0/imm32/no-xm32 -36601 68/push 0/imm32/no-disp32 -36602 68/push 0/imm32/no-imm8 -36603 68/push 0/imm32/no-imm32 -36604 68/push 0/imm32/no-r32 -36605 68/push 1/imm32/rm32-is-first-inout -36606 68/push 0/imm32/subx-name -36607 68/push 0/imm32/subx-name -36608 68/push 0/imm32/no-outputs -36609 68/push 0/imm32/no-outputs -36610 53/push-ebx/inouts # hack: reuse stmt-var from call stmt as (list var) in function declaration -36611 68/push 0x11/imm32/alloc-id:fake -36612 68/push 0/imm32/name -36613 68/push 0/imm32/name -36614 89/<- %ebx 4/r32/esp -36615 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name: -36616 # primitives->name = "increment" -36617 (copy-array Heap "increment" %ebx) # Primitive-name -36618 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name: -36619 # primitives->subx-name = "ff 0/subop/increment" -36620 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name -36621 (copy-array Heap "ff 0/subop/increment" %eax) -36622 # convert -36623 c7 0/subop/copy *Curr-block-depth 0/imm32 -36624 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) -36625 (flush _test-output-buffered-file) -36626 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36632 # check output -36633 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") -36634 # . epilogue -36635 89/<- %esp 5/r32/ebp -36636 5d/pop-to-ebp -36637 c3/return -36638 -36639 test-increment-register: -36640 # Select the right register between overloads. -36641 # foo <- increment -36642 # => -36643 # 50/increment-eax -36644 # -36645 # There's a variable on the var stack as follows: -36646 # name: 'foo' -36647 # type: int -36648 # register: 'eax' -36649 # -36650 # Primitives are the global definitions. -36651 # -36652 # . prologue -36653 55/push-ebp -36654 89/<- %ebp 4/r32/esp -36655 # setup -36656 (clear-stream _test-output-stream) -36657 (clear-stream $_test-output-buffered-file->buffer) -36658 $test-increment-register:initialize-type: -36659 # var type/ecx: (payload type-tree) = int -36660 68/push 0/imm32/right:null -36661 68/push 0/imm32/right:null -36662 68/push 0/imm32/left:unused -36663 68/push 1/imm32/value:int -36664 68/push 1/imm32/is-atom?:true -36665 68/push 0x11/imm32/alloc-id:fake:payload -36666 89/<- %ecx 4/r32/esp -36667 $test-increment-register:initialize-var: -36668 # var var-foo/ecx: (payload var) -36669 68/push 0/imm32/register -36670 68/push 0/imm32/register -36671 68/push 0/imm32/no-stack-offset -36672 68/push 1/imm32/block-depth -36673 51/push-ecx -36674 68/push 0x11/imm32/alloc-id:fake -36675 68/push 0/imm32/name -36676 68/push 0/imm32/name -36677 68/push 0x11/imm32/alloc-id:fake:payload -36678 89/<- %ecx 4/r32/esp -36679 $test-increment-register:initialize-var-name: -36680 # var-foo->name = "foo" -36681 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36682 (copy-array Heap "foo" %eax) -36683 $test-increment-register:initialize-var-register: -36684 # var-foo->register = "eax" -36685 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -36686 (copy-array Heap "eax" %eax) -36687 $test-increment-register:initialize-stmt-var: -36688 # var operand/ebx: (payload stmt-var) -36689 68/push 0/imm32/is-deref:false -36690 68/push 0/imm32/next -36691 68/push 0/imm32/next -36692 51/push-ecx/var-foo -36693 68/push 0x11/imm32/alloc-id:fake -36694 68/push 0x11/imm32/alloc-id:fake:payload -36695 89/<- %ebx 4/r32/esp -36696 $test-increment-register:initialize-stmt: -36697 # var stmt/esi: (addr statement) -36698 53/push-ebx/outputs -36699 68/push 0x11/imm32/alloc-id:fake -36700 68/push 0/imm32/no-inouts -36701 68/push 0/imm32/no-inouts -36702 68/push 0/imm32/operation -36703 68/push 0/imm32/operation -36704 68/push 1/imm32 -36705 89/<- %esi 4/r32/esp -36706 $test-increment-register:initialize-stmt-operation: -36707 # stmt->operation = "increment" -36708 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36709 (copy-array Heap "increment" %eax) -36710 # convert -36711 c7 0/subop/copy *Curr-block-depth 0/imm32 -36712 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -36713 (flush _test-output-buffered-file) -36714 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36720 # check output -36721 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -36722 # . epilogue -36723 89/<- %esp 5/r32/ebp -36724 5d/pop-to-ebp -36725 c3/return -36726 -36727 test-add-reg-to-reg: -36728 # var1/reg <- add var2/reg -36729 # => -36730 # 01/add-to %var1 var2 -36731 # -36732 # . prologue -36733 55/push-ebp -36734 89/<- %ebp 4/r32/esp -36735 # setup -36736 (clear-stream _test-output-stream) -36737 (clear-stream $_test-output-buffered-file->buffer) -36738 $test-add-reg-to-reg:initialize-type: -36739 # var type/ecx: (payload type-tree) = int -36740 68/push 0/imm32/right:null -36741 68/push 0/imm32/right:null -36742 68/push 0/imm32/left:unused -36743 68/push 1/imm32/value:int -36744 68/push 1/imm32/is-atom?:true -36745 68/push 0x11/imm32/alloc-id:fake:payload -36746 89/<- %ecx 4/r32/esp -36747 $test-add-reg-to-reg:initialize-var1: -36748 # var var1/ecx: (payload var) -36749 68/push 0/imm32/register -36750 68/push 0/imm32/register -36751 68/push 0/imm32/no-stack-offset -36752 68/push 1/imm32/block-depth -36753 51/push-ecx -36754 68/push 0x11/imm32/alloc-id:fake -36755 68/push 0/imm32/name -36756 68/push 0/imm32/name -36757 68/push 0x11/imm32/alloc-id:fake:payload -36758 89/<- %ecx 4/r32/esp -36759 $test-add-reg-to-reg:initialize-var1-name: -36760 # var1->name = "var1" -36761 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36762 (copy-array Heap "var1" %eax) -36763 $test-add-reg-to-reg:initialize-var1-register: -36764 # var1->register = "eax" -36765 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -36766 (copy-array Heap "eax" %eax) -36767 $test-add-reg-to-reg:initialize-var2: -36768 # var var2/edx: (payload var) -36769 68/push 0/imm32/register -36770 68/push 0/imm32/register -36771 68/push 0/imm32/no-stack-offset -36772 68/push 1/imm32/block-depth -36773 ff 6/subop/push *(ecx+0x10) -36774 68/push 0x11/imm32/alloc-id:fake -36775 68/push 0/imm32/name -36776 68/push 0/imm32/name -36777 68/push 0x11/imm32/alloc-id:fake:payload -36778 89/<- %edx 4/r32/esp -36779 $test-add-reg-to-reg:initialize-var2-name: -36780 # var2->name = "var2" -36781 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -36782 (copy-array Heap "var2" %eax) -36783 $test-add-reg-to-reg:initialize-var2-register: -36784 # var2->register = "ecx" -36785 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 -36786 (copy-array Heap "ecx" %eax) -36787 $test-add-reg-to-reg:initialize-inouts: -36788 # var inouts/esi: (payload stmt-var) = [var2] -36789 68/push 0/imm32/is-deref:false -36790 68/push 0/imm32/next -36791 68/push 0/imm32/next -36792 52/push-edx/var2 -36793 68/push 0x11/imm32/alloc-id:fake -36794 68/push 0x11/imm32/alloc-id:fake:payload -36795 89/<- %esi 4/r32/esp -36796 $test-add-reg-to-reg:initialize-outputs: -36797 # var outputs/edi: (payload stmt-var) = [var1] -36798 68/push 0/imm32/is-deref:false -36799 68/push 0/imm32/next -36800 68/push 0/imm32/next -36801 51/push-ecx/var1 -36802 68/push 0x11/imm32/alloc-id:fake -36803 68/push 0x11/imm32/alloc-id:fake:payload -36804 89/<- %edi 4/r32/esp -36805 $test-add-reg-to-reg:initialize-stmt: -36806 # var stmt/esi: (addr statement) -36807 68/push 0/imm32/next -36808 68/push 0/imm32/next -36809 57/push-edi/outputs -36810 68/push 0x11/imm32/alloc-id:fake -36811 56/push-esi/inouts -36812 68/push 0x11/imm32/alloc-id:fake -36813 68/push 0/imm32/operation -36814 68/push 0/imm32/operation -36815 68/push 1/imm32/tag:stmt1 -36816 89/<- %esi 4/r32/esp -36817 $test-add-reg-to-reg:initialize-stmt-operation: -36818 # stmt->operation = "add" -36819 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36820 (copy-array Heap "add" %eax) -36821 # convert -36822 c7 0/subop/copy *Curr-block-depth 0/imm32 -36823 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -36824 (flush _test-output-buffered-file) -36825 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36831 # check output -36832 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -36833 # . epilogue -36834 89/<- %esp 5/r32/ebp -36835 5d/pop-to-ebp -36836 c3/return -36837 -36838 test-add-reg-to-mem: -36839 # add-to var1 var2/reg -36840 # => -36841 # 01/add-to *(ebp+__) var2 -36842 # -36843 # . prologue -36844 55/push-ebp -36845 89/<- %ebp 4/r32/esp -36846 # setup -36847 (clear-stream _test-output-stream) -36848 (clear-stream $_test-output-buffered-file->buffer) -36849 $test-add-reg-to-mem:initialize-type: -36850 # var type/ecx: (payload type-tree) = int -36851 68/push 0/imm32/right:null -36852 68/push 0/imm32/right:null -36853 68/push 0/imm32/left:unused -36854 68/push 1/imm32/value:int -36855 68/push 1/imm32/is-atom?:true -36856 68/push 0x11/imm32/alloc-id:fake:payload -36857 89/<- %ecx 4/r32/esp -36858 $test-add-reg-to-mem:initialize-var1: -36859 # var var1/ecx: (payload var) -36860 68/push 0/imm32/register -36861 68/push 0/imm32/register -36862 68/push 8/imm32/stack-offset -36863 68/push 1/imm32/block-depth -36864 51/push-ecx -36865 68/push 0x11/imm32/alloc-id:fake -36866 68/push 0/imm32/name -36867 68/push 0/imm32/name -36868 68/push 0x11/imm32/alloc-id:fake:payload -36869 89/<- %ecx 4/r32/esp -36870 $test-add-reg-to-mem:initialize-var1-name: -36871 # var1->name = "var1" -36872 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36873 (copy-array Heap "var1" %eax) -36874 $test-add-reg-to-mem:initialize-var2: -36875 # var var2/edx: (payload var) -36876 68/push 0/imm32/register -36877 68/push 0/imm32/register -36878 68/push 0/imm32/no-stack-offset -36879 68/push 1/imm32/block-depth -36880 ff 6/subop/push *(ecx+0x10) -36881 68/push 0x11/imm32/alloc-id:fake -36882 68/push 0/imm32/name -36883 68/push 0/imm32/name -36884 68/push 0x11/imm32/alloc-id:fake:payload -36885 89/<- %edx 4/r32/esp -36886 $test-add-reg-to-mem:initialize-var2-name: -36887 # var2->name = "var2" -36888 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -36889 (copy-array Heap "var2" %eax) -36890 $test-add-reg-to-mem:initialize-var2-register: -36891 # var2->register = "ecx" -36892 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 -36893 (copy-array Heap "ecx" %eax) -36894 $test-add-reg-to-mem:initialize-inouts: -36895 # var inouts/esi: (payload stmt-var) = [var2] -36896 68/push 0/imm32/is-deref:false +36595 # convert +36596 c7 0/subop/copy *Curr-block-depth 0/imm32 +36597 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) +36598 (flush _test-output-buffered-file) +36599 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +36605 # check output +36606 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register") +36607 # . epilogue +36608 89/<- %esp 5/r32/ebp +36609 5d/pop-to-ebp +36610 c3/return +36611 +36612 test-emit-subx-stmt-select-primitive: +36613 # Select the right primitive between overloads. +36614 # foo <- increment +36615 # => +36616 # ff 0/subop/increment %eax # sub-optimal, but should suffice +36617 # +36618 # There's a variable on the var stack as follows: +36619 # name: 'foo' +36620 # type: int +36621 # register: 'eax' +36622 # +36623 # There's two primitives, as follows: +36624 # - name: 'increment' +36625 # out: int/reg +36626 # value: 'ff 0/subop/increment' +36627 # - name: 'increment' +36628 # inout: int/mem +36629 # value: 'ff 0/subop/increment' +36630 # +36631 # . prologue +36632 55/push-ebp +36633 89/<- %ebp 4/r32/esp +36634 # setup +36635 (clear-stream _test-output-stream) +36636 (clear-stream $_test-output-buffered-file->buffer) +36637 $test-emit-subx-stmt-select-primitive:initialize-type: +36638 # var type/ecx: (payload type-tree) = int +36639 68/push 0/imm32/right:null +36640 68/push 0/imm32/right:null +36641 68/push 0/imm32/left:unused +36642 68/push 1/imm32/value:int +36643 68/push 1/imm32/is-atom?:true +36644 68/push 0x11/imm32/alloc-id:fake:payload +36645 89/<- %ecx 4/r32/esp +36646 $test-emit-subx-stmt-select-primitive:initialize-var: +36647 # var var-foo/ecx: (payload var) +36648 68/push 0/imm32/register +36649 68/push 0/imm32/register +36650 68/push 0/imm32/no-stack-offset +36651 68/push 1/imm32/block-depth +36652 51/push-ecx +36653 68/push 0x11/imm32/alloc-id:fake +36654 68/push 0/imm32/name +36655 68/push 0/imm32/name +36656 68/push 0x11/imm32/alloc-id:fake:payload +36657 89/<- %ecx 4/r32/esp +36658 $test-emit-subx-stmt-select-primitive:initialize-var-name: +36659 # var-foo->name = "foo" +36660 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +36661 (copy-array Heap "foo" %eax) +36662 $test-emit-subx-stmt-select-primitive:initialize-var-register: +36663 # var-foo->register = "eax" +36664 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +36665 (copy-array Heap "eax" %eax) +36666 $test-emit-subx-stmt-select-primitive:initialize-stmt-var: +36667 # var operand/ebx: (payload stmt-var) +36668 68/push 0/imm32/is-deref:false +36669 68/push 0/imm32/next +36670 68/push 0/imm32/next +36671 51/push-ecx/var-foo +36672 68/push 0x11/imm32/alloc-id:fake +36673 68/push 0x11/imm32/alloc-id:fake:payload +36674 89/<- %ebx 4/r32/esp +36675 $test-emit-subx-stmt-select-primitive:initialize-stmt: +36676 # var stmt/esi: (addr statement) +36677 53/push-ebx/outputs +36678 68/push 0x11/imm32/alloc-id:fake +36679 68/push 0/imm32/no-inouts +36680 68/push 0/imm32/no-inouts +36681 68/push 0/imm32/operation +36682 68/push 0/imm32/operation +36683 68/push 1/imm32 +36684 89/<- %esi 4/r32/esp +36685 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation: +36686 # stmt->operation = "increment" +36687 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +36688 (copy-array Heap "increment" %eax) +36689 $test-emit-subx-stmt-select-primitive:initialize-formal-var: +36690 # var formal-var/ebx: (payload var) +36691 68/push 0/imm32/register +36692 68/push 0/imm32/register +36693 68/push 0/imm32/no-stack-offset +36694 68/push 1/imm32/block-depth +36695 ff 6/subop/push *(ecx+0x10) # Var-type + payload alloc id + handle alloc id +36696 68/push 0x11/imm32/alloc-id:fake +36697 68/push 0/imm32/name +36698 68/push 0/imm32/name +36699 68/push 0x11/imm32/alloc-id:fake:payload +36700 89/<- %ebx 4/r32/esp +36701 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name: +36702 # formal-var->name = "dummy" +36703 8d/copy-address *(ebx+4) 0/r32/eax # Var-name + 4 +36704 (copy-array Heap "dummy" %eax) +36705 $test-emit-subx-stmt-select-primitive:initialize-formal-register: +36706 # formal-var->register = "*" +36707 8d/copy-address *(ebx+0x1c) 0/r32/eax # Var-register + 4 +36708 (copy-array Heap "*" %eax) # Any-register +36709 $test-emit-subx-stmt-select-primitive:initialize-var-list: +36710 # var formal-outputs/ebx: (payload list var) +36711 68/push 0/imm32/next +36712 68/push 0/imm32/next +36713 53/push-ebx/formal-var +36714 68/push 0x11/imm32/alloc-id:fake +36715 68/push 0x11/imm32/alloc-id:fake:payload +36716 89/<- %ebx 4/r32/esp +36717 $test-emit-subx-stmt-select-primitive:initialize-primitive2: +36718 # var primitive2/edi: (payload primitive) +36719 68/push 0/imm32/next +36720 68/push 0/imm32/next +36721 68/push 0/imm32/no-x32 +36722 68/push 0/imm32/no-xm32 +36723 68/push 0/imm32/no-disp32 +36724 68/push 0/imm32/no-imm8 +36725 68/push 0/imm32/no-imm32 +36726 68/push 0/imm32/no-r32 +36727 68/push 3/imm32/rm32-is-first-output +36728 68/push 0/imm32/subx-name +36729 68/push 0/imm32/subx-name +36730 53/push-ebx/outputs +36731 68/push 0x11/imm32/alloc-id:fake +36732 68/push 0/imm32/no-inouts +36733 68/push 0/imm32/no-inouts +36734 68/push 0/imm32/name +36735 68/push 0/imm32/name +36736 68/push 0x11/imm32/alloc-id:fake:payload +36737 89/<- %edi 4/r32/esp +36738 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name: +36739 # primitives->name = "increment" +36740 8d/copy-address *(edi+4) 0/r32/eax # Primitive-name + 4 +36741 (copy-array Heap "increment" %eax) +36742 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name: +36743 # primitives->subx-name = "ff 0/subop/increment" +36744 8d/copy-address *(edi+0x1c) 0/r32/eax # Primitive-subx-name + 4 +36745 (copy-array Heap "ff 0/subop/increment" %eax) +36746 $test-emit-subx-stmt-select-primitive:initialize-primitive: +36747 # var primitives/ebx: (addr primitive) +36748 57/push-edi +36749 68/push 0x11/imm32/alloc-id:fake +36750 68/push 0/imm32/no-x32 +36751 68/push 0/imm32/no-xm32 +36752 68/push 0/imm32/no-disp32 +36753 68/push 0/imm32/no-imm8 +36754 68/push 0/imm32/no-imm32 +36755 68/push 0/imm32/no-r32 +36756 68/push 1/imm32/rm32-is-first-inout +36757 68/push 0/imm32/subx-name +36758 68/push 0/imm32/subx-name +36759 68/push 0/imm32/no-outputs +36760 68/push 0/imm32/no-outputs +36761 53/push-ebx/inouts # hack: reuse stmt-var from call stmt as (list var) in function declaration +36762 68/push 0x11/imm32/alloc-id:fake +36763 68/push 0/imm32/name +36764 68/push 0/imm32/name +36765 89/<- %ebx 4/r32/esp +36766 $test-emit-subx-stmt-select-primitive:initialize-primitive-name: +36767 # primitives->name = "increment" +36768 (copy-array Heap "increment" %ebx) # Primitive-name +36769 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name: +36770 # primitives->subx-name = "ff 0/subop/increment" +36771 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name +36772 (copy-array Heap "ff 0/subop/increment" %eax) +36773 # convert +36774 c7 0/subop/copy *Curr-block-depth 0/imm32 +36775 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) +36776 (flush _test-output-buffered-file) +36777 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +36783 # check output +36784 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive") +36785 # . epilogue +36786 89/<- %esp 5/r32/ebp +36787 5d/pop-to-ebp +36788 c3/return +36789 +36790 test-emit-subx-stmt-select-primitive-2: +36791 # Select the right primitive between overloads. +36792 # increment foo +36793 # => +36794 # ff 0/subop/increment %eax # sub-optimal, but should suffice +36795 # +36796 # There's a variable on the var stack as follows: +36797 # name: 'foo' +36798 # type: int +36799 # register: 'eax' +36800 # +36801 # There's two primitives, as follows: +36802 # - name: 'increment' +36803 # out: int/reg +36804 # value: 'ff 0/subop/increment' +36805 # - name: 'increment' +36806 # inout: int/mem +36807 # value: 'ff 0/subop/increment' +36808 # +36809 # . prologue +36810 55/push-ebp +36811 89/<- %ebp 4/r32/esp +36812 # setup +36813 (clear-stream _test-output-stream) +36814 (clear-stream $_test-output-buffered-file->buffer) +36815 $test-emit-subx-stmt-select-primitive-2:initialize-type: +36816 # var type/ecx: (payload type-tree) = int +36817 68/push 0/imm32/right:null +36818 68/push 0/imm32/right:null +36819 68/push 0/imm32/left:unused +36820 68/push 1/imm32/value:int +36821 68/push 1/imm32/is-atom?:true +36822 68/push 0x11/imm32/alloc-id:fake:payload +36823 89/<- %ecx 4/r32/esp +36824 $test-emit-subx-stmt-select-primitive-2:initialize-var: +36825 # var var-foo/ecx: (payload var) +36826 68/push 0/imm32/register +36827 68/push 0/imm32/register +36828 68/push 0/imm32/no-stack-offset +36829 68/push 1/imm32/block-depth +36830 51/push-ecx +36831 68/push 0x11/imm32/alloc-id:fake +36832 68/push 0/imm32/name +36833 68/push 0/imm32/name +36834 68/push 0x11/imm32/alloc-id:fake:payload +36835 89/<- %ecx 4/r32/esp +36836 $test-emit-subx-stmt-select-primitive-2:initialize-var-name: +36837 # var-foo->name = "foo" +36838 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +36839 (copy-array Heap "foo" %eax) +36840 $test-emit-subx-stmt-select-primitive-2:initialize-var-register: +36841 # var-foo->register = "eax" +36842 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +36843 (copy-array Heap "eax" %eax) +36844 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var: +36845 # var operand/ebx: (payload stmt-var) +36846 68/push 0/imm32/is-deref:false +36847 68/push 0/imm32/next +36848 68/push 0/imm32/next +36849 51/push-ecx/var-foo +36850 68/push 0x11/imm32/alloc-id:fake +36851 68/push 0x11/imm32/alloc-id:fake:payload +36852 89/<- %ebx 4/r32/esp +36853 $test-emit-subx-stmt-select-primitive-2:initialize-stmt: +36854 # var stmt/esi: (addr statement) +36855 68/push 0/imm32/no-outputs +36856 68/push 0/imm32/no-outputs +36857 53/push-ebx/inouts +36858 68/push 0x11/imm32/alloc-id:fake +36859 68/push 0/imm32/operation +36860 68/push 0/imm32/operation +36861 68/push 1/imm32 +36862 89/<- %esi 4/r32/esp +36863 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation: +36864 # stmt->operation = "increment" +36865 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +36866 (copy-array Heap "increment" %eax) +36867 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var: +36868 # var formal-var/ebx: (payload var) +36869 68/push 0/imm32/register +36870 68/push 0/imm32/register +36871 68/push 0/imm32/no-stack-offset +36872 68/push 1/imm32/block-depth +36873 ff 6/subop/push *(ecx+0x10) # Var-type + payload alloc id + handle alloc id +36874 68/push 0x11/imm32/alloc-id:fake +36875 68/push 0/imm32/name +36876 68/push 0/imm32/name +36877 68/push 0x11/imm32/alloc-id:fake:payload +36878 89/<- %ebx 4/r32/esp +36879 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name: +36880 # formal-var->name = "dummy" +36881 8d/copy-address *(ebx+4) 0/r32/eax # Var-name + 4 +36882 (copy-array Heap "dummy" %eax) +36883 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register: +36884 # formal-var->register = "*" +36885 8d/copy-address *(ebx+0x1c) 0/r32/eax # Var-register + 4 +36886 (copy-array Heap "*" %eax) # Any-register +36887 $test-emit-subx-stmt-select-primitive-2:initialize-var-list: +36888 # var formal-outputs/ebx: (payload list stmt-var) +36889 68/push 0/imm32/next +36890 68/push 0/imm32/next +36891 53/push-ebx/formal-var +36892 68/push 0x11/imm32/alloc-id:fake +36893 68/push 0x11/imm32/alloc-id:fake:payload +36894 89/<- %ebx 4/r32/esp +36895 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2: +36896 # var primitive2/edi: (payload primitive) 36897 68/push 0/imm32/next 36898 68/push 0/imm32/next -36899 52/push-edx/var2 -36900 68/push 0x11/imm32/alloc-id:fake -36901 68/push 0x11/imm32/alloc-id:fake:payload -36902 89/<- %esi 4/r32/esp -36903 # inouts = [var1, var2] -36904 68/push 0/imm32/is-deref:false -36905 56/push-esi/next -36906 68/push 0x11/imm32/alloc-id:fake -36907 51/push-ecx/var1 -36908 68/push 0x11/imm32/alloc-id:fake -36909 68/push 0x11/imm32/alloc-id:fake:payload -36910 89/<- %esi 4/r32/esp -36911 $test-add-reg-to-mem:initialize-stmt: -36912 # var stmt/esi: (addr statement) -36913 68/push 0/imm32/next -36914 68/push 0/imm32/next -36915 68/push 0/imm32/outputs -36916 68/push 0/imm32/outputs -36917 56/push-esi/inouts -36918 68/push 0x11/imm32/alloc-id:fake -36919 68/push 0/imm32/operation -36920 68/push 0/imm32/operation -36921 68/push 1/imm32/tag:stmt1 -36922 89/<- %esi 4/r32/esp -36923 $test-add-reg-to-mem:initialize-stmt-operation: -36924 # stmt->operation = "add-to" -36925 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -36926 (copy-array Heap "add-to" %eax) -36927 # convert -36928 c7 0/subop/copy *Curr-block-depth 0/imm32 -36929 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -36930 (flush _test-output-buffered-file) -36931 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -36937 # check output -36938 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -36939 # . epilogue -36940 89/<- %esp 5/r32/ebp -36941 5d/pop-to-ebp -36942 c3/return -36943 -36944 test-add-mem-to-reg: -36945 # var1/reg <- add var2 -36946 # => -36947 # 03/add *(ebp+__) var1 -36948 # -36949 # . prologue -36950 55/push-ebp -36951 89/<- %ebp 4/r32/esp -36952 # setup -36953 (clear-stream _test-output-stream) -36954 (clear-stream $_test-output-buffered-file->buffer) -36955 $test-add-mem-to-reg:initialize-type: -36956 # var type/ecx: (payload type-tree) = int -36957 68/push 0/imm32/right:null -36958 68/push 0/imm32/right:null -36959 68/push 0/imm32/left:unused -36960 68/push 1/imm32/value:int -36961 68/push 1/imm32/is-atom?:true -36962 68/push 0x11/imm32/alloc-id:fake:payload -36963 89/<- %ecx 4/r32/esp -36964 $test-add-mem-to-reg:initialize-var: -36965 # var var1/ecx: (payload var) -36966 68/push 0/imm32/register -36967 68/push 0/imm32/register -36968 68/push 0/imm32/no-stack-offset -36969 68/push 1/imm32/block-depth -36970 51/push-ecx -36971 68/push 0x11/imm32/alloc-id:fake -36972 68/push 0/imm32/name -36973 68/push 0/imm32/name -36974 68/push 0x11/imm32/alloc-id:fake:payload -36975 89/<- %ecx 4/r32/esp -36976 $test-add-mem-to-reg:initialize-var-name: -36977 # var1->name = "foo" -36978 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -36979 (copy-array Heap "var1" %eax) -36980 $test-add-mem-to-reg:initialize-var-register: -36981 # var1->register = "eax" -36982 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -36983 (copy-array Heap "eax" %eax) -36984 $test-add-mem-to-reg:initialize-var2: -36985 # var var2/edx: (payload var) -36986 68/push 0/imm32/register -36987 68/push 0/imm32/register -36988 68/push 8/imm32/stack-offset -36989 68/push 1/imm32/block-depth -36990 ff 6/subop/push *(ecx+0x10) -36991 68/push 0x11/imm32/alloc-id:fake -36992 68/push 0/imm32/name -36993 68/push 0/imm32/name +36899 68/push 0/imm32/no-x32 +36900 68/push 0/imm32/no-xm32 +36901 68/push 0/imm32/no-disp32 +36902 68/push 0/imm32/no-imm8 +36903 68/push 0/imm32/no-imm32 +36904 68/push 0/imm32/no-r32 +36905 68/push 3/imm32/rm32-is-first-output +36906 68/push 0/imm32/subx-name +36907 68/push 0/imm32/subx-name +36908 53/push-ebx/outputs +36909 68/push 0x11/imm32/alloc-id:fake +36910 68/push 0/imm32/no-inouts +36911 68/push 0/imm32/no-inouts +36912 68/push 0/imm32/name +36913 68/push 0/imm32/name +36914 68/push 0x11/imm32/alloc-id:fake:payload +36915 89/<- %edi 4/r32/esp +36916 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name: +36917 # primitives->name = "increment" +36918 8d/copy-address *(edi+4) 0/r32/eax # Primitive-name + 4 +36919 (copy-array Heap "increment" %eax) +36920 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name: +36921 # primitives->subx-name = "ff 0/subop/increment" +36922 8d/copy-address *(edi+0x1c) 0/r32/eax # Primitive-subx-name + 4 +36923 (copy-array Heap "ff 0/subop/increment" %eax) +36924 $test-emit-subx-stmt-select-primitive-2:initialize-primitive: +36925 # var primitives/ebx: (addr primitive) +36926 57/push-edi +36927 68/push 0x11/imm32/alloc-id:fake +36928 68/push 0/imm32/no-x32 +36929 68/push 0/imm32/no-xm32 +36930 68/push 0/imm32/no-disp32 +36931 68/push 0/imm32/no-imm8 +36932 68/push 0/imm32/no-imm32 +36933 68/push 0/imm32/no-r32 +36934 68/push 1/imm32/rm32-is-first-inout +36935 68/push 0/imm32/subx-name +36936 68/push 0/imm32/subx-name +36937 68/push 0/imm32/no-outputs +36938 68/push 0/imm32/no-outputs +36939 53/push-ebx/inouts # hack: reuse stmt-var from call stmt as (list var) in function declaration +36940 68/push 0x11/imm32/alloc-id:fake +36941 68/push 0/imm32/name +36942 68/push 0/imm32/name +36943 89/<- %ebx 4/r32/esp +36944 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name: +36945 # primitives->name = "increment" +36946 (copy-array Heap "increment" %ebx) # Primitive-name +36947 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name: +36948 # primitives->subx-name = "ff 0/subop/increment" +36949 8d/copy-address *(ebx+0x18) 0/r32/eax # Primitive-subx-name +36950 (copy-array Heap "ff 0/subop/increment" %eax) +36951 # convert +36952 c7 0/subop/copy *Curr-block-depth 0/imm32 +36953 (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0) +36954 (flush _test-output-buffered-file) +36955 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +36961 # check output +36962 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2") +36963 # . epilogue +36964 89/<- %esp 5/r32/ebp +36965 5d/pop-to-ebp +36966 c3/return +36967 +36968 test-increment-register: +36969 # Select the right register between overloads. +36970 # foo <- increment +36971 # => +36972 # 50/increment-eax +36973 # +36974 # There's a variable on the var stack as follows: +36975 # name: 'foo' +36976 # type: int +36977 # register: 'eax' +36978 # +36979 # Primitives are the global definitions. +36980 # +36981 # . prologue +36982 55/push-ebp +36983 89/<- %ebp 4/r32/esp +36984 # setup +36985 (clear-stream _test-output-stream) +36986 (clear-stream $_test-output-buffered-file->buffer) +36987 $test-increment-register:initialize-type: +36988 # var type/ecx: (payload type-tree) = int +36989 68/push 0/imm32/right:null +36990 68/push 0/imm32/right:null +36991 68/push 0/imm32/left:unused +36992 68/push 1/imm32/value:int +36993 68/push 1/imm32/is-atom?:true 36994 68/push 0x11/imm32/alloc-id:fake:payload -36995 89/<- %edx 4/r32/esp -36996 $test-add-mem-to-reg:initialize-var2-name: -36997 # var2->name = "var2" -36998 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -36999 (copy-array Heap "var2" %eax) -37000 $test-add-mem-to-reg:initialize-inouts: -37001 # var inouts/esi: (payload stmt-var) = [var2] -37002 68/push 0/imm32/is-deref:false -37003 68/push 0/imm32/next -37004 68/push 0/imm32/next -37005 52/push-edx/var2 -37006 68/push 0x11/imm32/alloc-id:fake -37007 68/push 0x11/imm32/alloc-id:fake:payload -37008 89/<- %esi 4/r32/esp -37009 $test-add-mem-to-reg:initialize-outputs: -37010 # var outputs/edi: (payload stmt-var) = [var1] -37011 68/push 0/imm32/is-deref:false -37012 68/push 0/imm32/next -37013 68/push 0/imm32/next -37014 51/push-ecx/var1 -37015 68/push 0x11/imm32/alloc-id:fake -37016 68/push 0x11/imm32/alloc-id:fake:payload -37017 89/<- %edi 4/r32/esp -37018 $test-add-mem-to-reg:initialize-stmt: -37019 # var stmt/esi: (addr statement) +36995 89/<- %ecx 4/r32/esp +36996 $test-increment-register:initialize-var: +36997 # var var-foo/ecx: (payload var) +36998 68/push 0/imm32/register +36999 68/push 0/imm32/register +37000 68/push 0/imm32/no-stack-offset +37001 68/push 1/imm32/block-depth +37002 51/push-ecx +37003 68/push 0x11/imm32/alloc-id:fake +37004 68/push 0/imm32/name +37005 68/push 0/imm32/name +37006 68/push 0x11/imm32/alloc-id:fake:payload +37007 89/<- %ecx 4/r32/esp +37008 $test-increment-register:initialize-var-name: +37009 # var-foo->name = "foo" +37010 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37011 (copy-array Heap "foo" %eax) +37012 $test-increment-register:initialize-var-register: +37013 # var-foo->register = "eax" +37014 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37015 (copy-array Heap "eax" %eax) +37016 $test-increment-register:initialize-stmt-var: +37017 # var operand/ebx: (payload stmt-var) +37018 68/push 0/imm32/is-deref:false +37019 68/push 0/imm32/next 37020 68/push 0/imm32/next -37021 68/push 0/imm32/next -37022 57/push-edi/outputs -37023 68/push 0x11/imm32/alloc-id:fake -37024 56/push-esi/inouts -37025 68/push 0x11/imm32/alloc-id:fake -37026 68/push 0/imm32/operation -37027 68/push 0/imm32/operation -37028 68/push 1/imm32/tag:stmt1 -37029 89/<- %esi 4/r32/esp -37030 $test-add-mem-to-reg:initialize-stmt-operation: -37031 # stmt->operation = "add" -37032 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37033 (copy-array Heap "add" %eax) -37034 # convert -37035 c7 0/subop/copy *Curr-block-depth 0/imm32 -37036 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37037 (flush _test-output-buffered-file) -37038 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37044 # check output -37045 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -37046 # . epilogue -37047 89/<- %esp 5/r32/ebp -37048 5d/pop-to-ebp -37049 c3/return -37050 -37051 test-add-literal-to-eax: -37052 # var1/eax <- add 0x34 -37053 # => -37054 # 05/add-to-eax 0x34/imm32 -37055 # -37056 # . prologue -37057 55/push-ebp -37058 89/<- %ebp 4/r32/esp -37059 # setup -37060 (clear-stream _test-output-stream) -37061 (clear-stream $_test-output-buffered-file->buffer) -37062 $test-add-literal-to-eax:initialize-var-type: -37063 # var type/ecx: (payload type-tree) = int -37064 68/push 0/imm32/right:null -37065 68/push 0/imm32/right:null -37066 68/push 0/imm32/left:unused -37067 68/push 1/imm32/value:int -37068 68/push 1/imm32/is-atom?:true -37069 68/push 0x11/imm32/alloc-id:fake:payload -37070 89/<- %ecx 4/r32/esp -37071 $test-add-literal-to-eax:initialize-var: -37072 # var v/ecx: (payload var) -37073 68/push 0/imm32/register -37074 68/push 0/imm32/register -37075 68/push 0/imm32/no-stack-offset -37076 68/push 1/imm32/block-depth -37077 51/push-ecx -37078 68/push 0x11/imm32/alloc-id:fake -37079 68/push 0/imm32/name -37080 68/push 0/imm32/name -37081 68/push 0x11/imm32/alloc-id:fake:payload -37082 89/<- %ecx 4/r32/esp -37083 $test-add-literal-to-eax:initialize-var-name: -37084 # v->name = "v" -37085 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37086 (copy-array Heap "v" %eax) -37087 $test-add-literal-to-eax:initialize-var-register: -37088 # v->register = "eax" -37089 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -37090 (copy-array Heap "eax" %eax) -37091 $test-add-literal-to-eax:initialize-literal-type: -37092 # var type/edx: (payload type-tree) = literal -37093 68/push 0/imm32/right:null -37094 68/push 0/imm32/right:null -37095 68/push 0/imm32/left:unused -37096 68/push 0/imm32/value:literal -37097 68/push 1/imm32/is-atom?:true -37098 68/push 0x11/imm32/alloc-id:fake:payload -37099 89/<- %edx 4/r32/esp -37100 $test-add-literal-to-eax:initialize-literal: -37101 # var l/edx: (payload var) -37102 68/push 0/imm32/register -37103 68/push 0/imm32/register -37104 68/push 0/imm32/no-stack-offset -37105 68/push 1/imm32/block-depth -37106 52/push-edx -37107 68/push 0x11/imm32/alloc-id:fake -37108 68/push 0/imm32/name -37109 68/push 0/imm32/name -37110 68/push 0x11/imm32/alloc-id:fake:payload -37111 89/<- %edx 4/r32/esp -37112 $test-add-literal-to-eax:initialize-literal-value: -37113 # l->name = "0x34" -37114 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37115 (copy-array Heap "0x34" %eax) -37116 $test-add-literal-to-eax:initialize-inouts: -37117 # var inouts/esi: (payload stmt-var) = [l] +37021 51/push-ecx/var-foo +37022 68/push 0x11/imm32/alloc-id:fake +37023 68/push 0x11/imm32/alloc-id:fake:payload +37024 89/<- %ebx 4/r32/esp +37025 $test-increment-register:initialize-stmt: +37026 # var stmt/esi: (addr statement) +37027 53/push-ebx/outputs +37028 68/push 0x11/imm32/alloc-id:fake +37029 68/push 0/imm32/no-inouts +37030 68/push 0/imm32/no-inouts +37031 68/push 0/imm32/operation +37032 68/push 0/imm32/operation +37033 68/push 1/imm32 +37034 89/<- %esi 4/r32/esp +37035 $test-increment-register:initialize-stmt-operation: +37036 # stmt->operation = "increment" +37037 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37038 (copy-array Heap "increment" %eax) +37039 # convert +37040 c7 0/subop/copy *Curr-block-depth 0/imm32 +37041 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37042 (flush _test-output-buffered-file) +37043 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37049 # check output +37050 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +37051 # . epilogue +37052 89/<- %esp 5/r32/ebp +37053 5d/pop-to-ebp +37054 c3/return +37055 +37056 test-add-reg-to-reg: +37057 # var1/reg <- add var2/reg +37058 # => +37059 # 01/add-to %var1 var2 +37060 # +37061 # . prologue +37062 55/push-ebp +37063 89/<- %ebp 4/r32/esp +37064 # setup +37065 (clear-stream _test-output-stream) +37066 (clear-stream $_test-output-buffered-file->buffer) +37067 $test-add-reg-to-reg:initialize-type: +37068 # var type/ecx: (payload type-tree) = int +37069 68/push 0/imm32/right:null +37070 68/push 0/imm32/right:null +37071 68/push 0/imm32/left:unused +37072 68/push 1/imm32/value:int +37073 68/push 1/imm32/is-atom?:true +37074 68/push 0x11/imm32/alloc-id:fake:payload +37075 89/<- %ecx 4/r32/esp +37076 $test-add-reg-to-reg:initialize-var1: +37077 # var var1/ecx: (payload var) +37078 68/push 0/imm32/register +37079 68/push 0/imm32/register +37080 68/push 0/imm32/no-stack-offset +37081 68/push 1/imm32/block-depth +37082 51/push-ecx +37083 68/push 0x11/imm32/alloc-id:fake +37084 68/push 0/imm32/name +37085 68/push 0/imm32/name +37086 68/push 0x11/imm32/alloc-id:fake:payload +37087 89/<- %ecx 4/r32/esp +37088 $test-add-reg-to-reg:initialize-var1-name: +37089 # var1->name = "var1" +37090 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37091 (copy-array Heap "var1" %eax) +37092 $test-add-reg-to-reg:initialize-var1-register: +37093 # var1->register = "eax" +37094 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37095 (copy-array Heap "eax" %eax) +37096 $test-add-reg-to-reg:initialize-var2: +37097 # var var2/edx: (payload var) +37098 68/push 0/imm32/register +37099 68/push 0/imm32/register +37100 68/push 0/imm32/no-stack-offset +37101 68/push 1/imm32/block-depth +37102 ff 6/subop/push *(ecx+0x10) +37103 68/push 0x11/imm32/alloc-id:fake +37104 68/push 0/imm32/name +37105 68/push 0/imm32/name +37106 68/push 0x11/imm32/alloc-id:fake:payload +37107 89/<- %edx 4/r32/esp +37108 $test-add-reg-to-reg:initialize-var2-name: +37109 # var2->name = "var2" +37110 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37111 (copy-array Heap "var2" %eax) +37112 $test-add-reg-to-reg:initialize-var2-register: +37113 # var2->register = "ecx" +37114 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 +37115 (copy-array Heap "ecx" %eax) +37116 $test-add-reg-to-reg:initialize-inouts: +37117 # var inouts/esi: (payload stmt-var) = [var2] 37118 68/push 0/imm32/is-deref:false 37119 68/push 0/imm32/next 37120 68/push 0/imm32/next -37121 52/push-edx/l +37121 52/push-edx/var2 37122 68/push 0x11/imm32/alloc-id:fake 37123 68/push 0x11/imm32/alloc-id:fake:payload 37124 89/<- %esi 4/r32/esp -37125 $test-add-literal-to-eax:initialize-outputs: -37126 # var outputs/edi: (payload stmt-var) = [v] +37125 $test-add-reg-to-reg:initialize-outputs: +37126 # var outputs/edi: (payload stmt-var) = [var1] 37127 68/push 0/imm32/is-deref:false 37128 68/push 0/imm32/next 37129 68/push 0/imm32/next -37130 51/push-ecx/v +37130 51/push-ecx/var1 37131 68/push 0x11/imm32/alloc-id:fake 37132 68/push 0x11/imm32/alloc-id:fake:payload 37133 89/<- %edi 4/r32/esp -37134 $test-add-literal-to-eax:initialize-stmt: +37134 $test-add-reg-to-reg:initialize-stmt: 37135 # var stmt/esi: (addr statement) 37136 68/push 0/imm32/next 37137 68/push 0/imm32/next @@ -35478,26 +35493,26 @@ if ('onhashchange' in window) { 37143 68/push 0/imm32/operation 37144 68/push 1/imm32/tag:stmt1 37145 89/<- %esi 4/r32/esp -37146 $test-add-literal-to-eax:initialize-stmt-operation: +37146 $test-add-reg-to-reg:initialize-stmt-operation: 37147 # stmt->operation = "add" 37148 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation 37149 (copy-array Heap "add" %eax) 37150 # convert -37151 c7 0/subop/copy *Curr-block-depth 0/imm32 -37152 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37151 c7 0/subop/copy *Curr-block-depth 0/imm32 +37152 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) 37153 (flush _test-output-buffered-file) 37154 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- 37160 # check output -37161 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +37161 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") 37162 # . epilogue 37163 89/<- %esp 5/r32/ebp 37164 5d/pop-to-ebp 37165 c3/return 37166 -37167 test-add-literal-to-reg: -37168 # var1/ecx <- add 0x34 +37167 test-add-reg-to-mem: +37168 # add-to var1 var2/reg 37169 # => -37170 # 81 0/subop/add %ecx 0x34/imm32 +37170 # 01/add-to *(ebp+__) var2 37171 # 37172 # . prologue 37173 55/push-ebp @@ -35505,7 +35520,7 @@ if ('onhashchange' in window) { 37175 # setup 37176 (clear-stream _test-output-stream) 37177 (clear-stream $_test-output-buffered-file->buffer) -37178 $test-add-literal-to-reg:initialize-var-type: +37178 $test-add-reg-to-mem:initialize-type: 37179 # var type/ecx: (payload type-tree) = int 37180 68/push 0/imm32/right:null 37181 68/push 0/imm32/right:null @@ -35514,11 +35529,11 @@ if ('onhashchange' in window) { 37184 68/push 1/imm32/is-atom?:true 37185 68/push 0x11/imm32/alloc-id:fake:payload 37186 89/<- %ecx 4/r32/esp -37187 $test-add-literal-to-reg:initialize-var: -37188 # var v/ecx: (payload var) +37187 $test-add-reg-to-mem:initialize-var1: +37188 # var var1/ecx: (payload var) 37189 68/push 0/imm32/register 37190 68/push 0/imm32/register -37191 68/push 0/imm32/no-stack-offset +37191 68/push 8/imm32/stack-offset 37192 68/push 1/imm32/block-depth 37193 51/push-ecx 37194 68/push 0x11/imm32/alloc-id:fake @@ -35526,1248 +35541,1562 @@ if ('onhashchange' in window) { 37196 68/push 0/imm32/name 37197 68/push 0x11/imm32/alloc-id:fake:payload 37198 89/<- %ecx 4/r32/esp -37199 $test-add-literal-to-reg:initialize-var-name: -37200 # v->name = "v" +37199 $test-add-reg-to-mem:initialize-var1-name: +37200 # var1->name = "var1" 37201 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37202 (copy-array Heap "v" %eax) -37203 $test-add-literal-to-reg:initialize-var-register: -37204 # v->register = "ecx" -37205 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -37206 (copy-array Heap "ecx" %eax) -37207 $test-add-literal-to-reg:initialize-literal-type: -37208 # var type/edx: (payload type-tree) = literal -37209 68/push 0/imm32/right:null -37210 68/push 0/imm32/right:null -37211 68/push 0/imm32/left:unused -37212 68/push 0/imm32/value:literal -37213 68/push 1/imm32/is-atom?:true -37214 68/push 0x11/imm32/alloc-id:fake:payload -37215 89/<- %edx 4/r32/esp -37216 $test-add-literal-to-reg:initialize-literal: -37217 # var l/edx: (payload var) -37218 68/push 0/imm32/register -37219 68/push 0/imm32/register -37220 68/push 0/imm32/no-stack-offset -37221 68/push 1/imm32/block-depth -37222 52/push-edx -37223 68/push 0x11/imm32/alloc-id:fake -37224 68/push 0/imm32/name -37225 68/push 0/imm32/name -37226 68/push 0x11/imm32/alloc-id:fake:payload -37227 89/<- %edx 4/r32/esp -37228 $test-add-literal-to-reg:initialize-literal-value: -37229 # l->name = "0x34" -37230 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37231 (copy-array Heap "0x34" %eax) -37232 $test-add-literal-to-reg:initialize-inouts: -37233 # var inouts/esi: (payload stmt-var) = [l] -37234 68/push 0/imm32/is-deref:false -37235 68/push 0/imm32/next -37236 68/push 0/imm32/next -37237 52/push-edx/l -37238 68/push 0x11/imm32/alloc-id:fake -37239 68/push 0x11/imm32/alloc-id:fake:payload -37240 89/<- %esi 4/r32/esp -37241 $test-add-literal-to-reg:initialize-outputs: -37242 # var outputs/edi: (payload stmt-var) = [v] -37243 68/push 0/imm32/is-deref:false -37244 68/push 0/imm32/next -37245 68/push 0/imm32/next -37246 51/push-ecx/v +37202 (copy-array Heap "var1" %eax) +37203 $test-add-reg-to-mem:initialize-var2: +37204 # var var2/edx: (payload var) +37205 68/push 0/imm32/register +37206 68/push 0/imm32/register +37207 68/push 0/imm32/no-stack-offset +37208 68/push 1/imm32/block-depth +37209 ff 6/subop/push *(ecx+0x10) +37210 68/push 0x11/imm32/alloc-id:fake +37211 68/push 0/imm32/name +37212 68/push 0/imm32/name +37213 68/push 0x11/imm32/alloc-id:fake:payload +37214 89/<- %edx 4/r32/esp +37215 $test-add-reg-to-mem:initialize-var2-name: +37216 # var2->name = "var2" +37217 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37218 (copy-array Heap "var2" %eax) +37219 $test-add-reg-to-mem:initialize-var2-register: +37220 # var2->register = "ecx" +37221 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 +37222 (copy-array Heap "ecx" %eax) +37223 $test-add-reg-to-mem:initialize-inouts: +37224 # var inouts/esi: (payload stmt-var) = [var2] +37225 68/push 0/imm32/is-deref:false +37226 68/push 0/imm32/next +37227 68/push 0/imm32/next +37228 52/push-edx/var2 +37229 68/push 0x11/imm32/alloc-id:fake +37230 68/push 0x11/imm32/alloc-id:fake:payload +37231 89/<- %esi 4/r32/esp +37232 # inouts = [var1, var2] +37233 68/push 0/imm32/is-deref:false +37234 56/push-esi/next +37235 68/push 0x11/imm32/alloc-id:fake +37236 51/push-ecx/var1 +37237 68/push 0x11/imm32/alloc-id:fake +37238 68/push 0x11/imm32/alloc-id:fake:payload +37239 89/<- %esi 4/r32/esp +37240 $test-add-reg-to-mem:initialize-stmt: +37241 # var stmt/esi: (addr statement) +37242 68/push 0/imm32/next +37243 68/push 0/imm32/next +37244 68/push 0/imm32/outputs +37245 68/push 0/imm32/outputs +37246 56/push-esi/inouts 37247 68/push 0x11/imm32/alloc-id:fake -37248 68/push 0x11/imm32/alloc-id:fake:payload -37249 89/<- %edi 4/r32/esp -37250 $test-add-literal-to-reg:initialize-stmt: -37251 # var stmt/esi: (addr statement) -37252 68/push 0/imm32/next -37253 68/push 0/imm32/next -37254 57/push-edi/outputs -37255 68/push 0x11/imm32/alloc-id:fake -37256 56/push-esi/inouts -37257 68/push 0x11/imm32/alloc-id:fake -37258 68/push 0/imm32/operation -37259 68/push 0/imm32/operation -37260 68/push 1/imm32/tag:stmt1 -37261 89/<- %esi 4/r32/esp -37262 $test-add-literal-to-reg:initialize-stmt-operation: -37263 # stmt->operation = "add" -37264 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37265 (copy-array Heap "add" %eax) -37266 # convert -37267 c7 0/subop/copy *Curr-block-depth 0/imm32 -37268 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37269 (flush _test-output-buffered-file) -37270 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37276 # check output -37277 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -37278 # . epilogue -37279 89/<- %esp 5/r32/ebp -37280 5d/pop-to-ebp -37281 c3/return -37282 -37283 test-add-literal-to-mem: -37284 # add-to var1, 0x34 -37285 # => -37286 # 81 0/subop/add %eax 0x34/imm32 -37287 # -37288 # . prologue -37289 55/push-ebp -37290 89/<- %ebp 4/r32/esp -37291 # setup -37292 (clear-stream _test-output-stream) -37293 (clear-stream $_test-output-buffered-file->buffer) -37294 $test-add-literal-to-mem:initialize-type: -37295 # var type/ecx: (payload type-tree) = int -37296 68/push 0/imm32/right:null -37297 68/push 0/imm32/right:null -37298 68/push 0/imm32/left:unused -37299 68/push 1/imm32/value:int -37300 68/push 1/imm32/is-atom?:true -37301 68/push 0x11/imm32/alloc-id:fake:payload -37302 89/<- %ecx 4/r32/esp -37303 $test-add-literal-to-mem:initialize-var1: -37304 # var var1/ecx: (payload var) -37305 68/push 0/imm32/register -37306 68/push 0/imm32/register -37307 68/push 8/imm32/stack-offset -37308 68/push 1/imm32/block-depth -37309 51/push-ecx -37310 68/push 0x11/imm32/alloc-id:fake -37311 68/push 0/imm32/name -37312 68/push 0/imm32/name -37313 68/push 0x11/imm32/alloc-id:fake:payload -37314 89/<- %ecx 4/r32/esp -37315 $test-add-literal-to-mem:initialize-var1-name: -37316 # var1->name = "var1" -37317 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37318 (copy-array Heap "var1" %eax) -37319 $test-add-literal-to-mem:initialize-literal-type: -37320 # var type/edx: (payload type-tree) = literal -37321 68/push 0/imm32/right:null -37322 68/push 0/imm32/right:null -37323 68/push 0/imm32/left:unused -37324 68/push 0/imm32/value:literal -37325 68/push 1/imm32/is-atom?:true -37326 68/push 0x11/imm32/alloc-id:fake:payload -37327 89/<- %edx 4/r32/esp -37328 $test-add-literal-to-mem:initialize-literal: -37329 # var l/edx: (payload var) -37330 68/push 0/imm32/register -37331 68/push 0/imm32/register -37332 68/push 0/imm32/no-stack-offset -37333 68/push 1/imm32/block-depth -37334 52/push-edx +37248 68/push 0/imm32/operation +37249 68/push 0/imm32/operation +37250 68/push 1/imm32/tag:stmt1 +37251 89/<- %esi 4/r32/esp +37252 $test-add-reg-to-mem:initialize-stmt-operation: +37253 # stmt->operation = "add-to" +37254 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37255 (copy-array Heap "add-to" %eax) +37256 # convert +37257 c7 0/subop/copy *Curr-block-depth 0/imm32 +37258 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37259 (flush _test-output-buffered-file) +37260 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37266 # check output +37267 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +37268 # . epilogue +37269 89/<- %esp 5/r32/ebp +37270 5d/pop-to-ebp +37271 c3/return +37272 +37273 test-add-mem-to-reg: +37274 # var1/reg <- add var2 +37275 # => +37276 # 03/add *(ebp+__) var1 +37277 # +37278 # . prologue +37279 55/push-ebp +37280 89/<- %ebp 4/r32/esp +37281 # setup +37282 (clear-stream _test-output-stream) +37283 (clear-stream $_test-output-buffered-file->buffer) +37284 $test-add-mem-to-reg:initialize-type: +37285 # var type/ecx: (payload type-tree) = int +37286 68/push 0/imm32/right:null +37287 68/push 0/imm32/right:null +37288 68/push 0/imm32/left:unused +37289 68/push 1/imm32/value:int +37290 68/push 1/imm32/is-atom?:true +37291 68/push 0x11/imm32/alloc-id:fake:payload +37292 89/<- %ecx 4/r32/esp +37293 $test-add-mem-to-reg:initialize-var: +37294 # var var1/ecx: (payload var) +37295 68/push 0/imm32/register +37296 68/push 0/imm32/register +37297 68/push 0/imm32/no-stack-offset +37298 68/push 1/imm32/block-depth +37299 51/push-ecx +37300 68/push 0x11/imm32/alloc-id:fake +37301 68/push 0/imm32/name +37302 68/push 0/imm32/name +37303 68/push 0x11/imm32/alloc-id:fake:payload +37304 89/<- %ecx 4/r32/esp +37305 $test-add-mem-to-reg:initialize-var-name: +37306 # var1->name = "foo" +37307 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37308 (copy-array Heap "var1" %eax) +37309 $test-add-mem-to-reg:initialize-var-register: +37310 # var1->register = "eax" +37311 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37312 (copy-array Heap "eax" %eax) +37313 $test-add-mem-to-reg:initialize-var2: +37314 # var var2/edx: (payload var) +37315 68/push 0/imm32/register +37316 68/push 0/imm32/register +37317 68/push 8/imm32/stack-offset +37318 68/push 1/imm32/block-depth +37319 ff 6/subop/push *(ecx+0x10) +37320 68/push 0x11/imm32/alloc-id:fake +37321 68/push 0/imm32/name +37322 68/push 0/imm32/name +37323 68/push 0x11/imm32/alloc-id:fake:payload +37324 89/<- %edx 4/r32/esp +37325 $test-add-mem-to-reg:initialize-var2-name: +37326 # var2->name = "var2" +37327 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37328 (copy-array Heap "var2" %eax) +37329 $test-add-mem-to-reg:initialize-inouts: +37330 # var inouts/esi: (payload stmt-var) = [var2] +37331 68/push 0/imm32/is-deref:false +37332 68/push 0/imm32/next +37333 68/push 0/imm32/next +37334 52/push-edx/var2 37335 68/push 0x11/imm32/alloc-id:fake -37336 68/push 0/imm32/name -37337 68/push 0/imm32/name -37338 68/push 0x11/imm32/alloc-id:fake:payload -37339 89/<- %edx 4/r32/esp -37340 $test-add-literal-to-mem:initialize-literal-value: -37341 # l->name = "0x34" -37342 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37343 (copy-array Heap "0x34" %eax) -37344 $test-add-literal-to-mem:initialize-inouts: -37345 # var inouts/esi: (payload stmt-var) = [l] -37346 68/push 0/imm32/is-deref:false -37347 68/push 0/imm32/next -37348 68/push 0/imm32/next -37349 52/push-edx/l -37350 68/push 0x11/imm32/alloc-id:fake -37351 68/push 0x11/imm32/alloc-id:fake:payload -37352 89/<- %esi 4/r32/esp -37353 # var inouts = (handle stmt-var) = [var1, var2] -37354 68/push 0/imm32/is-deref:false -37355 56/push-esi/next -37356 68/push 0x11/imm32/alloc-id:fake -37357 51/push-ecx/var1 -37358 68/push 0x11/imm32/alloc-id:fake -37359 68/push 0x11/imm32/alloc-id:fake:payload -37360 89/<- %esi 4/r32/esp -37361 $test-add-literal-to-mem:initialize-stmt: -37362 # var stmt/esi: (addr statement) -37363 68/push 0/imm32/next -37364 68/push 0/imm32/next -37365 68/push 0/imm32/outputs -37366 68/push 0/imm32/outputs -37367 56/push-esi/inouts -37368 68/push 0x11/imm32/alloc-id:fake -37369 68/push 0/imm32/operation -37370 68/push 0/imm32/operation -37371 68/push 1/imm32/tag:stmt1 -37372 89/<- %esi 4/r32/esp -37373 $test-add-literal-to-mem:initialize-stmt-operation: -37374 # stmt->operation = "add-to" -37375 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37376 (copy-array Heap "add-to" %eax) -37377 # convert -37378 c7 0/subop/copy *Curr-block-depth 0/imm32 -37379 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37380 (flush _test-output-buffered-file) -37381 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37387 # check output -37388 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -37389 # . epilogue -37390 89/<- %esp 5/r32/ebp -37391 5d/pop-to-ebp -37392 c3/return -37393 -37394 test-shift-reg-by-literal: -37395 # var1/ecx <- shift-left 2 -37396 # => -37397 # c1/shift 4/subop/left %ecx 2/imm8 -37398 # -37399 # . prologue -37400 55/push-ebp -37401 89/<- %ebp 4/r32/esp -37402 # setup -37403 (clear-stream _test-output-stream) -37404 (clear-stream $_test-output-buffered-file->buffer) -37405 $test-shift-reg-by-literal:initialize-var-type: -37406 # var type/ecx: (payload type-tree) = int -37407 68/push 0/imm32/right:null -37408 68/push 0/imm32/right:null -37409 68/push 0/imm32/left:unused -37410 68/push 1/imm32/value:int -37411 68/push 1/imm32/is-atom?:true -37412 68/push 0x11/imm32/alloc-id:fake:payload -37413 89/<- %ecx 4/r32/esp -37414 $test-shift-reg-by-literal:initialize-var: -37415 # var v/ecx: (payload var) -37416 68/push 0/imm32/register -37417 68/push 0/imm32/register -37418 68/push 0/imm32/no-stack-offset -37419 68/push 1/imm32/block-depth -37420 51/push-ecx -37421 68/push 0x11/imm32/alloc-id:fake -37422 68/push 0/imm32/name -37423 68/push 0/imm32/name -37424 68/push 0x11/imm32/alloc-id:fake:payload -37425 89/<- %ecx 4/r32/esp -37426 $test-shift-reg-by-literal:initialize-var-name: -37427 # v->name = "v" -37428 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37429 (copy-array Heap "v" %eax) -37430 $test-shift-reg-by-literal:initialize-var-register: -37431 # v->register = "ecx" -37432 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -37433 (copy-array Heap "ecx" %eax) -37434 $test-shift-reg-by-literal:initialize-literal-type: -37435 # var type/edx: (payload type-tree) = literal -37436 68/push 0/imm32/right:null -37437 68/push 0/imm32/right:null -37438 68/push 0/imm32/left:unused -37439 68/push 0/imm32/value:literal -37440 68/push 1/imm32/is-atom?:true -37441 68/push 0x11/imm32/alloc-id:fake:payload -37442 89/<- %edx 4/r32/esp -37443 $test-shift-reg-by-literal:initialize-literal: -37444 # var l/edx: (payload var) -37445 68/push 0/imm32/register -37446 68/push 0/imm32/register -37447 68/push 0/imm32/no-stack-offset -37448 68/push 1/imm32/block-depth -37449 52/push-edx -37450 68/push 0x11/imm32/alloc-id:fake -37451 68/push 0/imm32/name -37452 68/push 0/imm32/name -37453 68/push 0x11/imm32/alloc-id:fake:payload -37454 89/<- %edx 4/r32/esp -37455 $test-shift-reg-by-literal:initialize-literal-value: -37456 # l->name = "2" -37457 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37458 (copy-array Heap "2" %eax) -37459 $test-shift-reg-by-literal:initialize-inouts: -37460 # var inouts/esi: (payload stmt-var) = [l] -37461 68/push 0/imm32/is-deref:false -37462 68/push 0/imm32/next -37463 68/push 0/imm32/next -37464 52/push-edx/l -37465 68/push 0x11/imm32/alloc-id:fake -37466 68/push 0x11/imm32/alloc-id:fake:payload -37467 89/<- %esi 4/r32/esp -37468 $test-shift-reg-by-literal:initialize-outputs: -37469 # var outputs/edi: (payload stmt-var) = [v] -37470 68/push 0/imm32/is-deref:false -37471 68/push 0/imm32/next -37472 68/push 0/imm32/next -37473 51/push-ecx/v -37474 68/push 0x11/imm32/alloc-id:fake -37475 68/push 0x11/imm32/alloc-id:fake:payload -37476 89/<- %edi 4/r32/esp -37477 $test-shift-reg-by-literal:initialize-stmt: -37478 # var stmt/esi: (addr statement) -37479 68/push 0/imm32/next -37480 68/push 0/imm32/next -37481 57/push-edi/outputs -37482 68/push 0x11/imm32/alloc-id:fake -37483 56/push-esi/inouts -37484 68/push 0x11/imm32/alloc-id:fake -37485 68/push 0/imm32/operation -37486 68/push 0/imm32/operation -37487 68/push 1/imm32/tag:stmt1 -37488 89/<- %esi 4/r32/esp -37489 $test-shift-reg-by-literal:initialize-stmt-operation: -37490 # stmt->operation = "shift-left" -37491 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37492 (copy-array Heap "shift-left" %eax) -37493 # convert -37494 c7 0/subop/copy *Curr-block-depth 0/imm32 -37495 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37496 (flush _test-output-buffered-file) -37497 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37503 # check output -37504 (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal") -37505 # . epilogue -37506 89/<- %esp 5/r32/ebp -37507 5d/pop-to-ebp -37508 c3/return -37509 -37510 test-shift-mem-by-literal: -37511 # shift-left var 3 -37512 # => -37513 # c1/shift 4/subop/left *(ebp+8) 3/imm8 -37514 # -37515 # . prologue -37516 55/push-ebp -37517 89/<- %ebp 4/r32/esp -37518 # setup -37519 (clear-stream _test-output-stream) -37520 (clear-stream $_test-output-buffered-file->buffer) -37521 $test-shift-mem-by-literal:initialize-type: -37522 # var type/ecx: (payload type-tree) = int -37523 68/push 0/imm32/right:null -37524 68/push 0/imm32/right:null -37525 68/push 0/imm32/left:unused -37526 68/push 1/imm32/value:int -37527 68/push 1/imm32/is-atom?:true -37528 68/push 0x11/imm32/alloc-id:fake:payload -37529 89/<- %ecx 4/r32/esp -37530 $test-shift-mem-by-literal:initialize-var1: -37531 # var var1/ecx: (payload var) -37532 68/push 0/imm32/register -37533 68/push 0/imm32/register -37534 68/push 8/imm32/stack-offset -37535 68/push 1/imm32/block-depth -37536 51/push-ecx -37537 68/push 0x11/imm32/alloc-id:fake -37538 68/push 0/imm32/name -37539 68/push 0/imm32/name -37540 68/push 0x11/imm32/alloc-id:fake:payload -37541 89/<- %ecx 4/r32/esp -37542 $test-shift-mem-by-literal:initialize-var1-name: -37543 # var1->name = "var1" -37544 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37545 (copy-array Heap "var1" %eax) -37546 $test-shift-mem-by-literal:initialize-literal-type: -37547 # var type/edx: (payload type-tree) = literal -37548 68/push 0/imm32/right:null -37549 68/push 0/imm32/right:null -37550 68/push 0/imm32/left:unused -37551 68/push 0/imm32/value:literal -37552 68/push 1/imm32/is-atom?:true -37553 68/push 0x11/imm32/alloc-id:fake:payload -37554 89/<- %edx 4/r32/esp -37555 $test-shift-mem-by-literal:initialize-literal: -37556 # var l/edx: (payload var) -37557 68/push 0/imm32/register -37558 68/push 0/imm32/register -37559 68/push 0/imm32/no-stack-offset -37560 68/push 1/imm32/block-depth -37561 52/push-edx -37562 68/push 0x11/imm32/alloc-id:fake -37563 68/push 0/imm32/name -37564 68/push 0/imm32/name -37565 68/push 0x11/imm32/alloc-id:fake:payload -37566 89/<- %edx 4/r32/esp -37567 $test-shift-mem-by-literal:initialize-literal-value: -37568 # l->name = "3" -37569 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37570 (copy-array Heap "3" %eax) -37571 $test-shift-mem-by-literal:initialize-inouts: -37572 # var inouts/esi: (payload stmt-var) = [l] -37573 68/push 0/imm32/is-deref:false +37336 68/push 0x11/imm32/alloc-id:fake:payload +37337 89/<- %esi 4/r32/esp +37338 $test-add-mem-to-reg:initialize-outputs: +37339 # var outputs/edi: (payload stmt-var) = [var1] +37340 68/push 0/imm32/is-deref:false +37341 68/push 0/imm32/next +37342 68/push 0/imm32/next +37343 51/push-ecx/var1 +37344 68/push 0x11/imm32/alloc-id:fake +37345 68/push 0x11/imm32/alloc-id:fake:payload +37346 89/<- %edi 4/r32/esp +37347 $test-add-mem-to-reg:initialize-stmt: +37348 # var stmt/esi: (addr statement) +37349 68/push 0/imm32/next +37350 68/push 0/imm32/next +37351 57/push-edi/outputs +37352 68/push 0x11/imm32/alloc-id:fake +37353 56/push-esi/inouts +37354 68/push 0x11/imm32/alloc-id:fake +37355 68/push 0/imm32/operation +37356 68/push 0/imm32/operation +37357 68/push 1/imm32/tag:stmt1 +37358 89/<- %esi 4/r32/esp +37359 $test-add-mem-to-reg:initialize-stmt-operation: +37360 # stmt->operation = "add" +37361 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37362 (copy-array Heap "add" %eax) +37363 # convert +37364 c7 0/subop/copy *Curr-block-depth 0/imm32 +37365 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37366 (flush _test-output-buffered-file) +37367 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37373 # check output +37374 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +37375 # . epilogue +37376 89/<- %esp 5/r32/ebp +37377 5d/pop-to-ebp +37378 c3/return +37379 +37380 test-add-literal-to-eax: +37381 # var1/eax <- add 0x34 +37382 # => +37383 # 05/add-to-eax 0x34/imm32 +37384 # +37385 # . prologue +37386 55/push-ebp +37387 89/<- %ebp 4/r32/esp +37388 # setup +37389 (clear-stream _test-output-stream) +37390 (clear-stream $_test-output-buffered-file->buffer) +37391 $test-add-literal-to-eax:initialize-var-type: +37392 # var type/ecx: (payload type-tree) = int +37393 68/push 0/imm32/right:null +37394 68/push 0/imm32/right:null +37395 68/push 0/imm32/left:unused +37396 68/push 1/imm32/value:int +37397 68/push 1/imm32/is-atom?:true +37398 68/push 0x11/imm32/alloc-id:fake:payload +37399 89/<- %ecx 4/r32/esp +37400 $test-add-literal-to-eax:initialize-var: +37401 # var v/ecx: (payload var) +37402 68/push 0/imm32/register +37403 68/push 0/imm32/register +37404 68/push 0/imm32/no-stack-offset +37405 68/push 1/imm32/block-depth +37406 51/push-ecx +37407 68/push 0x11/imm32/alloc-id:fake +37408 68/push 0/imm32/name +37409 68/push 0/imm32/name +37410 68/push 0x11/imm32/alloc-id:fake:payload +37411 89/<- %ecx 4/r32/esp +37412 $test-add-literal-to-eax:initialize-var-name: +37413 # v->name = "v" +37414 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37415 (copy-array Heap "v" %eax) +37416 $test-add-literal-to-eax:initialize-var-register: +37417 # v->register = "eax" +37418 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37419 (copy-array Heap "eax" %eax) +37420 $test-add-literal-to-eax:initialize-literal-type: +37421 # var type/edx: (payload type-tree) = literal +37422 68/push 0/imm32/right:null +37423 68/push 0/imm32/right:null +37424 68/push 0/imm32/left:unused +37425 68/push 0/imm32/value:literal +37426 68/push 1/imm32/is-atom?:true +37427 68/push 0x11/imm32/alloc-id:fake:payload +37428 89/<- %edx 4/r32/esp +37429 $test-add-literal-to-eax:initialize-literal: +37430 # var l/edx: (payload var) +37431 68/push 0/imm32/register +37432 68/push 0/imm32/register +37433 68/push 0/imm32/no-stack-offset +37434 68/push 1/imm32/block-depth +37435 52/push-edx +37436 68/push 0x11/imm32/alloc-id:fake +37437 68/push 0/imm32/name +37438 68/push 0/imm32/name +37439 68/push 0x11/imm32/alloc-id:fake:payload +37440 89/<- %edx 4/r32/esp +37441 $test-add-literal-to-eax:initialize-literal-value: +37442 # l->name = "0x34" +37443 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37444 (copy-array Heap "0x34" %eax) +37445 $test-add-literal-to-eax:initialize-inouts: +37446 # var inouts/esi: (payload stmt-var) = [l] +37447 68/push 0/imm32/is-deref:false +37448 68/push 0/imm32/next +37449 68/push 0/imm32/next +37450 52/push-edx/l +37451 68/push 0x11/imm32/alloc-id:fake +37452 68/push 0x11/imm32/alloc-id:fake:payload +37453 89/<- %esi 4/r32/esp +37454 $test-add-literal-to-eax:initialize-outputs: +37455 # var outputs/edi: (payload stmt-var) = [v] +37456 68/push 0/imm32/is-deref:false +37457 68/push 0/imm32/next +37458 68/push 0/imm32/next +37459 51/push-ecx/v +37460 68/push 0x11/imm32/alloc-id:fake +37461 68/push 0x11/imm32/alloc-id:fake:payload +37462 89/<- %edi 4/r32/esp +37463 $test-add-literal-to-eax:initialize-stmt: +37464 # var stmt/esi: (addr statement) +37465 68/push 0/imm32/next +37466 68/push 0/imm32/next +37467 57/push-edi/outputs +37468 68/push 0x11/imm32/alloc-id:fake +37469 56/push-esi/inouts +37470 68/push 0x11/imm32/alloc-id:fake +37471 68/push 0/imm32/operation +37472 68/push 0/imm32/operation +37473 68/push 1/imm32/tag:stmt1 +37474 89/<- %esi 4/r32/esp +37475 $test-add-literal-to-eax:initialize-stmt-operation: +37476 # stmt->operation = "add" +37477 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37478 (copy-array Heap "add" %eax) +37479 # convert +37480 c7 0/subop/copy *Curr-block-depth 0/imm32 +37481 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37482 (flush _test-output-buffered-file) +37483 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37489 # check output +37490 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +37491 # . epilogue +37492 89/<- %esp 5/r32/ebp +37493 5d/pop-to-ebp +37494 c3/return +37495 +37496 test-add-literal-to-reg: +37497 # var1/ecx <- add 0x34 +37498 # => +37499 # 81 0/subop/add %ecx 0x34/imm32 +37500 # +37501 # . prologue +37502 55/push-ebp +37503 89/<- %ebp 4/r32/esp +37504 # setup +37505 (clear-stream _test-output-stream) +37506 (clear-stream $_test-output-buffered-file->buffer) +37507 $test-add-literal-to-reg:initialize-var-type: +37508 # var type/ecx: (payload type-tree) = int +37509 68/push 0/imm32/right:null +37510 68/push 0/imm32/right:null +37511 68/push 0/imm32/left:unused +37512 68/push 1/imm32/value:int +37513 68/push 1/imm32/is-atom?:true +37514 68/push 0x11/imm32/alloc-id:fake:payload +37515 89/<- %ecx 4/r32/esp +37516 $test-add-literal-to-reg:initialize-var: +37517 # var v/ecx: (payload var) +37518 68/push 0/imm32/register +37519 68/push 0/imm32/register +37520 68/push 0/imm32/no-stack-offset +37521 68/push 1/imm32/block-depth +37522 51/push-ecx +37523 68/push 0x11/imm32/alloc-id:fake +37524 68/push 0/imm32/name +37525 68/push 0/imm32/name +37526 68/push 0x11/imm32/alloc-id:fake:payload +37527 89/<- %ecx 4/r32/esp +37528 $test-add-literal-to-reg:initialize-var-name: +37529 # v->name = "v" +37530 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37531 (copy-array Heap "v" %eax) +37532 $test-add-literal-to-reg:initialize-var-register: +37533 # v->register = "ecx" +37534 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37535 (copy-array Heap "ecx" %eax) +37536 $test-add-literal-to-reg:initialize-literal-type: +37537 # var type/edx: (payload type-tree) = literal +37538 68/push 0/imm32/right:null +37539 68/push 0/imm32/right:null +37540 68/push 0/imm32/left:unused +37541 68/push 0/imm32/value:literal +37542 68/push 1/imm32/is-atom?:true +37543 68/push 0x11/imm32/alloc-id:fake:payload +37544 89/<- %edx 4/r32/esp +37545 $test-add-literal-to-reg:initialize-literal: +37546 # var l/edx: (payload var) +37547 68/push 0/imm32/register +37548 68/push 0/imm32/register +37549 68/push 0/imm32/no-stack-offset +37550 68/push 1/imm32/block-depth +37551 52/push-edx +37552 68/push 0x11/imm32/alloc-id:fake +37553 68/push 0/imm32/name +37554 68/push 0/imm32/name +37555 68/push 0x11/imm32/alloc-id:fake:payload +37556 89/<- %edx 4/r32/esp +37557 $test-add-literal-to-reg:initialize-literal-value: +37558 # l->name = "0x34" +37559 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37560 (copy-array Heap "0x34" %eax) +37561 $test-add-literal-to-reg:initialize-inouts: +37562 # var inouts/esi: (payload stmt-var) = [l] +37563 68/push 0/imm32/is-deref:false +37564 68/push 0/imm32/next +37565 68/push 0/imm32/next +37566 52/push-edx/l +37567 68/push 0x11/imm32/alloc-id:fake +37568 68/push 0x11/imm32/alloc-id:fake:payload +37569 89/<- %esi 4/r32/esp +37570 $test-add-literal-to-reg:initialize-outputs: +37571 # var outputs/edi: (payload stmt-var) = [v] +37572 68/push 0/imm32/is-deref:false +37573 68/push 0/imm32/next 37574 68/push 0/imm32/next -37575 68/push 0/imm32/next -37576 52/push-edx/l -37577 68/push 0x11/imm32/alloc-id:fake -37578 68/push 0x11/imm32/alloc-id:fake:payload -37579 89/<- %esi 4/r32/esp -37580 # var inouts = (handle stmt-var) = [var1, var2] -37581 68/push 0/imm32/is-deref:false -37582 56/push-esi/next -37583 68/push 0x11/imm32/alloc-id:fake -37584 51/push-ecx/var1 -37585 68/push 0x11/imm32/alloc-id:fake -37586 68/push 0x11/imm32/alloc-id:fake:payload -37587 89/<- %esi 4/r32/esp -37588 $test-shift-mem-by-literal:initialize-stmt: -37589 # var stmt/esi: (addr statement) -37590 68/push 0/imm32/next -37591 68/push 0/imm32/next -37592 68/push 0/imm32/outputs -37593 68/push 0/imm32/outputs -37594 56/push-esi/inouts -37595 68/push 0x11/imm32/alloc-id:fake -37596 68/push 0/imm32/operation -37597 68/push 0/imm32/operation -37598 68/push 1/imm32/tag:stmt1 -37599 89/<- %esi 4/r32/esp -37600 $test-shift-mem-by-literal:initialize-stmt-operation: -37601 # stmt->operation = "shift-left" -37602 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37603 (copy-array Heap "shift-left" %eax) -37604 # convert -37605 c7 0/subop/copy *Curr-block-depth 0/imm32 -37606 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37607 (flush _test-output-buffered-file) -37608 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37614 # check output -37615 (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal") -37616 # . epilogue -37617 89/<- %esp 5/r32/ebp -37618 5d/pop-to-ebp -37619 c3/return -37620 -37621 test-compare-reg-with-reg: -37622 # compare var1/ecx, var2/eax -37623 # => -37624 # 39/compare %ecx 0/r32/eax -37625 # -37626 # . prologue -37627 55/push-ebp -37628 89/<- %ebp 4/r32/esp -37629 # setup -37630 (clear-stream _test-output-stream) -37631 (clear-stream $_test-output-buffered-file->buffer) -37632 $test-compare-reg-with-reg:initialize-type: -37633 # var type/ecx: (payload type-tree) = int -37634 68/push 0/imm32/right:null -37635 68/push 0/imm32/right:null -37636 68/push 0/imm32/left:unused -37637 68/push 1/imm32/value:int -37638 68/push 1/imm32/is-atom?:true -37639 68/push 0x11/imm32/alloc-id:fake:payload -37640 89/<- %ecx 4/r32/esp -37641 $test-compare-reg-with-reg:initialize-var1: -37642 # var var1/ecx: (payload var) -37643 68/push 0/imm32/register -37644 68/push 0/imm32/register -37645 68/push 0/imm32/no-stack-offset -37646 68/push 1/imm32/block-depth -37647 51/push-ecx -37648 68/push 0x11/imm32/alloc-id:fake -37649 68/push 0/imm32/name -37650 68/push 0/imm32/name -37651 68/push 0x11/imm32/alloc-id:fake:payload -37652 89/<- %ecx 4/r32/esp -37653 $test-compare-reg-with-reg:initialize-var1-name: -37654 # var1->name = "var1" -37655 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37656 (copy-array Heap "var1" %eax) -37657 $test-compare-reg-with-reg:initialize-var1-register: -37658 # var1->register = "ecx" -37659 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -37660 (copy-array Heap "ecx" %eax) -37661 $test-compare-reg-with-reg:initialize-var2: -37662 # var var2/edx: (payload var) -37663 68/push 0/imm32/register -37664 68/push 0/imm32/register -37665 68/push 0/imm32/no-stack-offset -37666 68/push 1/imm32/block-depth -37667 ff 6/subop/push *(ecx+0x10) -37668 68/push 0x11/imm32/alloc-id:fake -37669 68/push 0/imm32/name -37670 68/push 0/imm32/name -37671 68/push 0x11/imm32/alloc-id:fake:payload -37672 89/<- %edx 4/r32/esp -37673 $test-compare-reg-with-reg:initialize-var2-name: -37674 # var2->name = "var2" -37675 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37676 (copy-array Heap "var2" %eax) -37677 $test-compare-reg-with-reg:initialize-var2-register: -37678 # var2->register = "eax" -37679 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 -37680 (copy-array Heap "eax" %eax) -37681 $test-compare-reg-with-reg:initialize-inouts: -37682 # var inouts/esi: (payload stmt-var) = [var2] +37575 51/push-ecx/v +37576 68/push 0x11/imm32/alloc-id:fake +37577 68/push 0x11/imm32/alloc-id:fake:payload +37578 89/<- %edi 4/r32/esp +37579 $test-add-literal-to-reg:initialize-stmt: +37580 # var stmt/esi: (addr statement) +37581 68/push 0/imm32/next +37582 68/push 0/imm32/next +37583 57/push-edi/outputs +37584 68/push 0x11/imm32/alloc-id:fake +37585 56/push-esi/inouts +37586 68/push 0x11/imm32/alloc-id:fake +37587 68/push 0/imm32/operation +37588 68/push 0/imm32/operation +37589 68/push 1/imm32/tag:stmt1 +37590 89/<- %esi 4/r32/esp +37591 $test-add-literal-to-reg:initialize-stmt-operation: +37592 # stmt->operation = "add" +37593 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37594 (copy-array Heap "add" %eax) +37595 # convert +37596 c7 0/subop/copy *Curr-block-depth 0/imm32 +37597 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37598 (flush _test-output-buffered-file) +37599 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37605 # check output +37606 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +37607 # . epilogue +37608 89/<- %esp 5/r32/ebp +37609 5d/pop-to-ebp +37610 c3/return +37611 +37612 test-add-literal-to-mem: +37613 # add-to var1, 0x34 +37614 # => +37615 # 81 0/subop/add %eax 0x34/imm32 +37616 # +37617 # . prologue +37618 55/push-ebp +37619 89/<- %ebp 4/r32/esp +37620 # setup +37621 (clear-stream _test-output-stream) +37622 (clear-stream $_test-output-buffered-file->buffer) +37623 $test-add-literal-to-mem:initialize-type: +37624 # var type/ecx: (payload type-tree) = int +37625 68/push 0/imm32/right:null +37626 68/push 0/imm32/right:null +37627 68/push 0/imm32/left:unused +37628 68/push 1/imm32/value:int +37629 68/push 1/imm32/is-atom?:true +37630 68/push 0x11/imm32/alloc-id:fake:payload +37631 89/<- %ecx 4/r32/esp +37632 $test-add-literal-to-mem:initialize-var1: +37633 # var var1/ecx: (payload var) +37634 68/push 0/imm32/register +37635 68/push 0/imm32/register +37636 68/push 8/imm32/stack-offset +37637 68/push 1/imm32/block-depth +37638 51/push-ecx +37639 68/push 0x11/imm32/alloc-id:fake +37640 68/push 0/imm32/name +37641 68/push 0/imm32/name +37642 68/push 0x11/imm32/alloc-id:fake:payload +37643 89/<- %ecx 4/r32/esp +37644 $test-add-literal-to-mem:initialize-var1-name: +37645 # var1->name = "var1" +37646 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37647 (copy-array Heap "var1" %eax) +37648 $test-add-literal-to-mem:initialize-literal-type: +37649 # var type/edx: (payload type-tree) = literal +37650 68/push 0/imm32/right:null +37651 68/push 0/imm32/right:null +37652 68/push 0/imm32/left:unused +37653 68/push 0/imm32/value:literal +37654 68/push 1/imm32/is-atom?:true +37655 68/push 0x11/imm32/alloc-id:fake:payload +37656 89/<- %edx 4/r32/esp +37657 $test-add-literal-to-mem:initialize-literal: +37658 # var l/edx: (payload var) +37659 68/push 0/imm32/register +37660 68/push 0/imm32/register +37661 68/push 0/imm32/no-stack-offset +37662 68/push 1/imm32/block-depth +37663 52/push-edx +37664 68/push 0x11/imm32/alloc-id:fake +37665 68/push 0/imm32/name +37666 68/push 0/imm32/name +37667 68/push 0x11/imm32/alloc-id:fake:payload +37668 89/<- %edx 4/r32/esp +37669 $test-add-literal-to-mem:initialize-literal-value: +37670 # l->name = "0x34" +37671 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37672 (copy-array Heap "0x34" %eax) +37673 $test-add-literal-to-mem:initialize-inouts: +37674 # var inouts/esi: (payload stmt-var) = [l] +37675 68/push 0/imm32/is-deref:false +37676 68/push 0/imm32/next +37677 68/push 0/imm32/next +37678 52/push-edx/l +37679 68/push 0x11/imm32/alloc-id:fake +37680 68/push 0x11/imm32/alloc-id:fake:payload +37681 89/<- %esi 4/r32/esp +37682 # var inouts = (handle stmt-var) = [var1, var2] 37683 68/push 0/imm32/is-deref:false -37684 68/push 0/imm32/next -37685 68/push 0/imm32/next -37686 52/push-edx/var2 +37684 56/push-esi/next +37685 68/push 0x11/imm32/alloc-id:fake +37686 51/push-ecx/var1 37687 68/push 0x11/imm32/alloc-id:fake 37688 68/push 0x11/imm32/alloc-id:fake:payload 37689 89/<- %esi 4/r32/esp -37690 # inouts = [var1, var2] -37691 68/push 0/imm32/is-deref:false -37692 56/push-esi/next -37693 68/push 0x11/imm32/alloc-id:fake -37694 51/push-ecx/var1 -37695 68/push 0x11/imm32/alloc-id:fake -37696 68/push 0x11/imm32/alloc-id:fake:payload -37697 89/<- %esi 4/r32/esp -37698 $test-compare-reg-with-reg:initialize-stmt: -37699 # var stmt/esi: (addr statement) -37700 68/push 0/imm32/next -37701 68/push 0/imm32/next -37702 68/push 0/imm32/outputs -37703 68/push 0/imm32/outputs -37704 56/push-esi/inouts -37705 68/push 0x11/imm32/alloc-id:fake -37706 68/push 0/imm32/operation -37707 68/push 0/imm32/operation -37708 68/push 1/imm32/tag:stmt1 -37709 89/<- %esi 4/r32/esp -37710 $test-compare-reg-with-reg:initialize-stmt-operation: -37711 # stmt->operation = "compare" -37712 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37713 (copy-array Heap "compare" %eax) -37714 # convert -37715 c7 0/subop/copy *Curr-block-depth 0/imm32 -37716 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37717 (flush _test-output-buffered-file) -37718 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37724 # check output -37725 (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg") -37726 # . epilogue -37727 89/<- %esp 5/r32/ebp -37728 5d/pop-to-ebp -37729 c3/return -37730 -37731 test-compare-mem-with-reg: -37732 # compare var1, var2/eax -37733 # => -37734 # 39/compare *(ebp+___) 0/r32/eax -37735 # -37736 # . prologue -37737 55/push-ebp -37738 89/<- %ebp 4/r32/esp -37739 # setup -37740 (clear-stream _test-output-stream) -37741 (clear-stream $_test-output-buffered-file->buffer) -37742 $test-compare-mem-with-reg:initialize-type: -37743 # var type/ecx: (payload type-tree) = int -37744 68/push 0/imm32/right:null -37745 68/push 0/imm32/right:null -37746 68/push 0/imm32/left:unused -37747 68/push 1/imm32/value:int -37748 68/push 1/imm32/is-atom?:true -37749 68/push 0x11/imm32/alloc-id:fake:payload -37750 89/<- %ecx 4/r32/esp -37751 $test-compare-mem-with-reg:initialize-var1: -37752 # var var1/ecx: (payload var) -37753 68/push 0/imm32/register -37754 68/push 0/imm32/register -37755 68/push 8/imm32/stack-offset -37756 68/push 1/imm32/block-depth -37757 51/push-ecx -37758 68/push 0x11/imm32/alloc-id:fake -37759 68/push 0/imm32/name -37760 68/push 0/imm32/name -37761 68/push 0x11/imm32/alloc-id:fake:payload -37762 89/<- %ecx 4/r32/esp -37763 $test-compare-mem-with-reg:initialize-var1-name: -37764 # var1->name = "var1" -37765 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37766 (copy-array Heap "var1" %eax) -37767 $test-compare-mem-with-reg:initialize-var2: -37768 # var var2/edx: (payload var) -37769 68/push 0/imm32/register -37770 68/push 0/imm32/register -37771 68/push 0/imm32/no-stack-offset -37772 68/push 1/imm32/block-depth -37773 ff 6/subop/push *(ecx+0x10) -37774 68/push 0x11/imm32/alloc-id:fake -37775 68/push 0/imm32/name -37776 68/push 0/imm32/name -37777 68/push 0x11/imm32/alloc-id:fake:payload -37778 89/<- %edx 4/r32/esp -37779 $test-compare-mem-with-reg:initialize-var2-name: -37780 # var2->name = "var2" -37781 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37782 (copy-array Heap "var2" %eax) -37783 $test-compare-mem-with-reg:initialize-var2-register: -37784 # var2->register = "eax" -37785 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 -37786 (copy-array Heap "eax" %eax) -37787 $test-compare-mem-with-reg:initialize-inouts: -37788 # var inouts/esi: (payload stmt-var) = [var2] -37789 68/push 0/imm32/is-deref:false -37790 68/push 0/imm32/next +37690 $test-add-literal-to-mem:initialize-stmt: +37691 # var stmt/esi: (addr statement) +37692 68/push 0/imm32/next +37693 68/push 0/imm32/next +37694 68/push 0/imm32/outputs +37695 68/push 0/imm32/outputs +37696 56/push-esi/inouts +37697 68/push 0x11/imm32/alloc-id:fake +37698 68/push 0/imm32/operation +37699 68/push 0/imm32/operation +37700 68/push 1/imm32/tag:stmt1 +37701 89/<- %esi 4/r32/esp +37702 $test-add-literal-to-mem:initialize-stmt-operation: +37703 # stmt->operation = "add-to" +37704 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37705 (copy-array Heap "add-to" %eax) +37706 # convert +37707 c7 0/subop/copy *Curr-block-depth 0/imm32 +37708 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37709 (flush _test-output-buffered-file) +37710 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37716 # check output +37717 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +37718 # . epilogue +37719 89/<- %esp 5/r32/ebp +37720 5d/pop-to-ebp +37721 c3/return +37722 +37723 test-shift-reg-by-literal: +37724 # var1/ecx <- shift-left 2 +37725 # => +37726 # c1/shift 4/subop/left %ecx 2/imm8 +37727 # +37728 # . prologue +37729 55/push-ebp +37730 89/<- %ebp 4/r32/esp +37731 # setup +37732 (clear-stream _test-output-stream) +37733 (clear-stream $_test-output-buffered-file->buffer) +37734 $test-shift-reg-by-literal:initialize-var-type: +37735 # var type/ecx: (payload type-tree) = int +37736 68/push 0/imm32/right:null +37737 68/push 0/imm32/right:null +37738 68/push 0/imm32/left:unused +37739 68/push 1/imm32/value:int +37740 68/push 1/imm32/is-atom?:true +37741 68/push 0x11/imm32/alloc-id:fake:payload +37742 89/<- %ecx 4/r32/esp +37743 $test-shift-reg-by-literal:initialize-var: +37744 # var v/ecx: (payload var) +37745 68/push 0/imm32/register +37746 68/push 0/imm32/register +37747 68/push 0/imm32/no-stack-offset +37748 68/push 1/imm32/block-depth +37749 51/push-ecx +37750 68/push 0x11/imm32/alloc-id:fake +37751 68/push 0/imm32/name +37752 68/push 0/imm32/name +37753 68/push 0x11/imm32/alloc-id:fake:payload +37754 89/<- %ecx 4/r32/esp +37755 $test-shift-reg-by-literal:initialize-var-name: +37756 # v->name = "v" +37757 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37758 (copy-array Heap "v" %eax) +37759 $test-shift-reg-by-literal:initialize-var-register: +37760 # v->register = "ecx" +37761 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37762 (copy-array Heap "ecx" %eax) +37763 $test-shift-reg-by-literal:initialize-literal-type: +37764 # var type/edx: (payload type-tree) = literal +37765 68/push 0/imm32/right:null +37766 68/push 0/imm32/right:null +37767 68/push 0/imm32/left:unused +37768 68/push 0/imm32/value:literal +37769 68/push 1/imm32/is-atom?:true +37770 68/push 0x11/imm32/alloc-id:fake:payload +37771 89/<- %edx 4/r32/esp +37772 $test-shift-reg-by-literal:initialize-literal: +37773 # var l/edx: (payload var) +37774 68/push 0/imm32/register +37775 68/push 0/imm32/register +37776 68/push 0/imm32/no-stack-offset +37777 68/push 1/imm32/block-depth +37778 52/push-edx +37779 68/push 0x11/imm32/alloc-id:fake +37780 68/push 0/imm32/name +37781 68/push 0/imm32/name +37782 68/push 0x11/imm32/alloc-id:fake:payload +37783 89/<- %edx 4/r32/esp +37784 $test-shift-reg-by-literal:initialize-literal-value: +37785 # l->name = "2" +37786 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37787 (copy-array Heap "2" %eax) +37788 $test-shift-reg-by-literal:initialize-inouts: +37789 # var inouts/esi: (payload stmt-var) = [l] +37790 68/push 0/imm32/is-deref:false 37791 68/push 0/imm32/next -37792 52/push-edx/var2 -37793 68/push 0x11/imm32/alloc-id:fake -37794 68/push 0x11/imm32/alloc-id:fake:payload -37795 89/<- %esi 4/r32/esp -37796 # inouts = [var1, var2] -37797 68/push 0/imm32/is-deref:false -37798 56/push-esi/next -37799 68/push 0x11/imm32/alloc-id:fake -37800 51/push-ecx/var1 -37801 68/push 0x11/imm32/alloc-id:fake -37802 68/push 0x11/imm32/alloc-id:fake:payload -37803 89/<- %esi 4/r32/esp -37804 $test-compare-mem-with-reg:initialize-stmt: -37805 # var stmt/esi: (addr statement) -37806 68/push 0/imm32/next -37807 68/push 0/imm32/next -37808 68/push 0/imm32/outputs -37809 68/push 0/imm32/outputs -37810 56/push-esi/inouts +37792 68/push 0/imm32/next +37793 52/push-edx/l +37794 68/push 0x11/imm32/alloc-id:fake +37795 68/push 0x11/imm32/alloc-id:fake:payload +37796 89/<- %esi 4/r32/esp +37797 $test-shift-reg-by-literal:initialize-outputs: +37798 # var outputs/edi: (payload stmt-var) = [v] +37799 68/push 0/imm32/is-deref:false +37800 68/push 0/imm32/next +37801 68/push 0/imm32/next +37802 51/push-ecx/v +37803 68/push 0x11/imm32/alloc-id:fake +37804 68/push 0x11/imm32/alloc-id:fake:payload +37805 89/<- %edi 4/r32/esp +37806 $test-shift-reg-by-literal:initialize-stmt: +37807 # var stmt/esi: (addr statement) +37808 68/push 0/imm32/next +37809 68/push 0/imm32/next +37810 57/push-edi/outputs 37811 68/push 0x11/imm32/alloc-id:fake -37812 68/push 0/imm32/operation -37813 68/push 0/imm32/operation -37814 68/push 1/imm32/tag:stmt1 -37815 89/<- %esi 4/r32/esp -37816 $test-compare-mem-with-reg:initialize-stmt-operation: -37817 # stmt->operation = "compare" -37818 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37819 (copy-array Heap "compare" %eax) -37820 # convert -37821 c7 0/subop/copy *Curr-block-depth 0/imm32 -37822 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37823 (flush _test-output-buffered-file) -37824 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37830 # check output -37831 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -37832 # . epilogue -37833 89/<- %esp 5/r32/ebp -37834 5d/pop-to-ebp -37835 c3/return -37836 -37837 test-compare-reg-with-mem: -37838 # compare var1/eax, var2 -37839 # => -37840 # 3b/compare<- *(ebp+___) 0/r32/eax -37841 # -37842 # . prologue -37843 55/push-ebp -37844 89/<- %ebp 4/r32/esp -37845 # setup -37846 (clear-stream _test-output-stream) -37847 (clear-stream $_test-output-buffered-file->buffer) -37848 $test-compare-reg-with-mem:initialize-type: -37849 # var type/ecx: (payload type-tree) = int -37850 68/push 0/imm32/right:null -37851 68/push 0/imm32/right:null -37852 68/push 0/imm32/left:unused -37853 68/push 1/imm32/value:int -37854 68/push 1/imm32/is-atom?:true -37855 68/push 0x11/imm32/alloc-id:fake:payload -37856 89/<- %ecx 4/r32/esp -37857 $test-compare-reg-with-mem:initialize-var1: -37858 # var var1/ecx: (payload var) -37859 68/push 0/imm32/register -37860 68/push 0/imm32/register -37861 68/push 0/imm32/no-stack-offset -37862 68/push 1/imm32/block-depth -37863 51/push-ecx -37864 68/push 0x11/imm32/alloc-id:fake -37865 68/push 0/imm32/name -37866 68/push 0/imm32/name -37867 68/push 0x11/imm32/alloc-id:fake:payload -37868 89/<- %ecx 4/r32/esp -37869 $test-compare-reg-with-mem:initialize-var1-name: -37870 # var1->name = "var1" -37871 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37872 (copy-array Heap "var1" %eax) -37873 $test-compare-reg-with-mem:initialize-var1-register: -37874 # var1->register = "eax" -37875 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -37876 (copy-array Heap "eax" %eax) -37877 $test-compare-reg-with-mem:initialize-var2: -37878 # var var2/edx: (payload var) -37879 68/push 0/imm32/register -37880 68/push 0/imm32/register -37881 68/push 8/imm32/stack-offset -37882 68/push 1/imm32/block-depth -37883 ff 6/subop/push *(ecx+0x10) -37884 68/push 0x11/imm32/alloc-id:fake -37885 68/push 0/imm32/name -37886 68/push 0/imm32/name -37887 68/push 0x11/imm32/alloc-id:fake:payload -37888 89/<- %edx 4/r32/esp -37889 $test-compare-reg-with-mem:initialize-var2-name: -37890 # var2->name = "var2" -37891 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -37892 (copy-array Heap "var2" %eax) -37893 $test-compare-reg-with-mem:initialize-inouts: -37894 # var inouts/esi: (payload stmt-var) = [var2] -37895 68/push 0/imm32/is-deref:false -37896 68/push 0/imm32/next -37897 68/push 0/imm32/next -37898 52/push-edx/var2 -37899 68/push 0x11/imm32/alloc-id:fake -37900 68/push 0x11/imm32/alloc-id:fake:payload -37901 89/<- %esi 4/r32/esp -37902 # inouts = [var1, var2] -37903 68/push 0/imm32/is-deref:false -37904 56/push-esi/next -37905 68/push 0x11/imm32/alloc-id:fake -37906 51/push-ecx/var1 -37907 68/push 0x11/imm32/alloc-id:fake -37908 68/push 0x11/imm32/alloc-id:fake:payload -37909 89/<- %esi 4/r32/esp -37910 $test-compare-reg-with-mem:initialize-stmt: -37911 # var stmt/esi: (addr statement) -37912 68/push 0/imm32/next -37913 68/push 0/imm32/next -37914 68/push 0/imm32/outputs -37915 68/push 0/imm32/outputs -37916 56/push-esi/inouts -37917 68/push 0x11/imm32/alloc-id:fake -37918 68/push 0/imm32/operation -37919 68/push 0/imm32/operation -37920 68/push 1/imm32/tag:stmt1 -37921 89/<- %esi 4/r32/esp -37922 $test-compare-reg-with-mem:initialize-stmt-operation: -37923 # stmt->operation = "compare" -37924 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -37925 (copy-array Heap "compare" %eax) -37926 # convert -37927 c7 0/subop/copy *Curr-block-depth 0/imm32 -37928 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -37929 (flush _test-output-buffered-file) -37930 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -37936 # check output -37937 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -37938 # . epilogue -37939 89/<- %esp 5/r32/ebp -37940 5d/pop-to-ebp -37941 c3/return -37942 -37943 test-compare-mem-with-literal: -37944 # compare var1, 0x34 -37945 # => -37946 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -37947 # -37948 # . prologue -37949 55/push-ebp -37950 89/<- %ebp 4/r32/esp -37951 # setup -37952 (clear-stream _test-output-stream) -37953 (clear-stream $_test-output-buffered-file->buffer) -37954 $test-compare-mem-with-literal:initialize-type: -37955 # var type/ecx: (payload type-tree) = int -37956 68/push 0/imm32/right:null -37957 68/push 0/imm32/right:null -37958 68/push 0/imm32/left:unused -37959 68/push 1/imm32/value:int -37960 68/push 1/imm32/is-atom?:true -37961 68/push 0x11/imm32/alloc-id:fake:payload -37962 89/<- %ecx 4/r32/esp -37963 $test-compare-mem-with-literal:initialize-var1: -37964 # var var1/ecx: (payload var) -37965 68/push 0/imm32/register -37966 68/push 0/imm32/register -37967 68/push 8/imm32/stack-offset -37968 68/push 1/imm32/block-depth -37969 51/push-ecx -37970 68/push 0x11/imm32/alloc-id:fake -37971 68/push 0/imm32/name -37972 68/push 0/imm32/name -37973 68/push 0x11/imm32/alloc-id:fake:payload -37974 89/<- %ecx 4/r32/esp -37975 $test-compare-mem-with-literal:initialize-var1-name: -37976 # var1->name = "var1" -37977 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -37978 (copy-array Heap "var1" %eax) -37979 $test-compare-mem-with-literal:initialize-literal-type: -37980 # var type/edx: (payload type-tree) = literal -37981 68/push 0/imm32/right:null -37982 68/push 0/imm32/right:null -37983 68/push 0/imm32/left:unused -37984 68/push 0/imm32/value:literal -37985 68/push 1/imm32/is-atom?:true -37986 68/push 0x11/imm32/alloc-id:fake:payload -37987 89/<- %edx 4/r32/esp -37988 $test-compare-mem-with-literal:initialize-literal: -37989 # var l/edx: (payload var) -37990 68/push 0/imm32/register -37991 68/push 0/imm32/register -37992 68/push 0/imm32/no-stack-offset -37993 68/push 1/imm32/block-depth -37994 52/push-edx -37995 68/push 0x11/imm32/alloc-id:fake -37996 68/push 0/imm32/name -37997 68/push 0/imm32/name -37998 68/push 0x11/imm32/alloc-id:fake:payload -37999 89/<- %edx 4/r32/esp -38000 $test-compare-mem-with-literal:initialize-literal-value: -38001 # l->name = "0x34" -38002 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -38003 (copy-array Heap "0x34" %eax) -38004 $test-compare-mem-with-literal:initialize-inouts: -38005 # var inouts/esi: (payload stmt-var) = [l] -38006 68/push 0/imm32/is-deref:false -38007 68/push 0/imm32/next -38008 68/push 0/imm32/next -38009 52/push-edx/l -38010 68/push 0x11/imm32/alloc-id:fake -38011 68/push 0x11/imm32/alloc-id:fake:payload -38012 89/<- %esi 4/r32/esp -38013 # var inouts = (handle stmt-var) = [var1, var2] -38014 68/push 0/imm32/is-deref:false -38015 56/push-esi/next +37812 56/push-esi/inouts +37813 68/push 0x11/imm32/alloc-id:fake +37814 68/push 0/imm32/operation +37815 68/push 0/imm32/operation +37816 68/push 1/imm32/tag:stmt1 +37817 89/<- %esi 4/r32/esp +37818 $test-shift-reg-by-literal:initialize-stmt-operation: +37819 # stmt->operation = "shift-left" +37820 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37821 (copy-array Heap "shift-left" %eax) +37822 # convert +37823 c7 0/subop/copy *Curr-block-depth 0/imm32 +37824 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37825 (flush _test-output-buffered-file) +37826 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37832 # check output +37833 (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal") +37834 # . epilogue +37835 89/<- %esp 5/r32/ebp +37836 5d/pop-to-ebp +37837 c3/return +37838 +37839 test-shift-mem-by-literal: +37840 # shift-left var 3 +37841 # => +37842 # c1/shift 4/subop/left *(ebp+8) 3/imm8 +37843 # +37844 # . prologue +37845 55/push-ebp +37846 89/<- %ebp 4/r32/esp +37847 # setup +37848 (clear-stream _test-output-stream) +37849 (clear-stream $_test-output-buffered-file->buffer) +37850 $test-shift-mem-by-literal:initialize-type: +37851 # var type/ecx: (payload type-tree) = int +37852 68/push 0/imm32/right:null +37853 68/push 0/imm32/right:null +37854 68/push 0/imm32/left:unused +37855 68/push 1/imm32/value:int +37856 68/push 1/imm32/is-atom?:true +37857 68/push 0x11/imm32/alloc-id:fake:payload +37858 89/<- %ecx 4/r32/esp +37859 $test-shift-mem-by-literal:initialize-var1: +37860 # var var1/ecx: (payload var) +37861 68/push 0/imm32/register +37862 68/push 0/imm32/register +37863 68/push 8/imm32/stack-offset +37864 68/push 1/imm32/block-depth +37865 51/push-ecx +37866 68/push 0x11/imm32/alloc-id:fake +37867 68/push 0/imm32/name +37868 68/push 0/imm32/name +37869 68/push 0x11/imm32/alloc-id:fake:payload +37870 89/<- %ecx 4/r32/esp +37871 $test-shift-mem-by-literal:initialize-var1-name: +37872 # var1->name = "var1" +37873 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37874 (copy-array Heap "var1" %eax) +37875 $test-shift-mem-by-literal:initialize-literal-type: +37876 # var type/edx: (payload type-tree) = literal +37877 68/push 0/imm32/right:null +37878 68/push 0/imm32/right:null +37879 68/push 0/imm32/left:unused +37880 68/push 0/imm32/value:literal +37881 68/push 1/imm32/is-atom?:true +37882 68/push 0x11/imm32/alloc-id:fake:payload +37883 89/<- %edx 4/r32/esp +37884 $test-shift-mem-by-literal:initialize-literal: +37885 # var l/edx: (payload var) +37886 68/push 0/imm32/register +37887 68/push 0/imm32/register +37888 68/push 0/imm32/no-stack-offset +37889 68/push 1/imm32/block-depth +37890 52/push-edx +37891 68/push 0x11/imm32/alloc-id:fake +37892 68/push 0/imm32/name +37893 68/push 0/imm32/name +37894 68/push 0x11/imm32/alloc-id:fake:payload +37895 89/<- %edx 4/r32/esp +37896 $test-shift-mem-by-literal:initialize-literal-value: +37897 # l->name = "3" +37898 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +37899 (copy-array Heap "3" %eax) +37900 $test-shift-mem-by-literal:initialize-inouts: +37901 # var inouts/esi: (payload stmt-var) = [l] +37902 68/push 0/imm32/is-deref:false +37903 68/push 0/imm32/next +37904 68/push 0/imm32/next +37905 52/push-edx/l +37906 68/push 0x11/imm32/alloc-id:fake +37907 68/push 0x11/imm32/alloc-id:fake:payload +37908 89/<- %esi 4/r32/esp +37909 # var inouts = (handle stmt-var) = [var1, var2] +37910 68/push 0/imm32/is-deref:false +37911 56/push-esi/next +37912 68/push 0x11/imm32/alloc-id:fake +37913 51/push-ecx/var1 +37914 68/push 0x11/imm32/alloc-id:fake +37915 68/push 0x11/imm32/alloc-id:fake:payload +37916 89/<- %esi 4/r32/esp +37917 $test-shift-mem-by-literal:initialize-stmt: +37918 # var stmt/esi: (addr statement) +37919 68/push 0/imm32/next +37920 68/push 0/imm32/next +37921 68/push 0/imm32/outputs +37922 68/push 0/imm32/outputs +37923 56/push-esi/inouts +37924 68/push 0x11/imm32/alloc-id:fake +37925 68/push 0/imm32/operation +37926 68/push 0/imm32/operation +37927 68/push 1/imm32/tag:stmt1 +37928 89/<- %esi 4/r32/esp +37929 $test-shift-mem-by-literal:initialize-stmt-operation: +37930 # stmt->operation = "shift-left" +37931 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +37932 (copy-array Heap "shift-left" %eax) +37933 # convert +37934 c7 0/subop/copy *Curr-block-depth 0/imm32 +37935 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +37936 (flush _test-output-buffered-file) +37937 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +37943 # check output +37944 (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal") +37945 # . epilogue +37946 89/<- %esp 5/r32/ebp +37947 5d/pop-to-ebp +37948 c3/return +37949 +37950 test-compare-reg-with-reg: +37951 # compare var1/ecx, var2/eax +37952 # => +37953 # 39/compare %ecx 0/r32/eax +37954 # +37955 # . prologue +37956 55/push-ebp +37957 89/<- %ebp 4/r32/esp +37958 # setup +37959 (clear-stream _test-output-stream) +37960 (clear-stream $_test-output-buffered-file->buffer) +37961 $test-compare-reg-with-reg:initialize-type: +37962 # var type/ecx: (payload type-tree) = int +37963 68/push 0/imm32/right:null +37964 68/push 0/imm32/right:null +37965 68/push 0/imm32/left:unused +37966 68/push 1/imm32/value:int +37967 68/push 1/imm32/is-atom?:true +37968 68/push 0x11/imm32/alloc-id:fake:payload +37969 89/<- %ecx 4/r32/esp +37970 $test-compare-reg-with-reg:initialize-var1: +37971 # var var1/ecx: (payload var) +37972 68/push 0/imm32/register +37973 68/push 0/imm32/register +37974 68/push 0/imm32/no-stack-offset +37975 68/push 1/imm32/block-depth +37976 51/push-ecx +37977 68/push 0x11/imm32/alloc-id:fake +37978 68/push 0/imm32/name +37979 68/push 0/imm32/name +37980 68/push 0x11/imm32/alloc-id:fake:payload +37981 89/<- %ecx 4/r32/esp +37982 $test-compare-reg-with-reg:initialize-var1-name: +37983 # var1->name = "var1" +37984 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +37985 (copy-array Heap "var1" %eax) +37986 $test-compare-reg-with-reg:initialize-var1-register: +37987 # var1->register = "ecx" +37988 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +37989 (copy-array Heap "ecx" %eax) +37990 $test-compare-reg-with-reg:initialize-var2: +37991 # var var2/edx: (payload var) +37992 68/push 0/imm32/register +37993 68/push 0/imm32/register +37994 68/push 0/imm32/no-stack-offset +37995 68/push 1/imm32/block-depth +37996 ff 6/subop/push *(ecx+0x10) +37997 68/push 0x11/imm32/alloc-id:fake +37998 68/push 0/imm32/name +37999 68/push 0/imm32/name +38000 68/push 0x11/imm32/alloc-id:fake:payload +38001 89/<- %edx 4/r32/esp +38002 $test-compare-reg-with-reg:initialize-var2-name: +38003 # var2->name = "var2" +38004 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +38005 (copy-array Heap "var2" %eax) +38006 $test-compare-reg-with-reg:initialize-var2-register: +38007 # var2->register = "eax" +38008 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 +38009 (copy-array Heap "eax" %eax) +38010 $test-compare-reg-with-reg:initialize-inouts: +38011 # var inouts/esi: (payload stmt-var) = [var2] +38012 68/push 0/imm32/is-deref:false +38013 68/push 0/imm32/next +38014 68/push 0/imm32/next +38015 52/push-edx/var2 38016 68/push 0x11/imm32/alloc-id:fake -38017 51/push-ecx/var1 -38018 68/push 0x11/imm32/alloc-id:fake -38019 68/push 0x11/imm32/alloc-id:fake:payload -38020 89/<- %esi 4/r32/esp -38021 $test-compare-mem-with-literal:initialize-stmt: -38022 # var stmt/esi: (addr statement) -38023 68/push 0/imm32/next -38024 68/push 0/imm32/next -38025 68/push 0/imm32/outputs -38026 68/push 0/imm32/outputs -38027 56/push-esi/inouts -38028 68/push 0x11/imm32/alloc-id:fake -38029 68/push 0/imm32/operation -38030 68/push 0/imm32/operation -38031 68/push 1/imm32/tag:stmt1 -38032 89/<- %esi 4/r32/esp -38033 $test-compare-mem-with-literal:initialize-stmt-operation: -38034 # stmt->operation = "compare" -38035 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -38036 (copy-array Heap "compare" %eax) -38037 # convert -38038 c7 0/subop/copy *Curr-block-depth 0/imm32 -38039 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -38040 (flush _test-output-buffered-file) -38041 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -38047 # check output -38048 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -38049 # . epilogue -38050 89/<- %esp 5/r32/ebp -38051 5d/pop-to-ebp -38052 c3/return -38053 -38054 test-compare-eax-with-literal: -38055 # compare var1/eax 0x34 -38056 # => -38057 # 3d/compare-eax-with 0x34/imm32 -38058 # -38059 # . prologue -38060 55/push-ebp -38061 89/<- %ebp 4/r32/esp -38062 # setup -38063 (clear-stream _test-output-stream) -38064 (clear-stream $_test-output-buffered-file->buffer) -38065 $test-compare-eax-with-literal:initialize-type: -38066 # var type/ecx: (payload type-tree) = int -38067 68/push 0/imm32/right:null -38068 68/push 0/imm32/right:null -38069 68/push 0/imm32/left:unused -38070 68/push 1/imm32/value:int -38071 68/push 1/imm32/is-atom?:true -38072 68/push 0x11/imm32/alloc-id:fake:payload -38073 89/<- %ecx 4/r32/esp -38074 $test-compare-eax-with-literal:initialize-var1: -38075 # var var1/ecx: (payload var) -38076 68/push 0/imm32/register -38077 68/push 0/imm32/register -38078 68/push 0/imm32/no-stack-offset -38079 68/push 1/imm32/block-depth -38080 51/push-ecx -38081 68/push 0x11/imm32/alloc-id:fake -38082 68/push 0/imm32/name -38083 68/push 0/imm32/name -38084 68/push 0x11/imm32/alloc-id:fake:payload -38085 89/<- %ecx 4/r32/esp -38086 $test-compare-eax-with-literal:initialize-var1-name: -38087 # var1->name = "var1" -38088 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -38089 (copy-array Heap "var1" %eax) -38090 $test-compare-eax-with-literal:initialize-var1-register: -38091 # v->register = "eax" -38092 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -38093 (copy-array Heap "eax" %eax) -38094 $test-compare-eax-with-literal:initialize-literal-type: -38095 # var type/edx: (payload type-tree) = literal -38096 68/push 0/imm32/right:null -38097 68/push 0/imm32/right:null -38098 68/push 0/imm32/left:unused -38099 68/push 0/imm32/value:literal -38100 68/push 1/imm32/is-atom?:true -38101 68/push 0x11/imm32/alloc-id:fake:payload -38102 89/<- %edx 4/r32/esp -38103 $test-compare-eax-with-literal:initialize-literal: -38104 # var l/edx: (payload var) -38105 68/push 0/imm32/register -38106 68/push 0/imm32/register -38107 68/push 0/imm32/no-stack-offset -38108 68/push 1/imm32/block-depth -38109 52/push-edx -38110 68/push 0x11/imm32/alloc-id:fake -38111 68/push 0/imm32/name -38112 68/push 0/imm32/name -38113 68/push 0x11/imm32/alloc-id:fake:payload -38114 89/<- %edx 4/r32/esp -38115 $test-compare-eax-with-literal:initialize-literal-value: -38116 # l->name = "0x34" -38117 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -38118 (copy-array Heap "0x34" %eax) -38119 $test-compare-eax-with-literal:initialize-inouts: -38120 # var inouts/esi: (payload stmt-var) = [l] -38121 68/push 0/imm32/is-deref:false -38122 68/push 0/imm32/next -38123 68/push 0/imm32/next -38124 52/push-edx/l -38125 68/push 0x11/imm32/alloc-id:fake -38126 68/push 0x11/imm32/alloc-id:fake:payload -38127 89/<- %esi 4/r32/esp -38128 # var inouts = (handle stmt-var) = [var1, var2] -38129 68/push 0/imm32/is-deref:false -38130 56/push-esi/next -38131 68/push 0x11/imm32/alloc-id:fake -38132 51/push-ecx/var1 -38133 68/push 0x11/imm32/alloc-id:fake -38134 68/push 0x11/imm32/alloc-id:fake:payload -38135 89/<- %esi 4/r32/esp -38136 $test-compare-eax-with-literal:initialize-stmt: -38137 # var stmt/esi: (addr statement) -38138 68/push 0/imm32/next -38139 68/push 0/imm32/next -38140 68/push 0/imm32/outputs -38141 68/push 0/imm32/outputs -38142 56/push-esi/inouts -38143 68/push 0x11/imm32/alloc-id:fake -38144 68/push 0/imm32/operation -38145 68/push 0/imm32/operation -38146 68/push 1/imm32/tag:stmt1 -38147 89/<- %esi 4/r32/esp -38148 $test-compare-eax-with-literal:initialize-stmt-operation: -38149 # stmt->operation = "compare" -38150 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -38151 (copy-array Heap "compare" %eax) -38152 # convert -38153 c7 0/subop/copy *Curr-block-depth 0/imm32 -38154 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -38155 (flush _test-output-buffered-file) -38156 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -38162 # check output -38163 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -38164 # . epilogue -38165 89/<- %esp 5/r32/ebp -38166 5d/pop-to-ebp -38167 c3/return -38168 -38169 test-compare-reg-with-literal: -38170 # compare var1/ecx 0x34 -38171 # => -38172 # 81 7/subop/compare %ecx 0x34/imm32 -38173 # -38174 # . prologue -38175 55/push-ebp -38176 89/<- %ebp 4/r32/esp -38177 # setup -38178 (clear-stream _test-output-stream) -38179 (clear-stream $_test-output-buffered-file->buffer) -38180 $test-compare-reg-with-literal:initialize-type: -38181 # var type/ecx: (payload type-tree) = int -38182 68/push 0/imm32/right:null -38183 68/push 0/imm32/right:null -38184 68/push 0/imm32/left:unused -38185 68/push 1/imm32/value:int -38186 68/push 1/imm32/is-atom?:true -38187 68/push 0x11/imm32/alloc-id:fake:payload -38188 89/<- %ecx 4/r32/esp -38189 $test-compare-reg-with-literal:initialize-var1: -38190 # var var1/ecx: (payload var) -38191 68/push 0/imm32/register -38192 68/push 0/imm32/register -38193 68/push 0/imm32/no-stack-offset -38194 68/push 1/imm32/block-depth -38195 51/push-ecx -38196 68/push 0x11/imm32/alloc-id:fake -38197 68/push 0/imm32/name -38198 68/push 0/imm32/name -38199 68/push 0x11/imm32/alloc-id:fake:payload -38200 89/<- %ecx 4/r32/esp -38201 $test-compare-reg-with-literal:initialize-var1-name: -38202 # var1->name = "var1" -38203 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -38204 (copy-array Heap "var1" %eax) -38205 $test-compare-reg-with-literal:initialize-var1-register: -38206 # v->register = "ecx" -38207 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 -38208 (copy-array Heap "ecx" %eax) -38209 $test-compare-reg-with-literal:initialize-literal-type: -38210 # var type/edx: (payload type-tree) = literal -38211 68/push 0/imm32/right:null -38212 68/push 0/imm32/right:null -38213 68/push 0/imm32/left:unused -38214 68/push 0/imm32/value:literal -38215 68/push 1/imm32/is-atom?:true +38017 68/push 0x11/imm32/alloc-id:fake:payload +38018 89/<- %esi 4/r32/esp +38019 # inouts = [var1, var2] +38020 68/push 0/imm32/is-deref:false +38021 56/push-esi/next +38022 68/push 0x11/imm32/alloc-id:fake +38023 51/push-ecx/var1 +38024 68/push 0x11/imm32/alloc-id:fake +38025 68/push 0x11/imm32/alloc-id:fake:payload +38026 89/<- %esi 4/r32/esp +38027 $test-compare-reg-with-reg:initialize-stmt: +38028 # var stmt/esi: (addr statement) +38029 68/push 0/imm32/next +38030 68/push 0/imm32/next +38031 68/push 0/imm32/outputs +38032 68/push 0/imm32/outputs +38033 56/push-esi/inouts +38034 68/push 0x11/imm32/alloc-id:fake +38035 68/push 0/imm32/operation +38036 68/push 0/imm32/operation +38037 68/push 1/imm32/tag:stmt1 +38038 89/<- %esi 4/r32/esp +38039 $test-compare-reg-with-reg:initialize-stmt-operation: +38040 # stmt->operation = "compare" +38041 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38042 (copy-array Heap "compare" %eax) +38043 # convert +38044 c7 0/subop/copy *Curr-block-depth 0/imm32 +38045 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +38046 (flush _test-output-buffered-file) +38047 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38053 # check output +38054 (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg") +38055 # . epilogue +38056 89/<- %esp 5/r32/ebp +38057 5d/pop-to-ebp +38058 c3/return +38059 +38060 test-compare-mem-with-reg: +38061 # compare var1, var2/eax +38062 # => +38063 # 39/compare *(ebp+___) 0/r32/eax +38064 # +38065 # . prologue +38066 55/push-ebp +38067 89/<- %ebp 4/r32/esp +38068 # setup +38069 (clear-stream _test-output-stream) +38070 (clear-stream $_test-output-buffered-file->buffer) +38071 $test-compare-mem-with-reg:initialize-type: +38072 # var type/ecx: (payload type-tree) = int +38073 68/push 0/imm32/right:null +38074 68/push 0/imm32/right:null +38075 68/push 0/imm32/left:unused +38076 68/push 1/imm32/value:int +38077 68/push 1/imm32/is-atom?:true +38078 68/push 0x11/imm32/alloc-id:fake:payload +38079 89/<- %ecx 4/r32/esp +38080 $test-compare-mem-with-reg:initialize-var1: +38081 # var var1/ecx: (payload var) +38082 68/push 0/imm32/register +38083 68/push 0/imm32/register +38084 68/push 8/imm32/stack-offset +38085 68/push 1/imm32/block-depth +38086 51/push-ecx +38087 68/push 0x11/imm32/alloc-id:fake +38088 68/push 0/imm32/name +38089 68/push 0/imm32/name +38090 68/push 0x11/imm32/alloc-id:fake:payload +38091 89/<- %ecx 4/r32/esp +38092 $test-compare-mem-with-reg:initialize-var1-name: +38093 # var1->name = "var1" +38094 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38095 (copy-array Heap "var1" %eax) +38096 $test-compare-mem-with-reg:initialize-var2: +38097 # var var2/edx: (payload var) +38098 68/push 0/imm32/register +38099 68/push 0/imm32/register +38100 68/push 0/imm32/no-stack-offset +38101 68/push 1/imm32/block-depth +38102 ff 6/subop/push *(ecx+0x10) +38103 68/push 0x11/imm32/alloc-id:fake +38104 68/push 0/imm32/name +38105 68/push 0/imm32/name +38106 68/push 0x11/imm32/alloc-id:fake:payload +38107 89/<- %edx 4/r32/esp +38108 $test-compare-mem-with-reg:initialize-var2-name: +38109 # var2->name = "var2" +38110 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +38111 (copy-array Heap "var2" %eax) +38112 $test-compare-mem-with-reg:initialize-var2-register: +38113 # var2->register = "eax" +38114 8d/copy-address *(edx+0x1c) 0/r32/eax # Var-register + 4 +38115 (copy-array Heap "eax" %eax) +38116 $test-compare-mem-with-reg:initialize-inouts: +38117 # var inouts/esi: (payload stmt-var) = [var2] +38118 68/push 0/imm32/is-deref:false +38119 68/push 0/imm32/next +38120 68/push 0/imm32/next +38121 52/push-edx/var2 +38122 68/push 0x11/imm32/alloc-id:fake +38123 68/push 0x11/imm32/alloc-id:fake:payload +38124 89/<- %esi 4/r32/esp +38125 # inouts = [var1, var2] +38126 68/push 0/imm32/is-deref:false +38127 56/push-esi/next +38128 68/push 0x11/imm32/alloc-id:fake +38129 51/push-ecx/var1 +38130 68/push 0x11/imm32/alloc-id:fake +38131 68/push 0x11/imm32/alloc-id:fake:payload +38132 89/<- %esi 4/r32/esp +38133 $test-compare-mem-with-reg:initialize-stmt: +38134 # var stmt/esi: (addr statement) +38135 68/push 0/imm32/next +38136 68/push 0/imm32/next +38137 68/push 0/imm32/outputs +38138 68/push 0/imm32/outputs +38139 56/push-esi/inouts +38140 68/push 0x11/imm32/alloc-id:fake +38141 68/push 0/imm32/operation +38142 68/push 0/imm32/operation +38143 68/push 1/imm32/tag:stmt1 +38144 89/<- %esi 4/r32/esp +38145 $test-compare-mem-with-reg:initialize-stmt-operation: +38146 # stmt->operation = "compare" +38147 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38148 (copy-array Heap "compare" %eax) +38149 # convert +38150 c7 0/subop/copy *Curr-block-depth 0/imm32 +38151 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +38152 (flush _test-output-buffered-file) +38153 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38159 # check output +38160 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +38161 # . epilogue +38162 89/<- %esp 5/r32/ebp +38163 5d/pop-to-ebp +38164 c3/return +38165 +38166 test-compare-reg-with-mem: +38167 # compare var1/eax, var2 +38168 # => +38169 # 3b/compare<- *(ebp+___) 0/r32/eax +38170 # +38171 # . prologue +38172 55/push-ebp +38173 89/<- %ebp 4/r32/esp +38174 # setup +38175 (clear-stream _test-output-stream) +38176 (clear-stream $_test-output-buffered-file->buffer) +38177 $test-compare-reg-with-mem:initialize-type: +38178 # var type/ecx: (payload type-tree) = int +38179 68/push 0/imm32/right:null +38180 68/push 0/imm32/right:null +38181 68/push 0/imm32/left:unused +38182 68/push 1/imm32/value:int +38183 68/push 1/imm32/is-atom?:true +38184 68/push 0x11/imm32/alloc-id:fake:payload +38185 89/<- %ecx 4/r32/esp +38186 $test-compare-reg-with-mem:initialize-var1: +38187 # var var1/ecx: (payload var) +38188 68/push 0/imm32/register +38189 68/push 0/imm32/register +38190 68/push 0/imm32/no-stack-offset +38191 68/push 1/imm32/block-depth +38192 51/push-ecx +38193 68/push 0x11/imm32/alloc-id:fake +38194 68/push 0/imm32/name +38195 68/push 0/imm32/name +38196 68/push 0x11/imm32/alloc-id:fake:payload +38197 89/<- %ecx 4/r32/esp +38198 $test-compare-reg-with-mem:initialize-var1-name: +38199 # var1->name = "var1" +38200 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38201 (copy-array Heap "var1" %eax) +38202 $test-compare-reg-with-mem:initialize-var1-register: +38203 # var1->register = "eax" +38204 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +38205 (copy-array Heap "eax" %eax) +38206 $test-compare-reg-with-mem:initialize-var2: +38207 # var var2/edx: (payload var) +38208 68/push 0/imm32/register +38209 68/push 0/imm32/register +38210 68/push 8/imm32/stack-offset +38211 68/push 1/imm32/block-depth +38212 ff 6/subop/push *(ecx+0x10) +38213 68/push 0x11/imm32/alloc-id:fake +38214 68/push 0/imm32/name +38215 68/push 0/imm32/name 38216 68/push 0x11/imm32/alloc-id:fake:payload 38217 89/<- %edx 4/r32/esp -38218 $test-compare-reg-with-literal:initialize-literal: -38219 # var l/edx: (payload var) -38220 68/push 0/imm32/register -38221 68/push 0/imm32/register -38222 68/push 0/imm32/no-stack-offset -38223 68/push 1/imm32/block-depth -38224 52/push-edx -38225 68/push 0x11/imm32/alloc-id:fake -38226 68/push 0/imm32/name -38227 68/push 0/imm32/name -38228 68/push 0x11/imm32/alloc-id:fake:payload -38229 89/<- %edx 4/r32/esp -38230 $test-compare-reg-with-literal:initialize-literal-value: -38231 # l->name = "0x34" -38232 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 -38233 (copy-array Heap "0x34" %eax) -38234 $test-compare-reg-with-literal:initialize-inouts: -38235 # var inouts/esi: (payload stmt-var) = [l] -38236 68/push 0/imm32/is-deref:false -38237 68/push 0/imm32/next -38238 68/push 0/imm32/next -38239 52/push-edx/l -38240 68/push 0x11/imm32/alloc-id:fake -38241 68/push 0x11/imm32/alloc-id:fake:payload -38242 89/<- %esi 4/r32/esp -38243 # var inouts = (handle stmt-var) = [var1, var2] -38244 68/push 0/imm32/is-deref:false -38245 56/push-esi/next +38218 $test-compare-reg-with-mem:initialize-var2-name: +38219 # var2->name = "var2" +38220 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +38221 (copy-array Heap "var2" %eax) +38222 $test-compare-reg-with-mem:initialize-inouts: +38223 # var inouts/esi: (payload stmt-var) = [var2] +38224 68/push 0/imm32/is-deref:false +38225 68/push 0/imm32/next +38226 68/push 0/imm32/next +38227 52/push-edx/var2 +38228 68/push 0x11/imm32/alloc-id:fake +38229 68/push 0x11/imm32/alloc-id:fake:payload +38230 89/<- %esi 4/r32/esp +38231 # inouts = [var1, var2] +38232 68/push 0/imm32/is-deref:false +38233 56/push-esi/next +38234 68/push 0x11/imm32/alloc-id:fake +38235 51/push-ecx/var1 +38236 68/push 0x11/imm32/alloc-id:fake +38237 68/push 0x11/imm32/alloc-id:fake:payload +38238 89/<- %esi 4/r32/esp +38239 $test-compare-reg-with-mem:initialize-stmt: +38240 # var stmt/esi: (addr statement) +38241 68/push 0/imm32/next +38242 68/push 0/imm32/next +38243 68/push 0/imm32/outputs +38244 68/push 0/imm32/outputs +38245 56/push-esi/inouts 38246 68/push 0x11/imm32/alloc-id:fake -38247 51/push-ecx/var1 -38248 68/push 0x11/imm32/alloc-id:fake -38249 68/push 0x11/imm32/alloc-id:fake:payload +38247 68/push 0/imm32/operation +38248 68/push 0/imm32/operation +38249 68/push 1/imm32/tag:stmt1 38250 89/<- %esi 4/r32/esp -38251 $test-compare-reg-with-literal:initialize-stmt: -38252 # var stmt/esi: (addr statement) -38253 68/push 0/imm32/next -38254 68/push 0/imm32/next -38255 68/push 0/imm32/outputs -38256 68/push 0/imm32/outputs -38257 56/push-esi/inouts -38258 68/push 0x11/imm32/alloc-id:fake -38259 68/push 0/imm32/operation -38260 68/push 0/imm32/operation -38261 68/push 1/imm32/tag:stmt1 -38262 89/<- %esi 4/r32/esp -38263 $test-compare-reg-with-literal:initialize-stmt-operation: -38264 # stmt->operation = "compare" -38265 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -38266 (copy-array Heap "compare" %eax) -38267 # convert -38268 c7 0/subop/copy *Curr-block-depth 0/imm32 -38269 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) -38270 (flush _test-output-buffered-file) -38271 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -38277 # check output -38278 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -38279 # . epilogue -38280 89/<- %esp 5/r32/ebp -38281 5d/pop-to-ebp -38282 c3/return -38283 -38284 test-emit-subx-stmt-function-call: -38285 # Call a function on a variable on the stack. -38286 # f foo -38287 # => -38288 # (f *(ebp-8)) -38289 # (Changing the function name supports overloading in general, but here it -38290 # just serves to help disambiguate things.) -38291 # -38292 # There's a variable on the var stack as follows: -38293 # name: 'foo' -38294 # type: int -38295 # stack-offset: -8 -38296 # -38297 # There's nothing in primitives. -38298 # -38299 # We don't perform any checking here on the type of 'f'. -38300 # -38301 # . prologue -38302 55/push-ebp -38303 89/<- %ebp 4/r32/esp -38304 # setup -38305 (clear-stream _test-output-stream) -38306 (clear-stream $_test-output-buffered-file->buffer) -38307 $test-emit-subx-function-call:initialize-type: -38308 # var type/ecx: (payload type-tree) = int -38309 68/push 0/imm32/right:null +38251 $test-compare-reg-with-mem:initialize-stmt-operation: +38252 # stmt->operation = "compare" +38253 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38254 (copy-array Heap "compare" %eax) +38255 # convert +38256 c7 0/subop/copy *Curr-block-depth 0/imm32 +38257 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +38258 (flush _test-output-buffered-file) +38259 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38265 # check output +38266 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +38267 # . epilogue +38268 89/<- %esp 5/r32/ebp +38269 5d/pop-to-ebp +38270 c3/return +38271 +38272 test-compare-mem-with-literal: +38273 # compare var1, 0x34 +38274 # => +38275 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +38276 # +38277 # . prologue +38278 55/push-ebp +38279 89/<- %ebp 4/r32/esp +38280 # setup +38281 (clear-stream _test-output-stream) +38282 (clear-stream $_test-output-buffered-file->buffer) +38283 $test-compare-mem-with-literal:initialize-type: +38284 # var type/ecx: (payload type-tree) = int +38285 68/push 0/imm32/right:null +38286 68/push 0/imm32/right:null +38287 68/push 0/imm32/left:unused +38288 68/push 1/imm32/value:int +38289 68/push 1/imm32/is-atom?:true +38290 68/push 0x11/imm32/alloc-id:fake:payload +38291 89/<- %ecx 4/r32/esp +38292 $test-compare-mem-with-literal:initialize-var1: +38293 # var var1/ecx: (payload var) +38294 68/push 0/imm32/register +38295 68/push 0/imm32/register +38296 68/push 8/imm32/stack-offset +38297 68/push 1/imm32/block-depth +38298 51/push-ecx +38299 68/push 0x11/imm32/alloc-id:fake +38300 68/push 0/imm32/name +38301 68/push 0/imm32/name +38302 68/push 0x11/imm32/alloc-id:fake:payload +38303 89/<- %ecx 4/r32/esp +38304 $test-compare-mem-with-literal:initialize-var1-name: +38305 # var1->name = "var1" +38306 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38307 (copy-array Heap "var1" %eax) +38308 $test-compare-mem-with-literal:initialize-literal-type: +38309 # var type/edx: (payload type-tree) = literal 38310 68/push 0/imm32/right:null -38311 68/push 0/imm32/left:unused -38312 68/push 1/imm32/value:int -38313 68/push 1/imm32/is-atom?:true -38314 68/push 0x11/imm32/alloc-id:fake:payload -38315 89/<- %ecx 4/r32/esp -38316 $test-emit-subx-function-call:initialize-var: -38317 # var var-foo/ecx: (payload var) = var(type) -38318 68/push 0/imm32/no-register -38319 68/push 0/imm32/no-register -38320 68/push -8/imm32/stack-offset -38321 68/push 1/imm32/block-depth -38322 51/push-ecx/type -38323 68/push 0x11/imm32/alloc-id:fake -38324 68/push 0/imm32/name +38311 68/push 0/imm32/right:null +38312 68/push 0/imm32/left:unused +38313 68/push 0/imm32/value:literal +38314 68/push 1/imm32/is-atom?:true +38315 68/push 0x11/imm32/alloc-id:fake:payload +38316 89/<- %edx 4/r32/esp +38317 $test-compare-mem-with-literal:initialize-literal: +38318 # var l/edx: (payload var) +38319 68/push 0/imm32/register +38320 68/push 0/imm32/register +38321 68/push 0/imm32/no-stack-offset +38322 68/push 1/imm32/block-depth +38323 52/push-edx +38324 68/push 0x11/imm32/alloc-id:fake 38325 68/push 0/imm32/name -38326 68/push 0x11/imm32/alloc-id:fake:payload -38327 89/<- %ecx 4/r32/esp -38328 $test-emit-subx-function-call:initialize-var-name: -38329 # var-foo->name = "foo" -38330 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -38331 (copy-array Heap "foo" %eax) -38332 $test-emit-subx-function-call:initialize-stmt-var: -38333 # var operand/ebx: (payload stmt-var) = stmt-var(var-foo) -38334 68/push 0/imm32/is-deref:false -38335 68/push 0/imm32/next +38326 68/push 0/imm32/name +38327 68/push 0x11/imm32/alloc-id:fake:payload +38328 89/<- %edx 4/r32/esp +38329 $test-compare-mem-with-literal:initialize-literal-value: +38330 # l->name = "0x34" +38331 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +38332 (copy-array Heap "0x34" %eax) +38333 $test-compare-mem-with-literal:initialize-inouts: +38334 # var inouts/esi: (payload stmt-var) = [l] +38335 68/push 0/imm32/is-deref:false 38336 68/push 0/imm32/next -38337 51/push-ecx/var-foo -38338 68/push 0x11/imm32/alloc-id:fake -38339 68/push 0x11/imm32/alloc-id:fake:payload -38340 89/<- %ebx 4/r32/esp -38341 $test-emit-subx-function-call:initialize-stmt: -38342 # var stmt/esi: (addr statement) -38343 68/push 0/imm32/no-outputs -38344 68/push 0/imm32/no-outputs -38345 53/push-ebx/inouts -38346 68/push 0x11/imm32/alloc-id:fake -38347 68/push 0/imm32/operation -38348 68/push 0/imm32/operation -38349 68/push 1/imm32/tag -38350 89/<- %esi 4/r32/esp -38351 $test-emit-subx-function-call:initialize-stmt-operation: -38352 # stmt->operation = "f" -38353 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -38354 (copy-array Heap "f" %eax) -38355 # convert -38356 c7 0/subop/copy *Curr-block-depth 0/imm32 -38357 (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0) -38358 (flush _test-output-buffered-file) -38359 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -38365 # check output -38366 (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") -38367 # . epilogue -38368 89/<- %esp 5/r32/ebp -38369 5d/pop-to-ebp -38370 c3/return -38371 -38372 test-emit-subx-stmt-function-call-with-literal-arg: -38373 # Call a function on a literal. -38374 # f 0x34 -38375 # => -38376 # (f2 0x34) -38377 # -38378 # . prologue -38379 55/push-ebp -38380 89/<- %ebp 4/r32/esp -38381 # setup -38382 (clear-stream _test-output-stream) -38383 (clear-stream $_test-output-buffered-file->buffer) -38384 $test-emit-subx-function-call-with-literal-arg:initialize-type: -38385 # var type/ecx: (payload type-tree) = int -38386 68/push 0/imm32/right:null -38387 68/push 0/imm32/right:null -38388 68/push 0/imm32/left:unused -38389 68/push 0/imm32/value:literal -38390 68/push 1/imm32/is-atom?:true -38391 68/push 0x11/imm32/alloc-id:fake:payload -38392 89/<- %ecx 4/r32/esp -38393 $test-emit-subx-function-call-with-literal-arg:initialize-var: -38394 # var var-foo/ecx: (payload var) = var(lit) -38395 68/push 0/imm32/no-register -38396 68/push 0/imm32/no-register -38397 68/push 0/imm32/no-stack-offset -38398 68/push 1/imm32/block-depth -38399 51/push-ecx/type -38400 68/push 0x11/imm32/alloc-id:fake -38401 68/push 0/imm32/name -38402 68/push 0/imm32/name -38403 68/push 0x11/imm32/alloc-id:fake:payload -38404 89/<- %ecx 4/r32/esp -38405 $test-emit-subx-function-call-with-literal-arg:initialize-var-name: -38406 # var-foo->name = "0x34" -38407 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 -38408 (copy-array Heap "0x34" %eax) -38409 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var: -38410 # var operand/ebx: (payload stmt-var) = stmt-var(var-foo) -38411 68/push 0/imm32/is-deref:false -38412 68/push 0/imm32/next -38413 68/push 0/imm32/next -38414 51/push-ecx/var-foo -38415 68/push 0x11/imm32/alloc-id:fake -38416 68/push 0x11/imm32/alloc-id:fake:payload -38417 89/<- %ebx 4/r32/esp -38418 $test-emit-subx-function-call-with-literal-arg:initialize-stmt: -38419 # var stmt/esi: (addr statement) -38420 68/push 0/imm32/no-outputs -38421 68/push 0/imm32/no-outputs -38422 53/push-ebx/inouts -38423 68/push 0x11/imm32/alloc-id:fake -38424 68/push 0/imm32/operation -38425 68/push 0/imm32/operation -38426 68/push 1/imm32/tag -38427 89/<- %esi 4/r32/esp -38428 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation: -38429 # stmt->operation = "f" -38430 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation -38431 (copy-array Heap "f" %eax) -38432 # convert -38433 c7 0/subop/copy *Curr-block-depth 0/imm32 -38434 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0) -38435 (flush _test-output-buffered-file) -38436 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -38442 # check output -38443 (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") -38444 # . epilogue -38445 89/<- %esp 5/r32/ebp -38446 5d/pop-to-ebp -38447 c3/return -38448 -38449 emit-indent: # out: (addr buffered-file), n: int -38450 # . prologue -38451 55/push-ebp -38452 89/<- %ebp 4/r32/esp -38453 # . save registers -38454 50/push-eax -38455 # var i/eax: int = n -38456 8b/-> *(ebp+0xc) 0/r32/eax -38457 { -38458 # if (i <= 0) break -38459 3d/compare-eax-with 0/imm32 -38460 7e/jump-if-<= break/disp8 -38461 (write-buffered *(ebp+8) " ") -38462 48/decrement-eax -38463 eb/jump loop/disp8 -38464 } -38465 $emit-indent:end: -38466 # . restore registers -38467 58/pop-to-eax -38468 # . epilogue -38469 89/<- %esp 5/r32/ebp -38470 5d/pop-to-ebp -38471 c3/return -38472 -38473 emit-subx-prologue: # out: (addr buffered-file) -38474 # . prologue -38475 55/push-ebp -38476 89/<- %ebp 4/r32/esp -38477 # -38478 (write-buffered *(ebp+8) " # . prologue\n") -38479 (write-buffered *(ebp+8) " 55/push-ebp\n") -38480 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -38481 $emit-subx-prologue:end: -38482 # . epilogue -38483 89/<- %esp 5/r32/ebp -38484 5d/pop-to-ebp -38485 c3/return -38486 -38487 emit-subx-epilogue: # out: (addr buffered-file) -38488 # . prologue -38489 55/push-ebp -38490 89/<- %ebp 4/r32/esp -38491 # -38492 (write-buffered *(ebp+8) " # . epilogue\n") -38493 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -38494 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -38495 (write-buffered *(ebp+8) " c3/return\n") -38496 $emit-subx-epilogue:end: -38497 # . epilogue -38498 89/<- %esp 5/r32/ebp -38499 5d/pop-to-ebp -38500 c3/return +38337 68/push 0/imm32/next +38338 52/push-edx/l +38339 68/push 0x11/imm32/alloc-id:fake +38340 68/push 0x11/imm32/alloc-id:fake:payload +38341 89/<- %esi 4/r32/esp +38342 # var inouts = (handle stmt-var) = [var1, var2] +38343 68/push 0/imm32/is-deref:false +38344 56/push-esi/next +38345 68/push 0x11/imm32/alloc-id:fake +38346 51/push-ecx/var1 +38347 68/push 0x11/imm32/alloc-id:fake +38348 68/push 0x11/imm32/alloc-id:fake:payload +38349 89/<- %esi 4/r32/esp +38350 $test-compare-mem-with-literal:initialize-stmt: +38351 # var stmt/esi: (addr statement) +38352 68/push 0/imm32/next +38353 68/push 0/imm32/next +38354 68/push 0/imm32/outputs +38355 68/push 0/imm32/outputs +38356 56/push-esi/inouts +38357 68/push 0x11/imm32/alloc-id:fake +38358 68/push 0/imm32/operation +38359 68/push 0/imm32/operation +38360 68/push 1/imm32/tag:stmt1 +38361 89/<- %esi 4/r32/esp +38362 $test-compare-mem-with-literal:initialize-stmt-operation: +38363 # stmt->operation = "compare" +38364 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38365 (copy-array Heap "compare" %eax) +38366 # convert +38367 c7 0/subop/copy *Curr-block-depth 0/imm32 +38368 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +38369 (flush _test-output-buffered-file) +38370 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38376 # check output +38377 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +38378 # . epilogue +38379 89/<- %esp 5/r32/ebp +38380 5d/pop-to-ebp +38381 c3/return +38382 +38383 test-compare-eax-with-literal: +38384 # compare var1/eax 0x34 +38385 # => +38386 # 3d/compare-eax-with 0x34/imm32 +38387 # +38388 # . prologue +38389 55/push-ebp +38390 89/<- %ebp 4/r32/esp +38391 # setup +38392 (clear-stream _test-output-stream) +38393 (clear-stream $_test-output-buffered-file->buffer) +38394 $test-compare-eax-with-literal:initialize-type: +38395 # var type/ecx: (payload type-tree) = int +38396 68/push 0/imm32/right:null +38397 68/push 0/imm32/right:null +38398 68/push 0/imm32/left:unused +38399 68/push 1/imm32/value:int +38400 68/push 1/imm32/is-atom?:true +38401 68/push 0x11/imm32/alloc-id:fake:payload +38402 89/<- %ecx 4/r32/esp +38403 $test-compare-eax-with-literal:initialize-var1: +38404 # var var1/ecx: (payload var) +38405 68/push 0/imm32/register +38406 68/push 0/imm32/register +38407 68/push 0/imm32/no-stack-offset +38408 68/push 1/imm32/block-depth +38409 51/push-ecx +38410 68/push 0x11/imm32/alloc-id:fake +38411 68/push 0/imm32/name +38412 68/push 0/imm32/name +38413 68/push 0x11/imm32/alloc-id:fake:payload +38414 89/<- %ecx 4/r32/esp +38415 $test-compare-eax-with-literal:initialize-var1-name: +38416 # var1->name = "var1" +38417 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38418 (copy-array Heap "var1" %eax) +38419 $test-compare-eax-with-literal:initialize-var1-register: +38420 # v->register = "eax" +38421 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +38422 (copy-array Heap "eax" %eax) +38423 $test-compare-eax-with-literal:initialize-literal-type: +38424 # var type/edx: (payload type-tree) = literal +38425 68/push 0/imm32/right:null +38426 68/push 0/imm32/right:null +38427 68/push 0/imm32/left:unused +38428 68/push 0/imm32/value:literal +38429 68/push 1/imm32/is-atom?:true +38430 68/push 0x11/imm32/alloc-id:fake:payload +38431 89/<- %edx 4/r32/esp +38432 $test-compare-eax-with-literal:initialize-literal: +38433 # var l/edx: (payload var) +38434 68/push 0/imm32/register +38435 68/push 0/imm32/register +38436 68/push 0/imm32/no-stack-offset +38437 68/push 1/imm32/block-depth +38438 52/push-edx +38439 68/push 0x11/imm32/alloc-id:fake +38440 68/push 0/imm32/name +38441 68/push 0/imm32/name +38442 68/push 0x11/imm32/alloc-id:fake:payload +38443 89/<- %edx 4/r32/esp +38444 $test-compare-eax-with-literal:initialize-literal-value: +38445 # l->name = "0x34" +38446 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +38447 (copy-array Heap "0x34" %eax) +38448 $test-compare-eax-with-literal:initialize-inouts: +38449 # var inouts/esi: (payload stmt-var) = [l] +38450 68/push 0/imm32/is-deref:false +38451 68/push 0/imm32/next +38452 68/push 0/imm32/next +38453 52/push-edx/l +38454 68/push 0x11/imm32/alloc-id:fake +38455 68/push 0x11/imm32/alloc-id:fake:payload +38456 89/<- %esi 4/r32/esp +38457 # var inouts = (handle stmt-var) = [var1, var2] +38458 68/push 0/imm32/is-deref:false +38459 56/push-esi/next +38460 68/push 0x11/imm32/alloc-id:fake +38461 51/push-ecx/var1 +38462 68/push 0x11/imm32/alloc-id:fake +38463 68/push 0x11/imm32/alloc-id:fake:payload +38464 89/<- %esi 4/r32/esp +38465 $test-compare-eax-with-literal:initialize-stmt: +38466 # var stmt/esi: (addr statement) +38467 68/push 0/imm32/next +38468 68/push 0/imm32/next +38469 68/push 0/imm32/outputs +38470 68/push 0/imm32/outputs +38471 56/push-esi/inouts +38472 68/push 0x11/imm32/alloc-id:fake +38473 68/push 0/imm32/operation +38474 68/push 0/imm32/operation +38475 68/push 1/imm32/tag:stmt1 +38476 89/<- %esi 4/r32/esp +38477 $test-compare-eax-with-literal:initialize-stmt-operation: +38478 # stmt->operation = "compare" +38479 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38480 (copy-array Heap "compare" %eax) +38481 # convert +38482 c7 0/subop/copy *Curr-block-depth 0/imm32 +38483 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +38484 (flush _test-output-buffered-file) +38485 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38491 # check output +38492 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +38493 # . epilogue +38494 89/<- %esp 5/r32/ebp +38495 5d/pop-to-ebp +38496 c3/return +38497 +38498 test-compare-reg-with-literal: +38499 # compare var1/ecx 0x34 +38500 # => +38501 # 81 7/subop/compare %ecx 0x34/imm32 +38502 # +38503 # . prologue +38504 55/push-ebp +38505 89/<- %ebp 4/r32/esp +38506 # setup +38507 (clear-stream _test-output-stream) +38508 (clear-stream $_test-output-buffered-file->buffer) +38509 $test-compare-reg-with-literal:initialize-type: +38510 # var type/ecx: (payload type-tree) = int +38511 68/push 0/imm32/right:null +38512 68/push 0/imm32/right:null +38513 68/push 0/imm32/left:unused +38514 68/push 1/imm32/value:int +38515 68/push 1/imm32/is-atom?:true +38516 68/push 0x11/imm32/alloc-id:fake:payload +38517 89/<- %ecx 4/r32/esp +38518 $test-compare-reg-with-literal:initialize-var1: +38519 # var var1/ecx: (payload var) +38520 68/push 0/imm32/register +38521 68/push 0/imm32/register +38522 68/push 0/imm32/no-stack-offset +38523 68/push 1/imm32/block-depth +38524 51/push-ecx +38525 68/push 0x11/imm32/alloc-id:fake +38526 68/push 0/imm32/name +38527 68/push 0/imm32/name +38528 68/push 0x11/imm32/alloc-id:fake:payload +38529 89/<- %ecx 4/r32/esp +38530 $test-compare-reg-with-literal:initialize-var1-name: +38531 # var1->name = "var1" +38532 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38533 (copy-array Heap "var1" %eax) +38534 $test-compare-reg-with-literal:initialize-var1-register: +38535 # v->register = "ecx" +38536 8d/copy-address *(ecx+0x1c) 0/r32/eax # Var-register + 4 +38537 (copy-array Heap "ecx" %eax) +38538 $test-compare-reg-with-literal:initialize-literal-type: +38539 # var type/edx: (payload type-tree) = literal +38540 68/push 0/imm32/right:null +38541 68/push 0/imm32/right:null +38542 68/push 0/imm32/left:unused +38543 68/push 0/imm32/value:literal +38544 68/push 1/imm32/is-atom?:true +38545 68/push 0x11/imm32/alloc-id:fake:payload +38546 89/<- %edx 4/r32/esp +38547 $test-compare-reg-with-literal:initialize-literal: +38548 # var l/edx: (payload var) +38549 68/push 0/imm32/register +38550 68/push 0/imm32/register +38551 68/push 0/imm32/no-stack-offset +38552 68/push 1/imm32/block-depth +38553 52/push-edx +38554 68/push 0x11/imm32/alloc-id:fake +38555 68/push 0/imm32/name +38556 68/push 0/imm32/name +38557 68/push 0x11/imm32/alloc-id:fake:payload +38558 89/<- %edx 4/r32/esp +38559 $test-compare-reg-with-literal:initialize-literal-value: +38560 # l->name = "0x34" +38561 8d/copy-address *(edx+4) 0/r32/eax # Var-name + 4 +38562 (copy-array Heap "0x34" %eax) +38563 $test-compare-reg-with-literal:initialize-inouts: +38564 # var inouts/esi: (payload stmt-var) = [l] +38565 68/push 0/imm32/is-deref:false +38566 68/push 0/imm32/next +38567 68/push 0/imm32/next +38568 52/push-edx/l +38569 68/push 0x11/imm32/alloc-id:fake +38570 68/push 0x11/imm32/alloc-id:fake:payload +38571 89/<- %esi 4/r32/esp +38572 # var inouts = (handle stmt-var) = [var1, var2] +38573 68/push 0/imm32/is-deref:false +38574 56/push-esi/next +38575 68/push 0x11/imm32/alloc-id:fake +38576 51/push-ecx/var1 +38577 68/push 0x11/imm32/alloc-id:fake +38578 68/push 0x11/imm32/alloc-id:fake:payload +38579 89/<- %esi 4/r32/esp +38580 $test-compare-reg-with-literal:initialize-stmt: +38581 # var stmt/esi: (addr statement) +38582 68/push 0/imm32/next +38583 68/push 0/imm32/next +38584 68/push 0/imm32/outputs +38585 68/push 0/imm32/outputs +38586 56/push-esi/inouts +38587 68/push 0x11/imm32/alloc-id:fake +38588 68/push 0/imm32/operation +38589 68/push 0/imm32/operation +38590 68/push 1/imm32/tag:stmt1 +38591 89/<- %esi 4/r32/esp +38592 $test-compare-reg-with-literal:initialize-stmt-operation: +38593 # stmt->operation = "compare" +38594 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38595 (copy-array Heap "compare" %eax) +38596 # convert +38597 c7 0/subop/copy *Curr-block-depth 0/imm32 +38598 (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0) +38599 (flush _test-output-buffered-file) +38600 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38606 # check output +38607 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +38608 # . epilogue +38609 89/<- %esp 5/r32/ebp +38610 5d/pop-to-ebp +38611 c3/return +38612 +38613 test-emit-subx-stmt-function-call: +38614 # Call a function on a variable on the stack. +38615 # f foo +38616 # => +38617 # (f *(ebp-8)) +38618 # (Changing the function name supports overloading in general, but here it +38619 # just serves to help disambiguate things.) +38620 # +38621 # There's a variable on the var stack as follows: +38622 # name: 'foo' +38623 # type: int +38624 # stack-offset: -8 +38625 # +38626 # There's nothing in primitives. +38627 # +38628 # We don't perform any checking here on the type of 'f'. +38629 # +38630 # . prologue +38631 55/push-ebp +38632 89/<- %ebp 4/r32/esp +38633 # setup +38634 (clear-stream _test-output-stream) +38635 (clear-stream $_test-output-buffered-file->buffer) +38636 $test-emit-subx-function-call:initialize-type: +38637 # var type/ecx: (payload type-tree) = int +38638 68/push 0/imm32/right:null +38639 68/push 0/imm32/right:null +38640 68/push 0/imm32/left:unused +38641 68/push 1/imm32/value:int +38642 68/push 1/imm32/is-atom?:true +38643 68/push 0x11/imm32/alloc-id:fake:payload +38644 89/<- %ecx 4/r32/esp +38645 $test-emit-subx-function-call:initialize-var: +38646 # var var-foo/ecx: (payload var) = var(type) +38647 68/push 0/imm32/no-register +38648 68/push 0/imm32/no-register +38649 68/push -8/imm32/stack-offset +38650 68/push 1/imm32/block-depth +38651 51/push-ecx/type +38652 68/push 0x11/imm32/alloc-id:fake +38653 68/push 0/imm32/name +38654 68/push 0/imm32/name +38655 68/push 0x11/imm32/alloc-id:fake:payload +38656 89/<- %ecx 4/r32/esp +38657 $test-emit-subx-function-call:initialize-var-name: +38658 # var-foo->name = "foo" +38659 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38660 (copy-array Heap "foo" %eax) +38661 $test-emit-subx-function-call:initialize-stmt-var: +38662 # var operand/ebx: (payload stmt-var) = stmt-var(var-foo) +38663 68/push 0/imm32/is-deref:false +38664 68/push 0/imm32/next +38665 68/push 0/imm32/next +38666 51/push-ecx/var-foo +38667 68/push 0x11/imm32/alloc-id:fake +38668 68/push 0x11/imm32/alloc-id:fake:payload +38669 89/<- %ebx 4/r32/esp +38670 $test-emit-subx-function-call:initialize-stmt: +38671 # var stmt/esi: (addr statement) +38672 68/push 0/imm32/no-outputs +38673 68/push 0/imm32/no-outputs +38674 53/push-ebx/inouts +38675 68/push 0x11/imm32/alloc-id:fake +38676 68/push 0/imm32/operation +38677 68/push 0/imm32/operation +38678 68/push 1/imm32/tag +38679 89/<- %esi 4/r32/esp +38680 $test-emit-subx-function-call:initialize-stmt-operation: +38681 # stmt->operation = "f" +38682 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38683 (copy-array Heap "f" %eax) +38684 # convert +38685 c7 0/subop/copy *Curr-block-depth 0/imm32 +38686 (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0) +38687 (flush _test-output-buffered-file) +38688 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38694 # check output +38695 (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call") +38696 # . epilogue +38697 89/<- %esp 5/r32/ebp +38698 5d/pop-to-ebp +38699 c3/return +38700 +38701 test-emit-subx-stmt-function-call-with-literal-arg: +38702 # Call a function on a literal. +38703 # f 0x34 +38704 # => +38705 # (f2 0x34) +38706 # +38707 # . prologue +38708 55/push-ebp +38709 89/<- %ebp 4/r32/esp +38710 # setup +38711 (clear-stream _test-output-stream) +38712 (clear-stream $_test-output-buffered-file->buffer) +38713 $test-emit-subx-function-call-with-literal-arg:initialize-type: +38714 # var type/ecx: (payload type-tree) = int +38715 68/push 0/imm32/right:null +38716 68/push 0/imm32/right:null +38717 68/push 0/imm32/left:unused +38718 68/push 0/imm32/value:literal +38719 68/push 1/imm32/is-atom?:true +38720 68/push 0x11/imm32/alloc-id:fake:payload +38721 89/<- %ecx 4/r32/esp +38722 $test-emit-subx-function-call-with-literal-arg:initialize-var: +38723 # var var-foo/ecx: (payload var) = var(lit) +38724 68/push 0/imm32/no-register +38725 68/push 0/imm32/no-register +38726 68/push 0/imm32/no-stack-offset +38727 68/push 1/imm32/block-depth +38728 51/push-ecx/type +38729 68/push 0x11/imm32/alloc-id:fake +38730 68/push 0/imm32/name +38731 68/push 0/imm32/name +38732 68/push 0x11/imm32/alloc-id:fake:payload +38733 89/<- %ecx 4/r32/esp +38734 $test-emit-subx-function-call-with-literal-arg:initialize-var-name: +38735 # var-foo->name = "0x34" +38736 8d/copy-address *(ecx+4) 0/r32/eax # Var-name + 4 +38737 (copy-array Heap "0x34" %eax) +38738 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var: +38739 # var operand/ebx: (payload stmt-var) = stmt-var(var-foo) +38740 68/push 0/imm32/is-deref:false +38741 68/push 0/imm32/next +38742 68/push 0/imm32/next +38743 51/push-ecx/var-foo +38744 68/push 0x11/imm32/alloc-id:fake +38745 68/push 0x11/imm32/alloc-id:fake:payload +38746 89/<- %ebx 4/r32/esp +38747 $test-emit-subx-function-call-with-literal-arg:initialize-stmt: +38748 # var stmt/esi: (addr statement) +38749 68/push 0/imm32/no-outputs +38750 68/push 0/imm32/no-outputs +38751 53/push-ebx/inouts +38752 68/push 0x11/imm32/alloc-id:fake +38753 68/push 0/imm32/operation +38754 68/push 0/imm32/operation +38755 68/push 1/imm32/tag +38756 89/<- %esi 4/r32/esp +38757 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation: +38758 # stmt->operation = "f" +38759 8d/copy-address *(esi+4) 0/r32/eax # Stmt1-operation +38760 (copy-array Heap "f" %eax) +38761 # convert +38762 c7 0/subop/copy *Curr-block-depth 0/imm32 +38763 (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0) +38764 (flush _test-output-buffered-file) +38765 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +38771 # check output +38772 (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg") +38773 # . epilogue +38774 89/<- %esp 5/r32/ebp +38775 5d/pop-to-ebp +38776 c3/return +38777 +38778 emit-indent: # out: (addr buffered-file), n: int +38779 # . prologue +38780 55/push-ebp +38781 89/<- %ebp 4/r32/esp +38782 # . save registers +38783 50/push-eax +38784 # var i/eax: int = n +38785 8b/-> *(ebp+0xc) 0/r32/eax +38786 { +38787 # if (i <= 0) break +38788 3d/compare-eax-with 0/imm32 +38789 7e/jump-if-<= break/disp8 +38790 (write-buffered *(ebp+8) " ") +38791 48/decrement-eax +38792 eb/jump loop/disp8 +38793 } +38794 $emit-indent:end: +38795 # . restore registers +38796 58/pop-to-eax +38797 # . epilogue +38798 89/<- %esp 5/r32/ebp +38799 5d/pop-to-ebp +38800 c3/return +38801 +38802 emit-subx-prologue: # out: (addr buffered-file) +38803 # . prologue +38804 55/push-ebp +38805 89/<- %ebp 4/r32/esp +38806 # +38807 (write-buffered *(ebp+8) " # . prologue\n") +38808 (write-buffered *(ebp+8) " 55/push-ebp\n") +38809 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +38810 $emit-subx-prologue:end: +38811 # . epilogue +38812 89/<- %esp 5/r32/ebp +38813 5d/pop-to-ebp +38814 c3/return +38815 +38816 emit-subx-epilogue: # out: (addr buffered-file) +38817 # . prologue +38818 55/push-ebp +38819 89/<- %ebp 4/r32/esp +38820 # +38821 (write-buffered *(ebp+8) " # . epilogue\n") +38822 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +38823 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +38824 (write-buffered *(ebp+8) " c3/return\n") +38825 $emit-subx-epilogue:end: +38826 # . epilogue +38827 89/<- %esp 5/r32/ebp +38828 5d/pop-to-ebp +38829 c3/return diff --git a/html/linux/print-file.mu.html b/html/linux/print-file.mu.html index e0af2261..34cb9c14 100644 --- a/html/linux/print-file.mu.html +++ b/html/linux/print-file.mu.html @@ -80,7 +80,7 @@ if ('onhashchange' in window) { 22 var in: (handle buffered-file) 23 { 24 var addr-in/eax: (addr handle buffered-file) <- address in -25 open *filename, 0/read-only, addr-in +25 open *filename, 0/read-only, addr-in 26 } 27 var _in-addr/eax: (addr buffered-file) <- lookup in 28 var in-addr/ecx: (addr buffered-file) <- copy _in-addr diff --git a/html/linux/sigils.subx.html b/html/linux/sigils.subx.html index 75b8733c..25ea9012 100644 --- a/html/linux/sigils.subx.html +++ b/html/linux/sigils.subx.html @@ -1645,7 +1645,7 @@ if ('onhashchange' in window) { 1895 68/push 0xe/imm32 1896 # . . push slice->start - _test-input-stream 1897 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1898 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1898 2d/subtract-from-eax _test-input-stream/imm32 1899 50/push-eax 1900 # . . call 1901 e8/call check-ints-equal/disp32 @@ -1658,7 +1658,7 @@ if ('onhashchange' in window) { 1908 68/push 0x10/imm32 1909 # . . push slice->end - _test-input-stream 1910 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1911 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1911 2d/subtract-from-eax _test-input-stream/imm32 1912 50/push-eax 1913 # . . call 1914 e8/call check-ints-equal/disp32 @@ -1718,7 +1718,7 @@ if ('onhashchange' in window) { 1968 68/push 0xe/imm32 1969 # . . push slice->start - _test-input-stream 1970 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1971 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1971 2d/subtract-from-eax _test-input-stream/imm32 1972 50/push-eax 1973 # . . call 1974 e8/call check-ints-equal/disp32 @@ -1731,7 +1731,7 @@ if ('onhashchange' in window) { 1981 68/push 0x11/imm32 1982 # . . push slice->end - _test-input-stream 1983 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1984 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1984 2d/subtract-from-eax _test-input-stream/imm32 1985 50/push-eax 1986 # . . call 1987 e8/call check-ints-equal/disp32 @@ -1823,7 +1823,7 @@ if ('onhashchange' in window) { 2073 68/push 0xd/imm32 2074 # . . push slice->start - _test-input-stream 2075 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -2076 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +2076 2d/subtract-from-eax _test-input-stream/imm32 2077 50/push-eax 2078 # . . call 2079 e8/call check-ints-equal/disp32 @@ -1836,7 +1836,7 @@ if ('onhashchange' in window) { 2086 68/push 0x18/imm32 2087 # . . push slice->end - _test-input-stream 2088 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -2089 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +2089 2d/subtract-from-eax _test-input-stream/imm32 2090 50/push-eax 2091 # . . call 2092 e8/call check-ints-equal/disp32 @@ -1886,7 +1886,7 @@ if ('onhashchange' in window) { 2136 68/push 0xd/imm32 2137 # . . push slice->start - _test-input-stream 2138 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -2139 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +2139 2d/subtract-from-eax _test-input-stream/imm32 2140 50/push-eax 2141 # . . call 2142 e8/call check-ints-equal/disp32 @@ -1899,7 +1899,7 @@ if ('onhashchange' in window) { 2149 68/push 0x15/imm32 2150 # . . push slice->end - _test-input-stream 2151 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -2152 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +2152 2d/subtract-from-eax _test-input-stream/imm32 2153 50/push-eax 2154 # . . call 2155 e8/call check-ints-equal/disp32 @@ -1949,7 +1949,7 @@ if ('onhashchange' in window) { 2199 68/push 0xd/imm32 2200 # . . push slice->start - _test-input-stream 2201 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -2202 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +2202 2d/subtract-from-eax _test-input-stream/imm32 2203 50/push-eax 2204 # . . call 2205 e8/call check-ints-equal/disp32 @@ -1962,7 +1962,7 @@ if ('onhashchange' in window) { 2212 68/push 0x19/imm32 2213 # . . push slice->end - _test-input-stream 2214 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -2215 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +2215 2d/subtract-from-eax _test-input-stream/imm32 2216 50/push-eax 2217 # . . call 2218 e8/call check-ints-equal/disp32 @@ -2041,7 +2041,7 @@ if ('onhashchange' in window) { 2291 # if (*local-slice->start == '(') goto compound expression 2292 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax 2293 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2294 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2294 25/and-eax-with 0xff/imm32 2295 3d/compare-eax-and 0x28/imm32/open-paren 2296 74/jump-if-= $parse-effective-address:compound-expression/disp8 2297 $parse-effective-address:simple-register: @@ -2107,7 +2107,7 @@ if ('onhashchange' in window) { 2357 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi 2358 # if (*local-slice->start == ')') goto end 2359 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2360 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2360 25/and-eax-with 0xff/imm32 2361 3d/compare-eax-and 0x29/imm32/close-paren 2362 0f 84/jump-if-= $parse-effective-address:end/disp32 2363 # if (*local-slice->start == '-') goto displacement @@ -2184,7 +2184,7 @@ if ('onhashchange' in window) { 2434 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi 2435 # if (*local-slice->start == ')') goto end 2436 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2437 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2437 25/and-eax-with 0xff/imm32 2438 3d/compare-eax-and 0x29/imm32/close-paren 2439 0f 84/jump-if-= $parse-effective-address:end/disp32 2440 $parse-effective-address:check-for-scale: @@ -2196,7 +2196,7 @@ if ('onhashchange' in window) { 2446 # if (*local-slice->start != '<') goto error2 2447 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax 2448 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2449 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2449 25/and-eax-with 0xff/imm32 2450 3d/compare-eax-and 0x3c/imm32/less-than 2451 0f 85/jump-if-!= $parse-effective-address:error2/disp32 2452 # ++local-slice->start to skip '<' @@ -2236,7 +2236,7 @@ if ('onhashchange' in window) { 2486 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi 2487 # if (*local-slice->start == ')') goto end 2488 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2489 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2489 25/and-eax-with 0xff/imm32 2490 3d/compare-eax-and 0x29/imm32/close-paren 2491 74/jump-if-= $parse-effective-address:end/disp8 2492 $parse-effective-address:check-for-displacement: @@ -2270,7 +2270,7 @@ if ('onhashchange' in window) { 2520 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi 2521 # if (*local-slice->start != ')') goto error4 2522 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2523 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2523 25/and-eax-with 0xff/imm32 2524 3d/compare-eax-and 0x29/imm32/close-paren 2525 0f 85/jump-if-!= $parse-effective-address:error4/disp32 2526 $parse-effective-address:end: @@ -3470,7 +3470,7 @@ if ('onhashchange' in window) { 3895 # if (*local-slice->start == '(') return false 3896 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax 3897 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -3898 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +3898 25/and-eax-with 0xff/imm32 3899 3d/compare-eax-and 0x28/imm32/open-paren 3900 74/jump-if-= $disp32-mode?:false/disp8 3901 $disp32-mode?:check-for-register: diff --git a/html/linux/stack_array.subx.html b/html/linux/stack_array.subx.html new file mode 100644 index 00000000..cbadf326 --- /dev/null +++ b/html/linux/stack_array.subx.html @@ -0,0 +1,699 @@ + + + + +Mu - linux/stack_array.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/stack_array.subx +
+  1 == code
+  2 
+  3 # Problem: create a function which pushes n zeros on the stack.
+  4 # This is not a regular function, so it won't be idiomatic.
+  5 # Registers must be properly restored.
+  6 # Registers can be spilled, but that modifies the stack and needs to be
+  7 # cleaned up.
+  8 
+  9 # This file is kinda like a research notebook, to interactively arrive at the
+ 10 # solution. Nobody should have to do this without a computer. To run it:
+ 11 #   $ ./translate_subx_debug 000init.linux stack_array.subx  &&  bootstrap/bootstrap --debug --trace --dump run a.elf
+ 12 # There are multiple versions. You'll need to uncomment exactly one.
+ 13 
+ 14 # The final version has its own Entry, but the others share this one.
+ 15 #? Entry:
+ 16 #?     # . prologue
+ 17 #?     89/<- %ebp 4/r32/esp
+ 18 #?     #
+ 19 #?     68/push 0xfcfdfeff/imm32
+ 20 #?     b8/copy-to-eax 0x34353637/imm32
+ 21 #? $dump-stack:
+ 22 #?     (push-n-zero-bytes 0x20)
+ 23 #? $dump-stack2:
+ 24 #?     68/push 0x20202020/imm32
+ 25 #? $dump-stack3:
+ 26 #?     b8/copy-to-eax 1/imm32/exit
+ 27 #?     cd/syscall 0x80/imm8
+ 28 
+ 29 ## 0
+ 30 
+ 31 #? push-n-zero-bytes:  # n: int
+ 32 #?     # . prologue
+ 33 #?     55/push-ebp
+ 34 #?     89/<- %ebp 4/r32/esp
+ 35 #? $push-n-zero-bytes:end:
+ 36 #?     # . epilogue
+ 37 #?     89/<- %esp 5/r32/ebp
+ 38 #?     5d/pop-to-ebp
+ 39 #?     c3/return
+ 40 
+ 41 # stack at dump-stack:
+ 42 # 0 a: bdffffd0: 00000000     00000000     00000000      00000000
+ 43 # 0 a: bdffffe0: 00000000     00000000     00000000      00000000
+ 44 # 0 a: bdfffff0: 00000000     fcfdfeff     00000001      bf000000
+ 45 #
+ 46 # =>
+ 47 #
+ 48 # stack at dump-stack3:
+ 49 # 0 a: stack:
+ 50 # 0 a: bdffffd0: 00000000     00000000     00000000      00000000
+ 51 # 0 a: bdffffe0: 00000000     00000000     bdfffff8/ebp  090000cc/ra
+ 52 # 0 a: bdfffff0: 00000004/arg fcfdfeff     00000001      bf000000
+ 53 
+ 54 ## 1
+ 55 
+ 56 #? push-n-zero-bytes:  # n: int
+ 57 #?     # . prologue
+ 58 #?     55/push-ebp
+ 59 #?     89/<- %ebp 4/r32/esp
+ 60 #?     # . save registers
+ 61 #?     50/push-eax
+ 62 #? $push-n-zero-bytes:end:
+ 63 #?     # . restore registers
+ 64 #?     58/pop-to-eax
+ 65 #?     # . epilogue
+ 66 #?     5d/pop-to-ebp
+ 67 #?     c3/return
+ 68 
+ 69 # stack at dump-stack3:
+ 70 # 0 a: bdffffd0: 00000000 00000000 00000000 00000000
+ 71 # 0 a: bdffffe0: 00000000 34353637 bdfffff8 090000d1
+ 72 # 0 a: bdfffff0: 00000004 fcfdfeff 00000001 bf000000
+ 73 
+ 74 ## 2
+ 75 
+ 76 #? push-n-zero-bytes:  # n: int
+ 77 #?     # . prologue
+ 78 #?     55/push-ebp
+ 79 #?     89/<- %ebp 4/r32/esp
+ 80 #?     # . save registers
+ 81 #?     50/push-eax
+ 82 #?     #
+ 83 #?     8b/-> *(esp+8) 0/r32/eax
+ 84 #?     2b/subtract *(ebp+8) 4/r32/esp
+ 85 #?     89/<- *(esp+8) 0/r32/eax
+ 86 #? $push-n-zero-bytes:end:
+ 87 #?     # . restore registers
+ 88 #?     58/pop-to-eax
+ 89 #?     # . epilogue
+ 90 #?     5d/pop-to-ebp
+ 91 #?     c3/return
+ 92 
+ 93 # stack at dump-stack3:
+ 94 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+ 95 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+ 96 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+ 97 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+ 98 # 0 a: bdffffd0: 00000000 00000000 00000000 00000000
+ 99 # 0 a: bdffffe0: 00000000 34353637 bdfffff8 090000d1
+100 # 0 a: bdfffff0: 00000020 fcfdfeff 00000001 bf000000
+101 
+102 ## 3
+103 
+104 #? push-n-zero-bytes:  # n: int
+105 #?     # . prologue
+106 #?     55/push-ebp
+107 #?     89/<- %ebp 4/r32/esp
+108 #?     # . save registers
+109 #?     # -- esp = ebp
+110 #?     50/push-eax
+111 #?     # -- esp+8 = ebp+4
+112 #?     8b/-> *(esp+8) 0/r32/eax
+113 #?     2b/subtract *(ebp+8) 4/r32/esp
+114 #?     89/<- *(esp+8) 0/r32/eax
+115 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+116 #? $push-n-zero-bytes:end:
+117 #?     # . restore registers
+118 #?     58/pop-to-eax
+119 #?     # . epilogue
+120 #?     5d/pop-to-ebp
+121 #?     c3/return
+122 
+123 # stack at dump-stack3:
+124 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+125 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+126 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+127 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+128 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+129 # 0 a: bdffffe0: 00000000 34353637 bdfffff8 00000000
+130 # 0 a: bdfffff0: 00000020 fcfdfeff 00000001 bf000000
+131 
+132 ## 4
+133 
+134 #? push-n-zero-bytes:  # n: int
+135 #?     # . prologue
+136 #?     55/push-ebp
+137 #?     89/<- %ebp 4/r32/esp
+138 #?     # . save registers
+139 #?     # -- esp = ebp
+140 #?     50/push-eax
+141 #?     # copy return address over
+142 #?     # -- esp+8 = ebp+4
+143 #?     8b/-> *(esp+8) 0/r32/eax
+144 #?     2b/subtract *(ebp+8) 4/r32/esp
+145 #?     89/<- *(esp+8) 0/r32/eax
+146 #?     58/pop-to-eax
+147 #?     c7 0/subop/copy *(ebp+8) 0/imm32
+148 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+149 #?     c7 0/subop/copy *(ebp+0) 0/imm32
+150 #?     c7 0/subop/copy *(ebp-4) 0/imm32
+151 #?     # . epilogue
+152 #?     5d/pop-to-ebp
+153 #?     c3/return
+154 
+155 # stack at dump-stack3:
+156 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+157 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+158 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+159 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+160 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+161 # 0 a: bdffffe0: 00000000 00000000 00000000 00000000
+162 # 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
+163 
+164 # Stack looks good now (the 20202020 marks where the array length 0x20 will
+165 # go, and the next 0x20 bytes show the space for the array has been zeroed
+166 # out).
+167 # Final issue: ebp has been clobbered on return.
+168 
+169 ## 5
+170 
+171 # I'd like to translate ebp to esp so we can stop pushing ebp. But we need to
+172 # hold 'n' somewhere, which would require a register, which we then need to
+173 # push.
+174 
+175 #? push-n-zero-bytes:  # n: int
+176 #?     55/push-ebp
+177 #?     89/<- %ebp 4/r32/esp
+178 #?     # -- esp = ebp
+179 #?     50/push-eax
+180 #? $push-n-zero-bytes:bulk-cleaning:
+181 #? $push-n-zero-bytes:copy-ra:
+182 #?     # -- esp+8 = ebp+4
+183 #?     8b/-> *(esp+8) 0/r32/eax
+184 #?     2b/subtract *(esp+0xc) 4/r32/esp
+185 #?     # -- esp+8+n = ebp+4
+186 #?     89/<- *(esp+8) 0/r32/eax
+187 #?     58/pop-to-eax
+188 #?     # -- esp+n = ebp
+189 #? $push-n-zero-bytes:spot-cleaning:
+190 #?     c7 0/subop/copy *(ebp+8) 0/imm32
+191 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+192 #?     c7 0/subop/copy *(ebp+0) 0/imm32
+193 #?     c7 0/subop/copy *(ebp-4) 0/imm32
+194 #?     5d/pop-to-ebp
+195 #?     c3/return
+196 
+197 # stack at dump-stack3:
+198 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+199 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+200 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+201 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+202 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+203 # 0 a: bdffffe0: 00000000 00000000 00000000 00000000
+204 # 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
+205 
+206 # Bah. May be simpler to just create a new segment of global space for this
+207 # function.
+208 
+209 ## 6
+210 
+211 #? push-n-zero-bytes:  # n: int
+212 #?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+213 #?     89/<- %ebp 4/r32/esp
+214 #?     # -- esp = ebp
+215 #?     50/push-eax
+216 #? $push-n-zero-bytes:bulk-cleaning:
+217 #? $push-n-zero-bytes:copy-ra:
+218 #?     # -- esp+8 = ebp+4
+219 #?     # -- esp+4 = ebp
+220 #?     8b/-> *(esp+4) 0/r32/eax
+221 #?     2b/subtract *(ebp+4) 4/r32/esp
+222 #?     # -- esp+4+n = ebp
+223 #?     89/<- *(esp+4) 0/r32/eax
+224 #?     58/pop-to-eax
+225 #?     # -- esp+n = ebp
+226 #? $push-n-zero-bytes:spot-cleaning:
+227 #?     c7 0/subop/copy *(ebp+4) 0/imm32
+228 #?     c7 0/subop/copy *(ebp+0) 0/imm32
+229 #?     c7 0/subop/copy *(ebp-4) 0/imm32
+230 #?     c7 0/subop/copy *(ebp-8) 0/imm32
+231 #?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+232 #?     c3/return
+233 #? 
+234 #? == data
+235 #? Push-n-zero-bytes-ebp:  # (addr int)
+236 #?   0/imm32
+237 #? == code
+238 
+239 # stack at dump-stack3:
+240 # 0 a: bdffff90: 00000000 00000000 00000000 00000000
+241 # 0 a: bdffffa0: 00000000 00000000 00000000 00000000
+242 # 0 a: bdffffb0: 00000000 00000000 00000000 00000000
+243 # 0 a: bdffffc0: 00000000 00000000 00000000 090000d1
+244 # 0 a: bdffffd0: 20202020 00000000 00000000 00000000
+245 # 0 a: bdffffe0: 00000000 00000000 00000000 00000000
+246 # 0 a: bdfffff0: 00000000 fcfdfeff 00000001 bf000000
+247 
+248 # Ok, we're there. Now start using zero-out rather than spot-cleaning.
+249 
+250 ## 7: we need to zero out the return address, but we can't do it inside the function.
+251 ## So we'll change the signature slightly.
+252 ## Before: clear N bytes and then push N as the array length.
+253 ## After: clear N bytes, set *esp to N.
+254 ## The helper adds and clears N bytes *before* esp. esp can't be cleared since
+255 ## it contains the return address.
+256 
+257 #? Entry:
+258 #?     # . prologue
+259 #?     89/<- %ebp 4/r32/esp
+260 #?     #
+261 #?     68/push 0xfcfdfeff/imm32
+262 #?     b8/copy-to-eax 0x34353637/imm32
+263 #? $dump-stack0:
+264 #?     (push-n-zero-bytes 0x20)
+265 #? $dump-stack9:
+266 #?     c7 0/subop/copy *esp 0x20/imm32
+267 #? $dump-stacka:
+268 #?     b8/copy-to-eax 1/imm32/exit
+269 #?     cd/syscall 0x80/imm8
+270 #? 
+271 #? push-n-zero-bytes:  # n: int
+272 #? $push-n-zero-bytes:prologue:
+273 #?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+274 #?     89/<- %ebp 4/r32/esp
+275 #? $push-n-zero-bytes:copy-ra:
+276 #? $dump-stack1:
+277 #?     # -- esp = ebp
+278 #?     50/push-eax
+279 #? $dump-stack2:
+280 #?     # -- esp+8 = ebp+4
+281 #?     # -- esp+4 = ebp
+282 #?     8b/-> *(esp+4) 0/r32/eax
+283 #? $dump-stack3:
+284 #?     2b/subtract *(ebp+4) 4/r32/esp
+285 #? $dump-stack4:
+286 #?     # -- esp+4+n = ebp
+287 #?     89/<- *(esp+4) 0/r32/eax
+288 #? $dump-stack5:
+289 #?     58/pop-to-eax
+290 #?     # -- esp+n = ebp
+291 #? $push-n-zero-bytes:bulk-cleaning:
+292 #? $dump-stack6:
+293 #?     89/<- *Push-n-zero-bytes-esp 4/r32/esp
+294 #?     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
+295 #? $dump-stack7:
+296 #?     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
+297 #? $push-n-zero-bytes:epilogue:
+298 #? $dump-stack8:
+299 #?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+300 #?     c3/return
+301 #? 
+302 #? zero-out:  # start: (addr byte), len: int
+303 #?     # pseudocode:
+304 #?     #   curr/esi = start
+305 #?     #   i/ecx = 0
+306 #?     #   while true
+307 #?     #     if (i >= len) break
+308 #?     #     *curr = 0
+309 #?     #     ++curr
+310 #?     #     ++i
+311 #?     #
+312 #?     # . prologue
+313 #?     55/push-ebp
+314 #?     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+315 #?     # . save registers
+316 #?     50/push-eax
+317 #?     51/push-ecx
+318 #?     52/push-edx
+319 #?     56/push-esi
+320 #?     # curr/esi = start
+321 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+322 #?     # var i/ecx: int = 0
+323 #?     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+324 #?     # edx = len
+325 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+326 #? $zero-out:loop:
+327 #?     # if (i >= len) break
+328 #?     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+329 #?     7d/jump-if->=  $zero-out:end/disp8
+330 #?     # *curr = 0
+331 #?     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+332 #?     # ++curr
+333 #?     46/increment-esi
+334 #?     # ++i
+335 #?     41/increment-ecx
+336 #?     eb/jump  $zero-out:loop/disp8
+337 #? $zero-out:end:
+338 #?     # . restore registers
+339 #?     5e/pop-to-esi
+340 #?     5a/pop-to-edx
+341 #?     59/pop-to-ecx
+342 #?     58/pop-to-eax
+343 #?     # . epilogue
+344 #?     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+345 #?     5d/pop-to-ebp
+346 #?     c3/return
+347 #? 
+348 #? == data
+349 #? Push-n-zero-bytes-ebp:  # (addr int)
+350 #?   0/imm32
+351 #? Push-n-zero-bytes-esp:  # (addr int)
+352 #?   0/imm32
+353 #? == code
+354 
+355 # stack at dump-stack0:
+356 # 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
+357 # 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
+358 # 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
+359 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+360 # 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
+361 
+362 # desired state after push-n-zero-bytes:
+363 # 0 a: bdffff90:  00000000   00000000   00000000   00000000 
+364 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
+365 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
+366 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
+367 # 0 a: bdffffd0: [rrrrrrrr]  00000000   00000000   00000000 
+368 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+369 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
+370 
+371 # Stack pointer contains ra is caller's responsibility to over-write with array length.
+372 
+373 # actual state:
+374 # 0 a: bdffff90:  00000000   00000000   00000000   00000000
+375 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000
+376 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
+377 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1
+378 # 0 a: bdffffd0:  00000000  [00000000]  00000000   00000000
+379 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000
+380 # 0 a: bdfffff0:  00000020   fcfdfeff   00000001   bf000000
+381 
+382 # Couple of issues. But where does the return address disappear to?
+383 
+384 ## 8:
+385 
+386 #? Entry:
+387 #?     # . prologue
+388 #?     89/<- %ebp 4/r32/esp
+389 #?     #
+390 #?     68/push 0xfcfdfeff/imm32
+391 #?     b8/copy-to-eax 0x34353637/imm32
+392 #? $dump-stack0:
+393 #?     (push-n-zero-bytes 0x20)
+394 #? $dump-stack9:
+395 #?     68/push 0x20/imm32
+396 #? #?     c7 0/subop/copy *esp 0x20/imm32
+397 #? $dump-stacka:
+398 #?     b8/copy-to-eax 1/imm32/exit
+399 #?     cd/syscall 0x80/imm8
+400 #? 
+401 #? push-n-zero-bytes:  # n: int
+402 #? $push-n-zero-bytes:prologue:
+403 #?     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+404 #?     89/<- %ebp 4/r32/esp
+405 #? $push-n-zero-bytes:copy-ra:
+406 #? $dump-stack1:
+407 #?     # -- esp = ebp
+408 #?     50/push-eax
+409 #? $dump-stack2:
+410 #?     # -- esp+8 = ebp+4
+411 #?     # -- esp+4 = ebp
+412 #?     8b/-> *(esp+4) 0/r32/eax
+413 #? $dump-stack3:
+414 #?     2b/subtract *(ebp+4) 4/r32/esp
+415 #? $dump-stack4:
+416 #?     # -- esp+4+n = ebp
+417 #?     89/<- *(esp+4) 0/r32/eax
+418 #? $dump-stack5:
+419 #?     58/pop-to-eax
+420 #?     # -- esp+n = ebp
+421 #? $push-n-zero-bytes:bulk-cleaning:
+422 #? $dump-stack6:
+423 #?     89/<- *Push-n-zero-bytes-esp 4/r32/esp
+424 #?     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
+425 #? $dump-stack7:
+426 #?     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
+427 #? $push-n-zero-bytes:epilogue:
+428 #? $dump-stack8:
+429 #?     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+430 #?     c3/return
+431 #? 
+432 #? zero-out:  # start: (addr byte), len: int
+433 #?     # pseudocode:
+434 #?     #   curr/esi = start
+435 #?     #   i/ecx = 0
+436 #?     #   while true
+437 #?     #     if (i >= len) break
+438 #?     #     *curr = 0
+439 #?     #     ++curr
+440 #?     #     ++i
+441 #?     #
+442 #?     # . prologue
+443 #?     55/push-ebp
+444 #?     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+445 #?     # . save registers
+446 #?     50/push-eax
+447 #?     51/push-ecx
+448 #?     52/push-edx
+449 #?     56/push-esi
+450 #?     # curr/esi = start
+451 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+452 #?     # var i/ecx: int = 0
+453 #?     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+454 #?     # edx = len
+455 #?     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+456 #? $zero-out:loop:
+457 #?     # if (i >= len) break
+458 #?     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+459 #?     7d/jump-if->=  $zero-out:end/disp8
+460 #?     # *curr = 0
+461 #?     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+462 #?     # ++curr
+463 #?     46/increment-esi
+464 #?     # ++i
+465 #?     41/increment-ecx
+466 #?     eb/jump  $zero-out:loop/disp8
+467 #? $zero-out:end:
+468 #?     # . restore registers
+469 #?     5e/pop-to-esi
+470 #?     5a/pop-to-edx
+471 #?     59/pop-to-ecx
+472 #?     58/pop-to-eax
+473 #?     # . epilogue
+474 #?     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+475 #?     5d/pop-to-ebp
+476 #?     c3/return
+477 #? 
+478 #? == data
+479 #? Push-n-zero-bytes-ebp:  # (addr int)
+480 #?   0/imm32
+481 #? Push-n-zero-bytes-esp:  # (addr int)
+482 #?   0/imm32
+483 #? == code
+484 
+485 # stack at dump-stack0:
+486 # 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
+487 # 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
+488 # 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
+489 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+490 # 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
+491 
+492 # desired state after push-n-zero-bytes:
+493 # 0 a: bdffff90:  00000000   00000000   00000000   00000000 
+494 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
+495 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
+496 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
+497 # 0 a: bdffffd0: [rrrrrrrr]  00000000   00000000   00000000 
+498 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+499 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
+500 
+501 # actual state:
+502 # 0 a: bdffff90:  00000000   00000000   00000000   00000000
+503 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000
+504 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
+505 # 0 a: bdffffc0:  09000124   bdffffd0   00000020   090000d1
+506 # 0 a: bdffffd0: [00000000]  00000000   00000000   00000000
+507 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000
+508 # 0 a: bdfffff0:  00000020   fcfdfeff   00000001   bf000000
+509 
+510 # Ok, just one diff, at bdfffff0
+511 
+512 ## 9:
+513 
+514 Entry:
+515     # . prologue
+516     89/<- %ebp 4/r32/esp
+517     #
+518     68/push 0xfcfdfeff/imm32
+519     b8/copy-to-eax 0x34353637/imm32
+520 $dump-stack0:
+521     (push-n-zero-bytes 0x20)
+522 $dump-stack9:
+523     68/push 0x20/imm32
+524 $dump-stacka:
+525     b8/copy-to-eax 1/imm32/exit
+526     cd/syscall 0x80/imm8
+527 
+528 push-n-zero-bytes:  # n: int
+529 $push-n-zero-bytes:prologue:
+530     89/<- *Push-n-zero-bytes-ebp 5/r32/ebp  # spill ebp without affecting stack
+531     89/<- %ebp 4/r32/esp
+532 $push-n-zero-bytes:copy-ra:
+533 $dump-stack1:
+534     # -- esp = ebp
+535     50/push-eax
+536 $dump-stack2:
+537     # -- esp+8 = ebp+4
+538     # -- esp+4 = ebp
+539     8b/-> *(esp+4) 0/r32/eax
+540 $dump-stack3:
+541     2b/subtract *(ebp+4) 4/r32/esp
+542 $dump-stack4:
+543     # -- esp+4+n = ebp
+544     89/<- *(esp+4) 0/r32/eax
+545 $dump-stack5:
+546     58/pop-to-eax
+547     # -- esp+n = ebp
+548 $push-n-zero-bytes:bulk-cleaning:
+549 $dump-stack6:
+550     89/<- *Push-n-zero-bytes-esp 4/r32/esp
+551     81 0/subop/add *Push-n-zero-bytes-esp 4/imm32
+552 $dump-stack7:
+553     81 0/subop/add *(ebp+4) 4/imm32
+554     (zero-out *Push-n-zero-bytes-esp *(ebp+4))  # n
+555 $push-n-zero-bytes:epilogue:
+556 $dump-stack8:
+557     8b/-> *Push-n-zero-bytes-ebp 5/r32/ebp  # restore spill
+558     c3/return
+559 
+560 zero-out:  # start: (addr byte), len: int
+561     # pseudocode:
+562     #   curr/esi = start
+563     #   i/ecx = 0
+564     #   while true
+565     #     if (i >= len) break
+566     #     *curr = 0
+567     #     ++curr
+568     #     ++i
+569     #
+570     # . prologue
+571     55/push-ebp
+572     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+573     # . save registers
+574     50/push-eax
+575     51/push-ecx
+576     52/push-edx
+577     56/push-esi
+578     # curr/esi = start
+579     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
+580     # var i/ecx: int = 0
+581     31/xor                          3/mod/direct    1/rm32/ecx    .           .             .           1/r32/ecx   .               .                 # clear ecx
+582     # edx = len
+583     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
+584 $zero-out:loop:
+585     # if (i >= len) break
+586     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+587     7d/jump-if->=  $zero-out:end/disp8
+588     # *curr = 0
+589     c6          0/subop/copy        0/mod/direct    6/rm32/esi    .           .             .           .           .               0/imm8            # copy byte to *esi
+590     # ++curr
+591     46/increment-esi
+592     # ++i
+593     41/increment-ecx
+594     eb/jump  $zero-out:loop/disp8
+595 $zero-out:end:
+596     # . restore registers
+597     5e/pop-to-esi
+598     5a/pop-to-edx
+599     59/pop-to-ecx
+600     58/pop-to-eax
+601     # . epilogue
+602     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+603     5d/pop-to-ebp
+604     c3/return
+605 
+606 == data
+607 Push-n-zero-bytes-ebp:  # (addr int)
+608   0/imm32
+609 Push-n-zero-bytes-esp:  # (addr int)
+610   0/imm32
+611 == code
+612 
+613 # stack at dump-stack0:
+614 # 0 a: bdffffb0:  00000000   00000000   00000000   00000000 
+615 # 0 a: bdffffc0:  00000000   00000000   00000000   00000000 
+616 # 0 a: bdffffd0:  00000000   00000000   00000000   00000000 
+617 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+618 # 0 a: bdfffff0:  00000000  [fcfdfeff]  00000001   bf000000 
+619 
+620 # desired state after push-n-zero-bytes:
+621 # 0 a: bdffff90:  00000000   00000000   00000000   00000000 
+622 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000 
+623 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec 
+624 # 0 a: bdffffc0:  0900012a   bdffffd0   00000020   090000d1 
+625 # 0 a: bdffffd0: [xxxxxxxx]  00000000   00000000   00000000 
+626 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000 
+627 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000 
+628 
+629 # actual state:
+630 # 0 a: bdffff90:  00000000   00000000   00000000   00000000
+631 # 0 a: bdffffa0:  00000000   00000000   00000000   00000000
+632 # 0 a: bdffffb0:  00000000   00000000   00000000   bdffffec
+633 # 0 a: bdffffc0:  0900012f   bdffffd0   00000024   090000d1
+634 # 0 a: bdffffd0: [00000000]  00000000   00000000   00000000
+635 # 0 a: bdffffe0:  00000000   00000000   00000000   00000000
+636 # 0 a: bdfffff0:  00000000   fcfdfeff   00000001   bf000000
+
+ + + diff --git a/html/linux/survey_baremetal.subx.html b/html/linux/survey_baremetal.subx.html index 90aa4eeb..c35811d7 100644 --- a/html/linux/survey_baremetal.subx.html +++ b/html/linux/survey_baremetal.subx.html @@ -63,2864 +63,976 @@ if ('onhashchange' in window) {
    1 # Assign addresses (co-ordinates) to instructions (landmarks) in a program
    2 # (landscape).
-   3 # Use the addresses assigned to replace labels.
-   4 #
-   5 # To build:
-   6 #   $ bootstrap/bootstrap translate [01]*.subx subx-params.subx survey_baremetal.subx  -o survey_baremetal
-   7 #
-   8 # The expected input is a stream of bytes and some interspersed labels.
-   9 # Comments and '==' segment headers are allowed, but names are ignored. The
-  10 # emitted code will all lie in a single contiguous address range starting at
-  11 # address 0x7c00. Addresses in segment headers are optional. If provided, this
-  12 # program will insert padding in the output until the desired address is
-  13 # reached.
-  14 #
-  15 #   $ cat x
-  16 #   == code
-  17 #   l1:
-  18 #   aa bb l1/imm8
-  19 #   cc dd l2/disp32
-  20 #   l2:
-  21 #   ee foo/imm32
-  22 #   == data 0x7c10
-  23 #   foo:
-  24 #     34
-  25 #
-  26 # The output is the stream of bytes without segment headers or label definitions,
-  27 # and with label references replaced with numeric values/displacements.
-  28 #
-  29 #   $ cat x  |bootstrap/bootstrap run survey_baremetal
-  30 #   # 0x7c00
-  31 #   aa bb nn  # some computed address
-  32 #   cc dd nn nn nn nn  # some computed displacement
-  33 #   ee nn nn nn nn  # address right after this instruction
-  34 #   # 0x7c0e
-  35 #   00 00  # padding
-  36 #   # 0x7c10
-  37 #   34  # data segment interleaved with code
-  38 
-  39 == code
-  40 #   instruction                     effective address                                                   register    displacement    immediate
-  41 # . op          subop               mod             rm32          base        index         scale       r32
-  42 # . 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
-  43 
-  44 Entry:  # run tests if necessary, convert stdin if not
-  45     # . prologue
-  46     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-  47 
-  48     # Heap = new-segment(Heap-size)
-  49     # . . push args
-  50     68/push  Heap/imm32
-  51     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Heap-size/disp32                  # push *Heap-size
+   3 #
+   4 # To build:
+   5 #   $ bootstrap/bootstrap translate [01]*.subx subx-params.subx survey_baremetal.subx  -o survey_baremetal
+   6 #
+   7 # The expected input is a stream of bytes and some interspersed labels.
+   8 # Comments and '==' segment headers are allowed, but names are ignored. The
+   9 # emitted code will all lie in a single contiguous address range starting at
+  10 # address 0x7c00. Addresses in segment headers are optional. If provided, this
+  11 # program will insert padding in the output until the desired address is
+  12 # reached.
+  13 #
+  14 #   $ cat x
+  15 #   == code
+  16 #   l1:
+  17 #   aa bb l1/imm8
+  18 #   cc dd l2/disp32
+  19 #   l2:
+  20 #   ee foo/imm32
+  21 #   == data 0x7c10
+  22 #   foo:
+  23 #     34
+  24 #
+  25 # The output is a list of labels and their computed addresses.
+  26 #
+  27 #   $ cat x  |bootstrap/bootstrap run survey_baremetal
+  28 #   0x7c00 l1
+  29 #   0x7c09 l2
+  30 #   0x7c10 foo
+  31 
+  32 == code
+  33 #   instruction                     effective address                                                   register    displacement    immediate
+  34 # . op          subop               mod             rm32          base        index         scale       r32
+  35 # . 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
+  36 
+  37 Entry:  # run tests if necessary, convert stdin if not
+  38     # . prologue
+  39     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+  40 
+  41     # Heap = new-segment(Heap-size)
+  42     # . . push args
+  43     68/push  Heap/imm32
+  44     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Heap-size/disp32                  # push *Heap-size
+  45     # . . call
+  46     e8/call  new-segment/disp32
+  47     # . . discard args
+  48     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+  49     # initialize-trace-stream(Trace-size)
+  50     # . . push args
+  51     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-size/disp32                 # push *Heap-size
   52     # . . call
-  53     e8/call  new-segment/disp32
+  53     e8/call  initialize-trace-stream/disp32
   54     # . . discard args
-  55     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-  56     # initialize-trace-stream(Trace-size)
-  57     # . . push args
-  58     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-size/disp32                 # push *Heap-size
-  59     # . . call
-  60     e8/call  initialize-trace-stream/disp32
-  61     # . . discard args
-  62     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-  63 
-  64     # - if argc > 1 and argv[1] == "test", then return run_tests()
-  65     # if (argc <= 1) goto interactive
-  66     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0/disp8         1/imm32           # compare *ebp
-  67     7e/jump-if-<=  $subx-survey-main:interactive/disp8
-  68     # if (!kernel-string-equal?(argv[1], "test")) goto interactive
-  69     # . eax = kernel-string-equal?(argv[1], "test")
-  70     # . . push args
-  71     68/push  "test"/imm32
-  72     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
-  73     # . . call
-  74     e8/call  kernel-string-equal?/disp32
-  75     # . . discard args
-  76     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-  77     # . if (eax == false) goto interactive
-  78     3d/compare-eax-and  0/imm32/false
-  79     74/jump-if-=  $subx-survey-main:interactive/disp8
-  80     # run-tests()
-  81 #?     e8/call  test-emit-output-with-padding/disp32
-  82     e8/call  run-tests/disp32
-  83     # syscall(exit, *Num-test-failures)
-  84     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/ebx   Num-test-failures/disp32          # copy *Num-test-failures to ebx
-  85     eb/jump  $subx-survey-main:end/disp8
-  86 $subx-survey-main:interactive:
-  87     # - otherwise convert stdin
-  88     # subx-survey(Stdin, Stdout)
-  89     # . . push args
-  90     68/push  Stdout/imm32
-  91     68/push  Stdin/imm32
-  92     # . . call
-  93     e8/call  subx-survey/disp32
-  94     # . . discard args
-  95     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-  96 #?     # . write-stream(2/stderr, Trace-stream)
-  97 #?     # . . push args
-  98 #?     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
-  99 #?     68/push  2/imm32/stderr
- 100 #?     # . . call
- 101 #?     e8/call  write-stream/disp32
- 102 #?     # . . discard args
- 103 #?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 104     # syscall(exit, 0)
- 105     bb/copy-to-ebx  0/imm32
- 106 $subx-survey-main:end:
- 107     e8/call  syscall_exit/disp32
- 108 
- 109 subx-survey:  # infile: (addr buffered-file), out: (addr buffered-file)
- 110     # pseudocode
- 111     #   var in: (stream byte Input-size)
- 112     #   slurp(infile, in)
- 113     #   var labels: (stream {label-name, address} Max-labels)
- 114     #   compute-offsets(in, labels)
- 115     #   rewind-stream(in)
- 116     #   emit-output(in, out, labels)
- 117     #
- 118     # . prologue
- 119     55/push-ebp
- 120     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 121     # . save registers
- 122     51/push-ecx
- 123     52/push-edx
- 124     56/push-esi
- 125     # var labels/edx: (stream {label-name, address} Max-labels)
- 126     # (we get more rows than Max-labels advertises because row size is smaller than in survey_elf)
- 127     # . data
- 128     2b/subtract                     0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Max-labels/disp32                 # subtract *Max-labels from esp
- 129     # . size
- 130     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Max-labels/disp32                 # push *Max-labels
- 131     # . read
- 132     68/push  0/imm32/read
- 133     # . write
- 134     68/push  0/imm32/write
- 135     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
- 136     # var in/esi: (stream byte Input-size)
- 137     # . data
- 138     2b/subtract                     0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Input-size/disp32                 # subtract *Input-size from esp
- 139     # . size
- 140     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Input-size/disp32                 # push *Input-size
- 141     # . read
- 142     68/push  0/imm32/read
- 143     # . write
- 144     68/push  0/imm32/write
- 145     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           4/r32/esp   .               .                 # copy esp to esi
- 146     # slurp(infile, in)
- 147     # . . push args
+  55     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+  56 
+  57     # - if argc > 1 and argv[1] == "test", then return run_tests()
+  58     # if (argc <= 1) goto interactive
+  59     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0/disp8         1/imm32           # compare *ebp
+  60     7e/jump-if-<=  $subx-survey-main:interactive/disp8
+  61     # if (!kernel-string-equal?(argv[1], "test")) goto interactive
+  62     # . eax = kernel-string-equal?(argv[1], "test")
+  63     # . . push args
+  64     68/push  "test"/imm32
+  65     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+  66     # . . call
+  67     e8/call  kernel-string-equal?/disp32
+  68     # . . discard args
+  69     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+  70     # . if (eax == false) goto interactive
+  71     3d/compare-eax-and  0/imm32/false
+  72     74/jump-if-=  $subx-survey-main:interactive/disp8
+  73     # run-tests()
+  74     e8/call  run-tests/disp32
+  75     # syscall(exit, *Num-test-failures)
+  76     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/ebx   Num-test-failures/disp32          # copy *Num-test-failures to ebx
+  77     eb/jump  $subx-survey-main:end/disp8
+  78 $subx-survey-main:interactive:
+  79     # - otherwise convert stdin
+  80     # subx-survey(Stdin, Stdout)
+  81     # . . push args
+  82     68/push  Stdout/imm32
+  83     68/push  Stdin/imm32
+  84     # . . call
+  85     e8/call  subx-survey/disp32
+  86     # . . discard args
+  87     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+  88 #?     # . write-stream(2/stderr, Trace-stream)
+  89 #?     # . . push args
+  90 #?     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+  91 #?     68/push  2/imm32/stderr
+  92 #?     # . . call
+  93 #?     e8/call  write-stream/disp32
+  94 #?     # . . discard args
+  95 #?     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+  96     # syscall(exit, 0)
+  97     bb/copy-to-ebx  0/imm32
+  98 $subx-survey-main:end:
+  99     e8/call  syscall_exit/disp32
+ 100 
+ 101 subx-survey:  # infile: (addr buffered-file), out: (addr buffered-file)
+ 102     # pseudocode
+ 103     #   var in: (stream byte Input-size)
+ 104     #   slurp(infile, in)
+ 105     #   var labels: (stream {label-name, address} Max-labels)
+ 106     #   compute-addresses(in, labels)
+ 107     #   emit-labels(out, labels)
+ 108     #
+ 109     # . prologue
+ 110     55/push-ebp
+ 111     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 112     # . save registers
+ 113     51/push-ecx
+ 114     52/push-edx
+ 115     56/push-esi
+ 116     # var labels/edx: (stream {label-name, address} Max-labels)
+ 117     # (we get more rows than Max-labels advertises because row size is smaller than in survey_elf)
+ 118     # . data
+ 119     2b/subtract                     0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Max-labels/disp32                 # subtract *Max-labels from esp
+ 120     # . size
+ 121     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Max-labels/disp32                 # push *Max-labels
+ 122     # . read
+ 123     68/push  0/imm32/read
+ 124     # . write
+ 125     68/push  0/imm32/write
+ 126     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+ 127     # var in/esi: (stream byte Input-size)
+ 128     # . data
+ 129     2b/subtract                     0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Input-size/disp32                 # subtract *Input-size from esp
+ 130     # . size
+ 131     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Input-size/disp32                 # push *Input-size
+ 132     # . read
+ 133     68/push  0/imm32/read
+ 134     # . write
+ 135     68/push  0/imm32/write
+ 136     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           4/r32/esp   .               .                 # copy esp to esi
+ 137     # slurp(infile, in)
+ 138     # . . push args
+ 139     56/push-esi
+ 140     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 141     # . . call
+ 142     e8/call  slurp/disp32
+ 143     # . . discard args
+ 144     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 145     # compute-addresses(in, labels)
+ 146     # . . push args
+ 147     52/push-edx
  148     56/push-esi
- 149     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
- 150     # . . call
- 151     e8/call  slurp/disp32
- 152     # . . discard args
- 153     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 154     # compute-offsets(in, labels)
- 155     # . . push args
- 156     52/push-edx
- 157     56/push-esi
- 158     # . . call
- 159     e8/call  compute-offsets/disp32
- 160     # . . discard args
- 161     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 162     # rewind-stream(in)
- 163     # . . push args
- 164     56/push-esi
- 165     # . . call
- 166     e8/call  rewind-stream/disp32
- 167     # . . discard args
- 168     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 169     # emit-output(in, out, labels)
- 170     # . . push args
- 171     52/push-edx
- 172     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
- 173     56/push-esi
- 174     # . . call
- 175     e8/call  emit-output/disp32
- 176     # . . discard args
- 177     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
- 178     # flush(out)
- 179     # . . push args
- 180     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
- 181     # . . call
- 182     e8/call  flush/disp32
- 183     # . . discard args
- 184     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 185 $subx-survey:end:
- 186     # . reclaim locals
- 187     03/add                          0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Max-labels/disp32                 # add *Max-labels to esp
- 188     03/add                          0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Input-size/disp32                 # add *Input-size to esp
- 189     # . restore registers
- 190     5e/pop-to-esi
- 191     5a/pop-to-edx
- 192     59/pop-to-ecx
- 193     # . epilogue
- 194     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 195     5d/pop-to-ebp
- 196     c3/return
- 197 
- 198 test-subx-survey-computes-addresses:
- 199     # input:
- 200     #   == code
- 201     #   ab x/imm32
- 202     #   == data
- 203     #   x:
- 204     #     01
- 205     #
- 206     # trace contains (in any order):
- 207     #   label x is at address 0x7c05
- 208     #
- 209     # . prologue
- 210     55/push-ebp
- 211     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 212     # setup
- 213     # . clear-stream(_test-input-stream)
- 214     # . . push args
- 215     68/push  _test-input-stream/imm32
- 216     # . . call
- 217     e8/call  clear-stream/disp32
- 218     # . . discard args
- 219     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 220     # . clear-stream($_test-input-buffered-file->buffer)
- 221     # . . push args
- 222     68/push  $_test-input-buffered-file->buffer/imm32
- 223     # . . call
- 224     e8/call  clear-stream/disp32
- 225     # . . discard args
- 226     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 227     # . clear-stream(_test-output-stream)
- 228     # . . push args
- 229     68/push  _test-output-stream/imm32
+ 149     # . . call
+ 150     e8/call  compute-addresses/disp32
+ 151     # . . discard args
+ 152     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 153     # emit-labels(out, labels)
+ 154     # . . push args
+ 155     52/push-edx
+ 156     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 157     # . . call
+ 158     e8/call  emit-labels/disp32
+ 159     # . . discard args
+ 160     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 161     # flush(out)
+ 162     # . . push args
+ 163     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 164     # . . call
+ 165     e8/call  flush/disp32
+ 166     # . . discard args
+ 167     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 168 $subx-survey:end:
+ 169     # . reclaim locals
+ 170     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x18/imm32        # add to esp
+ 171     03/add                          0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Max-labels/disp32                 # add *Max-labels to esp
+ 172     03/add                          0/mod/indirect  5/rm32/.disp32            .             .           4/r32/esp   Input-size/disp32                 # add *Input-size to esp
+ 173     # . restore registers
+ 174     5e/pop-to-esi
+ 175     5a/pop-to-edx
+ 176     59/pop-to-ecx
+ 177     # . epilogue
+ 178     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 179     5d/pop-to-ebp
+ 180     c3/return
+ 181 
+ 182 test-subx-survey-computes-addresses:
+ 183     # input:
+ 184     #   == code
+ 185     #   ab x/imm32
+ 186     #   == data
+ 187     #   x:
+ 188     #     01
+ 189     #
+ 190     # trace contains (in any order):
+ 191     #   label x is at address 0x7c05
+ 192     #
+ 193     # . prologue
+ 194     55/push-ebp
+ 195     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 196     # setup
+ 197     # . clear-stream(_test-input-stream)
+ 198     # . . push args
+ 199     68/push  _test-input-stream/imm32
+ 200     # . . call
+ 201     e8/call  clear-stream/disp32
+ 202     # . . discard args
+ 203     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 204     # . clear-stream($_test-input-buffered-file->buffer)
+ 205     # . . push args
+ 206     68/push  $_test-input-buffered-file->buffer/imm32
+ 207     # . . call
+ 208     e8/call  clear-stream/disp32
+ 209     # . . discard args
+ 210     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 211     # . clear-stream(_test-output-stream)
+ 212     # . . push args
+ 213     68/push  _test-output-stream/imm32
+ 214     # . . call
+ 215     e8/call  clear-stream/disp32
+ 216     # . . discard args
+ 217     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 218     # . clear-stream($_test-output-buffered-file->buffer)
+ 219     # . . push args
+ 220     68/push  $_test-output-buffered-file->buffer/imm32
+ 221     # . . call
+ 222     e8/call  clear-stream/disp32
+ 223     # . . discard args
+ 224     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 225     # initialize input
+ 226     # . write(_test-input-stream, "== code\n")
+ 227     # . . push args
+ 228     68/push  "== code\n"/imm32
+ 229     68/push  _test-input-stream/imm32
  230     # . . call
- 231     e8/call  clear-stream/disp32
+ 231     e8/call  write/disp32
  232     # . . discard args
- 233     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 234     # . clear-stream($_test-output-buffered-file->buffer)
+ 233     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 234     # . write(_test-input-stream, "ab x/imm32\n")
  235     # . . push args
- 236     68/push  $_test-output-buffered-file->buffer/imm32
- 237     # . . call
- 238     e8/call  clear-stream/disp32
- 239     # . . discard args
- 240     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 241     # initialize input
- 242     # . write(_test-input-stream, "== code\n")
+ 236     68/push  "ab x/imm32\n"/imm32
+ 237     68/push  _test-input-stream/imm32
+ 238     # . . call
+ 239     e8/call  write/disp32
+ 240     # . . discard args
+ 241     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 242     # . write(_test-input-stream, "== data\n")
  243     # . . push args
- 244     68/push  "== code\n"/imm32
+ 244     68/push  "== data\n"/imm32
  245     68/push  _test-input-stream/imm32
  246     # . . call
  247     e8/call  write/disp32
  248     # . . discard args
  249     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 250     # . write(_test-input-stream, "ab x/imm32\n")
+ 250     # . write(_test-input-stream, "x:\n")
  251     # . . push args
- 252     68/push  "ab x/imm32\n"/imm32
+ 252     68/push  "x:\n"/imm32
  253     68/push  _test-input-stream/imm32
  254     # . . call
  255     e8/call  write/disp32
  256     # . . discard args
  257     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 258     # . write(_test-input-stream, "== data\n")
+ 258     # . write(_test-input-stream, "01\n")
  259     # . . push args
- 260     68/push  "== data\n"/imm32
+ 260     68/push  "01\n"/imm32
  261     68/push  _test-input-stream/imm32
  262     # . . call
  263     e8/call  write/disp32
  264     # . . discard args
  265     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 266     # . write(_test-input-stream, "x:\n")
+ 266     # subx-survey(_test-input-buffered-file, _test-output-buffered-file)
  267     # . . push args
- 268     68/push  "x:\n"/imm32
- 269     68/push  _test-input-stream/imm32
+ 268     68/push  _test-output-buffered-file/imm32
+ 269     68/push  _test-input-buffered-file/imm32
  270     # . . call
- 271     e8/call  write/disp32
+ 271     e8/call  subx-survey/disp32
  272     # . . discard args
  273     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 274     # . write(_test-input-stream, "01\n")
- 275     # . . push args
- 276     68/push  "01\n"/imm32
- 277     68/push  _test-input-stream/imm32
- 278     # . . call
- 279     e8/call  write/disp32
- 280     # . . discard args
- 281     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 282     # subx-survey(_test-input-buffered-file, _test-output-buffered-file)
- 283     # . . push args
- 284     68/push  _test-output-buffered-file/imm32
- 285     68/push  _test-input-buffered-file/imm32
- 286     # . . call
- 287     e8/call  subx-survey/disp32
- 288     # . . discard args
- 289     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 290     # check trace
- 291 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
- 317     # . check-trace-contains("label 'x' is at address 0x00007c05.", msg)
- 318     # . . push args
- 319     68/push  "F - test-subx-survey-computes-addresses/0"/imm32
- 320     68/push  "label 'x' is at address 0x00007c05."/imm32
- 321     # . . call
- 322     e8/call  check-trace-contains/disp32
- 323     # . . discard args
- 324     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 325     # . epilogue
- 326     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 327     5d/pop-to-ebp
- 328     c3/return
- 329 
- 330 test-subx-survey-computes-addresses-with-padding:
- 331     # input:
- 332     #   == code
- 333     #   ab x/imm32
- 334     #   == data 0x7c10
- 335     #   x:
- 336     #     01
- 337     #
- 338     # trace contains (in any order):
- 339     #   label x is at address 0x7c10
- 340     #
- 341     # . prologue
- 342     55/push-ebp
- 343     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 344     # setup
- 345     # . clear-stream(_test-input-stream)
- 346     # . . push args
- 347     68/push  _test-input-stream/imm32
- 348     # . . call
- 349     e8/call  clear-stream/disp32
- 350     # . . discard args
- 351     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 352     # . clear-stream($_test-input-buffered-file->buffer)
- 353     # . . push args
- 354     68/push  $_test-input-buffered-file->buffer/imm32
- 355     # . . call
- 356     e8/call  clear-stream/disp32
- 357     # . . discard args
- 358     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 359     # . clear-stream(_test-output-stream)
- 360     # . . push args
- 361     68/push  _test-output-stream/imm32
+ 274     # check trace
+ 275 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
+ 301     # . check-trace-contains("label 'x' is at address 0x00007c05.", msg)
+ 302     # . . push args
+ 303     68/push  "F - test-subx-survey-computes-addresses/0"/imm32
+ 304     68/push  "label 'x' is at address 0x00007c05."/imm32
+ 305     # . . call
+ 306     e8/call  check-trace-contains/disp32
+ 307     # . . discard args
+ 308     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 309     # . epilogue
+ 310     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 311     5d/pop-to-ebp
+ 312     c3/return
+ 313 
+ 314 test-subx-survey-computes-addresses-with-padding:
+ 315     # input:
+ 316     #   == code
+ 317     #   ab x/imm32
+ 318     #   == data 0x7c10
+ 319     #   x:
+ 320     #     01
+ 321     #
+ 322     # trace contains (in any order):
+ 323     #   label x is at address 0x7c10
+ 324     #
+ 325     # . prologue
+ 326     55/push-ebp
+ 327     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 328     # setup
+ 329     # . clear-stream(_test-input-stream)
+ 330     # . . push args
+ 331     68/push  _test-input-stream/imm32
+ 332     # . . call
+ 333     e8/call  clear-stream/disp32
+ 334     # . . discard args
+ 335     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 336     # . clear-stream($_test-input-buffered-file->buffer)
+ 337     # . . push args
+ 338     68/push  $_test-input-buffered-file->buffer/imm32
+ 339     # . . call
+ 340     e8/call  clear-stream/disp32
+ 341     # . . discard args
+ 342     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 343     # . clear-stream(_test-output-stream)
+ 344     # . . push args
+ 345     68/push  _test-output-stream/imm32
+ 346     # . . call
+ 347     e8/call  clear-stream/disp32
+ 348     # . . discard args
+ 349     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 350     # . clear-stream($_test-output-buffered-file->buffer)
+ 351     # . . push args
+ 352     68/push  $_test-output-buffered-file->buffer/imm32
+ 353     # . . call
+ 354     e8/call  clear-stream/disp32
+ 355     # . . discard args
+ 356     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 357     # initialize input
+ 358     # . write(_test-input-stream, "== code\n")
+ 359     # . . push args
+ 360     68/push  "== code\n"/imm32
+ 361     68/push  _test-input-stream/imm32
  362     # . . call
- 363     e8/call  clear-stream/disp32
+ 363     e8/call  write/disp32
  364     # . . discard args
- 365     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 366     # . clear-stream($_test-output-buffered-file->buffer)
+ 365     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 366     # . write(_test-input-stream, "ab x/imm32\n")
  367     # . . push args
- 368     68/push  $_test-output-buffered-file->buffer/imm32
- 369     # . . call
- 370     e8/call  clear-stream/disp32
- 371     # . . discard args
- 372     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 373     # initialize input
- 374     # . write(_test-input-stream, "== code\n")
+ 368     68/push  "ab x/imm32\n"/imm32
+ 369     68/push  _test-input-stream/imm32
+ 370     # . . call
+ 371     e8/call  write/disp32
+ 372     # . . discard args
+ 373     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 374     # . write(_test-input-stream, "== data\n")
  375     # . . push args
- 376     68/push  "== code\n"/imm32
+ 376     68/push  "== data 0x7c10\n"/imm32
  377     68/push  _test-input-stream/imm32
  378     # . . call
  379     e8/call  write/disp32
  380     # . . discard args
  381     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 382     # . write(_test-input-stream, "ab x/imm32\n")
+ 382     # . write(_test-input-stream, "x:\n")
  383     # . . push args
- 384     68/push  "ab x/imm32\n"/imm32
+ 384     68/push  "x:\n"/imm32
  385     68/push  _test-input-stream/imm32
  386     # . . call
  387     e8/call  write/disp32
  388     # . . discard args
  389     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 390     # . write(_test-input-stream, "== data\n")
+ 390     # . write(_test-input-stream, "01\n")
  391     # . . push args
- 392     68/push  "== data 0x7c10\n"/imm32
+ 392     68/push  "01\n"/imm32
  393     68/push  _test-input-stream/imm32
  394     # . . call
  395     e8/call  write/disp32
  396     # . . discard args
  397     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 398     # . write(_test-input-stream, "x:\n")
+ 398     # subx-survey(_test-input-buffered-file, _test-output-buffered-file)
  399     # . . push args
- 400     68/push  "x:\n"/imm32
- 401     68/push  _test-input-stream/imm32
+ 400     68/push  _test-output-buffered-file/imm32
+ 401     68/push  _test-input-buffered-file/imm32
  402     # . . call
- 403     e8/call  write/disp32
+ 403     e8/call  subx-survey/disp32
  404     # . . discard args
  405     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 406     # . write(_test-input-stream, "01\n")
- 407     # . . push args
- 408     68/push  "01\n"/imm32
- 409     68/push  _test-input-stream/imm32
- 410     # . . call
- 411     e8/call  write/disp32
- 412     # . . discard args
- 413     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 414     # subx-survey(_test-input-buffered-file, _test-output-buffered-file)
- 415     # . . push args
- 416     68/push  _test-output-buffered-file/imm32
- 417     68/push  _test-input-buffered-file/imm32
- 418     # . . call
- 419     e8/call  subx-survey/disp32
- 420     # . . discard args
- 421     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 422     # check trace
- 423 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
- 449     # . check-trace-contains("label 'x' is at address 0x00007c10.", msg)
- 450     # . . push args
- 451     68/push  "F - test-subx-survey-computes-addresses-with-padding/0"/imm32
- 452     68/push  "label 'x' is at address 0x00007c10."/imm32
- 453     # . . call
- 454     e8/call  check-trace-contains/disp32
- 455     # . . discard args
- 456     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 457     # . epilogue
- 458     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 459     5d/pop-to-ebp
- 460     c3/return
- 461 
- 462 compute-offsets:  # in: (addr stream byte), labels: (addr stream {(handle array byte), address})
- 463     # pseudocode:
- 464     #   var current-address = 0x7c00
- 465     #   var line: (stream byte 512)
- 466     #   while true                                  # line loop
- 467     #     clear-stream(line)
- 468     #     read-line(in, line)
- 469     #     if (line->write == 0) break               # end of file
- 470     #     while true                                # word loop
- 471     #       word-slice = next-word(line)
- 472     #       if slice-empty?(word-slice)             # end of line
- 473     #         break
- 474     #       else if slice-starts-with?(word-slice, "#")  # comment
- 475     #         break                                 # end of line
- 476     #       else if slice-equal?(word-slice, "==")  # segment header
- 477     #         word-slice = next-word(line)
- 478     #         if slice-empty?(word-slice)
- 479     #           abort
- 480     #         word-slice = next-word(line)  # segment address
- 481     #         if slice-empty?(word-slice)
- 482     #           goto line-loop              # segment address is optional
- 483     #         new-address = parse-hex-int-from-slice(word-slice)
- 484     #         if new-address < current-address
- 485     #           abort
- 486     #         current-address = new-address
- 487     #       else if label?(word-slice)
- 488     #         strip trailing ':' from word-slice
- 489     #         trace("label '" word-slice "' is at address " current-address ".")
- 490     #         # labels occupy no space, so no need to increment offsets
- 491     #       else
- 492     #         width = compute-width-of-slice(word-slice)
- 493     #         current-address += width
- 494     #
- 495     # . prologue
- 496     55/push-ebp
- 497     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 498     # . save registers
- 499     50/push-eax
- 500     51/push-ecx
- 501     52/push-edx
- 502     53/push-ebx
- 503     56/push-esi
- 504     57/push-edi
- 505     # var current-address/esi: int = 0x7c00
- 506     be/copy-to-esi  0x7c00/imm32
- 507     # var line/ecx: (stream byte 512)
- 508     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x200/imm32       # subtract from esp
- 509     68/push  0x200/imm32/size
- 510     68/push  0/imm32/read
- 511     68/push  0/imm32/write
- 512     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
- 513     # var word-slice/edx: (addr slice)
- 514     68/push  0/imm32
- 515     68/push  0/imm32
- 516     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
- 517 $compute-offsets:line-loop:
- 518     # clear-stream(line)
- 519     # . . push args
- 520     51/push-ecx
- 521     # . . call
- 522     e8/call  clear-stream/disp32
- 523     # . . discard args
- 524     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 525     # read-line(in, line)
- 526     # . . push args
- 527     51/push-ecx
- 528     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
- 529     # . . call
- 530     e8/call  read-line/disp32
- 531     # . . discard args
- 532     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 533     # if (line->write == 0) break
- 534     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # copy *ecx to eax
- 535     3d/compare-eax-and  0/imm32
- 536     0f 84/jump-if-=  $compute-offsets:end/disp32
- 537 +-- 33 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
- 570 $compute-offsets:word-loop:
- 571     # next-word(line, word-slice)
- 572     # . . push args
- 573     52/push-edx
- 574     51/push-ecx
- 575     # . . call
- 576     e8/call  next-word/disp32
- 577     # . . discard args
- 578     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 579 $compute-offsets:case-empty:
- 580     # if slice-empty?(word-slice) break
- 581     # . eax = slice-empty?(word-slice)
- 582     # . . push args
- 583     52/push-edx
- 584     # . . call
- 585     e8/call  slice-empty?/disp32
- 586     # . . discard args
- 587     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 588     # . if (eax != false) break
- 589     3d/compare-eax-and  0/imm32/false
- 590     0f 85/jump-if-!=  $compute-offsets:line-loop/disp32
- 591 $compute-offsets:case-comment:
- 592     # if slice-starts-with?(word-slice, "#") break
- 593     # . . push args
- 594     68/push  "#"/imm32
- 595     52/push-edx
- 596     # . . call
- 597     e8/call  slice-starts-with?/disp32
- 598     # . . discard args
- 599     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 600     # . if (eax != false) break
- 601     3d/compare-eax-and  0/imm32/false
- 602     0f 85/jump-if-!=  $compute-offsets:line-loop/disp32
- 603 $compute-offsets:case-segment-header:
- 604     # if !slice-equal?(word-slice, "==") goto next case
- 605     # . eax = slice-equal?(word-slice, "==")
- 606     # . . push args
- 607     68/push  "=="/imm32
- 608     52/push-edx
- 609     # . . call
- 610     e8/call  slice-equal?/disp32
- 611     # . . discard args
- 612     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 613     # . if (eax != false) break
- 614     3d/compare-eax-and  0/imm32/false
- 615     0f 84/jump-if-=  $compute-offsets:case-label/disp32
- 616     # next-word(line, word-slice)
- 617     # . . push args
- 618     52/push-edx
- 619     51/push-ecx
- 620     # . . call
- 621     e8/call  next-word/disp32
- 622     # . . discard args
- 623     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 624     # if slice-empty?(word-slice) abort
- 625     # . eax = slice-empty?(word-slice)
- 626     # . . push args
- 627     52/push-edx
- 628     # . . call
- 629     e8/call  slice-empty?/disp32
- 630     # . . discard args
- 631     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 632     # . if (eax != false) abort
- 633     3d/compare-eax-and  0/imm32/false
- 634     0f 85/jump-if-!=  $compute-offsets:abort/disp32
- 635     # next-word(line, word-slice)
- 636     # . . push args
- 637     52/push-edx
- 638     51/push-ecx
- 639     # . . call
- 640     e8/call  next-word/disp32
- 641     # . . discard args
- 642     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 643     # if slice-empty?(word-slice) break
- 644     # . eax = slice-empty?(word-slice)
- 645     # . . push args
- 646     52/push-edx
- 647     # . . call
- 648     e8/call  slice-empty?/disp32
- 649     # . . discard args
- 650     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 651     # . if (eax != false) break
- 652     3d/compare-eax-and  0/imm32/false
- 653     0f 85/jump-if-!=  $compute-offsets:line-loop/disp32
- 654     # var new-address/eax: int = parse-hex-int-from-slice(word-slice)
+ 406     # check trace
+ 407 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
+ 433     # . check-trace-contains("label 'x' is at address 0x00007c10.", msg)
+ 434     # . . push args
+ 435     68/push  "F - test-subx-survey-computes-addresses-with-padding/0"/imm32
+ 436     68/push  "label 'x' is at address 0x00007c10."/imm32
+ 437     # . . call
+ 438     e8/call  check-trace-contains/disp32
+ 439     # . . discard args
+ 440     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 441     # . epilogue
+ 442     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 443     5d/pop-to-ebp
+ 444     c3/return
+ 445 
+ 446 compute-addresses:  # in: (addr stream byte), labels: (addr stream {(handle array byte), address})
+ 447     # pseudocode:
+ 448     #   var current-address = 0x7c00
+ 449     #   var line: (stream byte 512)
+ 450     #   while true                                  # line loop
+ 451     #     clear-stream(line)
+ 452     #     read-line(in, line)
+ 453     #     if (line->write == 0) break               # end of file
+ 454     #     while true                                # word loop
+ 455     #       word-slice = next-word(line)
+ 456     #       if slice-empty?(word-slice)             # end of line
+ 457     #         break
+ 458     #       else if slice-starts-with?(word-slice, "#")  # comment
+ 459     #         break                                 # end of line
+ 460     #       else if slice-equal?(word-slice, "==")  # segment header
+ 461     #         word-slice = next-word(line)
+ 462     #         if slice-empty?(word-slice)
+ 463     #           abort
+ 464     #         word-slice = next-word(line)  # segment address
+ 465     #         if slice-empty?(word-slice)
+ 466     #           goto line-loop              # segment address is optional
+ 467     #         new-address = parse-hex-int-from-slice(word-slice)
+ 468     #         if new-address < current-address
+ 469     #           abort
+ 470     #         current-address = new-address
+ 471     #       else if label?(word-slice)
+ 472     #         strip trailing ':' from word-slice
+ 473     #         trace("label '" word-slice "' is at address " current-address ".")
+ 474     #         # labels occupy no space, so no need to increment offsets
+ 475     #       else
+ 476     #         width = compute-width-of-slice(word-slice)
+ 477     #         current-address += width
+ 478     #
+ 479     # . prologue
+ 480     55/push-ebp
+ 481     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 482     # . save registers
+ 483     50/push-eax
+ 484     51/push-ecx
+ 485     52/push-edx
+ 486     53/push-ebx
+ 487     56/push-esi
+ 488     57/push-edi
+ 489     # var current-address/esi: int = 0x7c00
+ 490     be/copy-to-esi  0x7c00/imm32
+ 491     # var line/ecx: (stream byte 512)
+ 492     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x200/imm32       # subtract from esp
+ 493     68/push  0x200/imm32/size
+ 494     68/push  0/imm32/read
+ 495     68/push  0/imm32/write
+ 496     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
+ 497     # var word-slice/edx: (addr slice)
+ 498     68/push  0/imm32
+ 499     68/push  0/imm32
+ 500     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+ 501 $compute-addresses:line-loop:
+ 502     # clear-stream(line)
+ 503     # . . push args
+ 504     51/push-ecx
+ 505     # . . call
+ 506     e8/call  clear-stream/disp32
+ 507     # . . discard args
+ 508     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 509     # read-line(in, line)
+ 510     # . . push args
+ 511     51/push-ecx
+ 512     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 513     # . . call
+ 514     e8/call  read-line/disp32
+ 515     # . . discard args
+ 516     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 517     # if (line->write == 0) break
+ 518     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           0/r32/eax   .               .                 # copy *ecx to eax
+ 519     3d/compare-eax-and  0/imm32
+ 520     0f 84/jump-if-=  $compute-addresses:end/disp32
+ 521 +-- 33 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
+ 554 $compute-addresses:word-loop:
+ 555     # next-word(line, word-slice)
+ 556     # . . push args
+ 557     52/push-edx
+ 558     51/push-ecx
+ 559     # . . call
+ 560     e8/call  next-word/disp32
+ 561     # . . discard args
+ 562     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 563 $compute-addresses:case-empty:
+ 564     # if slice-empty?(word-slice) break
+ 565     # . eax = slice-empty?(word-slice)
+ 566     # . . push args
+ 567     52/push-edx
+ 568     # . . call
+ 569     e8/call  slice-empty?/disp32
+ 570     # . . discard args
+ 571     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 572     # . if (eax != false) break
+ 573     3d/compare-eax-and  0/imm32/false
+ 574     0f 85/jump-if-!=  $compute-addresses:line-loop/disp32
+ 575 $compute-addresses:case-comment:
+ 576     # if slice-starts-with?(word-slice, "#") break
+ 577     # . . push args
+ 578     68/push  "#"/imm32
+ 579     52/push-edx
+ 580     # . . call
+ 581     e8/call  slice-starts-with?/disp32
+ 582     # . . discard args
+ 583     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 584     # . if (eax != false) break
+ 585     3d/compare-eax-and  0/imm32/false
+ 586     0f 85/jump-if-!=  $compute-addresses:line-loop/disp32
+ 587 $compute-addresses:case-segment-header:
+ 588     # if !slice-equal?(word-slice, "==") goto next case
+ 589     # . eax = slice-equal?(word-slice, "==")
+ 590     # . . push args
+ 591     68/push  "=="/imm32
+ 592     52/push-edx
+ 593     # . . call
+ 594     e8/call  slice-equal?/disp32
+ 595     # . . discard args
+ 596     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 597     # . if (eax != false) break
+ 598     3d/compare-eax-and  0/imm32/false
+ 599     0f 84/jump-if-=  $compute-addresses:case-label/disp32
+ 600     # next-word(line, word-slice)
+ 601     # . . push args
+ 602     52/push-edx
+ 603     51/push-ecx
+ 604     # . . call
+ 605     e8/call  next-word/disp32
+ 606     # . . discard args
+ 607     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 608     # if slice-empty?(word-slice) abort
+ 609     # . eax = slice-empty?(word-slice)
+ 610     # . . push args
+ 611     52/push-edx
+ 612     # . . call
+ 613     e8/call  slice-empty?/disp32
+ 614     # . . discard args
+ 615     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 616     # . if (eax != false) abort
+ 617     3d/compare-eax-and  0/imm32/false
+ 618     0f 85/jump-if-!=  $compute-addresses:abort/disp32
+ 619     # next-word(line, word-slice)
+ 620     # . . push args
+ 621     52/push-edx
+ 622     51/push-ecx
+ 623     # . . call
+ 624     e8/call  next-word/disp32
+ 625     # . . discard args
+ 626     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 627     # if slice-empty?(word-slice) break
+ 628     # . eax = slice-empty?(word-slice)
+ 629     # . . push args
+ 630     52/push-edx
+ 631     # . . call
+ 632     e8/call  slice-empty?/disp32
+ 633     # . . discard args
+ 634     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 635     # . if (eax != false) break
+ 636     3d/compare-eax-and  0/imm32/false
+ 637     0f 85/jump-if-!=  $compute-addresses:line-loop/disp32
+ 638     # var new-address/eax: int = parse-hex-int-from-slice(word-slice)
+ 639     # . . push args
+ 640     52/push-edx
+ 641     # . . call
+ 642     e8/call  parse-hex-int-from-slice/disp32
+ 643     # . . discard args
+ 644     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 645     # if (new-address < current-address) abort
+ 646     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           6/r32/esi   .               .                 # compare eax with esi
+ 647     0f 82/jump-if-addr<  $compute-addresses:error-bad-segment-address/disp32
+ 648     # current-address = new-address
+ 649     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy eax to esi
+ 650     # break
+ 651     e9/jump  $compute-addresses:line-loop/disp32
+ 652 $compute-addresses:case-label:
+ 653     # if (!label?(word-slice)) goto next case
+ 654     # . eax = label?(word-slice)
  655     # . . push args
  656     52/push-edx
  657     # . . call
- 658     e8/call  parse-hex-int-from-slice/disp32
+ 658     e8/call  label?/disp32
  659     # . . discard args
  660     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 661     # if (new-address < current-address) abort
- 662     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           6/r32/esi   .               .                 # compare eax with esi
- 663     0f 82/jump-if-addr<  $compute-offsets:error-bad-segment-address/disp32
- 664     # current-address = new-address
- 665     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy eax to esi
- 666     # break
- 667     e9/jump  $compute-offsets:line-loop/disp32
- 668 $compute-offsets:case-label:
- 669     # if (!label?(word-slice)) goto next case
- 670     # . eax = label?(word-slice)
- 671     # . . push args
- 672     52/push-edx
- 673     # . . call
- 674     e8/call  label?/disp32
- 675     # . . discard args
- 676     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 677     # . if (eax == false) goto next case
- 678     3d/compare-eax-and  0/imm32/false
- 679     0f 84/jump-if-=  $compute-offsets:case-default/disp32
- 680     # strip trailing ':' from word-slice
- 681     ff          1/subop/decrement   1/mod/*+disp8   2/rm32/edx    .           .             .           .           4/disp8         .                 # decrement *(edx+4)
- 682     # var tmp/eax: (addr int) = get-or-insert-slice(labels, word-slice, row-size=12)
- 683     # . . push args
- 684     68/push  Heap/imm32
- 685     68/push  0xc/imm32/row-size
- 686     52/push-edx
- 687     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
- 688     # . . call
- 689     e8/call  get-or-insert-slice/disp32
- 690     # . . discard args
- 691     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
- 692     # *tmp = current-address
- 693     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           6/r32/esi   .               .                 # copy esi to *eax
- 694     # trace-slsns("label '" word-slice "' is at address " current-address ".")
- 695     # . . push args
- 696     68/push  "."/imm32
- 697     56/push-esi
- 698     68/push  "' is at address "/imm32
- 699     52/push-edx
- 700     68/push  "label '"/imm32
- 701     # . . call
- 702     e8/call  trace-slsns/disp32
- 703     # . . discard args
- 704     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
- 705     # continue
- 706     e9/jump  $compute-offsets:word-loop/disp32
- 707 $compute-offsets:case-default:
- 708     # width/eax = compute-width-of-slice(word-slice)
- 709     # . . push args
- 710     52/push-edx
- 711     # . . call
- 712     e8/call compute-width-of-slice/disp32
- 713     # . . discard args
- 714     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 715     # current-address += width
- 716     01/add                          3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # add eax to *esi
- 717 +-- 41 lines: #?     # dump segment-offset ----------------------------------------------------------------------------------------------------------------------------------------------
- 758     e9/jump $compute-offsets:word-loop/disp32
- 759 $compute-offsets:end:
- 760     # . reclaim locals
- 761     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x214/imm32       # add to esp
- 762     # . restore registers
- 763     5f/pop-to-edi
- 764     5e/pop-to-esi
- 765     5b/pop-to-ebx
- 766     5a/pop-to-edx
- 767     59/pop-to-ecx
- 768     58/pop-to-eax
- 769     # . epilogue
- 770     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 771     5d/pop-to-ebp
- 772     c3/return
- 773 
- 774 $compute-offsets:abort:
- 775     # . _write(2/stderr, error)
- 776     # . . push args
- 777     68/push  "'==' must be followed by segment name and optionally an address\n"/imm32
- 778     68/push  2/imm32/stderr
- 779     # . . call
- 780     e8/call  _write/disp32
- 781     # . . discard args
- 782     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 783     # . syscall(exit, 1)
- 784     bb/copy-to-ebx  1/imm32
- 785     e8/call  syscall_exit/disp32
- 786     # never gets here
- 787 
- 788 $compute-offsets:error-bad-segment-address:
- 789     # . _write(2/stderr, error)
- 790     # . . push args
- 791     68/push  "'==' specifies an address that implies negative padding\n"/imm32
- 792     68/push  2/imm32/stderr
- 793     # . . call
- 794     e8/call  _write/disp32
- 795     # . . discard args
- 796     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 797     # . syscall(exit, 1)
- 798     bb/copy-to-ebx  1/imm32
- 799     e8/call  syscall_exit/disp32
- 800     # never gets here
- 801 
- 802 test-compute-offsets:
- 803     # input:
- 804     #   == code
- 805     #   ab x/imm32  # skip comment
- 806     #   == data
- 807     #   00
- 808     #   x:
- 809     #     34
- 810     #
- 811     # trace contains (in any order):
- 812     #   label 'x' is at address 0x7c06.
- 813     #
- 814     # . prologue
- 815     55/push-ebp
- 816     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
- 817     # setup
- 818     # . clear-stream(_test-input-stream)
- 819     # . . push args
- 820     68/push  _test-input-stream/imm32
- 821     # . . call
- 822     e8/call  clear-stream/disp32
- 823     # . . discard args
- 824     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
- 825     # var labels/edx: (stream byte 2*12)
- 826     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x18/imm32        # subtract from esp
- 827     68/push  0x18/imm32/size
- 828     68/push  0/imm32/read
- 829     68/push  0/imm32/write
- 830     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
- 831     # initialize input
- 832     # . write(_test-input-stream, "== code\n")
+ 661     # . if (eax == false) goto next case
+ 662     3d/compare-eax-and  0/imm32/false
+ 663     0f 84/jump-if-=  $compute-addresses:case-default/disp32
+ 664     # strip trailing ':' from word-slice
+ 665     ff          1/subop/decrement   1/mod/*+disp8   2/rm32/edx    .           .             .           .           4/disp8         .                 # decrement *(edx+4)
+ 666     # var tmp/eax: (addr int) = get-or-insert-slice(labels, word-slice, row-size=12)
+ 667     # . . push args
+ 668     68/push  Heap/imm32
+ 669     68/push  0xc/imm32/row-size
+ 670     52/push-edx
+ 671     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+ 672     # . . call
+ 673     e8/call  get-or-insert-slice/disp32
+ 674     # . . discard args
+ 675     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
+ 676     # *tmp = current-address
+ 677     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           6/r32/esi   .               .                 # copy esi to *eax
+ 678     # trace-slsns("label '" word-slice "' is at address " current-address ".")
+ 679     # . . push args
+ 680     68/push  "."/imm32
+ 681     56/push-esi
+ 682     68/push  "' is at address "/imm32
+ 683     52/push-edx
+ 684     68/push  "label '"/imm32
+ 685     # . . call
+ 686     e8/call  trace-slsns/disp32
+ 687     # . . discard args
+ 688     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
+ 689     # continue
+ 690     e9/jump  $compute-addresses:word-loop/disp32
+ 691 $compute-addresses:case-default:
+ 692     # width/eax = compute-width-of-slice(word-slice)
+ 693     # . . push args
+ 694     52/push-edx
+ 695     # . . call
+ 696     e8/call compute-width-of-slice/disp32
+ 697     # . . discard args
+ 698     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 699     # current-address += width
+ 700     01/add                          3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # add eax to *esi
+ 701 +-- 41 lines: #?     # dump segment-offset ----------------------------------------------------------------------------------------------------------------------------------------------
+ 742     e9/jump $compute-addresses:word-loop/disp32
+ 743 $compute-addresses:end:
+ 744     # . reclaim locals
+ 745     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x214/imm32       # add to esp
+ 746     # . restore registers
+ 747     5f/pop-to-edi
+ 748     5e/pop-to-esi
+ 749     5b/pop-to-ebx
+ 750     5a/pop-to-edx
+ 751     59/pop-to-ecx
+ 752     58/pop-to-eax
+ 753     # . epilogue
+ 754     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 755     5d/pop-to-ebp
+ 756     c3/return
+ 757 
+ 758 $compute-addresses:abort:
+ 759     # . _write(2/stderr, error)
+ 760     # . . push args
+ 761     68/push  "'==' must be followed by segment name and optionally an address\n"/imm32
+ 762     68/push  2/imm32/stderr
+ 763     # . . call
+ 764     e8/call  _write/disp32
+ 765     # . . discard args
+ 766     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 767     # . syscall(exit, 1)
+ 768     bb/copy-to-ebx  1/imm32
+ 769     e8/call  syscall_exit/disp32
+ 770     # never gets here
+ 771 
+ 772 $compute-addresses:error-bad-segment-address:
+ 773     # . _write(2/stderr, error)
+ 774     # . . push args
+ 775     68/push  "'==' specifies an address that implies negative padding\n"/imm32
+ 776     68/push  2/imm32/stderr
+ 777     # . . call
+ 778     e8/call  _write/disp32
+ 779     # . . discard args
+ 780     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 781     # . syscall(exit, 1)
+ 782     bb/copy-to-ebx  1/imm32
+ 783     e8/call  syscall_exit/disp32
+ 784     # never gets here
+ 785 
+ 786 test-compute-addresses:
+ 787     # input:
+ 788     #   == code
+ 789     #   ab x/imm32  # skip comment
+ 790     #   == data
+ 791     #   00
+ 792     #   x:
+ 793     #     34
+ 794     #
+ 795     # trace contains (in any order):
+ 796     #   label 'x' is at address 0x7c06.
+ 797     #
+ 798     # . prologue
+ 799     55/push-ebp
+ 800     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 801     # setup
+ 802     # . clear-stream(_test-input-stream)
+ 803     # . . push args
+ 804     68/push  _test-input-stream/imm32
+ 805     # . . call
+ 806     e8/call  clear-stream/disp32
+ 807     # . . discard args
+ 808     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 809     # var labels/edx: (stream byte 2*12)
+ 810     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x18/imm32        # subtract from esp
+ 811     68/push  0x18/imm32/size
+ 812     68/push  0/imm32/read
+ 813     68/push  0/imm32/write
+ 814     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
+ 815     # initialize input
+ 816     # . write(_test-input-stream, "== code\n")
+ 817     # . . push args
+ 818     68/push  "== code\n"/imm32
+ 819     68/push  _test-input-stream/imm32
+ 820     # . . call
+ 821     e8/call  write/disp32
+ 822     # . . discard args
+ 823     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 824     # . write(_test-input-stream, "ab x/imm32  # skip comment\n")
+ 825     # . . push args
+ 826     68/push  "ab x/imm32  # skip comment\n"/imm32
+ 827     68/push  _test-input-stream/imm32
+ 828     # . . call
+ 829     e8/call  write/disp32
+ 830     # . . discard args
+ 831     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 832     # . write(_test-input-stream, "== data\n")
  833     # . . push args
- 834     68/push  "== code\n"/imm32
+ 834     68/push  "== data\n"/imm32
  835     68/push  _test-input-stream/imm32
  836     # . . call
  837     e8/call  write/disp32
  838     # . . discard args
  839     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 840     # . write(_test-input-stream, "ab x/imm32  # skip comment\n")
+ 840     # . write(_test-input-stream, "00\n")
  841     # . . push args
- 842     68/push  "ab x/imm32  # skip comment\n"/imm32
+ 842     68/push  "00\n"/imm32
  843     68/push  _test-input-stream/imm32
  844     # . . call
  845     e8/call  write/disp32
  846     # . . discard args
  847     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 848     # . write(_test-input-stream, "== data\n")
+ 848     # . write(_test-input-stream, "x:\n")
  849     # . . push args
- 850     68/push  "== data\n"/imm32
+ 850     68/push  "x:\n"/imm32
  851     68/push  _test-input-stream/imm32
  852     # . . call
  853     e8/call  write/disp32
  854     # . . discard args
  855     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 856     # . write(_test-input-stream, "00\n")
+ 856     # . write(_test-input-stream, "34\n")
  857     # . . push args
- 858     68/push  "00\n"/imm32
+ 858     68/push  "34\n"/imm32
  859     68/push  _test-input-stream/imm32
  860     # . . call
  861     e8/call  write/disp32
  862     # . . discard args
  863     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 864     # . write(_test-input-stream, "x:\n")
+ 864     # compute-addresses(_test-input-stream, labels)
  865     # . . push args
- 866     68/push  "x:\n"/imm32
+ 866     52/push-edx
  867     68/push  _test-input-stream/imm32
  868     # . . call
- 869     e8/call  write/disp32
+ 869     e8/call  compute-addresses/disp32
  870     # . . discard args
- 871     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 872     # . write(_test-input-stream, "34\n")
- 873     # . . push args
- 874     68/push  "34\n"/imm32
- 875     68/push  _test-input-stream/imm32
- 876     # . . call
- 877     e8/call  write/disp32
- 878     # . . discard args
- 879     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 880     # compute-offsets(_test-input-stream, labels)
- 881     # . . push args
- 882     52/push-edx
- 883     68/push  _test-input-stream/imm32
- 884     # . . call
- 885     e8/call  compute-offsets/disp32
- 886     # . . discard args
- 887     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32          # add to esp
- 888 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
- 914     # . check-trace-contains("label 'x' is at address 0x00007c06.", msg)
- 915     # . . push args
- 916     68/push  "F - test-compute-offsets"/imm32
- 917     68/push  "label 'x' is at address 0x00007c06."/imm32
- 918     # . . call
- 919     e8/call  check-trace-contains/disp32
- 920     # . . discard args
- 921     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
- 922     # . check-ints-equal(labels->write, 0xc, msg)
- 923     # . . push args
- 924     68/push  "F - test-compute-offsets-maintains-labels-write-index"/imm32
- 925     68/push  0xc/imm32/1-entry
- 926     ff          6/subop/push        0/mod/indirect  2/rm32/edx    .           .             .           .           .               .                 # push *edx
- 927     # . . call
- 928     e8/call  check-ints-equal/disp32
- 929     # . . discard args
- 930     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
- 931     # . reclaim locals
- 932     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x24/imm32        # add to esp
- 933     # . epilogue
- 934     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
- 935     5d/pop-to-ebp
- 936     c3/return
- 937 
- 938 # global scratch space for emit-output
- 939 == data
- 940 
- 941 emit-output:datum:  # slice
- 942   0/imm32/start
- 943   0/imm32/end
- 944 
- 945 == code
- 946 
- 947 emit-output:  # in: (addr stream byte), out: (addr buffered-file), labels: (addr stream {(handle array byte), address})
- 948     # pseudocode:
- 949     #   var address-of-next-instruction = 0x7c00
- 950     #   var line: (stream byte 512)
- 951     #   line-loop:
- 952     #   while true
- 953     #     clear-stream(line)
- 954     #     read-line(in, line)
- 955     #     if (line->write == 0) break               # end of file
- 956     #     address-of-next-instruction += num-bytes(line)
- 957     #     var far-jump-or-call? = far-jump-or-call?(line)
- 958     #     rewind-stream(line)
- 959     #     while true
- 960     #       var word-slice = next-word(line)
- 961     #       if slice-empty?(word-slice)             # end of line
- 962     #         break
- 963     #       if slice-starts-with?(word-slice, "#")  # comment
- 964     #         break
- 965     #       if label?(word-slice)                # no need for label declarations anymore
- 966     #         goto line-loop                        # don't insert empty lines
- 967     #       if slice-equal?(word-slice, "==")       # no need for segment header lines
- 968     #         word-slice = next-word(line)          # skip segment name
- 969     #         word-slice = next-word(line)
- 970     #         if !slice-empty?(word-slice)
- 971     #           new-address = parse-hex-int-from-slice(word-slice)
- 972     #           write-buffered(out, "# " address-of-next-instruction "\n")
- 973     #           while address-of-next-instruction < new-address
- 974     #             write-buffered("00")
- 975     #             ++address-of-next-instruction
- 976     #           write-buffered(out, "# " address-of-next-instruction "\n")
- 977     #           goto line-loop                      # don't insert empty lines
- 978     #       if length(word-slice) == 2
- 979     #         write-slice-buffered(out, word-slice)
- 980     #         write-buffered(out, " ")
- 981     #         continue
- 982     #       var datum: (addr slice) = next-token-from-slice(word-slice->start, word-slice->end, "/")
- 983     #       var address: (addr int) = get-slice(labels, datum)
- 984     #       if has-metadata?(word-slice, "imm8")
- 985     #         emit(out, *address, 1)
- 986     #       else if has-metadata?(word-slice, "imm16")
- 987     #         emit(out, *address, 2)
- 988     #       else if has-metadata?(word-slice, "imm32")
- 989     #         emit(out, *address, 4)
- 990     #       else if has-metadata?(word-slice, "disp8")
- 991     #         value = *address - address-of-next-instruction
- 992     #         emit(out, value, 1)
- 993     #       else if has-metadata?(word-slice, "disp32")
- 994     #         if far-jump-or-call?
- 995     #           value = *address - address-of-next-instruction
- 996     #         else
- 997     #           value = *address
- 998     #         emit(out, value, 4)
- 999     #       else
-1000     #         abort
-1001     #     write-buffered(out, "\n")
-1002     #
-1003     # registers:
-1004     #   line: ecx
-1005     #   word-slice: edx
-1006     #   address-of-next-instruction: ebx
-1007     #   far-jump-or-call?: edi
-1008     #   address: esi (inner loop only)
-1009     #   temporaries: eax, esi (outer loop)
-1010     #
-1011     # . prologue
-1012     55/push-ebp
-1013     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-1014     # . save registers
-1015     50/push-eax
-1016     51/push-ecx
-1017     52/push-edx
-1018     53/push-ebx
-1019     56/push-esi
-1020     57/push-edi
-1021     # var line/ecx: (stream byte 512)
-1022     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0x200/imm32       # subtract from esp
-1023     68/push  0x200/imm32/size
-1024     68/push  0/imm32/read
-1025     68/push  0/imm32/write
-1026     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
-1027     # var word-slice/edx: slice
-1028     68/push  0/imm32/end
-1029     68/push  0/imm32/start
-1030     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-1031     # var address-of-next-instruction/ebx = 0x7c00
-1032     bb/copy-to-ebx  0x7c00/imm32
-1033 $emit-output:line-loop:
-1034     # clear-stream(line)
-1035     # . . push args
-1036     51/push-ecx
-1037     # . . call
-1038     e8/call  clear-stream/disp32
-1039     # . . discard args
-1040     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1041     # read-line(in, line)
-1042     # . . push args
-1043     51/push-ecx
-1044     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
-1045     # . . call
-1046     e8/call  read-line/disp32
-1047     # . . discard args
-1048     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1049 +-- 33 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
-1082 $emit-output:check-for-end-of-input:
-1083     # if (line->write == 0) break
-1084     81          7/subop/compare     0/mod/indirect  1/rm32/ecx    .           .             .           .           .               0/imm32           # compare *ecx
-1085     0f 84/jump-if-=  $emit-output:end/disp32
-1086     # address-of-next-instruction += num-bytes(line)
-1087     # . eax = num-bytes(line)
-1088     # . . push args
-1089     51/push-ecx
-1090     # . . call
-1091     e8/call  num-bytes/disp32
-1092     # . . discard args
-1093     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1094     # . ebx += eax
-1095     01/add                          3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # add eax to ebx
-1096     # var far-jump-or-call?/edi: boolean = far-jump-or-call?(line)
-1097     # . . push args
-1098     51/push-ecx
-1099     # . . call
-1100     e8/call  far-jump-or-call?/disp32
-1101     # . . discard args
-1102     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1103     # rewind-stream(line)
-1104     # . . push args
-1105     51/push-ecx
-1106     # . . call
-1107     e8/call  rewind-stream/disp32
-1108     # . . discard args
-1109     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1110 $emit-output:word-loop:
-1111     # next-word(line, word-slice)
-1112     # . . push args
-1113     52/push-edx
-1114     51/push-ecx
-1115     # . . call
-1116     e8/call  next-word/disp32
-1117     # . . discard args
-1118     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1119 +-- 33 lines: #?     # dump word-slice --------------------------------------------------------------------------------------------------------------------------------------------------
-1152 $emit-output:check-for-end-of-line:
-1153     # if (slice-empty?(word-slice)) break
-1154     # . eax = slice-empty?(word-slice)
-1155     # . . push args
-1156     52/push-edx
-1157     # . . call
-1158     e8/call  slice-empty?/disp32
-1159     # . . discard args
-1160     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1161     # . if (eax != 0) break
-1162     3d/compare-eax-and  0/imm32/false
-1163     0f 85/jump-if-!=  $emit-output:next-line/disp32
-1164 $emit-output:check-for-comment:
-1165     # if (slice-starts-with?(word-slice, "#")) break
-1166     # . start/esi = word-slice->start
-1167     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           6/r32/esi   .               .                 # copy *edx to esi
-1168     # . c/eax = *start
-1169     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
-1170     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           0/r32/AL    .               .                 # copy byte at *esi to AL
-1171     # . if (eax == '#') break
-1172     3d/compare-eax-and  0x23/imm32/hash
-1173     0f 84/jump-if-=  $emit-output:next-line/disp32
-1174 $emit-output:check-for-label:
-1175     # if label?(word-slice) break
-1176     # . eax = label?(word-slice)
-1177     # . . push args
-1178     52/push-edx
-1179     # . . call
-1180     e8/call  label?/disp32
-1181     # . . discard args
-1182     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1183     # . if (eax != false) break
-1184     3d/compare-eax-and  0/imm32/false
-1185     0f 85/jump-if-!=  $emit-output:line-loop/disp32
-1186 $emit-output:check-for-segment-header:
-1187     # if !slice-equal?(word-slice, "==") goto next check
-1188     # . eax = slice-equal?(word-slice, "==")
-1189     # . . push args
-1190     68/push  "=="/imm32
-1191     52/push-edx
-1192     # . . call
-1193     e8/call  slice-equal?/disp32
-1194     # . . discard args
-1195     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1196     # . if (eax == false) goto next check
-1197     3d/compare-eax-and  0/imm32/false
-1198     0f 84/jump-if-=  $emit-output:2-character/disp32
-1199     # skip segment name
-1200     # . next-word(line, word-slice)
-1201     # . . push args
-1202     52/push-edx
-1203     51/push-ecx
-1204     # . . call
-1205     e8/call  next-word/disp32
-1206     # . . discard args
-1207     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1208     # compute segment address if it exists
-1209     # . next-word(line, word-slice)
-1210     # . . push args
-1211     52/push-edx
-1212     51/push-ecx
-1213     # . . call
-1214     e8/call  next-word/disp32
-1215     # . . discard args
-1216     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1217     # . if slice-empty?(word-slice) goto padding-done
-1218     # . . push args
-1219     52/push-edx
-1220     # . . call
-1221     e8/call  slice-empty?/disp32
-1222     # . . discard args
-1223     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1224     # . .
-1225     3d/compare-eax-and  0/imm32/false
-1226     0f 85/jump-if-!=  $emit-output:padding-done/disp32
-1227     # . var new-address/eax: int = parse-hex-int-from-slice(word-slice)
-1228     # . . push args
-1229     52/push-edx
-1230     # . . call
-1231     e8/call  parse-hex-int-from-slice/disp32
-1232     # . . discard args
-1233     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1234     # write-buffered(out, "# " address-of-next-instruction "\n")
-1235     # . write-buffered(out, "# ")
-1236     # . . push args
-1237     68/push  "# "/imm32
-1238     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1239     # . . call
-1240     e8/call  write-buffered/disp32
-1241     # . . discard args
-1242     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1243     # . write-int32-hex-buffered(out, address-of-next-instruction)
-1244     # . . push args
-1245     53/push-ebx
-1246     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1247     # . . call
-1248     e8/call  write-int32-hex-buffered/disp32
-1249     # . . discard args
-1250     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1251     # . write-buffered(out, "\n")
-1252     # . . push args
-1253     68/push  Newline/imm32
-1254     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1255     # . . call
-1256     e8/call  write-buffered/disp32
-1257     # . . discard args
-1258     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1259 $emit-output:padding-loop:
-1260     # if (address-of-next-instruction >= new-address) goto padding-loop-done
-1261     39/compare                      3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # compare ebx with eax
-1262     73/jump-if-addr>=  $emit-output:padding-loop-done/disp8
-1263     # if (address-of-next-instruction % 8 == 0) write-buffered("\n")
-1264     53/push-ebx
-1265     81          4/subop/and         3/mod/direct    3/rm32/ebx    .           .             .           .           .               7/imm32           # bitwise and of ebx
-1266     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0/imm32           # compare ebx
-1267     5b/pop-to-ebx
-1268     75/jump-if-!=  $emit-output:padding-core/disp8
-1269     # . write-buffered(out, "\n")
-1270     # . . push args
-1271     68/push  Newline/imm32
-1272     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1273     # . . call
-1274     e8/call  write-buffered/disp32
-1275     # . . discard args
-1276     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1277 $emit-output:padding-core:
-1278     # write-buffered("00")
-1279     # . . push args
-1280     68/push  "00 "/imm32
-1281     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1282     # . . call
-1283     e8/call  write-buffered/disp32
-1284     # . . discard args
-1285     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1286     # ++address-of-next-instruction
-1287     43/increment-ebx
-1288     # loop
-1289     eb/jump $emit-output:padding-loop/disp8
-1290 $emit-output:padding-loop-done:
-1291     # . write-buffered(out, "\n")
-1292     # . . push args
-1293     68/push  Newline/imm32
-1294     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1295     # . . call
-1296     e8/call  write-buffered/disp32
-1297     # . . discard args
-1298     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1299 $emit-output:padding-done:
-1300     # write-buffered(out, "# " address-of-next-instruction "\n")
-1301     # . write-buffered(out, "# ")
-1302     # . . push args
-1303     68/push  "# "/imm32
-1304     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1305     # . . call
-1306     e8/call  write-buffered/disp32
-1307     # . . discard args
-1308     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1309     # . write-int32-hex-buffered(out, address-of-next-instruction)
-1310     # . . push args
-1311     53/push-ebx
-1312     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1313     # . . call
-1314     e8/call  write-int32-hex-buffered/disp32
-1315     # . . discard args
-1316     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1317     # . write-buffered(out, "\n")
-1318     # . . push args
-1319     68/push  Newline/imm32
-1320     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1321     # . . call
-1322     e8/call  write-buffered/disp32
-1323     # . . discard args
-1324     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1325     #
-1326     e9/jump  $emit-output:line-loop/disp32
-1327 $emit-output:2-character:
-1328     # if (size(word-slice) != 2) goto next check
-1329     # . eax = size(word-slice)
-1330     8b/copy                         1/mod/*+disp8   2/rm32/edx    .           .             .           0/r32/eax   4/disp8         .                 # copy *(edx+4) to eax
-1331     2b/subtract                     0/mod/indirect  2/rm32/edx    .           .             .           0/r32/eax   .               .                 # subtract *edx from eax
-1332     # . if (eax != 2) goto next check
-1333     3d/compare-eax-and  2/imm32
-1334     75/jump-if-!=  $emit-output:check-metadata/disp8
-1335     # write-slice-buffered(out, word-slice)
-1336     # . . push args
-1337     52/push-edx
-1338     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1339     # . . call
-1340     e8/call  write-slice-buffered/disp32
-1341     # . . discard args
-1342     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1343     # write-buffered(out, " ")
-1344     # . . push args
-1345     68/push  Space/imm32
-1346     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1347     # . . call
-1348     e8/call  write-buffered/disp32
-1349     # . . discard args
-1350     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1351     # continue
-1352     e9/jump  $emit-output:word-loop/disp32
-1353 $emit-output:check-metadata:
-1354     # - if we get here, 'word-slice' must be a label to be looked up
-1355     # datum = next-token-from-slice(word-slice->start, word-slice->end, "/")
-1356     # . . push args
-1357     68/push  emit-output:datum/imm32
-1358     68/push  0x2f/imm32/slash
-1359     ff          6/subop/push        1/mod/*+disp8   2/rm32/edx    .           .             .           .           4/disp8         .                 # push *(edx+4)
-1360     ff          6/subop/push        0/mod/indirect  2/rm32/edx    .           .             .           .           .               .                 # push *edx
-1361     # . . call
-1362     e8/call  next-token-from-slice/disp32
-1363     # . . discard args
-1364     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-1365 +-- 33 lines: #?     # dump datum -------------------------------------------------------------------------------------------------------------------------------------------------------
-1398     # address/esi: (addr int) = get-slice(labels, datum, row-size=12, "label table")
-1399     # . eax = get-slice(labels, datum, row-size=24, "label table")
-1400     # . . push args
-1401     68/push  "label table"/imm32
-1402     68/push  0xc/imm32/row-size
-1403     68/push  emit-output:datum/imm32
-1404     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
-1405     # . . call
-1406     e8/call  get-slice/disp32
-1407     # . . discard args
-1408     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-1409     # . esi = eax
-1410     89/copy                         3/mod/direct    6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy eax to esi
-1411 $emit-output:check-imm8:
-1412     # if (!has-metadata?(word-slice, "imm8")) goto next check
-1413     # . eax = has-metadata?(edx, "imm8")
-1414     # . . push args
-1415     68/push  "imm8"/imm32
-1416     52/push-edx
-1417     # . . call
-1418     e8/call  has-metadata?/disp32
-1419     # . . discard args
-1420     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1421     # . if (eax != false) abort
-1422     3d/compare-eax-and  0/imm32/false
-1423     74/jump-if-=  $emit-output:check-imm16/disp8
-1424 $emit-output:emit-imm8:
-1425     # emit-hex(out, *address, 1)
-1426     # . . push args
-1427     68/push  1/imm32
-1428     ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
-1429     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1430     # . . call
-1431     e8/call  emit-hex/disp32
-1432     # . . discard args
-1433     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1434     # continue
-1435     e9/jump  $emit-output:word-loop/disp32
-1436 $emit-output:check-imm16:
-1437     # if (!has-metadata?(word-slice, "imm16")) goto next check
-1438     # . eax = has-metadata?(edx, "imm16")
-1439     # . . push args
-1440     68/push  "imm16"/imm32
-1441     52/push-edx
-1442     # . . call
-1443     e8/call  has-metadata?/disp32
-1444     # . . discard args
-1445     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1446     # . if (eax == false) goto next check
-1447     3d/compare-eax-and  0/imm32/false
-1448     74/jump-if-=  $emit-output:check-imm32/disp8
-1449 +-- 33 lines: #?     # dump *address ----------------------------------------------------------------------------------------------------------------------------------------------------
-1482 $emit-output:emit-imm16:
-1483     # emit-hex(out, *address, 2)
-1484     # . . push args
-1485     68/push  2/imm32
-1486     ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
-1487     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1488     # . . call
-1489     e8/call  emit-hex/disp32
-1490     # . . discard args
-1491     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1492     # TODO: ensure that the higher 2 bytes are zero
-1493     # continue
-1494     e9/jump  $emit-output:word-loop/disp32
-1495 $emit-output:check-imm32:
-1496     # if (!has-metadata?(word-slice, "imm32")) goto next check
-1497     # . eax = has-metadata?(edx, "imm32")
-1498     # . . push args
-1499     68/push  "imm32"/imm32
-1500     52/push-edx
-1501     # . . call
-1502     e8/call  has-metadata?/disp32
-1503     # . . discard args
-1504     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1505     # . if (eax == false) goto next check
-1506     3d/compare-eax-and  0/imm32/false
-1507     74/jump-if-=  $emit-output:check-disp8/disp8
-1508 +-- 33 lines: #?     # dump *address ----------------------------------------------------------------------------------------------------------------------------------------------------
-1541 $emit-output:emit-imm32:
-1542     # emit-hex(out, *address, 4)
-1543     # . . push args
-1544     68/push  4/imm32
-1545     ff          6/subop/push        0/mod/indirect  6/rm32/esi    .           .             .           .           .               .                 # push *esi
-1546     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1547     # . . call
-1548     e8/call  emit-hex/disp32
-1549     # . . discard args
-1550     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1551     # continue
-1552     e9/jump  $emit-output:word-loop/disp32
-1553 $emit-output:check-disp8:
-1554     # if (!has-metadata?(word-slice, "disp8")) goto next check
-1555     # . eax = has-metadata?(edx, "disp8")
-1556     # . . push args
-1557     68/push  "disp8"/imm32
-1558     52/push-edx
-1559     # . . call
-1560     e8/call  has-metadata?/disp32
-1561     # . . discard args
-1562     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1563     # . if (eax == false) goto next check
-1564     3d/compare-eax-and  0/imm32/false
-1565     74/jump-if-=  $emit-output:check-disp16/disp8
-1566 $emit-output:emit-disp8:
-1567     # emit-hex(out, *address - address-of-next-instruction, 1)
-1568     # . . push args
-1569     68/push  1/imm32
-1570     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
-1571     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
-1572     50/push-eax
-1573     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1574     # . . call
-1575     e8/call  emit-hex/disp32
-1576     # . . discard args
-1577     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1578     # continue
-1579     e9/jump  $emit-output:word-loop/disp32
-1580 $emit-output:check-disp16:
-1581     # if (!has-metadata?(word-slice, "disp16")) goto next check
-1582     # . eax = has-metadata?(edx, "disp16")
-1583     # . . push args
-1584     68/push  "disp16"/imm32
-1585     52/push-edx
-1586     # . . call
-1587     e8/call  has-metadata?/disp32
-1588     # . . discard args
-1589     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1590     # . if (eax == false) goto next check
-1591     3d/compare-eax-and  0/imm32/false
-1592     74/jump-if-=  $emit-output:check-disp32/disp8
-1593 $emit-output:emit-disp16:
-1594     # emit-hex(out, *address - address-of-next-instruction, 2)
-1595     # . . push args
-1596     68/push  2/imm32
-1597     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
-1598     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
-1599     50/push-eax
-1600     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1601     # . . call
-1602     e8/call  emit-hex/disp32
-1603     # . . discard args
-1604     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1605     # continue
-1606     e9/jump  $emit-output:word-loop/disp32
-1607 $emit-output:check-disp32:
-1608     # if (!has-metadata?(word-slice, "disp32")) abort
-1609     # . eax = has-metadata?(edx, "disp32")
-1610     # . . push args
-1611     68/push  "disp32"/imm32
-1612     52/push-edx
-1613     # . . call
-1614     e8/call  has-metadata?/disp32
-1615     # . . discard args
-1616     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1617     # . if (eax == false) abort
-1618     3d/compare-eax-and  0/imm32/false
-1619     0f 84/jump-if-=  $emit-output:abort/disp32
-1620 $emit-output:emit-disp32:
-1621     # var value/eax = *address
-1622     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
-1623     # if (far-jump-or-call?) value -= address-of-next-instruction
-1624     81          7/subop/compare     3/mod/direct    7/rm32/edi    .           .             .           .           .               0/imm32/false     # compare edi
-1625     74/jump-if-=  $emit-output:really-emit-disp32/disp8
-1626     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
-1627 $emit-output:really-emit-disp32:
-1628     # emit-hex(out, value, 4)
-1629     # . . push args
-1630     68/push  4/imm32
-1631     50/push-eax
-1632     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1633     # . . call
-1634     e8/call  emit-hex/disp32
-1635     # . . discard args
-1636     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1637     # continue
-1638     e9/jump  $emit-output:word-loop/disp32
-1639 $emit-output:next-line:
-1640     # write-buffered(out, "\n")
-1641     # . . push args
-1642     68/push  Newline/imm32
-1643     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-1644     # . . call
-1645     e8/call  write-buffered/disp32
-1646     # . . discard args
-1647     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1648     # loop
-1649     e9/jump  $emit-output:line-loop/disp32
-1650 $emit-output:end:
-1651     # . reclaim locals
-1652     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x214/imm32       # add to esp
-1653     # . restore registers
-1654     5f/pop-to-edi
-1655     5e/pop-to-esi
-1656     5b/pop-to-ebx
-1657     5a/pop-to-edx
-1658     59/pop-to-ecx
-1659     58/pop-to-eax
-1660     # . epilogue
-1661     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-1662     5d/pop-to-ebp
-1663     c3/return
-1664 
-1665 $emit-output:abort:
-1666     # print(stderr, "missing metadata in " word-slice)
-1667     # . _write(2/stderr, "missing metadata in word ")
-1668     # . . push args
-1669     68/push  "emit-output: missing metadata in "/imm32
-1670     68/push  2/imm32/stderr
-1671     # . . call
-1672     e8/call  _write/disp32
-1673     # . . discard args
-1674     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1675     # . write-slice-buffered(Stderr, word-slice)
-1676     # . . push args
-1677     52/push-edx
-1678     68/push  Stderr/imm32
-1679     # . . call
-1680     e8/call  write-slice-buffered/disp32
-1681     # . . discard args
-1682     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1683     # . flush(Stderr)
-1684     # . . push args
-1685     68/push  Stderr/imm32
-1686     # . . call
-1687     e8/call  flush/disp32
-1688     # . . discard args
-1689     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1690     # . syscall(exit, 1)
-1691     bb/copy-to-ebx  1/imm32
-1692     e8/call  syscall_exit/disp32
-1693     # never gets here
-1694 
-1695 test-emit-output-non-far-control-flow:
-1696     # labels turn into absolute addresses if opcodes are not far jumps or calls
-1697     #
-1698     # input:
-1699     #   in:
-1700     #     == code
-1701     #     ab cd ef gh
-1702     #     ij x/disp32
-1703     #     == data
-1704     #     00
-1705     #     34
-1706     #   labels:
-1707     #     - 'x': 0x11223344
-1708     #
-1709     # output:
-1710     #   ab cd ef gh
-1711     #   ij 44 33 22 11
-1712     #   00
-1713     #   34
-1714     #
-1715     # . prologue
-1716     55/push-ebp
-1717     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-1718     # setup
-1719     # . clear-stream(_test-input-stream)
-1720     # . . push args
-1721     68/push  _test-input-stream/imm32
-1722     # . . call
-1723     e8/call  clear-stream/disp32
-1724     # . . discard args
-1725     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1726     # . clear-stream(_test-output-stream)
-1727     # . . push args
-1728     68/push  _test-output-stream/imm32
-1729     # . . call
-1730     e8/call  clear-stream/disp32
-1731     # . . discard args
-1732     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1733     # . clear-stream($_test-output-buffered-file->buffer)
-1734     # . . push args
-1735     68/push  $_test-output-buffered-file->buffer/imm32
-1736     # . . call
-1737     e8/call  clear-stream/disp32
-1738     # . . discard args
-1739     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1740     # . var labels/edx: (stream byte 8*24)
-1741     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
-1742     68/push  0xc0/imm32/size
-1743     68/push  0/imm32/read
-1744     68/push  0/imm32/write
-1745     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-1746     # . var h/ebx: (handle array byte)
-1747     68/push  0/imm32
-1748     68/push  0/imm32
-1749     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
-1750     # initialize input
-1751     # . write(_test-input-stream, "== code\n")
-1752     # . . push args
-1753     68/push  "== code\n"/imm32
-1754     68/push  _test-input-stream/imm32
-1755     # . . call
-1756     e8/call  write/disp32
-1757     # . . discard args
-1758     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1759     # . write(_test-input-stream, "ab cd ef gh\n")
-1760     # . . push args
-1761     68/push  "ab cd ef gh\n"/imm32
-1762     68/push  _test-input-stream/imm32
-1763     # . . call
-1764     e8/call  write/disp32
-1765     # . . discard args
-1766     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1767     # . write(_test-input-stream, "ij x/disp32\n")
-1768     # . . push args
-1769     68/push  "ij x/disp32\n"/imm32
-1770     68/push  _test-input-stream/imm32
-1771     # . . call
-1772     e8/call  write/disp32
-1773     # . . discard args
-1774     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1775     # . write(_test-input-stream, "== data\n")
-1776     # . . push args
-1777     68/push  "== data\n"/imm32
-1778     68/push  _test-input-stream/imm32
-1779     # . . call
-1780     e8/call  write/disp32
-1781     # . . discard args
-1782     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1783     # . write(_test-input-stream, "00\n")
-1784     # . . push args
-1785     68/push  "00\n"/imm32
-1786     68/push  _test-input-stream/imm32
-1787     # . . call
-1788     e8/call  write/disp32
-1789     # . . discard args
-1790     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1791     # . write(_test-input-stream, "34\n")
-1792     # . . push args
-1793     68/push  "34\n"/imm32
-1794     68/push  _test-input-stream/imm32
-1795     # . . call
-1796     e8/call  write/disp32
-1797     # . . discard args
-1798     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1799     # . stream-add2(labels, "x", 0x11223344)
-1800     68/push  0x11223344/imm32/label-address
-1801     # . . push handle for "x"
-1802     53/push-ebx
-1803     68/push  "x"/imm32
-1804     68/push  Heap/imm32
-1805     e8/call  copy-array/disp32
-1806     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1807     ff          6/subop/push        1/mod/*+disp8   3/rm32/ebx    .           .             .           .           4/disp8         .                 # push *(ebx+4)
-1808     ff          6/subop/push        0/mod/indirect  3/rm32/ebx    .           .             .           .           .               .                 # push *ebx
-1809     # . . push labels
-1810     52/push-edx
-1811     # . . call
-1812     e8/call  stream-add2/disp32
-1813     # . . discard args
-1814     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-1815     # component under test
-1816     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
-1817     # . . push args
-1818     52/push-edx
-1819     68/push  _test-output-buffered-file/imm32
-1820     68/push  _test-input-stream/imm32
-1821     # . . call
-1822     e8/call  emit-output/disp32
-1823     # . . discard args
-1824     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1825     # checks
-1826     # . flush(_test-output-buffered-file)
-1827     # . . push args
-1828     68/push  _test-output-buffered-file/imm32
-1829     # . . call
-1830     e8/call  flush/disp32
-1831     # . . discard args
-1832     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1833 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
-1866     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
-1867     # . . push args
-1868     68/push  "F - test-emit-output-non-far-control-flow/0"/imm32
-1869     68/push  "# 0x00007c00"/imm32
-1870     68/push  _test-output-stream/imm32
-1871     # . . call
-1872     e8/call  check-next-stream-line-equal/disp32
-1873     # . . discard args
-1874     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1875     # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg)
-1876     # . . push args
-1877     68/push  "F - test-emit-output-non-far-control-flow/1"/imm32
-1878     68/push  "ab cd ef gh "/imm32
-1879     68/push  _test-output-stream/imm32
-1880     # . . call
-1881     e8/call  check-next-stream-line-equal/disp32
-1882     # . . discard args
-1883     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1884     # . check-next-stream-line-equal(_test-output-stream, "ij 44 33 22 11 ", msg)
-1885     # . . push args
-1886     68/push  "F - test-emit-output-non-far-control-flow/2"/imm32
-1887     68/push  "ij 44 33 22 11 "/imm32
-1888     68/push  _test-output-stream/imm32
-1889     # . . call
-1890     e8/call  check-next-stream-line-equal/disp32
-1891     # . . discard args
-1892     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1893     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c09", msg)
-1894     # . . push args
-1895     68/push  "F - test-emit-output-non-far-control-flow/3"/imm32
-1896     68/push  "# 0x00007c09"/imm32
-1897     68/push  _test-output-stream/imm32
-1898     # . . call
-1899     e8/call  check-next-stream-line-equal/disp32
-1900     # . . discard args
-1901     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1902     # . check-next-stream-line-equal(_test-output-stream, "00 ", msg)
-1903     # . . push args
-1904     68/push  "F - test-emit-output-non-far-control-flow/3"/imm32
-1905     68/push  "00 "/imm32
-1906     68/push  _test-output-stream/imm32
-1907     # . . call
-1908     e8/call  check-next-stream-line-equal/disp32
-1909     # . . discard args
-1910     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1911     # . check-next-stream-line-equal(_test-output-stream, "34 ", msg)
-1912     # . . push args
-1913     68/push  "F - test-emit-output-non-far-control-flow/4"/imm32
-1914     68/push  "34 "/imm32
-1915     68/push  _test-output-stream/imm32
-1916     # . . call
-1917     e8/call  check-next-stream-line-equal/disp32
-1918     # . . discard args
-1919     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-1920     # . epilogue
-1921     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-1922     5d/pop-to-ebp
-1923     c3/return
-1924 
-1925 test-emit-output-with-padding:
-1926     # labels turn into absolute addresses if opcodes are not far jumps or calls
-1927     #
-1928     # input:
-1929     #   in:
-1930     #     == code
-1931     #     ab cd ef gh
-1932     #     == data 0x7c10
-1933     #     34
-1934     #
-1935     # output:
-1936     #   ab cd ef gh
-1937     #   # 0x7c04
-1938     #   00 00 00 00
-1939     #   00 00 00 00 00 00 00 00
-1940     #   # 0x7c10
-1941     #   34
-1942     #
-1943     # . prologue
-1944     55/push-ebp
-1945     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-1946     # setup
-1947     # . clear-stream(_test-input-stream)
-1948     # . . push args
-1949     68/push  _test-input-stream/imm32
-1950     # . . call
-1951     e8/call  clear-stream/disp32
-1952     # . . discard args
-1953     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1954     # . clear-stream(_test-output-stream)
-1955     # . . push args
-1956     68/push  _test-output-stream/imm32
-1957     # . . call
-1958     e8/call  clear-stream/disp32
-1959     # . . discard args
-1960     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1961     # . clear-stream($_test-output-buffered-file->buffer)
-1962     # . . push args
-1963     68/push  $_test-output-buffered-file->buffer/imm32
-1964     # . . call
-1965     e8/call  clear-stream/disp32
-1966     # . . discard args
-1967     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-1968     # . var labels/edx: (stream byte 8*24)
-1969     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
-1970     68/push  0xc0/imm32/size
-1971     68/push  0/imm32/read
-1972     68/push  0/imm32/write
-1973     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-1974     # . var h/ebx: (handle array byte)
-1975     68/push  0/imm32
-1976     68/push  0/imm32
-1977     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
-1978     # initialize input
-1979     # . write(_test-input-stream, "== code\n")
-1980     # . . push args
-1981     68/push  "== code\n"/imm32
-1982     68/push  _test-input-stream/imm32
-1983     # . . call
-1984     e8/call  write/disp32
-1985     # . . discard args
-1986     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1987     # . write(_test-input-stream, "ab cd ef gh\n")
-1988     # . . push args
-1989     68/push  "ab cd ef gh\n"/imm32
-1990     68/push  _test-input-stream/imm32
-1991     # . . call
-1992     e8/call  write/disp32
-1993     # . . discard args
-1994     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-1995     # . write(_test-input-stream, "== data 0x7c10\n")
-1996     # . . push args
-1997     68/push  "== data 0x7c10\n"/imm32
-1998     68/push  _test-input-stream/imm32
-1999     # . . call
-2000     e8/call  write/disp32
-2001     # . . discard args
-2002     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2003     # . write(_test-input-stream, "34\n")
-2004     # . . push args
-2005     68/push  "34\n"/imm32
-2006     68/push  _test-input-stream/imm32
-2007     # . . call
-2008     e8/call  write/disp32
-2009     # . . discard args
-2010     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2011     # component under test
-2012     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
-2013     # . . push args
-2014     52/push-edx
-2015     68/push  _test-output-buffered-file/imm32
-2016     68/push  _test-input-stream/imm32
-2017     # . . call
-2018     e8/call  emit-output/disp32
-2019     # . . discard args
-2020     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2021     # checks
-2022     # . flush(_test-output-buffered-file)
-2023     # . . push args
-2024     68/push  _test-output-buffered-file/imm32
-2025     # . . call
-2026     e8/call  flush/disp32
-2027     # . . discard args
-2028     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2029 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
-2062     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
-2063     # . . push args
-2064     68/push  "F - test-emit-output-with-padding/0"/imm32
-2065     68/push  "# 0x00007c00"/imm32
-2066     68/push  _test-output-stream/imm32
-2067     # . . call
-2068     e8/call  check-next-stream-line-equal/disp32
-2069     # . . discard args
-2070     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2071     # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg)
-2072     # . . push args
-2073     68/push  "F - test-emit-output-with-padding/1"/imm32
-2074     68/push  "ab cd ef gh "/imm32
-2075     68/push  _test-output-stream/imm32
-2076     # . . call
-2077     e8/call  check-next-stream-line-equal/disp32
-2078     # . . discard args
-2079     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2080     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c04", msg)
-2081     # . . push args
-2082     68/push  "F - test-emit-output-with-padding/0"/imm32
-2083     68/push  "# 0x00007c04"/imm32
-2084     68/push  _test-output-stream/imm32
-2085     # . . call
-2086     e8/call  check-next-stream-line-equal/disp32
-2087     # . . discard args
-2088     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2089     # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg)
-2090     # . . push args
-2091     68/push  "F - test-emit-output-with-padding/2"/imm32
-2092     68/push  "00 00 00 00 "/imm32
-2093     68/push  _test-output-stream/imm32
-2094     # . . call
-2095     e8/call  check-next-stream-line-equal/disp32
-2096     # . . discard args
-2097     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2098     # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg)
-2099     # . . push args
-2100     68/push  "F - test-emit-output-with-padding/3"/imm32
-2101     68/push  "00 00 00 00 00 00 00 00 "/imm32
-2102     68/push  _test-output-stream/imm32
-2103     # . . call
-2104     e8/call  check-next-stream-line-equal/disp32
-2105     # . . discard args
-2106     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2107     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c10", msg)
-2108     # . . push args
-2109     68/push  "F - test-emit-output-with-padding/0"/imm32
-2110     68/push  "# 0x00007c10"/imm32
-2111     68/push  _test-output-stream/imm32
-2112     # . . call
-2113     e8/call  check-next-stream-line-equal/disp32
-2114     # . . discard args
-2115     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2116     # . check-next-stream-line-equal(_test-output-stream, "34 ", msg)
-2117     # . . push args
-2118     68/push  "F - test-emit-output-with-padding/4"/imm32
-2119     68/push  "34 "/imm32
-2120     68/push  _test-output-stream/imm32
-2121     # . . call
-2122     e8/call  check-next-stream-line-equal/disp32
-2123     # . . discard args
-2124     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2125     # . epilogue
-2126     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2127     5d/pop-to-ebp
-2128     c3/return
-2129 
-2130 test-emit-output-code-label:
-2131     # labels turn into PC-relative addresses if opcodes are far jumps or calls
-2132     #
-2133     # input:
-2134     #   in:
-2135     #     == code
-2136     #     ab cd
-2137     #     ef gh
-2138     #     e8 l1/disp32
-2139     #   labels:
-2140     #     - 'l1': 0x7c10
-2141     #
-2142     # output:
-2143     #   ab cd
-2144     #   ef gh
-2145     #   e8 07 00 00 00  # 0x7c10 - 0x7c09 = 7
-2146     #
-2147     # . prologue
-2148     55/push-ebp
-2149     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2150     # setup
-2151     # . clear-stream(_test-input-stream)
-2152     # . . push args
-2153     68/push  _test-input-stream/imm32
-2154     # . . call
-2155     e8/call  clear-stream/disp32
-2156     # . . discard args
-2157     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2158     # . clear-stream(_test-output-stream)
-2159     # . . push args
-2160     68/push  _test-output-stream/imm32
-2161     # . . call
-2162     e8/call  clear-stream/disp32
-2163     # . . discard args
-2164     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2165     # . clear-stream($_test-output-buffered-file->buffer)
-2166     # . . push args
-2167     68/push  $_test-output-buffered-file->buffer/imm32
-2168     # . . call
-2169     e8/call  clear-stream/disp32
-2170     # . . discard args
-2171     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2172     # . var labels/edx: (stream byte 8*24)
-2173     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
-2174     68/push  0xc0/imm32/size
-2175     68/push  0/imm32/read
-2176     68/push  0/imm32/write
-2177     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-2178     # . var h/ebx: (handle array byte)
-2179     68/push  0/imm32
-2180     68/push  0/imm32
-2181     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
-2182     # initialize input
-2183     # . write(_test-input-stream, "== code\n")
-2184     # . . push args
-2185     68/push  "== code\n"/imm32
-2186     68/push  _test-input-stream/imm32
-2187     # . . call
-2188     e8/call  write/disp32
-2189     # . . discard args
-2190     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2191     # . write(_test-input-stream, "ab cd\n")
-2192     # . . push args
-2193     68/push  "ab cd\n"/imm32
-2194     68/push  _test-input-stream/imm32
-2195     # . . call
-2196     e8/call  write/disp32
-2197     # . . discard args
-2198     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2199     # . write(_test-input-stream, "ef gh\n")
-2200     # . . push args
-2201     68/push  "ef gh\n"/imm32
-2202     68/push  _test-input-stream/imm32
-2203     # . . call
-2204     e8/call  write/disp32
-2205     # . . discard args
-2206     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2207     # . write(_test-input-stream, "e8 l1/disp32\n")
-2208     # . . push args
-2209     68/push  "e8 l1/disp32\n"/imm32
-2210     68/push  _test-input-stream/imm32
-2211     # . . call
-2212     e8/call  write/disp32
-2213     # . . discard args
-2214     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2215     # . stream-add2(labels, "l1", 0x7c10)
-2216     68/push  0x7c10/imm32/label-address
-2217     # . . push handle for "l1"
-2218     53/push-ebx
-2219     68/push  "l1"/imm32
-2220     68/push  Heap/imm32
-2221     e8/call  copy-array/disp32
-2222     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2223     ff          6/subop/push        1/mod/*+disp8   3/rm32/ebx    .           .             .           .           4/disp8         .                 # push *(ebx+4)
-2224     ff          6/subop/push        0/mod/indirect  3/rm32/ebx    .           .             .           .           .               .                 # push *ebx
-2225     # . . push labels
-2226     52/push-edx
-2227     # . . call
-2228     e8/call  stream-add2/disp32
-2229     # . . discard args
-2230     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-2231     # component under test
-2232     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
-2233     # . . push args
-2234     52/push-edx
-2235     68/push  _test-output-buffered-file/imm32
-2236     68/push  _test-input-stream/imm32
-2237     # . . call
-2238     e8/call  emit-output/disp32
-2239     # . . discard args
-2240     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2241     # checks
-2242     # . flush(_test-output-buffered-file)
-2243     # . . push args
-2244     68/push  _test-output-buffered-file/imm32
-2245     # . . call
-2246     e8/call  flush/disp32
-2247     # . . discard args
-2248     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2249 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
-2282     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
-2283     # . . push args
-2284     68/push  "F - test-emit-output-code-label/0"/imm32
-2285     68/push  "# 0x00007c00"/imm32
-2286     68/push  _test-output-stream/imm32
-2287     # . . call
-2288     e8/call  check-next-stream-line-equal/disp32
-2289     # . . discard args
-2290     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2291     # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg)
-2292     # . . push args
-2293     68/push  "F - test-emit-output-code-label/1"/imm32
-2294     68/push  "ab cd "/imm32
-2295     68/push  _test-output-stream/imm32
-2296     # . . call
-2297     e8/call  check-next-stream-line-equal/disp32
-2298     # . . discard args
-2299     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2300     # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg)
-2301     # . . push args
-2302     68/push  "F - test-emit-output-code-label/2"/imm32
-2303     68/push  "ef gh "/imm32
-2304     68/push  _test-output-stream/imm32
-2305     # . . call
-2306     e8/call  check-next-stream-line-equal/disp32
-2307     # . . discard args
-2308     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2309     # . check-next-stream-line-equal(_test-output-stream, "e8 07 00 00 00 ", msg)
-2310     # . . push args
-2311     68/push  "F - test-emit-output-code-label/3"/imm32
-2312     68/push  "e8 07 00 00 00 "/imm32
-2313     68/push  _test-output-stream/imm32
-2314     # . . call
-2315     e8/call  check-next-stream-line-equal/disp32
-2316     # . . discard args
-2317     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2318     # . epilogue
-2319     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2320     5d/pop-to-ebp
-2321     c3/return
-2322 
-2323 test-emit-output-code-label-absolute:
-2324     # labels can also convert to absolute addresses
-2325     #
-2326     # input:
-2327     #   in:
-2328     #     == code
-2329     #     ab cd
-2330     #     ef gh
-2331     #     ij l1/imm32
-2332     #   labels:
-2333     #     - 'l1': 0x1056
-2334     #
-2335     # output:
-2336     #   ab cd
-2337     #   ef gh
-2338     #   ij 56 10 00 00
-2339     #
-2340     # . prologue
-2341     55/push-ebp
-2342     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2343     # setup
-2344     # . clear-stream(_test-input-stream)
-2345     # . . push args
-2346     68/push  _test-input-stream/imm32
-2347     # . . call
-2348     e8/call  clear-stream/disp32
-2349     # . . discard args
-2350     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2351     # . clear-stream(_test-output-stream)
-2352     # . . push args
-2353     68/push  _test-output-stream/imm32
-2354     # . . call
-2355     e8/call  clear-stream/disp32
-2356     # . . discard args
-2357     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2358     # . clear-stream($_test-output-buffered-file->buffer)
-2359     # . . push args
-2360     68/push  $_test-output-buffered-file->buffer/imm32
-2361     # . . call
-2362     e8/call  clear-stream/disp32
-2363     # . . discard args
-2364     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2365     # . var labels/edx: (stream byte 8*24)
-2366     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc0/imm32        # subtract from esp
-2367     68/push  0xc0/imm32/size
-2368     68/push  0/imm32/read
-2369     68/push  0/imm32/write
-2370     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-2371     # . var h/ebx: (handle array byte)
-2372     68/push  0/imm32
-2373     68/push  0/imm32
-2374     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
-2375     # initialize input
-2376     # . write(_test-input-stream, "== code 0x1000\n")
-2377     # . . push args
-2378     68/push  "== code\n"/imm32
-2379     68/push  _test-input-stream/imm32
-2380     # . . call
-2381     e8/call  write/disp32
-2382     # . . discard args
-2383     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2384     # . write(_test-input-stream, "ab cd\n")
-2385     # . . push args
-2386     68/push  "ab cd\n"/imm32
-2387     68/push  _test-input-stream/imm32
-2388     # . . call
-2389     e8/call  write/disp32
-2390     # . . discard args
-2391     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2392     # . write(_test-input-stream, "ef gh\n")
-2393     # . . push args
-2394     68/push  "ef gh\n"/imm32
-2395     68/push  _test-input-stream/imm32
-2396     # . . call
-2397     e8/call  write/disp32
-2398     # . . discard args
-2399     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2400     # . write(_test-input-stream, "ij l1/imm32\n")
-2401     # . . push args
-2402     68/push  "ij l1/imm32\n"/imm32
-2403     68/push  _test-input-stream/imm32
-2404     # . . call
-2405     e8/call  write/disp32
-2406     # . . discard args
-2407     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2408     # . stream-add2(labels, "l1", 0x1056)
-2409     68/push  0x1056/imm32/label-address
-2410     # . . push handle for "l1"
-2411     53/push-ebx
-2412     68/push  "l1"/imm32
-2413     68/push  Heap/imm32
-2414     e8/call  copy-array/disp32
-2415     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2416     ff          6/subop/push        1/mod/*+disp8   3/rm32/ebx    .           .             .           .           4/disp8         .                 # push *(ebx+4)
-2417     ff          6/subop/push        0/mod/indirect  3/rm32/ebx    .           .             .           .           .               .                 # push *ebx
-2418     # . . push labels
-2419     52/push-edx
-2420     # . . call
-2421     e8/call  stream-add2/disp32
-2422     # . . discard args
-2423     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-2424     # component under test
-2425     # . emit-output(_test-input-stream, _test-output-buffered-file, labels)
-2426     # . . push args
-2427     52/push-edx
-2428     68/push  _test-output-buffered-file/imm32
-2429     68/push  _test-input-stream/imm32
-2430     # . . call
-2431     e8/call  emit-output/disp32
-2432     # . . discard args
-2433     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2434     # checks
-2435     # . flush(_test-output-buffered-file)
-2436     # . . push args
-2437     68/push  _test-output-buffered-file/imm32
-2438     # . . call
-2439     e8/call  flush/disp32
-2440     # . . discard args
-2441     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2442 +-- 33 lines: #?     # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------
-2475     # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg)
-2476     # . . push args
-2477     68/push  "F - test-emit-output-code-label-absolute/0"/imm32
-2478     68/push  "# 0x00007c00"/imm32
-2479     68/push  _test-output-stream/imm32
-2480     # . . call
-2481     e8/call  check-next-stream-line-equal/disp32
-2482     # . . discard args
-2483     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2484     # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg)
-2485     # . . push args
-2486     68/push  "F - test-emit-output-code-label-absolute/1"/imm32
-2487     68/push  "ab cd "/imm32
-2488     68/push  _test-output-stream/imm32
-2489     # . . call
-2490     e8/call  check-next-stream-line-equal/disp32
-2491     # . . discard args
-2492     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2493     # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg)
-2494     # . . push args
-2495     68/push  "F - test-emit-output-code-label-absolute/2"/imm32
-2496     68/push  "ef gh "/imm32
-2497     68/push  _test-output-stream/imm32
-2498     # . . call
-2499     e8/call  check-next-stream-line-equal/disp32
-2500     # . . discard args
-2501     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2502     # . check-next-stream-line-equal(_test-output-stream, "ij f9 ff ff ff ", msg)
-2503     # . . push args
-2504     68/push  "F - test-emit-output-code-label-absolute/3"/imm32
-2505     68/push  "ij 56 10 00 00 "/imm32
-2506     68/push  _test-output-stream/imm32
-2507     # . . call
-2508     e8/call  check-next-stream-line-equal/disp32
-2509     # . . discard args
-2510     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-2511     # . epilogue
-2512     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2513     5d/pop-to-ebp
-2514     c3/return
-2515 
-2516 # reads line to make some checks
-2517 # don't assume the read state of line after calling this function
-2518 far-jump-or-call?:  # line: (addr stream byte) -> result/edi: boolean
-2519     # . prologue
-2520     55/push-ebp
-2521     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2522     # . save registers
-2523     50/push-eax
-2524     51/push-ecx
-2525     52/push-edx
-2526     53/push-ebx
-2527     # ecx = line
-2528     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
-2529     # var word-slice/edx: slice
-2530     68/push  0/imm32/end
-2531     68/push  0/imm32/start
-2532     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           4/r32/esp   .               .                 # copy esp to edx
-2533     # var datum-slice/ebx: slice
-2534     68/push  0/imm32/end
-2535     68/push  0/imm32/start
-2536     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
-2537     # result = false
-2538     bf/copy-to-edi  0/imm32/false
-2539 $far-jump-or-call?:check-first-word:
-2540     # next-word(line, word-slice)
-2541     # . . push args
-2542     52/push-edx
-2543     51/push-ecx
-2544     # . . call
-2545     e8/call  next-word/disp32
-2546     # . . discard args
-2547     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2548     # if (slice-empty?(word-slice)) return false
-2549     # . eax = slice-empty?(word-slice)
-2550     # . . push args
-2551     52/push-edx
-2552     # . . call
-2553     e8/call  slice-empty?/disp32
-2554     # . . discard args
-2555     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2556     # . if (eax != 0) return
-2557     3d/compare-eax-and  0/imm32/false
-2558     0f 85/jump-if-!=  $far-jump-or-call?:end/disp32
-2559     # datum = next-token-from-slice(word-slice->start, word-slice->end, "/")
-2560     # . . push args
-2561     53/push-ebx
-2562     68/push  0x2f/imm32/slash
-2563     ff          6/subop/push        1/mod/*+disp8   2/rm32/edx    .           .             .           .           4/disp8         .                 # push *(edx+4)
-2564     ff          6/subop/push        0/mod/indirect  2/rm32/edx    .           .             .           .           .               .                 # push *edx
-2565     # . . call
-2566     e8/call  next-token-from-slice/disp32
-2567     # . . discard args
-2568     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-2569     # if (datum-slice == "e8") return true
-2570     # . eax = slice-equal?(datum-slice, "e8")
-2571     # . . push args
-2572     68/push  "e8"/imm32
-2573     53/push-ebx
-2574     # . . call
-2575     e8/call  slice-equal?/disp32
-2576     # . . discard args
-2577     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2578     # . if (eax != false) return true
-2579     3d/compare-eax-and  0/imm32/false
-2580     75/jump-if-!=  $far-jump-or-call?:return-true/disp8
-2581     # if (datum-slice == "e9") return true
-2582     # . eax = slice-equal?(datum-slice, "e9")
-2583     # . . push args
-2584     68/push  "e9"/imm32
-2585     53/push-ebx
-2586     # . . call
-2587     e8/call  slice-equal?/disp32
-2588     # . . discard args
-2589     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2590     # . if (eax != false) return true
-2591     3d/compare-eax-and  0/imm32/false
-2592     75/jump-if-!=  $far-jump-or-call?:return-true/disp8
-2593     # if (datum-slice != "0f") return false
-2594     # . eax = slice-equal?(datum-slice, "0f")
-2595     # . . push args
-2596     68/push  "0f"/imm32
-2597     53/push-ebx
-2598     # . . call
-2599     e8/call  slice-equal?/disp32
-2600     # . . discard args
-2601     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2602     # . if (eax == false) return
-2603     3d/compare-eax-and  0/imm32/false
-2604     74/jump-if-=  $far-jump-or-call?:end/disp8
-2605 $far-jump-or-call?:check-second-word:
-2606     # next-word(line, word-slice)
-2607     # . . push args
-2608     52/push-edx
-2609     51/push-ecx
-2610     # . . call
-2611     e8/call  next-word/disp32
-2612     # . . discard args
-2613     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2614     # if (slice-empty?(word-slice)) return false
-2615     # . eax = slice-empty?(word-slice)
-2616     # . . push args
-2617     52/push-edx
-2618     # . . call
-2619     e8/call  slice-empty?/disp32
-2620     # . . discard args
-2621     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2622     # . if (eax != 0) return
-2623     3d/compare-eax-and  0/imm32/false
-2624     75/jump-if-!=  $far-jump-or-call?:end/disp8
-2625     # if datum of word-slice does not start with "8", return false
-2626     # . start/eax = word-slice->start
-2627     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           0/r32/eax   .               .                 # copy *edx to eax
-2628     # . c/eax = *start
-2629     8a/copy-byte                    0/mod/indirect  0/rm32/eax    .           .             .           0/r32/AL    .               .                 # copy byte at *eax to AL
-2630     81          4/subop/and         3/mod/direct    0/rm32/eax    .           .             .           .           .               0xff/imm32        # bitwise and of eax
-2631     # . if (eax != '8') return
-2632     3d/compare-eax-and  0x38/imm32/8
-2633     75/jump-if-!=  $far-jump-or-call?:end/disp8
-2634     # otherwise return true
-2635 $far-jump-or-call?:return-true:
-2636     bf/copy-to-edi  1/imm32/true
-2637 $far-jump-or-call?:end:
-2638     # . reclaim locals
-2639     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
-2640     # . restore registers
-2641     5b/pop-to-ebx
-2642     5a/pop-to-edx
-2643     59/pop-to-ecx
-2644     58/pop-to-eax
-2645     # . epilogue
-2646     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2647     5d/pop-to-ebp
-2648     c3/return
-2649 
-2650 # - some helpers for tests
-2651 
-2652 stream-add2:  # in: (addr stream byte), key: handle, val: int
-2653     # . prologue
-2654     55/push-ebp
-2655     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2656     # . save registers
-2657     50/push-eax
-2658     51/push-ecx
-2659     52/push-edx
-2660     56/push-esi
-2661     # esi = in
-2662     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
-2663     # curr/eax = &in->data[in->write]
-2664     # . eax = in->write
-2665     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
-2666     # . eax = esi+eax+12
-2667     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
-2668     # max/edx = &in->data[in->size]
-2669     # . edx = in->size
-2670     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           2/r32/edx   8/disp8         .                 # copy *(esi+8) to edx
-2671     # . edx = esi+edx+12
-2672     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  2/index/edx   .           2/r32/edx   0xc/disp8       .                 # copy esi+edx+12 to edx
-2673     # if (curr >= max) abort
-2674     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax with edx
-2675     73/jump-if-addr>=  $stream-add2:abort/disp8
-2676     # *curr = key->alloc-id
-2677     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   0xc/disp8       .                 # copy *(ebp+12) to ecx
-2678     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
-2679     # curr += 4
-2680     05/add-to-eax  4/imm32
-2681     # if (curr >= max) abort
-2682     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax with edx
-2683     73/jump-if-addr>=  $stream-add2:abort/disp8
-2684     # *curr = key->payload
-2685     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   0x10/disp8      .                 # copy *(ebp+16) to ecx
-2686     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
-2687     # curr += 4
-2688     05/add-to-eax  4/imm32
-2689     # if (curr >= max) abort
-2690     39/compare                      3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # compare eax with edx
-2691     73/jump-if-addr>=  $stream-add2:abort/disp8
-2692     # *curr = val
-2693     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         1/r32/ecx   0x14/disp8      .                 # copy *(ebp+20) to ecx
-2694     89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
-2695     # in->write += 0xc
-2696     81          0/subop/add         0/mod/indirect  6/rm32/esi    .           .             .           .           .               0xc/imm32         # add to *esi
-2697 $stream-add2:end:
-2698     # . restore registers
-2699     5e/pop-to-esi
-2700     5a/pop-to-edx
-2701     59/pop-to-ecx
-2702     58/pop-to-eax
-2703     # . epilogue
-2704     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2705     5d/pop-to-ebp
-2706     c3/return
-2707 
-2708 $stream-add2:abort:
-2709     # . _write(2/stderr, error)
-2710     # . . push args
-2711     68/push  "overflow in stream-add2\n"/imm32
-2712     68/push  2/imm32/stderr
-2713     # . . call
-2714     e8/call  _write/disp32
-2715     # . . discard args
-2716     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2717     # . syscall(exit, 1)
-2718     bb/copy-to-ebx  1/imm32
-2719     e8/call  syscall_exit/disp32
-2720     # never gets here
-2721 
-2722 # some variants of 'trace' that take multiple arguments in different combinations of types:
-2723 #   n: int
-2724 #   c: character [4-bytes, will eventually be UTF-8]
-2725 #   s: (addr array byte)
-2726 #   l: (addr slice)
-2727 # one gotcha: 's5' must not be empty
-2728 
-2729 trace-slsns:  # s1: (addr array byte), l2: (addr slice), s3: (addr array byte), n4: int, s5: (addr array byte)
-2730     # . prologue
-2731     55/push-ebp
-2732     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2733     # write(*Trace-stream, s1)
-2734     # . . push args
-2735     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
-2736     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
-2737     # . . call
-2738     e8/call  write/disp32
-2739     # . . discard args
-2740     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2741     # write-slice(*Trace-stream, l2)
-2742     # . . push args
-2743     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
-2744     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
-2745     # . . call
-2746     e8/call  write-slice/disp32
-2747     # . . discard args
-2748     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2749     # write(*Trace-stream, s3)
-2750     # . . push args
-2751     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
-2752     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
-2753     # . . call
-2754     e8/call  write/disp32
-2755     # . . discard args
-2756     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2757     # write-int32-hex(*Trace-stream, n4)
-2758     # . . push args
-2759     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x14/disp8      .                 # push *(ebp+20)
-2760     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
-2761     # . . call
-2762     e8/call  write-int32-hex/disp32
-2763     # . . discard args
-2764     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2765     # trace(s5)  # implicitly adds a newline and finalizes the trace line
-2766     # . . push args
-2767     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x18/disp8      .                 # push *(ebp+24)
-2768     # . . call
-2769     e8/call  trace/disp32
-2770     # . . discard args
-2771     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2772 $trace-slsns:end:
-2773     # . epilogue
-2774     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2775     5d/pop-to-ebp
-2776     c3/return
-2777 
-2778 test-trace-slsns:
-2779     # . prologue
-2780     55/push-ebp
-2781     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2782     # setup
-2783     # . *Trace-stream->write = 0
-2784     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/eax   Trace-stream/disp32               # copy *Trace-stream to eax
-2785     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm32           # clear *eax
-2786     # (eax..ecx) = "b"
-2787     b8/copy-to-eax  "b"/imm32
-2788     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
-2789     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
-2790     05/add-to-eax  4/imm32
-2791     # var b/ebx: slice = {eax, ecx}
-2792     51/push-ecx
-2793     50/push-eax
-2794     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
-2795     # trace-slsls("A" b "c " 3 " e")
-2796     # . . push args
-2797     68/push  " e"/imm32
-2798     68/push  3/imm32
-2799     68/push  "c "/imm32
-2800     53/push-ebx
-2801     68/push  "A"/imm32
-2802     # . . call
-2803     e8/call  trace-slsns/disp32
-2804     # . . discard args
-2805     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
-2806 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
-2832     # check-trace-contains("Abc 0x00000003 e")
-2833     # . . push args
-2834     68/push  "F - test-trace-slsls"/imm32
-2835     68/push  "Abc 0x00000003 e"/imm32
-2836     # . . call
-2837     e8/call  check-trace-contains/disp32
-2838     # . . discard args
-2839     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2840     # . epilogue
-2841     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-2842     5d/pop-to-ebp
-2843     c3/return
-2844 
-2845 num-bytes:  # line: (addr stream byte) -> eax: int
-2846     # pseudocode:
-2847     #   result = 0
-2848     #   while true
-2849     #     var word-slice = next-word(line)
-2850     #     if slice-empty?(word-slice)             # end of line
-2851     #       break
-2852     #     if slice-starts-with?(word-slice, "#")  # comment
-2853     #       break
-2854     #     if label?(word-slice)                # no need for label declarations anymore
-2855     #       break
-2856     #     if slice-equal?(word-slice, "==")
-2857     #       break                                 # no need for segment header lines
-2858     #     result += compute-width(word-slice)
-2859     #   return result
-2860     #
-2861     # . prologue
-2862     55/push-ebp
-2863     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-2864     # . save registers
-2865     51/push-ecx
-2866     52/push-edx
-2867     53/push-ebx
-2868     # var result/eax = 0
-2869     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
-2870     # var word-slice/ecx: slice
-2871     68/push  0/imm32/end
-2872     68/push  0/imm32/start
-2873     89/copy                         3/mod/direct    1/rm32/ecx    .           .             .           4/r32/esp   .               .                 # copy esp to ecx
-2874 +-- 26 lines: #?     # dump line --------------------------------------------------------------------------------------------------------------------------------------------------------
-2900     # . rewind-stream(line)
-2901     # . . push args
-2902     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
-2903     # . . call
-2904     e8/call  rewind-stream/disp32
-2905     # . . discard args
-2906     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2907 $num-bytes:loop:
-2908     # next-word(line, word-slice)
-2909     # . . push args
-2910     51/push-ecx
-2911     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
-2912     # . . call
-2913     e8/call  next-word/disp32
-2914     # . . discard args
-2915     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-2916 +-- 40 lines: #?     # dump word-slice --------------------------------------------------------------------------------------------------------------------------------------------------
-2956 $num-bytes:check0:
-2957     # if (slice-empty?(word-slice)) break
-2958     # . save result
-2959     50/push-eax
-2960     # . eax = slice-empty?(word-slice)
-2961     # . . push args
-2962     51/push-ecx
-2963     # . . call
-2964     e8/call  slice-empty?/disp32
-2965     # . . discard args
-2966     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-2967     # . if (eax != false) break
-2968     3d/compare-eax-and  0/imm32/false
-2969     # . restore result now that ZF is set
-2970     58/pop-to-eax
-2971     75/jump-if-!=  $num-bytes:end/disp8
-2972 $num-bytes:check-for-comment:
-2973     # if (slice-starts-with?(word-slice, "#")) break
-2974     # . start/edx = word-slice->start
-2975     8b/copy                         0/mod/indirect  1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # copy *ecx to edx
-2976     # . c/ebx = *start
-2977     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
-2978     8a/copy-byte                    0/mod/indirect  2/rm32/edx    .           .             .           3/r32/BL    .               .                 # copy byte at *edx to BL
-2979     # . if (ebx == '#') break
-2980     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x23/imm32/hash   # compare ebx
-2981     74/jump-if-=  $num-bytes:end/disp8
-2982 $num-bytes:check-for-label:
-2983     # if (slice-ends-with?(word-slice, ":")) break
-2984     # . end/edx = word-slice->end
-2985     8b/copy                         1/mod/*+disp8   1/rm32/ecx    .           .             .           2/r32/edx   4/disp8         .                 # copy *(ecx+4) to edx
-2986     # . c/ebx = *(end-1)
-2987     31/xor                          3/mod/direct    3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # clear ebx
-2988     8a/copy-byte                    1/mod/*+disp8   2/rm32/edx    .           .             .           3/r32/BL    -1/disp8        .                 # copy byte at *ecx to BL
-2989     # . if (ebx == ':') break
-2990     81          7/subop/compare     3/mod/direct    3/rm32/ebx    .           .             .           .           .               0x3a/imm32/colon  # compare ebx
-2991     74/jump-if-=  $num-bytes:end/disp8
-2992 $num-bytes:check-for-segment-header:
-2993     # if (slice-equal?(word-slice, "==")) break
-2994     # . push result
-2995     50/push-eax
-2996     # . eax = slice-equal?(word-slice, "==")
-2997     # . . push args
-2998     68/push  "=="/imm32
-2999     51/push-ecx
-3000     # . . call
-3001     e8/call  slice-equal?/disp32
-3002     # . . discard args
-3003     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3004     # . if (eax != false) break
-3005     3d/compare-eax-and  0/imm32/false
-3006     # . restore result now that ZF is set
-3007     58/pop-to-eax
-3008     75/jump-if-!=  $num-bytes:end/disp8
-3009 $num-bytes:loop-body:
-3010     # result += compute-width-of-slice(word-slice)
-3011     # . copy result to edx
-3012     89/copy                         3/mod/direct    2/rm32/edx    .           .             .           0/r32/eax   .               .                 # copy eax to edx
-3013     # . eax = compute-width-of-slice(word-slice)
-3014     # . . push args
-3015     51/push-ecx
-3016     # . . call
-3017     e8/call compute-width-of-slice/disp32
-3018     # . . discard args
-3019     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3020     # . eax += result
-3021     01/add                          3/mod/direct    0/rm32/eax    .           .             .           2/r32/edx   .               .                 # add edx to eax
-3022     e9/jump  $num-bytes:loop/disp32
-3023 $num-bytes:end:
-3024     # . rewind-stream(line)
-3025     # . . push args
-3026     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
-3027     # . . call
-3028     e8/call  rewind-stream/disp32
-3029     # . . discard args
-3030     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3031     # . reclaim locals
-3032     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3033     # . restore registers
-3034     5b/pop-to-ebx
-3035     5a/pop-to-edx
-3036     59/pop-to-ecx
-3037     # . epilogue
-3038     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3039     5d/pop-to-ebp
-3040     c3/return
-3041 
-3042 test-num-bytes-handles-empty-string:
-3043     # if a line starts with '#', return 0
-3044     # . prologue
-3045     55/push-ebp
-3046     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3047     # setup
-3048     # . clear-stream(_test-input-stream)
-3049     # . . push args
-3050     68/push  _test-input-stream/imm32
-3051     # . . call
-3052     e8/call  clear-stream/disp32
-3053     # . . discard args
-3054     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3055     # . clear-stream(_test-output-stream)
-3056     # . . push args
-3057     68/push  _test-output-stream/imm32
-3058     # . . call
-3059     e8/call  clear-stream/disp32
-3060     # . . discard args
-3061     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3062     # no contents in input
-3063     # eax = num-bytes(_test-input-stream)
-3064     # . . push args
-3065     68/push  _test-input-stream/imm32
-3066     # . . call
-3067     e8/call  num-bytes/disp32
-3068     # . . discard args
-3069     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3070     # check-ints-equal(eax, 0, msg)
-3071     # . . push args
-3072     68/push  "F - test-num-bytes-handles-empty-string"/imm32
-3073     68/push  0/imm32/true
-3074     50/push-eax
-3075     # . . call
-3076     e8/call  check-ints-equal/disp32
-3077     # . . discard args
-3078     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3079     # . epilogue
-3080     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3081     5d/pop-to-ebp
-3082     c3/return
-3083 
-3084 test-num-bytes-ignores-comments:
-3085     # if a line starts with '#', return 0
-3086     # . prologue
-3087     55/push-ebp
-3088     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3089     # setup
-3090     # . clear-stream(_test-input-stream)
-3091     # . . push args
-3092     68/push  _test-input-stream/imm32
-3093     # . . call
-3094     e8/call  clear-stream/disp32
-3095     # . . discard args
-3096     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3097     # . clear-stream(_test-output-stream)
-3098     # . . push args
-3099     68/push  _test-output-stream/imm32
-3100     # . . call
-3101     e8/call  clear-stream/disp32
-3102     # . . discard args
-3103     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3104     # initialize input
-3105     # . write(_test-input-stream, "# abcd")
-3106     # . . push args
-3107     68/push  "# abcd"/imm32
-3108     68/push  _test-input-stream/imm32
-3109     # . . call
-3110     e8/call  write/disp32
-3111     # . . discard args
-3112     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3113     # eax = num-bytes(_test-input-stream)
-3114     # . . push args
-3115     68/push  _test-input-stream/imm32
-3116     # . . call
-3117     e8/call  num-bytes/disp32
-3118     # . . discard args
-3119     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3120     # check-ints-equal(eax, 0, msg)
-3121     # . . push args
-3122     68/push  "F - test-num-bytes-ignores-comments"/imm32
-3123     68/push  0/imm32/true
-3124     50/push-eax
-3125     # . . call
-3126     e8/call  check-ints-equal/disp32
-3127     # . . discard args
-3128     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3129     # . epilogue
-3130     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3131     5d/pop-to-ebp
-3132     c3/return
-3133 
-3134 test-num-bytes-ignores-labels:
-3135     # if the first word ends with ':', return 0
-3136     # . prologue
-3137     55/push-ebp
-3138     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3139     # setup
-3140     # . clear-stream(_test-input-stream)
-3141     # . . push args
-3142     68/push  _test-input-stream/imm32
-3143     # . . call
-3144     e8/call  clear-stream/disp32
-3145     # . . discard args
-3146     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3147     # . clear-stream(_test-output-stream)
-3148     # . . push args
-3149     68/push  _test-output-stream/imm32
-3150     # . . call
-3151     e8/call  clear-stream/disp32
-3152     # . . discard args
-3153     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3154     # initialize input
-3155     # . write(_test-input-stream, "ab: # cd")
-3156     # . . push args
-3157     68/push  "ab: # cd"/imm32
-3158     68/push  _test-input-stream/imm32
-3159     # . . call
-3160     e8/call  write/disp32
-3161     # . . discard args
-3162     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3163     # eax = num-bytes(_test-input-stream)
-3164     # . . push args
-3165     68/push  _test-input-stream/imm32
-3166     # . . call
-3167     e8/call  num-bytes/disp32
-3168     # . . discard args
-3169     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3170     # check-ints-equal(eax, 0, msg)
-3171     # . . push args
-3172     68/push  "F - test-num-bytes-ignores-labels"/imm32
-3173     68/push  0/imm32/true
-3174     50/push-eax
-3175     # . . call
-3176     e8/call  check-ints-equal/disp32
-3177     # . . discard args
-3178     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3179     # . epilogue
-3180     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3181     5d/pop-to-ebp
-3182     c3/return
-3183 
-3184 test-num-bytes-ignores-segment-headers:
-3185     # if the first word is '==', return 0
-3186     # . prologue
-3187     55/push-ebp
-3188     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3189     # setup
-3190     # . clear-stream(_test-input-stream)
-3191     # . . push args
-3192     68/push  _test-input-stream/imm32
-3193     # . . call
-3194     e8/call  clear-stream/disp32
-3195     # . . discard args
-3196     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3197     # . clear-stream(_test-output-stream)
-3198     # . . push args
-3199     68/push  _test-output-stream/imm32
-3200     # . . call
-3201     e8/call  clear-stream/disp32
-3202     # . . discard args
-3203     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3204     # initialize input
-3205     # . write(_test-input-stream, "== ab cd")
-3206     # . . push args
-3207     68/push  "== ab cd"/imm32
-3208     68/push  _test-input-stream/imm32
-3209     # . . call
-3210     e8/call  write/disp32
-3211     # . . discard args
-3212     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3213     # eax = num-bytes(_test-input-stream)
-3214     # . . push args
-3215     68/push  _test-input-stream/imm32
-3216     # . . call
-3217     e8/call  num-bytes/disp32
-3218     # . . discard args
-3219     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3220     # check-ints-equal(eax, 0, msg)
-3221     # . . push args
-3222     68/push  "F - test-num-bytes-ignores-segment-headers"/imm32
-3223     68/push  0/imm32/true
-3224     50/push-eax
-3225     # . . call
-3226     e8/call  check-ints-equal/disp32
-3227     # . . discard args
-3228     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3229     # . epilogue
-3230     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3231     5d/pop-to-ebp
-3232     c3/return
-3233 
-3234 test-num-bytes-counts-words-by-default:
-3235     # without metadata, count words
-3236     # . prologue
-3237     55/push-ebp
-3238     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3239     # setup
-3240     # . clear-stream(_test-input-stream)
-3241     # . . push args
-3242     68/push  _test-input-stream/imm32
-3243     # . . call
-3244     e8/call  clear-stream/disp32
-3245     # . . discard args
-3246     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3247     # . clear-stream(_test-output-stream)
-3248     # . . push args
-3249     68/push  _test-output-stream/imm32
-3250     # . . call
-3251     e8/call  clear-stream/disp32
-3252     # . . discard args
-3253     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3254     # initialize input
-3255     # . write(_test-input-stream, "ab cd ef")
-3256     # . . push args
-3257     68/push  "ab cd ef"/imm32
-3258     68/push  _test-input-stream/imm32
-3259     # . . call
-3260     e8/call  write/disp32
-3261     # . . discard args
-3262     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3263     # eax = num-bytes(_test-input-stream)
-3264     # . . push args
-3265     68/push  _test-input-stream/imm32
-3266     # . . call
-3267     e8/call  num-bytes/disp32
-3268     # . . discard args
-3269     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3270     # check-ints-equal(eax, 3, msg)
-3271     # . . push args
-3272     68/push  "F - test-num-bytes-counts-words-by-default"/imm32
-3273     68/push  3/imm32/true
-3274     50/push-eax
-3275     # . . call
-3276     e8/call  check-ints-equal/disp32
-3277     # . . discard args
-3278     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3279     # . epilogue
-3280     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3281     5d/pop-to-ebp
-3282     c3/return
-3283 
-3284 test-num-bytes-ignores-trailing-comment:
-3285     # trailing comments appropriately ignored
-3286     # . prologue
-3287     55/push-ebp
-3288     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3289     # setup
-3290     # . clear-stream(_test-input-stream)
-3291     # . . push args
-3292     68/push  _test-input-stream/imm32
-3293     # . . call
-3294     e8/call  clear-stream/disp32
-3295     # . . discard args
-3296     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3297     # . clear-stream(_test-output-stream)
-3298     # . . push args
-3299     68/push  _test-output-stream/imm32
-3300     # . . call
-3301     e8/call  clear-stream/disp32
-3302     # . . discard args
-3303     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3304     # initialize input
-3305     # . write(_test-input-stream, "ab cd # ef")
-3306     # . . push args
-3307     68/push  "ab cd # ef"/imm32
-3308     68/push  _test-input-stream/imm32
-3309     # . . call
-3310     e8/call  write/disp32
-3311     # . . discard args
-3312     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3313     # eax = num-bytes(_test-input-stream)
-3314     # . . push args
-3315     68/push  _test-input-stream/imm32
-3316     # . . call
-3317     e8/call  num-bytes/disp32
-3318     # . . discard args
-3319     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3320     # check-ints-equal(eax, 2, msg)
-3321     # . . push args
-3322     68/push  "F - test-num-bytes-ignores-trailing-comment"/imm32
-3323     68/push  2/imm32/true
-3324     50/push-eax
-3325     # . . call
-3326     e8/call  check-ints-equal/disp32
-3327     # . . discard args
-3328     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3329     # . epilogue
-3330     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3331     5d/pop-to-ebp
-3332     c3/return
-3333 
-3334 test-num-bytes-handles-imm32:
-3335     # if a word has the /imm32 metadata, count it as 4 bytes
-3336     # . prologue
-3337     55/push-ebp
-3338     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
-3339     # setup
-3340     # . clear-stream(_test-input-stream)
-3341     # . . push args
-3342     68/push  _test-input-stream/imm32
-3343     # . . call
-3344     e8/call  clear-stream/disp32
-3345     # . . discard args
-3346     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3347     # . clear-stream(_test-output-stream)
-3348     # . . push args
-3349     68/push  _test-output-stream/imm32
-3350     # . . call
-3351     e8/call  clear-stream/disp32
-3352     # . . discard args
-3353     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3354     # initialize input
-3355     # . write(_test-input-stream, "ab cd/imm32 ef")
-3356     # . . push args
-3357     68/push  "ab cd/imm32 ef"/imm32
-3358     68/push  _test-input-stream/imm32
-3359     # . . call
-3360     e8/call  write/disp32
-3361     # . . discard args
-3362     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-3363     # eax = num-bytes(_test-input-stream)
-3364     # . . push args
-3365     68/push  _test-input-stream/imm32
-3366     # . . call
-3367     e8/call  num-bytes/disp32
-3368     # . . discard args
-3369     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
-3370     # check-ints-equal(eax, 6, msg)
-3371     # . . push args
-3372     68/push  "F - test-num-bytes-handles-imm32"/imm32
-3373     68/push  6/imm32/true
-3374     50/push-eax
-3375     # . . call
-3376     e8/call  check-ints-equal/disp32
-3377     # . . discard args
-3378     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
-3379     # . epilogue
-3380     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
-3381     5d/pop-to-ebp
-3382     c3/return
-3383 
-3384 # . . vim:nowrap:textwidth=0
+ 871     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32          # add to esp
+ 872 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
+ 898     # . check-trace-contains("label 'x' is at address 0x00007c06.", msg)
+ 899     # . . push args
+ 900     68/push  "F - test-compute-addresses"/imm32
+ 901     68/push  "label 'x' is at address 0x00007c06."/imm32
+ 902     # . . call
+ 903     e8/call  check-trace-contains/disp32
+ 904     # . . discard args
+ 905     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 906     # . check-ints-equal(labels->write, 0xc, msg)
+ 907     # . . push args
+ 908     68/push  "F - test-compute-addresses-maintains-labels-write-index"/imm32
+ 909     68/push  0xc/imm32/1-entry
+ 910     ff          6/subop/push        0/mod/indirect  2/rm32/edx    .           .             .           .           .               .                 # push *edx
+ 911     # . . call
+ 912     e8/call  check-ints-equal/disp32
+ 913     # . . discard args
+ 914     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
+ 915     # . reclaim locals
+ 916     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x24/imm32        # add to esp
+ 917     # . epilogue
+ 918     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+ 919     5d/pop-to-ebp
+ 920     c3/return
+ 921 
+ 922 emit-labels:  # out: (addr buffered-file), labels: (addr stream {(handle array byte), address})
+ 923     # pseudocode:
+ 924     #   curr = table->data
+ 925     #   max = &table->data[table->write]
+ 926     #   while curr < max
+ 927     #     var label: (addr array byte) = lookup(*curr)
+ 928     #     curr += 8
+ 929     #     write-buffered(out, label)
+ 930     #     write-buffered(out, ' ')
+ 931     #     write-buffered(out, *curr)
+ 932     #     curr += 4
+ 933     #     write(out, '\n')
+ 934     #   return 0
+ 935     #
+ 936     # . prologue
+ 937     55/push-ebp
+ 938     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+ 939     # . save registers
+ 940     50/push-eax
+ 941     51/push-ecx
+ 942     52/push-edx
+ 943     56/push-esi
+ 944     # esi = table
+ 945     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0xc/disp8       .                 # copy *(ebp+12) to esi
+ 946     # var curr/ecx: (addr handle array byte) = table->data
+ 947     8d/copy-address                 1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy esi+12 to ecx
+ 948     # var max/edx: (addr byte) = &table->data[table->write]
+ 949     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           2/r32/edx   .               .                 # copy *esi to edx
+ 950     8d/copy-address                 0/mod/indirect  4/rm32/sib    1/base/ecx  2/index/edx   .           2/r32/edx   .               .                 # copy ecx+edx to edx
+ 951 $emit-labels:loop:
+ 952     # if (curr >= max) return null
+ 953     39/compare                      3/mod/direct    1/rm32/ecx    .           .             .           2/r32/edx   .               .                 # compare ecx with edx
+ 954     0f 83/jump-if-addr>=  $emit-labels:end/disp32
+ 955     # var label/eax: (addr array byte) = lookup(*curr)
+ 956     # . . push args
+ 957     ff          6/subop/push        1/mod/*+disp8   1/rm32/ecx    .           .             .           .           4/disp8         .                 # push *(ecx+4)
+ 958     ff          6/subop/push        0/mod/indirect  1/rm32/ecx    .           .             .           .           .               .                 # push *ecx
+ 959     # . . call
+ 960     e8/call  lookup/disp32
+ 961     # . . discard args
+ 962     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 963     # curr += 8
+ 964     81          0/subop/add         3/mod/direct    1/rm32/ecx    .           .             .           .           .               8/imm32           # add to ecx
+ 965     # write-buffered(out, label)
+ 966     # . . push args
+ 967     50/push-eax
+ 968     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 969     # . . call
+ 970     e8/call  write-buffered/disp32
+ 971     # . . discard args
+ 972     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 973     # write-buffered(out, ' ')
+ 974     # . . push args
+ 975     68/push  Space/imm32
+ 976     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 977     # . . call
+ 978     e8/call  write-buffered/disp32
+ 979     # . . discard args
+ 980     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 981     # . flush(Stderr)
+ 982     # . . push args
+ 983     68/push  Stderr/imm32
+ 984     # . . call
+ 985     e8/call  flush/disp32
+ 986     # . . discard args
+ 987     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+ 988     # write-int32-hex-buffered(out, *curr)
+ 989     # . . push args
+ 990     ff          6/subop/push        0/mod/indirect  1/rm32/ecx    .           .             .           .           .               .                 # push *ecx
+ 991     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+ 992     # . . call
+ 993     e8/call  write-int32-hex-buffered/disp32
+ 994     # . . discard args
+ 995     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+ 996     # curr += 4
+ 997     81          0/subop/add         3/mod/direct    1/rm32/ecx    .           .             .           .           .               4/imm32           # add to ecx
+ 998     # write-buffered(out, '\n')
+ 999     # . . push args
+1000     68/push  Newline/imm32
+1001     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+1002     # . . call
+1003     e8/call  write-buffered/disp32
+1004     # . . discard args
+1005     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1006     # loop
+1007     e9/jump  $emit-labels:loop/disp32
+1008 $emit-labels:end:
+1009     # . restore registers
+1010     5e/pop-to-esi
+1011     5a/pop-to-edx
+1012     59/pop-to-ecx
+1013     58/pop-to-eax
+1014     # . epilogue
+1015     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1016     5d/pop-to-ebp
+1017     c3/return
+1018 
+1019 # - some helpers for tests
+1020 
+1021 # some variants of 'trace' that take multiple arguments in different combinations of types:
+1022 #   n: int
+1023 #   c: character [4-bytes, will eventually be UTF-8]
+1024 #   s: (addr array byte)
+1025 #   l: (addr slice)
+1026 # one gotcha: 's5' must not be empty
+1027 
+1028 trace-slsns:  # s1: (addr array byte), l2: (addr slice), s3: (addr array byte), n4: int, s5: (addr array byte)
+1029     # . prologue
+1030     55/push-ebp
+1031     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1032     # write(*Trace-stream, s1)
+1033     # . . push args
+1034     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+1035     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+1036     # . . call
+1037     e8/call  write/disp32
+1038     # . . discard args
+1039     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1040     # write-slice(*Trace-stream, l2)
+1041     # . . push args
+1042     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
+1043     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+1044     # . . call
+1045     e8/call  write-slice/disp32
+1046     # . . discard args
+1047     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1048     # write(*Trace-stream, s3)
+1049     # . . push args
+1050     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x10/disp8      .                 # push *(ebp+16)
+1051     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+1052     # . . call
+1053     e8/call  write/disp32
+1054     # . . discard args
+1055     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1056     # write-int32-hex(*Trace-stream, n4)
+1057     # . . push args
+1058     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x14/disp8      .                 # push *(ebp+20)
+1059     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Trace-stream/disp32               # push *Trace-stream
+1060     # . . call
+1061     e8/call  write-int32-hex/disp32
+1062     # . . discard args
+1063     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1064     # trace(s5)  # implicitly adds a newline and finalizes the trace line
+1065     # . . push args
+1066     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0x18/disp8      .                 # push *(ebp+24)
+1067     # . . call
+1068     e8/call  trace/disp32
+1069     # . . discard args
+1070     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+1071 $trace-slsns:end:
+1072     # . epilogue
+1073     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1074     5d/pop-to-ebp
+1075     c3/return
+1076 
+1077 test-trace-slsns:
+1078     # . prologue
+1079     55/push-ebp
+1080     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
+1081     # setup
+1082     # . *Trace-stream->write = 0
+1083     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           0/r32/eax   Trace-stream/disp32               # copy *Trace-stream to eax
+1084     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0/imm32           # clear *eax
+1085     # (eax..ecx) = "b"
+1086     b8/copy-to-eax  "b"/imm32
+1087     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
+1088     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
+1089     05/add-to-eax  4/imm32
+1090     # var b/ebx: slice = {eax, ecx}
+1091     51/push-ecx
+1092     50/push-eax
+1093     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           4/r32/esp   .               .                 # copy esp to ebx
+1094     # trace-slsls("A" b "c " 3 " e")
+1095     # . . push args
+1096     68/push  " e"/imm32
+1097     68/push  3/imm32
+1098     68/push  "c "/imm32
+1099     53/push-ebx
+1100     68/push  "A"/imm32
+1101     # . . call
+1102     e8/call  trace-slsns/disp32
+1103     # . . discard args
+1104     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x14/imm32        # add to esp
+1105 +-- 26 lines: #?     # dump *Trace-stream -----------------------------------------------------------------------------------------------------------------------------------------------
+1131     # check-trace-contains("Abc 0x00000003 e")
+1132     # . . push args
+1133     68/push  "F - test-trace-slsls"/imm32
+1134     68/push  "Abc 0x00000003 e"/imm32
+1135     # . . call
+1136     e8/call  check-trace-contains/disp32
+1137     # . . discard args
+1138     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+1139     # . epilogue
+1140     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+1141     5d/pop-to-ebp
+1142     c3/return
+1143 
+1144 # . . vim:nowrap:textwidth=0
 
diff --git a/html/linux/survey_elf.subx.html b/html/linux/survey_elf.subx.html index f586c32e..d8add4b5 100644 --- a/html/linux/survey_elf.subx.html +++ b/html/linux/survey_elf.subx.html @@ -2695,7 +2695,7 @@ if ('onhashchange' in window) { 3119 8b/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy *edx to eax 3120 # . c/eax = *start 3121 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -3122 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +3122 25/and-eax-with 0xff/imm32 3123 # . if (eax != '8') return 3124 3d/compare-eax-and 0x38/imm32/8 3125 75/jump-if-!= $far-jump-or-call?:end/disp8 @@ -2763,7 +2763,7 @@ if ('onhashchange' in window) { 3257 # . . discard args 3258 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3259 # curr-segment += 20 # size of a row -3260 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 0x14/imm32 # add to eax +3260 05/add-to-eax 0x14/imm32 3261 e9/jump $emit-headers:loop/disp32 3262 $emit-headers:end: 3263 # . restore registers diff --git a/html/linux/tile/rpn.mu.html b/html/linux/tile/rpn.mu.html index 82650d2c..5ed618a4 100644 --- a/html/linux/tile/rpn.mu.html +++ b/html/linux/tile/rpn.mu.html @@ -209,7 +209,7 @@ if ('onhashchange' in window) { 149 var src-ah/eax: (addr handle array byte) <- get target-val, text-data 150 var src/eax: (addr array byte) <- lookup *src-ah 151 var result-ah/ecx: (addr handle buffered-file) <- get target-val, file-data -152 open src, 0, result-ah # write? = false +152 open src, 0, result-ah # write? = false 153 # save result into target-val 154 var type-addr/eax: (addr int) <- get target-val, type 155 copy-to *type-addr, 3/file diff --git a/html/mandelbrot-fixed.mu.html b/html/mandelbrot-fixed.mu.html index 3b786876..3f7a6acb 100644 --- a/html/mandelbrot-fixed.mu.html +++ b/html/mandelbrot-fixed.mu.html @@ -70,223 +70,255 @@ if ('onhashchange' in window) { 11 # $ qemu-system-i386 code.img 12 13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { - 14 mandelbrot screen - 15 } - 16 - 17 # Since they still look like int types, we'll append a '-f' suffix to variable - 18 # names to designate fixed-point numbers. - 19 - 20 fn int-to-fixed in: int -> _/eax: int { - 21 var result-f/eax: int <- copy in - 22 result-f <- shift-left 8/fixed-precision - 23 { - 24 break-if-not-overflow - 25 abort "int-to-fixed: overflow" - 26 } - 27 return result-f - 28 } - 29 - 30 fn fixed-to-int in-f: int -> _/eax: int { - 31 var result/eax: int <- copy in-f - 32 result <- shift-right-signed 8/fixed-precision - 33 return result - 34 } + 14 # Initially the viewport is centered at 0, 0 in the scene. + 15 var scene-cx-f: int + 16 var scene-cy-f: int + 17 # Initially the viewport shows a section of the scene 4 units wide. + 18 var scene-width-f: int + 19 copy-to scene-width-f, 0x400/4 + 20 { + 21 mandelbrot screen scene-cx-f, scene-cy-f, scene-width-f + 22 # move at an angle slowly towards the edge + 23 var adj-f/eax: int <- multiply-fixed scene-width-f, 0x12/0.07 + 24 subtract-from scene-cx-f, adj-f + 25 add-to scene-cy-f, adj-f + 26 # slowly shrink the scene width to zoom in + 27 var tmp-f/eax: int <- multiply-fixed scene-width-f, 0x80/0.5 + 28 copy-to scene-width-f, tmp-f + 29 loop + 30 } + 31 } + 32 + 33 # Since they still look like int types, we'll append a '-f' suffix to variable + 34 # names to designate fixed-point numbers. 35 - 36 # The process of throwing bits away always adjusts a number towards -infinity. - 37 fn test-fixed-conversion { - 38 # 0 - 39 var f/eax: int <- int-to-fixed 0 - 40 var result/eax: int <- fixed-to-int f - 41 check-ints-equal result, 0, "F - test-fixed-conversion - 0" - 42 # 1 - 43 var f/eax: int <- int-to-fixed 1 - 44 var result/eax: int <- fixed-to-int f - 45 check-ints-equal result, 1, "F - test-fixed-conversion - 1" - 46 # -1 - 47 var f/eax: int <- int-to-fixed -1 - 48 var result/eax: int <- fixed-to-int f - 49 check-ints-equal result, -1, "F - test-fixed-conversion - -1" - 50 # 0.5 = 1/2 - 51 var f/eax: int <- int-to-fixed 1 - 52 f <- shift-right-signed 1 - 53 var result/eax: int <- fixed-to-int f - 54 check-ints-equal result, 0, "F - test-fixed-conversion - 0.5" - 55 # -0.5 = -1/2 - 56 var f/eax: int <- int-to-fixed -1 - 57 f <- shift-right-signed 1 - 58 var result/eax: int <- fixed-to-int f - 59 check-ints-equal result, -1, "F - test-fixed-conversion - -0.5" - 60 # 1.5 = 3/2 - 61 var f/eax: int <- int-to-fixed 3 - 62 f <- shift-right-signed 1 - 63 var result/eax: int <- fixed-to-int f - 64 check-ints-equal result, 1, "F - test-fixed-conversion - 1.5" - 65 # -1.5 = -3/2 - 66 var f/eax: int <- int-to-fixed -3 - 67 f <- shift-right-signed 1 - 68 var result/eax: int <- fixed-to-int f - 69 check-ints-equal result, -2, "F - test-fixed-conversion - -1.5" - 70 # 1.25 = 5/4 - 71 var f/eax: int <- int-to-fixed 5 - 72 f <- shift-right-signed 2 - 73 var result/eax: int <- fixed-to-int f - 74 check-ints-equal result, 1, "F - test-fixed-conversion - 1.25" - 75 # -1.25 = -5/4 - 76 var f/eax: int <- int-to-fixed -5 - 77 f <- shift-right-signed 2 - 78 var result/eax: int <- fixed-to-int f - 79 check-ints-equal result, -2, "F - test-fixed-conversion - -1.25" - 80 } - 81 - 82 # special routines for multiplying and dividing fixed-point numbers - 83 - 84 fn multiply-fixed a-f: int, b-f: int -> _/eax: int { - 85 var result/eax: int <- copy a-f - 86 result <- multiply b-f - 87 { - 88 break-if-not-overflow - 89 abort "multiply-fixed: overflow" - 90 } - 91 result <- shift-right-signed 8/fixed-precision - 92 return result - 93 } - 94 - 95 fn divide-fixed a-f: int, b-f: int -> _/eax: int { - 96 var result-f/eax: int <- copy a-f - 97 result-f <- shift-left 8/fixed-precision - 98 { - 99 break-if-not-overflow -100 abort "divide-fixed: overflow" -101 } -102 var dummy-remainder/edx: int <- copy 0 -103 result-f, dummy-remainder <- integer-divide result-f, b-f -104 return result-f -105 } -106 -107 # multiplying or dividing by an integer can use existing instructions. -108 -109 # adding and subtracting two fixed-point numbers can use existing instructions. + 36 fn int-to-fixed in: int -> _/eax: int { + 37 var result-f/eax: int <- copy in + 38 result-f <- shift-left 8/fixed-precision + 39 { + 40 break-if-not-overflow + 41 abort "int-to-fixed: overflow" + 42 } + 43 return result-f + 44 } + 45 + 46 fn fixed-to-int in-f: int -> _/eax: int { + 47 var result/eax: int <- copy in-f + 48 result <- shift-right-signed 8/fixed-precision + 49 return result + 50 } + 51 + 52 # The process of throwing bits away always adjusts a number towards -infinity. + 53 fn test-fixed-conversion { + 54 # 0 + 55 var f/eax: int <- int-to-fixed 0 + 56 var result/eax: int <- fixed-to-int f + 57 check-ints-equal result, 0, "F - test-fixed-conversion - 0" + 58 # 1 + 59 var f/eax: int <- int-to-fixed 1 + 60 var result/eax: int <- fixed-to-int f + 61 check-ints-equal result, 1, "F - test-fixed-conversion - 1" + 62 # -1 + 63 var f/eax: int <- int-to-fixed -1 + 64 var result/eax: int <- fixed-to-int f + 65 check-ints-equal result, -1, "F - test-fixed-conversion - -1" + 66 # 0.5 = 1/2 + 67 var f/eax: int <- int-to-fixed 1 + 68 f <- shift-right-signed 1 + 69 var result/eax: int <- fixed-to-int f + 70 check-ints-equal result, 0, "F - test-fixed-conversion - 0.5" + 71 # -0.5 = -1/2 + 72 var f/eax: int <- int-to-fixed -1 + 73 f <- shift-right-signed 1 + 74 var result/eax: int <- fixed-to-int f + 75 check-ints-equal result, -1, "F - test-fixed-conversion - -0.5" + 76 # 1.5 = 3/2 + 77 var f/eax: int <- int-to-fixed 3 + 78 f <- shift-right-signed 1 + 79 var result/eax: int <- fixed-to-int f + 80 check-ints-equal result, 1, "F - test-fixed-conversion - 1.5" + 81 # -1.5 = -3/2 + 82 var f/eax: int <- int-to-fixed -3 + 83 f <- shift-right-signed 1 + 84 var result/eax: int <- fixed-to-int f + 85 check-ints-equal result, -2, "F - test-fixed-conversion - -1.5" + 86 # 1.25 = 5/4 + 87 var f/eax: int <- int-to-fixed 5 + 88 f <- shift-right-signed 2 + 89 var result/eax: int <- fixed-to-int f + 90 check-ints-equal result, 1, "F - test-fixed-conversion - 1.25" + 91 # -1.25 = -5/4 + 92 var f/eax: int <- int-to-fixed -5 + 93 f <- shift-right-signed 2 + 94 var result/eax: int <- fixed-to-int f + 95 check-ints-equal result, -2, "F - test-fixed-conversion - -1.25" + 96 } + 97 + 98 # special routines for multiplying and dividing fixed-point numbers + 99 +100 fn multiply-fixed a-f: int, b-f: int -> _/eax: int { +101 var result/eax: int <- copy a-f +102 result <- multiply b-f +103 { +104 break-if-not-overflow +105 abort "multiply-fixed: overflow" +106 } +107 result <- shift-right-signed 8/fixed-precision +108 return result +109 } 110 -111 fn mandelbrot screen: (addr screen) { -112 var a/eax: int <- copy 0 -113 var b/ecx: int <- copy 0 -114 a, b <- screen-size screen -115 var width/esi: int <- copy a -116 width <- shift-left 3/log2-font-width -117 var height/edi: int <- copy b -118 height <- shift-left 4/log2-font-height -119 var y/ecx: int <- copy 0 -120 { -121 compare y, height -122 break-if->= -123 var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width, height -124 var x/eax: int <- copy 0 -125 { -126 compare x, width -127 break-if->= -128 var real-f/edx: int <- viewport-to-real-f x, width -129 var iterations/esi: int <- mandelbrot-iterations-for-point real-f, imaginary-f, 0x400/max -130 compare iterations, 0x400/max -131 { -132 break-if->= -133 pixel screen, x, y, 0xf/white -134 } -135 compare iterations, 0x400/max -136 { -137 break-if-< -138 pixel screen, x, y, 0/black -139 } -140 x <- increment -141 loop -142 } -143 y <- increment -144 loop -145 } -146 } -147 -148 fn mandelbrot-iterations-for-point real-f: int, imaginary-f: int, max: int -> _/esi: int { -149 var x-f/esi: int <- copy 0 -150 var y-f/edi: int <- copy 0 -151 var iterations/ecx: int <- copy 0 -152 { -153 var done?/eax: boolean <- mandelbrot-done? x-f, y-f -154 compare done?, 0/false -155 break-if-!= -156 compare iterations, max -157 break-if->= -158 var x2-f/edx: int <- mandelbrot-x x-f, y-f, real-f -159 var y2-f/ebx: int <- mandelbrot-y x-f, y-f, imaginary-f -160 x-f <- copy x2-f -161 y-f <- copy y2-f -162 iterations <- increment -163 loop -164 } -165 return iterations -166 } -167 -168 fn mandelbrot-done? x-f: int, y-f: int -> _/eax: boolean { -169 # x*x + y*y > 4 -170 var tmp-f/eax: int <- multiply-fixed x-f, x-f -171 var result-f/ecx: int <- copy tmp-f -172 tmp-f <- multiply-fixed y-f, y-f -173 result-f <- add tmp-f -174 compare result-f, 0x400/4 -175 { -176 break-if-> -177 return 0/false +111 fn divide-fixed a-f: int, b-f: int -> _/eax: int { +112 var result-f/eax: int <- copy a-f +113 result-f <- shift-left 8/fixed-precision +114 { +115 break-if-not-overflow +116 abort "divide-fixed: overflow" +117 } +118 var dummy-remainder/edx: int <- copy 0 +119 result-f, dummy-remainder <- integer-divide result-f, b-f +120 return result-f +121 } +122 +123 # multiplying or dividing by an integer can use existing instructions. +124 +125 # adding and subtracting two fixed-point numbers can use existing instructions. +126 +127 fn mandelbrot screen: (addr screen), scene-cx-f: int, scene-cy-f: int, scene-width-f: int { +128 var a/eax: int <- copy 0 +129 var b/ecx: int <- copy 0 +130 a, b <- screen-size screen +131 var width/esi: int <- copy a +132 width <- shift-left 3/log2-font-width +133 var height/edi: int <- copy b +134 height <- shift-left 4/log2-font-height +135 var y/ecx: int <- copy 0 +136 { +137 compare y, height +138 break-if->= +139 var imaginary-f/ebx: int <- viewport-to-imaginary-f y, width, height, scene-cy-f, scene-width-f +140 var x/eax: int <- copy 0 +141 { +142 compare x, width +143 break-if->= +144 var real-f/edx: int <- viewport-to-real-f x, width, scene-cx-f, scene-width-f +145 var iterations/esi: int <- mandelbrot-iterations-for-point real-f, imaginary-f, 0x400/max +146 iterations <- shift-right 3 +147 var color/edx: int <- copy 0 +148 { +149 var dummy/eax: int <- copy 0 +150 dummy, color <- integer-divide iterations, 0x18/24/size-of-cycle-0 +151 color <- add 0x20/cycle-0 +152 } +153 pixel screen, x, y, color +154 x <- increment +155 loop +156 } +157 y <- increment +158 loop +159 } +160 } +161 +162 fn mandelbrot-iterations-for-point real-f: int, imaginary-f: int, max: int -> _/esi: int { +163 var x-f/esi: int <- copy 0 +164 var y-f/edi: int <- copy 0 +165 var iterations/ecx: int <- copy 0 +166 { +167 var done?/eax: boolean <- mandelbrot-done? x-f, y-f +168 compare done?, 0/false +169 break-if-!= +170 compare iterations, max +171 break-if->= +172 var x2-f/edx: int <- mandelbrot-x x-f, y-f, real-f +173 var y2-f/ebx: int <- mandelbrot-y x-f, y-f, imaginary-f +174 x-f <- copy x2-f +175 y-f <- copy y2-f +176 iterations <- increment +177 loop 178 } -179 return 1/true +179 return iterations 180 } 181 -182 fn mandelbrot-x x-f: int, y-f: int, real-f: int -> _/edx: int { -183 # x*x - y*y + real -184 var tmp-f/eax: int <- multiply-fixed x-f, x-f +182 fn mandelbrot-done? x-f: int, y-f: int -> _/eax: boolean { +183 # x*x + y*y > 4 +184 var tmp-f/eax: int <- multiply-fixed x-f, x-f 185 var result-f/ecx: int <- copy tmp-f -186 tmp-f <- multiply-fixed y-f, y-f -187 result-f <- subtract tmp-f -188 result-f <- add real-f -189 return result-f -190 } -191 -192 fn mandelbrot-y x-f: int, y-f: int, imaginary-f: int -> _/ebx: int { -193 # 2*x*y + imaginary -194 var result-f/eax: int <- copy x-f -195 result-f <- shift-left 1/log2 -196 result-f <- multiply-fixed result-f, y-f -197 result-f <- add imaginary-f -198 return result-f -199 } -200 -201 # Scale (x, y) pixel coordinates to a complex plane where the viewport width -202 # ranges from -2 to +2. Viewport height just follows the viewport's aspect -203 # ratio. -204 -205 fn viewport-to-real-f x: int, width: int -> _/edx: int { -206 # (x - width/2)*4/width -207 var result-f/eax: int <- int-to-fixed x -208 var width-f/ecx: int <- copy width -209 width-f <- shift-left 8/fixed-precision -210 var half-width-f/edx: int <- copy width-f -211 half-width-f <- shift-right-signed 1/log2 -212 result-f <- subtract half-width-f -213 result-f <- shift-left 2/log4 -214 result-f <- divide-fixed result-f, width-f -215 return result-f -216 } -217 -218 fn viewport-to-imaginary-f y: int, width: int, height: int -> _/ebx: int { -219 # (y - height/2)*4/width -220 var result-f/eax: int <- int-to-fixed y -221 var half-height-f/ecx: int <- copy height -222 half-height-f <- shift-left 8/fixed-precision -223 half-height-f <- shift-right-signed 1/log2 -224 result-f <- subtract half-height-f -225 result-f <- shift-left 2/log4 -226 var width-f/ecx: int <- copy width -227 width-f <- shift-left 8/fixed-precision -228 result-f <- divide-fixed result-f, width-f -229 return result-f -230 } +186 tmp-f <- multiply-fixed y-f, y-f +187 result-f <- add tmp-f +188 compare result-f, 0x400/4 +189 { +190 break-if-> +191 return 0/false +192 } +193 return 1/true +194 } +195 +196 fn mandelbrot-x x-f: int, y-f: int, real-f: int -> _/edx: int { +197 # x*x - y*y + real +198 var tmp-f/eax: int <- multiply-fixed x-f, x-f +199 var result-f/ecx: int <- copy tmp-f +200 tmp-f <- multiply-fixed y-f, y-f +201 result-f <- subtract tmp-f +202 result-f <- add real-f +203 return result-f +204 } +205 +206 fn mandelbrot-y x-f: int, y-f: int, imaginary-f: int -> _/ebx: int { +207 # 2*x*y + imaginary +208 var result-f/eax: int <- copy x-f +209 result-f <- shift-left 1/log2 +210 result-f <- multiply-fixed result-f, y-f +211 result-f <- add imaginary-f +212 return result-f +213 } +214 +215 # Scale (x, y) pixel coordinates to a complex plane where the viewport width +216 # ranges from -2 to +2. Viewport height just follows the viewport's aspect +217 # ratio. +218 +219 fn viewport-to-real-f x: int, width: int, scene-cx-f: int, scene-width-f: int -> _/edx: int { +220 # 0 in the viewport goes to scene-cx - scene-width/2 +221 # width in the viewport goes to scene-cx + scene-width/2 +222 # Therefore: +223 # x in the viewport goes to (scene-cx - scene-width/2) + x*scene-width/width +224 # At most two numbers being multiplied before a divide, so no risk of overflow. +225 var result-f/eax: int <- int-to-fixed x +226 result-f <- multiply-fixed result-f, scene-width-f +227 var width-f/ecx: int <- copy width +228 width-f <- shift-left 8/fixed-precision +229 result-f <- divide-fixed result-f, width-f +230 result-f <- add scene-cx-f +231 var half-scene-width-f/ecx: int <- copy scene-width-f +232 half-scene-width-f <- shift-right 1 +233 result-f <- subtract half-scene-width-f +234 return result-f +235 } +236 +237 fn viewport-to-imaginary-f y: int, width: int, height: int, scene-cy-f: int, scene-width-f: int -> _/ebx: int { +238 # 0 in the viewport goes to scene-cy - scene-width/2*height/width +239 # height in the viewport goes to scene-cy + scene-width/2*height/width +240 # Therefore: +241 # y in the viewport goes to (scene-cy - scene-width/2*height/width) + y*scene-width/width +242 # scene-cy - scene-width/width * (height/2 + y) +243 # At most two numbers being multiplied before a divide, so no risk of overflow. +244 var result-f/eax: int <- int-to-fixed y +245 result-f <- multiply-fixed result-f, scene-width-f +246 var width-f/ecx: int <- copy width +247 width-f <- shift-left 8/fixed-precision +248 result-f <- divide-fixed result-f, width-f +249 result-f <- add scene-cy-f +250 var second-term-f/edx: int <- copy 0 +251 { +252 var _second-term-f/eax: int <- copy scene-width-f +253 _second-term-f <- shift-right 1 +254 var height-f/ebx: int <- copy height +255 height-f <- shift-left 8/fixed-precision +256 _second-term-f <- multiply-fixed _second-term-f, height-f +257 _second-term-f <- divide-fixed _second-term-f, width-f +258 second-term-f <- copy _second-term-f +259 } +260 result-f <- subtract second-term-f +261 return result-f +262 } diff --git a/html/mandelbrot.mu.html b/html/mandelbrot.mu.html index d86c66ae..6cc460b6 100644 --- a/html/mandelbrot.mu.html +++ b/html/mandelbrot.mu.html @@ -69,143 +69,172 @@ if ('onhashchange' in window) { 11 # $ qemu-system-i386 code.img 12 13 fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk) { - 14 mandelbrot screen - 15 } - 16 - 17 fn mandelbrot screen: (addr screen) { - 18 var a/eax: int <- copy 0 - 19 var b/ecx: int <- copy 0 - 20 a, b <- screen-size screen - 21 var width/esi: int <- copy a - 22 width <- shift-left 3/log2-font-width - 23 var height/edi: int <- copy b - 24 height <- shift-left 4/log2-font-height - 25 var y/ecx: int <- copy 0 - 26 { - 27 compare y, height - 28 break-if->= - 29 var imaginary/xmm1: float <- viewport-to-imaginary y, width, height - 30 var x/edx: int <- copy 0 - 31 { - 32 compare x, width - 33 break-if->= - 34 var real/xmm0: float <- viewport-to-real x, width - 35 var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max - 36 compare iterations, 0x400/max - 37 { - 38 break-if->= - 39 pixel screen, x, y, 0xf/white - 40 } - 41 compare iterations, 0x400/max - 42 { - 43 break-if-< - 44 pixel screen, x, y, 0/black - 45 } - 46 x <- increment - 47 loop - 48 } - 49 y <- increment - 50 loop - 51 } - 52 } - 53 - 54 fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int { - 55 var zero: float - 56 var x/xmm0: float <- copy zero - 57 var y/xmm1: float <- copy zero - 58 var iterations/ecx: int <- copy 0 - 59 { - 60 var done?/eax: boolean <- mandelbrot-done? x, y - 61 compare done?, 0/false - 62 break-if-!= - 63 compare iterations, max - 64 break-if->= - 65 var newx/xmm2: float <- mandelbrot-x x, y, real - 66 var newy/xmm3: float <- mandelbrot-y x, y, imaginary - 67 x <- copy newx - 68 y <- copy newy - 69 iterations <- increment - 70 loop - 71 } - 72 return iterations - 73 } - 74 - 75 fn mandelbrot-done? x: float, y: float -> _/eax: boolean { - 76 # x*x + y*y > 4 - 77 var x2/xmm0: float <- copy x - 78 x2 <- multiply x - 79 var y2/xmm1: float <- copy y - 80 y2 <- multiply y - 81 var sum/xmm0: float <- copy x2 - 82 sum <- add y2 - 83 var four/eax: int <- copy 4 - 84 var four-f/xmm1: float <- convert four - 85 compare sum, four-f - 86 { - 87 break-if-float> - 88 return 0/false - 89 } - 90 return 1/true - 91 } - 92 - 93 fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float { - 94 # x*x - y*y + real - 95 var x2/xmm0: float <- copy x - 96 x2 <- multiply x - 97 var y2/xmm1: float <- copy y - 98 y2 <- multiply y - 99 var result/xmm0: float <- copy x2 -100 result <- subtract y2 -101 result <- add real -102 return result -103 } -104 -105 fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float { -106 # 2*x*y + imaginary -107 var two/eax: int <- copy 2 -108 var result/xmm0: float <- convert two -109 result <- multiply x -110 result <- multiply y -111 result <- add imaginary -112 return result -113 } -114 -115 # Scale (x, y) pixel coordinates to a complex plane where the viewport width -116 # ranges from -2 to +2. Viewport height just follows the viewport's aspect -117 # ratio. -118 -119 fn viewport-to-real x: int, width: int -> _/xmm0: float { -120 # (x - width/2)*4/width -121 var result/xmm0: float <- convert x -122 var width-f/xmm1: float <- convert width -123 var two/eax: int <- copy 2 -124 var two-f/xmm2: float <- convert two -125 var half-width-f/xmm2: float <- reciprocal two-f -126 half-width-f <- multiply width-f -127 result <- subtract half-width-f -128 var four/eax: int <- copy 4 -129 var four-f/xmm2: float <- convert four -130 result <- multiply four-f -131 result <- divide width-f -132 return result -133 } -134 -135 fn viewport-to-imaginary y: int, width: int, height: int -> _/xmm1: float { -136 # (y - height/2)*4/width -137 var result/xmm0: float <- convert y -138 var height-f/xmm1: float <- convert height -139 var half-height-f/xmm1: float <- copy height-f -140 var two/eax: int <- copy 2 -141 var two-f/xmm2: float <- convert two -142 half-height-f <- divide two-f -143 result <- subtract half-height-f -144 var four/eax: int <- copy 4 -145 var four-f/xmm1: float <- convert four -146 result <- multiply four-f -147 var width-f/xmm1: float <- convert width -148 result <- divide width-f -149 return result -150 } + 14 # Initially the viewport is centered at 0, 0 in the scene. + 15 var zero: float + 16 var scene-cx/xmm1: float <- copy zero + 17 var scene-cy/xmm2: float <- copy zero + 18 # Initially the viewport shows a section of the scene 4 units wide. + 19 # scene-width-scale = 0.5 + 20 var scene-width-scale: float + 21 var dest/eax: (addr float) <- address scene-width-scale + 22 fill-in-rational dest, 1, 2 + 23 # scene-width = 4 + 24 var four: float + 25 var dest/eax: (addr float) <- address four + 26 fill-in-rational dest, 4, 1 + 27 var scene-width/xmm3: float <- copy four + 28 { + 29 mandelbrot screen scene-cx, scene-cy, scene-width + 30 # move the center some % of the current screen-width + 31 var adj/xmm0: float <- rational 2, 0x1c/28 + 32 adj <- multiply scene-width + 33 scene-cx <- subtract adj + 34 scene-cy <- add adj + 35 # slowly shrink the scene width to zoom in + 36 scene-width <- multiply scene-width-scale + 37 loop + 38 } + 39 } + 40 + 41 fn mandelbrot screen: (addr screen), scene-cx: float, scene-cy: float, scene-width: float { + 42 var a/eax: int <- copy 0 + 43 var b/ecx: int <- copy 0 + 44 a, b <- screen-size screen + 45 var width/esi: int <- copy a + 46 width <- shift-left 3/log2-font-width + 47 var height/edi: int <- copy b + 48 height <- shift-left 4/log2-font-height + 49 var y/ecx: int <- copy 0 + 50 { + 51 compare y, height + 52 break-if->= + 53 var imaginary/xmm1: float <- viewport-to-imaginary y, width, height, scene-cy, scene-width + 54 var x/ebx: int <- copy 0 + 55 { + 56 compare x, width + 57 break-if->= + 58 var real/xmm0: float <- viewport-to-real x, width, scene-cx, scene-width + 59 var iterations/eax: int <- mandelbrot-iterations-for-point real, imaginary, 0x400/max + 60 iterations <- shift-right 3 + 61 var color/edx: int <- copy 0 + 62 iterations, color <- integer-divide iterations, 0x18/24/size-of-cycle-0 + 63 color <- add 0x20/cycle-0 + 64 pixel screen, x, y, color + 65 x <- increment + 66 loop + 67 } + 68 y <- increment + 69 loop + 70 } + 71 } + 72 + 73 fn mandelbrot-iterations-for-point real: float, imaginary: float, max: int -> _/eax: int { + 74 var zero: float + 75 var x/xmm0: float <- copy zero + 76 var y/xmm1: float <- copy zero + 77 var iterations/ecx: int <- copy 0 + 78 { + 79 var done?/eax: boolean <- mandelbrot-done? x, y + 80 compare done?, 0/false + 81 break-if-!= + 82 compare iterations, max + 83 break-if->= + 84 var newx/xmm2: float <- mandelbrot-x x, y, real + 85 var newy/xmm3: float <- mandelbrot-y x, y, imaginary + 86 x <- copy newx + 87 y <- copy newy + 88 iterations <- increment + 89 loop + 90 } + 91 return iterations + 92 } + 93 + 94 fn mandelbrot-done? x: float, y: float -> _/eax: boolean { + 95 # x*x + y*y > 4 + 96 var x2/xmm0: float <- copy x + 97 x2 <- multiply x + 98 var y2/xmm1: float <- copy y + 99 y2 <- multiply y +100 var sum/xmm0: float <- copy x2 +101 sum <- add y2 +102 var four/eax: int <- copy 4 +103 var four-f/xmm1: float <- convert four +104 compare sum, four-f +105 { +106 break-if-float> +107 return 0/false +108 } +109 return 1/true +110 } +111 +112 fn mandelbrot-x x: float, y: float, real: float -> _/xmm2: float { +113 # x*x - y*y + real +114 var x2/xmm0: float <- copy x +115 x2 <- multiply x +116 var y2/xmm1: float <- copy y +117 y2 <- multiply y +118 var result/xmm0: float <- copy x2 +119 result <- subtract y2 +120 result <- add real +121 return result +122 } +123 +124 fn mandelbrot-y x: float, y: float, imaginary: float -> _/xmm3: float { +125 # 2*x*y + imaginary +126 var two/eax: int <- copy 2 +127 var result/xmm0: float <- convert two +128 result <- multiply x +129 result <- multiply y +130 result <- add imaginary +131 return result +132 } +133 +134 # Scale (x, y) pixel coordinates to a complex plane where the viewport width +135 # ranges from -2 to +2. Viewport height just follows the viewport's aspect +136 # ratio. +137 +138 fn viewport-to-real x: int, width: int, scene-cx: float, scene-width: float -> _/xmm0: float { +139 # 0 in the viewport goes to scene-cx - scene-width/2 +140 # width in the viewport goes to scene-cx + scene-width/2 +141 # Therefore: +142 # x in the viewport goes to (scene-cx - scene-width/2) + x*scene-width/width +143 # At most two numbers being multiplied before a divide, so no risk of overflow. +144 var result/xmm0: float <- convert x +145 result <- multiply scene-width +146 var width-f/xmm1: float <- convert width +147 result <- divide width-f +148 result <- add scene-cx +149 var two/eax: int <- copy 2 +150 var two-f/xmm2: float <- convert two +151 var half-scene-width/xmm1: float <- copy scene-width +152 half-scene-width <- divide two-f +153 result <- subtract half-scene-width +154 return result +155 } +156 +157 fn viewport-to-imaginary y: int, width: int, height: int, scene-cy: float, scene-width: float -> _/xmm1: float { +158 # 0 in the viewport goes to scene-cy - scene-width/2*height/width +159 # height in the viewport goes to scene-cy + scene-width/2*height/width +160 # Therefore: +161 # y in the viewport goes to (scene-cy - scene-width/2*height/width) + y*scene-width/width +162 # scene-cy - scene-width/width * (height/2 + y) +163 # At most two numbers being multiplied before a divide, so no risk of overflow. +164 var result/xmm0: float <- convert y +165 result <- multiply scene-width +166 var width-f/xmm1: float <- convert width +167 result <- divide width-f +168 result <- add scene-cy +169 var two/eax: int <- copy 2 +170 var two-f/xmm2: float <- convert two +171 var second-term/xmm1: float <- copy scene-width +172 second-term <- divide two-f +173 var height-f/xmm2: float <- convert height +174 second-term <- multiply height-f +175 var width-f/xmm2: float <- convert width +176 second-term <- divide width-f +177 result <- subtract second-term +178 return result +179 } diff --git a/html/mu-init.subx.html b/html/mu-init.subx.html index 8aa49531..e36e8a54 100644 --- a/html/mu-init.subx.html +++ b/html/mu-init.subx.html @@ -68,30 +68,25 @@ if ('onhashchange' in window) { 12 Entry: 13 # initialize stack 14 bd/copy-to-ebp 0/imm32 -15 # Clear memory location 0 to ensure that uninitialized arrays run afoul of -16 # the bounds checker. -17 # TODO: This is utterly bonkers, and does not actually protect us against -18 # all null pointer reads/writes. Create a real page table sometime. -19 b8/copy-to-eax 0/imm32 -20 c7 0/subop/copy *eax 0/imm32 -21 #? (main 0 0 Primary-bus-secondary-drive) -22 # always first run tests -23 (run-tests) -24 (num-test-failures) # => eax -25 # call main if tests all passed -26 { -27 3d/compare-eax-and 0/imm32 -28 75/jump-if-!= break/disp8 -29 (clear-real-screen) -30 c7 0/subop/copy *Real-screen-cursor-x 0/imm32 -31 c7 0/subop/copy *Real-screen-cursor-y 0/imm32 -32 (main 0 0 Primary-bus-secondary-drive) +15 # +16 #? (main 0 0 Primary-bus-secondary-drive) +17 # always first run tests +18 (run-tests) +19 (num-test-failures) # => eax +20 # call main if tests all passed +21 { +22 3d/compare-eax-and 0/imm32 +23 75/jump-if-!= break/disp8 +24 (clear-real-screen) +25 c7 0/subop/copy *Real-screen-cursor-x 0/imm32 +26 c7 0/subop/copy *Real-screen-cursor-y 0/imm32 +27 (main 0 0 Primary-bus-secondary-drive) +28 } +29 +30 # hang indefinitely +31 { +32 eb/jump loop/disp8 33 } -34 -35 # hang indefinitely -36 { -37 eb/jump loop/disp8 -38 } diff --git a/html/mu_instructions.html b/html/mu_instructions.html index 14b2c931..e5e43cd9 100644 --- a/html/mu_instructions.html +++ b/html/mu_instructions.html @@ -100,6 +100,10 @@ var/reg <- or n => "81 1/subop/or *(ebp+" var.stack-offset ") " n "/imm32" or-with *var/reg, n => "81 1/subop/or *" reg " " n "/imm32" +var/reg <- not => "f7 2/subop/not %" reg +not var => "f7 2/subop/not *(ebp+" var.stack-offset ")" +not *var/reg => "f7 2/subop/not *" reg + var/reg <- xor var2/reg2 => "31/xor-with %" reg " " reg2 "/r32" var/reg <- xor var2 => "33/xor *(ebp+" var2.stack-offset ") " reg "/r32" var/reg <- xor *var2/reg2 => "33/xor *" reg2 " " reg "/r32" diff --git a/html/rpn.mu.html b/html/rpn.mu.html index 28ba33c3..d6f10d20 100644 --- a/html/rpn.mu.html +++ b/html/rpn.mu.html @@ -183,7 +183,7 @@ if ('onhashchange' in window) { 125 var self/esi: (addr int-stack) <- copy _self 126 var top-addr/ecx: (addr int) <- get self, top 127 var data-ah/edx: (addr handle array int) <- get self, data -128 var data/eax: (addr array int) <- lookup *data-ah +128 var data/eax: (addr array int) <- lookup *data-ah 129 var top/edx: int <- copy *top-addr 130 var dest-addr/edx: (addr int) <- index data, top 131 var val/eax: int <- copy _val @@ -201,7 +201,7 @@ if ('onhashchange' in window) { 143 } 144 subtract-from *top-addr, 1 145 var data-ah/edx: (addr handle array int) <- get self, data -146 var data/eax: (addr array int) <- lookup *data-ah +146 var data/eax: (addr array int) <- lookup *data-ah 147 var top/edx: int <- copy *top-addr 148 var result-addr/eax: (addr int) <- index data, top 149 var val/eax: int <- copy *result-addr diff --git a/html/shell/cell.mu.html b/html/shell/cell.mu.html index 1b15ee5f..5386139c 100644 --- a/html/shell/cell.mu.html +++ b/html/shell/cell.mu.html @@ -73,194 +73,195 @@ if ('onhashchange' in window) { 15 # type 6: keyboard 16 keyboard-data: (handle gap-buffer) 17 # TODO: array, (associative) table - 18 } - 19 - 20 fn allocate-symbol _out: (addr handle cell) { - 21 var out/eax: (addr handle cell) <- copy _out - 22 allocate out - 23 var out-addr/eax: (addr cell) <- lookup *out - 24 var type/ecx: (addr int) <- get out-addr, type - 25 copy-to *type, 2/symbol - 26 var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data - 27 populate-stream dest-ah, 0x40/max-symbol-size - 28 } - 29 - 30 fn initialize-symbol _out: (addr handle cell), val: (addr array byte) { - 31 var out/eax: (addr handle cell) <- copy _out - 32 var out-addr/eax: (addr cell) <- lookup *out - 33 var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data - 34 var dest/eax: (addr stream byte) <- lookup *dest-ah - 35 write dest, val - 36 } - 37 - 38 fn new-symbol out: (addr handle cell), val: (addr array byte) { - 39 allocate-symbol out - 40 initialize-symbol out, val - 41 } - 42 - 43 fn symbol-equal? _in: (addr cell), name: (addr array byte) -> _/eax: boolean { - 44 var in/esi: (addr cell) <- copy _in - 45 var in-type/eax: (addr int) <- get in, type - 46 compare *in-type, 2/symbol - 47 { - 48 break-if-= - 49 return 0/false - 50 } - 51 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data - 52 var in-data/eax: (addr stream byte) <- lookup *in-data-ah - 53 var result/eax: boolean <- stream-data-equal? in-data, name - 54 return result - 55 } - 56 - 57 fn allocate-stream _out: (addr handle cell) { - 58 var out/eax: (addr handle cell) <- copy _out - 59 allocate out - 60 var out-addr/eax: (addr cell) <- lookup *out - 61 var type/ecx: (addr int) <- get out-addr, type - 62 copy-to *type, 3/stream - 63 var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data - 64 populate-stream dest-ah, 0x40/max-stream-size - 65 } - 66 - 67 fn allocate-number _out: (addr handle cell) { - 68 var out/eax: (addr handle cell) <- copy _out - 69 allocate out - 70 var out-addr/eax: (addr cell) <- lookup *out - 71 var type/ecx: (addr int) <- get out-addr, type - 72 copy-to *type, 1/number - 73 } - 74 - 75 fn initialize-integer _out: (addr handle cell), n: int { - 76 var out/eax: (addr handle cell) <- copy _out - 77 var out-addr/eax: (addr cell) <- lookup *out - 78 var dest-addr/eax: (addr float) <- get out-addr, number-data - 79 var src/xmm0: float <- convert n - 80 copy-to *dest-addr, src - 81 } - 82 - 83 fn new-integer out: (addr handle cell), n: int { - 84 allocate-number out - 85 initialize-integer out, n - 86 } - 87 - 88 fn initialize-float _out: (addr handle cell), n: float { - 89 var out/eax: (addr handle cell) <- copy _out - 90 var out-addr/eax: (addr cell) <- lookup *out - 91 var dest-ah/eax: (addr float) <- get out-addr, number-data - 92 var src/xmm0: float <- copy n - 93 copy-to *dest-ah, src - 94 } - 95 - 96 fn new-float out: (addr handle cell), n: float { - 97 allocate-number out - 98 initialize-float out, n - 99 } -100 -101 fn allocate-pair out: (addr handle cell) { -102 allocate out -103 # new cells have type pair by default -104 } -105 -106 fn initialize-pair _out: (addr handle cell), left: (handle cell), right: (handle cell) { -107 var out/eax: (addr handle cell) <- copy _out -108 var out-addr/eax: (addr cell) <- lookup *out -109 var dest-ah/ecx: (addr handle cell) <- get out-addr, left -110 copy-handle left, dest-ah -111 dest-ah <- get out-addr, right -112 copy-handle right, dest-ah -113 } -114 -115 fn new-pair out: (addr handle cell), left: (handle cell), right: (handle cell) { -116 allocate-pair out -117 initialize-pair out, left, right -118 } -119 -120 fn nil out: (addr handle cell) { -121 allocate-pair out -122 } -123 -124 fn allocate-primitive-function _out: (addr handle cell) { -125 var out/eax: (addr handle cell) <- copy _out -126 allocate out -127 var out-addr/eax: (addr cell) <- lookup *out -128 var type/ecx: (addr int) <- get out-addr, type -129 copy-to *type, 4/primitive-function -130 } -131 -132 fn initialize-primitive-function _out: (addr handle cell), n: int { -133 var out/eax: (addr handle cell) <- copy _out -134 var out-addr/eax: (addr cell) <- lookup *out -135 var dest-addr/eax: (addr int) <- get out-addr, index-data -136 var src/ecx: int <- copy n -137 copy-to *dest-addr, src -138 } -139 -140 fn new-primitive-function out: (addr handle cell), n: int { -141 allocate-primitive-function out -142 initialize-primitive-function out, n -143 } -144 -145 fn allocate-screen _out: (addr handle cell) { -146 var out/eax: (addr handle cell) <- copy _out -147 allocate out -148 var out-addr/eax: (addr cell) <- lookup *out -149 var type/ecx: (addr int) <- get out-addr, type -150 copy-to *type, 5/screen -151 } -152 -153 fn new-fake-screen _out: (addr handle cell), width: int, height: int, pixel-graphics?: boolean { -154 var out/eax: (addr handle cell) <- copy _out -155 allocate-screen out -156 var out-addr/eax: (addr cell) <- lookup *out -157 var dest-ah/eax: (addr handle screen) <- get out-addr, screen-data -158 allocate dest-ah -159 var dest-addr/eax: (addr screen) <- lookup *dest-ah -160 initialize-screen dest-addr, width, height, pixel-graphics? -161 } -162 -163 fn clear-screen-cell _self-ah: (addr handle cell) { -164 var self-ah/eax: (addr handle cell) <- copy _self-ah -165 var self/eax: (addr cell) <- lookup *self-ah -166 compare self, 0 -167 { -168 break-if-!= -169 return -170 } -171 var screen-ah/eax: (addr handle screen) <- get self, screen-data -172 var screen/eax: (addr screen) <- lookup *screen-ah -173 clear-screen screen -174 } -175 -176 fn allocate-keyboard _out: (addr handle cell) { -177 var out/eax: (addr handle cell) <- copy _out -178 allocate out -179 var out-addr/eax: (addr cell) <- lookup *out -180 var type/ecx: (addr int) <- get out-addr, type -181 copy-to *type, 6/keyboard -182 } -183 -184 fn new-fake-keyboard _out: (addr handle cell), capacity: int { -185 var out/eax: (addr handle cell) <- copy _out -186 allocate-keyboard out -187 var out-addr/eax: (addr cell) <- lookup *out -188 var dest-ah/eax: (addr handle gap-buffer) <- get out-addr, keyboard-data -189 allocate dest-ah -190 var dest-addr/eax: (addr gap-buffer) <- lookup *dest-ah -191 initialize-gap-buffer dest-addr, capacity -192 } -193 -194 fn rewind-keyboard-cell _self-ah: (addr handle cell) { -195 var self-ah/eax: (addr handle cell) <- copy _self-ah -196 var self/eax: (addr cell) <- lookup *self-ah -197 compare self, 0 -198 { -199 break-if-!= -200 return -201 } -202 var keyboard-ah/eax: (addr handle gap-buffer) <- get self, keyboard-data -203 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah -204 rewind-gap-buffer keyboard -205 } + 18 # if you add types here, don't forget to update cell-isomorphic? + 19 } + 20 + 21 fn allocate-symbol _out: (addr handle cell) { + 22 var out/eax: (addr handle cell) <- copy _out + 23 allocate out + 24 var out-addr/eax: (addr cell) <- lookup *out + 25 var type/ecx: (addr int) <- get out-addr, type + 26 copy-to *type, 2/symbol + 27 var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data + 28 populate-stream dest-ah, 0x40/max-symbol-size + 29 } + 30 + 31 fn initialize-symbol _out: (addr handle cell), val: (addr array byte) { + 32 var out/eax: (addr handle cell) <- copy _out + 33 var out-addr/eax: (addr cell) <- lookup *out + 34 var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data + 35 var dest/eax: (addr stream byte) <- lookup *dest-ah + 36 write dest, val + 37 } + 38 + 39 fn new-symbol out: (addr handle cell), val: (addr array byte) { + 40 allocate-symbol out + 41 initialize-symbol out, val + 42 } + 43 + 44 fn symbol-equal? _in: (addr cell), name: (addr array byte) -> _/eax: boolean { + 45 var in/esi: (addr cell) <- copy _in + 46 var in-type/eax: (addr int) <- get in, type + 47 compare *in-type, 2/symbol + 48 { + 49 break-if-= + 50 return 0/false + 51 } + 52 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data + 53 var in-data/eax: (addr stream byte) <- lookup *in-data-ah + 54 var result/eax: boolean <- stream-data-equal? in-data, name + 55 return result + 56 } + 57 + 58 fn allocate-stream _out: (addr handle cell) { + 59 var out/eax: (addr handle cell) <- copy _out + 60 allocate out + 61 var out-addr/eax: (addr cell) <- lookup *out + 62 var type/ecx: (addr int) <- get out-addr, type + 63 copy-to *type, 3/stream + 64 var dest-ah/eax: (addr handle stream byte) <- get out-addr, text-data + 65 populate-stream dest-ah, 0x40/max-stream-size + 66 } + 67 + 68 fn allocate-number _out: (addr handle cell) { + 69 var out/eax: (addr handle cell) <- copy _out + 70 allocate out + 71 var out-addr/eax: (addr cell) <- lookup *out + 72 var type/ecx: (addr int) <- get out-addr, type + 73 copy-to *type, 1/number + 74 } + 75 + 76 fn initialize-integer _out: (addr handle cell), n: int { + 77 var out/eax: (addr handle cell) <- copy _out + 78 var out-addr/eax: (addr cell) <- lookup *out + 79 var dest-addr/eax: (addr float) <- get out-addr, number-data + 80 var src/xmm0: float <- convert n + 81 copy-to *dest-addr, src + 82 } + 83 + 84 fn new-integer out: (addr handle cell), n: int { + 85 allocate-number out + 86 initialize-integer out, n + 87 } + 88 + 89 fn initialize-float _out: (addr handle cell), n: float { + 90 var out/eax: (addr handle cell) <- copy _out + 91 var out-addr/eax: (addr cell) <- lookup *out + 92 var dest-ah/eax: (addr float) <- get out-addr, number-data + 93 var src/xmm0: float <- copy n + 94 copy-to *dest-ah, src + 95 } + 96 + 97 fn new-float out: (addr handle cell), n: float { + 98 allocate-number out + 99 initialize-float out, n +100 } +101 +102 fn allocate-pair out: (addr handle cell) { +103 allocate out +104 # new cells have type pair by default +105 } +106 +107 fn initialize-pair _out: (addr handle cell), left: (handle cell), right: (handle cell) { +108 var out/eax: (addr handle cell) <- copy _out +109 var out-addr/eax: (addr cell) <- lookup *out +110 var dest-ah/ecx: (addr handle cell) <- get out-addr, left +111 copy-handle left, dest-ah +112 dest-ah <- get out-addr, right +113 copy-handle right, dest-ah +114 } +115 +116 fn new-pair out: (addr handle cell), left: (handle cell), right: (handle cell) { +117 allocate-pair out +118 initialize-pair out, left, right +119 } +120 +121 fn nil out: (addr handle cell) { +122 allocate-pair out +123 } +124 +125 fn allocate-primitive-function _out: (addr handle cell) { +126 var out/eax: (addr handle cell) <- copy _out +127 allocate out +128 var out-addr/eax: (addr cell) <- lookup *out +129 var type/ecx: (addr int) <- get out-addr, type +130 copy-to *type, 4/primitive-function +131 } +132 +133 fn initialize-primitive-function _out: (addr handle cell), n: int { +134 var out/eax: (addr handle cell) <- copy _out +135 var out-addr/eax: (addr cell) <- lookup *out +136 var dest-addr/eax: (addr int) <- get out-addr, index-data +137 var src/ecx: int <- copy n +138 copy-to *dest-addr, src +139 } +140 +141 fn new-primitive-function out: (addr handle cell), n: int { +142 allocate-primitive-function out +143 initialize-primitive-function out, n +144 } +145 +146 fn allocate-screen _out: (addr handle cell) { +147 var out/eax: (addr handle cell) <- copy _out +148 allocate out +149 var out-addr/eax: (addr cell) <- lookup *out +150 var type/ecx: (addr int) <- get out-addr, type +151 copy-to *type, 5/screen +152 } +153 +154 fn new-fake-screen _out: (addr handle cell), width: int, height: int, pixel-graphics?: boolean { +155 var out/eax: (addr handle cell) <- copy _out +156 allocate-screen out +157 var out-addr/eax: (addr cell) <- lookup *out +158 var dest-ah/eax: (addr handle screen) <- get out-addr, screen-data +159 allocate dest-ah +160 var dest-addr/eax: (addr screen) <- lookup *dest-ah +161 initialize-screen dest-addr, width, height, pixel-graphics? +162 } +163 +164 fn clear-screen-cell _self-ah: (addr handle cell) { +165 var self-ah/eax: (addr handle cell) <- copy _self-ah +166 var self/eax: (addr cell) <- lookup *self-ah +167 compare self, 0 +168 { +169 break-if-!= +170 return +171 } +172 var screen-ah/eax: (addr handle screen) <- get self, screen-data +173 var screen/eax: (addr screen) <- lookup *screen-ah +174 clear-screen screen +175 } +176 +177 fn allocate-keyboard _out: (addr handle cell) { +178 var out/eax: (addr handle cell) <- copy _out +179 allocate out +180 var out-addr/eax: (addr cell) <- lookup *out +181 var type/ecx: (addr int) <- get out-addr, type +182 copy-to *type, 6/keyboard +183 } +184 +185 fn new-fake-keyboard _out: (addr handle cell), capacity: int { +186 var out/eax: (addr handle cell) <- copy _out +187 allocate-keyboard out +188 var out-addr/eax: (addr cell) <- lookup *out +189 var dest-ah/eax: (addr handle gap-buffer) <- get out-addr, keyboard-data +190 allocate dest-ah +191 var dest-addr/eax: (addr gap-buffer) <- lookup *dest-ah +192 initialize-gap-buffer dest-addr, capacity +193 } +194 +195 fn rewind-keyboard-cell _self-ah: (addr handle cell) { +196 var self-ah/eax: (addr handle cell) <- copy _self-ah +197 var self/eax: (addr cell) <- lookup *self-ah +198 compare self, 0 +199 { +200 break-if-!= +201 return +202 } +203 var keyboard-ah/eax: (addr handle gap-buffer) <- get self, keyboard-data +204 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah +205 rewind-gap-buffer keyboard +206 } diff --git a/html/shell/evaluate.mu.html b/html/shell/evaluate.mu.html index f44b87c9..4ea7e6a2 100644 --- a/html/shell/evaluate.mu.html +++ b/html/shell/evaluate.mu.html @@ -60,17 +60,17 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/main/shell/evaluate.mu
    1 # env is an alist of ((sym . val) (sym . val) ...)
-   2 # we never modify `in` or `env`
-   3 # ignore 'screen-cell' on a first reading; it's a hack for sandboxes
+   2 # we never modify `_in-ah` or `env`
+   3 # ignore args past 'trace' on a first reading; they're for the environment not the language
    4 # 'call-number' is just for showing intermediate progress; this is a _slow_ interpreter
-   5 fn evaluate _in: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
+   5 fn evaluate _in-ah: (addr handle cell), _out-ah: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
    6   # stack overflow?   # disable when enabling Really-debug-print
    7   check-stack
    8   {
    9     var screen-cell/eax: (addr handle cell) <- copy screen-cell
   10     compare screen-cell, 0
   11     break-if-=
-  12     var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
+  12     var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
   13     compare screen-cell-addr, 0
   14     break-if-=
   15     # if screen-cell exists, we're probably not in a test
@@ -85,7 +85,7 @@ if ('onhashchange' in window) {
   24     break-if-=
   25     return
   26   }
-  27   var in/esi: (addr handle cell) <- copy _in
+  27   var in-ah/esi: (addr handle cell) <- copy _in-ah
   28   # show intermediate progress on screen if necessary
   29   {
   30     compare screen-cell, 0
@@ -95,16 +95,16 @@ if ('onhashchange' in window) {
   34     compare tmp, 0
   35     break-if-!=
   36     var screen-cell/eax: (addr handle cell) <- copy screen-cell
-  37     var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
+  37     var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
   38     compare screen-cell-addr, 0
   39     break-if-=
   40     var screen-obj-ah/eax: (addr handle screen) <- get screen-cell-addr, screen-data
-  41     var screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
+  41     var screen-obj/eax: (addr screen) <- lookup *screen-obj-ah
   42     compare screen-obj, 0
   43     break-if-=
   44     var y/ecx: int <- render-screen 0/screen, screen-obj, 0x70/xmin, 1/ymin
   45   }
-  46 #?   dump-cell in
+  46 #?   dump-cell in-ah
   47 #?   {
   48 #?     var foo/eax: byte <- read-key 0/keyboard
   49 #?     compare foo, 0
@@ -112,24 +112,24 @@ if ('onhashchange' in window) {
   51 #?   }
   52 +-- 14 lines: # trace "evaluate " in " in environment " env -----------------------------------------------------------------------------------------------------------------------------
   66   trace-lower trace
-  67   var in-addr/eax: (addr cell) <- lookup *in
+  67   var in/eax: (addr cell) <- lookup *in-ah
   68   {
-  69     var nil?/eax: boolean <- nil? in-addr
-  70     compare nil?, 0/false
+  69     var nil?/eax: boolean <- nil? in
+  70     compare nil?, 0/false
   71     break-if-=
   72     # nil is a literal
   73     trace-text trace, "eval", "nil"
-  74     copy-object _in, out
+  74     copy-object _in-ah, _out-ah
   75     trace-higher trace
   76     return
   77   }
-  78   var in-type/ecx: (addr int) <- get in-addr, type
+  78   var in-type/ecx: (addr int) <- get in, type
   79   compare *in-type, 1/number
   80   {
   81     break-if-!=
   82     # numbers are literals
   83     trace-text trace, "eval", "number"
-  84     copy-object _in, out
+  84     copy-object _in-ah, _out-ah
   85     trace-higher trace
   86     return
   87   }
@@ -138,7 +138,7 @@ if ('onhashchange' in window) {
   90     break-if-!=
   91     # streams are literals
   92     trace-text trace, "eval", "stream"
-  93     copy-object _in, out
+  93     copy-object _in-ah, _out-ah
   94     trace-higher trace
   95     return
   96   }
@@ -146,9 +146,9 @@ if ('onhashchange' in window) {
   98   {
   99     break-if-!=
  100     trace-text trace, "eval", "symbol"
- 101     debug-print "a", 7/fg, 0xc5/bg=blue-bg
- 102     lookup-symbol in-addr, out, env-h, globals, trace, screen-cell, keyboard-cell
- 103     debug-print "z", 7/fg, 0xc5/bg=blue-bg
+ 101     debug-print "a", 7/fg, 0/bg
+ 102     lookup-symbol in, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell
+ 103     debug-print "z", 7/fg, 0/bg
  104     trace-higher trace
  105     return
  106   }
@@ -156,7 +156,7 @@ if ('onhashchange' in window) {
  108   {
  109     break-if-!=
  110     trace-text trace, "eval", "screen"
- 111     copy-object _in, out
+ 111     copy-object _in-ah, _out-ah
  112     trace-higher trace
  113     return
  114   }
@@ -164,1033 +164,1541 @@ if ('onhashchange' in window) {
  116   {
  117     break-if-!=
  118     trace-text trace, "eval", "keyboard"
- 119     copy-object _in, out
+ 119     copy-object _in-ah, _out-ah
  120     trace-higher trace
  121     return
  122   }
- 123   # in-addr is a syntax tree
- 124   $evaluate:anonymous-function: {
- 125     # trees starting with "fn" are anonymous functions
- 126     var expr/esi: (addr cell) <- copy in-addr
- 127     # if its first elem is not "fn", break
- 128     var in-addr/edx: (addr cell) <- copy in-addr
- 129     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 130     var first/eax: (addr cell) <- lookup *first-ah
- 131     var fn?/eax: boolean <- fn? first
- 132     compare fn?, 0/false
- 133     break-if-=
- 134     # turn (fn ...) into (fn env ...)
- 135     trace-text trace, "eval", "anonymous function"
- 136     var rest-ah/eax: (addr handle cell) <- get in-addr, right
- 137     var tmp: (handle cell)
- 138     var tmp-ah/edi: (addr handle cell) <- address tmp
- 139     new-pair tmp-ah, env-h, *rest-ah
- 140     new-pair out, *first-ah, *tmp-ah
- 141     trace-higher trace
- 142     return
- 143   }
- 144   # builtins with "special" evaluation rules
- 145   $evaluate:quote: {
- 146     # trees starting with single quote create literals
- 147     var expr/esi: (addr cell) <- copy in-addr
- 148     # if its first elem is not "'", break
- 149     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 150     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 151     var first/eax: (addr cell) <- lookup *first-ah
- 152     var quote?/eax: boolean <- symbol-equal? first, "'"
- 153     compare quote?, 0/false
- 154     break-if-=
- 155     #
- 156     trace-text trace, "eval", "quote"
- 157     copy-object rest-ah, out
- 158     trace-higher trace
- 159     return
- 160   }
- 161   $evaluate:def: {
- 162     # trees starting with "def" define globals
- 163     var expr/esi: (addr cell) <- copy in-addr
- 164     # if its first elem is not "def", break
- 165     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 166     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 167     var first/eax: (addr cell) <- lookup *first-ah
- 168     var def?/eax: boolean <- symbol-equal? first, "def"
- 169     compare def?, 0/false
- 170     break-if-=
- 171     #
- 172     trace-text trace, "eval", "def"
- 173     trace-text trace, "eval", "evaluating second arg"
- 174     var rest/eax: (addr cell) <- lookup *rest-ah
- 175     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
- 176     {
- 177       var first-arg/eax: (addr cell) <- lookup *first-arg-ah
- 178       var first-arg-type/eax: (addr int) <- get first-arg, type
- 179       compare *first-arg-type, 2/symbol
- 180       break-if-=
- 181       error trace, "first arg to def must be a symbol"
- 182       trace-higher trace
- 183       return
- 184     }
- 185     rest-ah <- get rest, right
- 186     rest <- lookup *rest-ah
- 187     var second-arg-ah/edx: (addr handle cell) <- get rest, left
- 188     debug-print "P", 4/fg, 0xc5/bg=blue-bg
- 189     increment call-number
- 190     evaluate second-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 191     debug-print "Q", 4/fg, 0xc5/bg=blue-bg
- 192     trace-text trace, "eval", "saving global binding"
- 193     var first-arg/eax: (addr cell) <- lookup *first-arg-ah
- 194     var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
- 195     var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
- 196     var tmp-string: (handle array byte)
- 197     var tmp-ah/edx: (addr handle array byte) <- address tmp-string
- 198     rewind-stream first-arg-data
- 199     stream-to-array first-arg-data, tmp-ah
- 200     var first-arg-data-string/eax: (addr array byte) <- lookup *tmp-ah
- 201     var out2/edi: (addr handle cell) <- copy out
- 202     assign-or-create-global globals, first-arg-data-string, *out2, trace
- 203     trace-higher trace
- 204     return
- 205   }
- 206   $evaluate:set: {
- 207     # trees starting with "set" mutate bindings
- 208     var expr/esi: (addr cell) <- copy in-addr
- 209     # if its first elem is not "set", break
- 210     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 211     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 212     var first/eax: (addr cell) <- lookup *first-ah
- 213     var set?/eax: boolean <- symbol-equal? first, "set"
- 214     compare set?, 0/false
- 215     break-if-=
- 216     #
- 217     trace-text trace, "eval", "set"
- 218     trace-text trace, "eval", "evaluating second arg"
- 219     var rest/eax: (addr cell) <- lookup *rest-ah
- 220     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
- 221     {
- 222       var first-arg/eax: (addr cell) <- lookup *first-arg-ah
- 223       var first-arg-type/eax: (addr int) <- get first-arg, type
- 224       compare *first-arg-type, 2/symbol
- 225       break-if-=
- 226       error trace, "first arg to set must be a symbol"
- 227       trace-higher trace
- 228       return
- 229     }
- 230     rest-ah <- get rest, right
- 231     rest <- lookup *rest-ah
- 232     var second-arg-ah/edx: (addr handle cell) <- get rest, left
- 233     debug-print "P", 4/fg, 0xc5/bg=blue-bg
- 234     increment call-number
- 235     evaluate second-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 236     debug-print "Q", 4/fg, 0xc5/bg=blue-bg
- 237     trace-text trace, "eval", "mutating binding"
- 238     var first-arg/eax: (addr cell) <- lookup *first-arg-ah
- 239     var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
- 240     var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
- 241     mutate-binding first-arg-data, out, env-h, globals, trace
- 242     trace-higher trace
- 243     return
- 244   }
- 245   $evaluate:and: {
- 246     var expr/esi: (addr cell) <- copy in-addr
- 247     # if its first elem is not "and", break
- 248     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 249     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 250     var first/eax: (addr cell) <- lookup *first-ah
- 251     var and?/eax: boolean <- symbol-equal? first, "and"
- 252     compare and?, 0/false
- 253     break-if-=
- 254     #
- 255     trace-text trace, "eval", "and"
- 256     trace-text trace, "eval", "evaluating first arg"
- 257     var rest/eax: (addr cell) <- lookup *rest-ah
- 258     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
- 259     debug-print "R2", 4/fg, 0xc5/bg=blue-bg
- 260     increment call-number
- 261     evaluate first-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 262     debug-print "S2", 4/fg, 0xc5/bg=blue-bg
- 263     # if first arg is nil, short-circuit
- 264     var out-ah/eax: (addr handle cell) <- copy out
- 265     var out-a/eax: (addr cell) <- lookup *out-ah
- 266     var nil?/eax: boolean <- nil? out-a
- 267     compare nil?, 0/false
- 268     {
- 269       break-if-=
- 270       return
- 271     }
- 272     var rest/eax: (addr cell) <- lookup *rest-ah
- 273     rest-ah <- get rest, right
- 274     rest <- lookup *rest-ah
- 275     var second-ah/eax: (addr handle cell) <- get rest, left
- 276     debug-print "T2", 4/fg, 0xc5/bg=blue-bg
- 277     increment call-number
- 278     evaluate second-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 279     debug-print "U2", 4/fg, 0xc5/bg=blue-bg
- 280     trace-higher trace
- 281     return
- 282   }
- 283   $evaluate:or: {
- 284     var expr/esi: (addr cell) <- copy in-addr
- 285     # if its first elem is not "or", break
- 286     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 287     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 288     var first/eax: (addr cell) <- lookup *first-ah
- 289     var or?/eax: boolean <- symbol-equal? first, "or"
- 290     compare or?, 0/false
- 291     break-if-=
- 292     #
- 293     trace-text trace, "eval", "or"
- 294     trace-text trace, "eval", "evaluating first arg"
- 295     var rest/eax: (addr cell) <- lookup *rest-ah
- 296     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
- 297     debug-print "R2", 4/fg, 0xc5/bg=blue-bg
- 298     increment call-number
- 299     evaluate first-arg-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 300     debug-print "S2", 4/fg, 0xc5/bg=blue-bg
- 301     # if first arg is not nil, short-circuit
- 302     var out-ah/eax: (addr handle cell) <- copy out
- 303     var out-a/eax: (addr cell) <- lookup *out-ah
- 304     var nil?/eax: boolean <- nil? out-a
- 305     compare nil?, 0/false
- 306     {
- 307       break-if-!=
- 308       return
- 309     }
- 310     var rest/eax: (addr cell) <- lookup *rest-ah
- 311     rest-ah <- get rest, right
- 312     rest <- lookup *rest-ah
- 313     var second-ah/eax: (addr handle cell) <- get rest, left
- 314     debug-print "T2", 4/fg, 0xc5/bg=blue-bg
- 315     increment call-number
- 316     evaluate second-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 317     debug-print "U2", 4/fg, 0xc5/bg=blue-bg
- 318     trace-higher trace
- 319     return
- 320   }
- 321   $evaluate:if: {
- 322     # trees starting with "if" are conditionals
- 323     var expr/esi: (addr cell) <- copy in-addr
- 324     # if its first elem is not "if", break
- 325     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 326     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 327     var first/eax: (addr cell) <- lookup *first-ah
- 328     var if?/eax: boolean <- symbol-equal? first, "if"
- 329     compare if?, 0/false
- 330     break-if-=
- 331     #
- 332     trace-text trace, "eval", "if"
- 333     trace-text trace, "eval", "evaluating first arg"
- 334     var rest/eax: (addr cell) <- lookup *rest-ah
- 335     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
- 336     var guard-h: (handle cell)
- 337     var guard-ah/esi: (addr handle cell) <- address guard-h
- 338     debug-print "R", 4/fg, 0xc5/bg=blue-bg
- 339     increment call-number
- 340     evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 341     debug-print "S", 4/fg, 0xc5/bg=blue-bg
- 342     rest-ah <- get rest, right
- 343     rest <- lookup *rest-ah
- 344     var branch-ah/edi: (addr handle cell) <- get rest, left
- 345     var guard-a/eax: (addr cell) <- lookup *guard-ah
- 346     var skip-to-third-arg?/eax: boolean <- nil? guard-a
- 347     compare skip-to-third-arg?, 0/false
- 348     {
- 349       break-if-=
- 350       trace-text trace, "eval", "skipping to third arg"
- 351       var rest/eax: (addr cell) <- lookup *rest-ah
- 352       rest-ah <- get rest, right
- 353       rest <- lookup *rest-ah
- 354       branch-ah <- get rest, left
- 355     }
- 356     debug-print "T", 4/fg, 0xc5/bg=blue-bg
- 357     increment call-number
- 358     evaluate branch-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 359     debug-print "U", 4/fg, 0xc5/bg=blue-bg
- 360     trace-higher trace
- 361     return
- 362   }
- 363   $evaluate:while: {
- 364     # trees starting with "while" are loops
- 365     var expr/esi: (addr cell) <- copy in-addr
- 366     # if its first elem is not "while", break
- 367     var first-ah/ecx: (addr handle cell) <- get in-addr, left
- 368     var rest-ah/edx: (addr handle cell) <- get in-addr, right
- 369     var first/eax: (addr cell) <- lookup *first-ah
- 370     var first-type/ecx: (addr int) <- get first, type
- 371     compare *first-type, 2/symbol
- 372     break-if-!=
- 373     var sym-data-ah/eax: (addr handle stream byte) <- get first, text-data
- 374     var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
- 375     var while?/eax: boolean <- stream-data-equal? sym-data, "while"
- 376     compare while?, 0/false
- 377     break-if-=
- 378     #
- 379     trace-text trace, "eval", "while"
- 380     var rest/eax: (addr cell) <- lookup *rest-ah
- 381     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
- 382     rest-ah <- get rest, right
- 383     var guard-h: (handle cell)
- 384     var guard-ah/esi: (addr handle cell) <- address guard-h
- 385     $evaluate:while:loop-execution: {
- 386       {
- 387         compare trace, 0
- 388         break-if-=
- 389         var error?/eax: boolean <- has-errors? trace
- 390         compare error?, 0/false
- 391         break-if-!= $evaluate:while:loop-execution
- 392       }
- 393       trace-text trace, "eval", "loop termination check"
- 394       debug-print "V", 4/fg, 0xc5/bg=blue-bg
- 395       increment call-number
- 396       evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 397       debug-print "W", 4/fg, 0xc5/bg=blue-bg
- 398       var guard-a/eax: (addr cell) <- lookup *guard-ah
- 399       var done?/eax: boolean <- nil? guard-a
- 400       compare done?, 0/false
- 401       break-if-!=
- 402       evaluate-exprs rest-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 403       loop
- 404     }
- 405     trace-text trace, "eval", "loop terminated"
- 406     trace-higher trace
- 407     return
- 408   }
- 409   trace-text trace, "eval", "function call"
- 410   trace-text trace, "eval", "evaluating list elements"
- 411   trace-lower trace
- 412   var evaluated-list-storage: (handle cell)
- 413   var evaluated-list-ah/esi: (addr handle cell) <- address evaluated-list-storage
- 414   var curr-out-ah/edx: (addr handle cell) <- copy evaluated-list-ah
- 415   var curr/ecx: (addr cell) <- copy in-addr
- 416   $evaluate-list:loop: {
- 417     allocate-pair curr-out-ah
- 418     var nil?/eax: boolean <- nil? curr
- 419     compare nil?, 0/false
+ 123   # 'in' is a syntax tree
+ 124   $evaluate:literal-function: {
+ 125     # trees starting with "litfn" are literals
+ 126     var expr/esi: (addr cell) <- copy in
+ 127     var in/edx: (addr cell) <- copy in
+ 128     var first-ah/ecx: (addr handle cell) <- get in, left
+ 129     var first/eax: (addr cell) <- lookup *first-ah
+ 130     var litfn?/eax: boolean <- litfn? first
+ 131     compare litfn?, 0/false
+ 132     break-if-=
+ 133     trace-text trace, "eval", "literal function"
+ 134     copy-object _in-ah, _out-ah
+ 135     trace-higher trace
+ 136     return
+ 137   }
+ 138   $evaluate:literal-macro: {
+ 139     # trees starting with "litmac" are literals
+ 140     var expr/esi: (addr cell) <- copy in
+ 141     var in/edx: (addr cell) <- copy in
+ 142     var first-ah/ecx: (addr handle cell) <- get in, left
+ 143     var first/eax: (addr cell) <- lookup *first-ah
+ 144     var litmac?/eax: boolean <- litmac? first
+ 145     compare litmac?, 0/false
+ 146     break-if-=
+ 147     trace-text trace, "eval", "literal macro"
+ 148     copy-object _in-ah, _out-ah
+ 149     trace-higher trace
+ 150     return
+ 151   }
+ 152   $evaluate:anonymous-function: {
+ 153     # trees starting with "fn" are anonymous functions
+ 154     var expr/esi: (addr cell) <- copy in
+ 155     var in/edx: (addr cell) <- copy in
+ 156     var first-ah/ecx: (addr handle cell) <- get in, left
+ 157     var first/eax: (addr cell) <- lookup *first-ah
+ 158     var fn?/eax: boolean <- fn? first
+ 159     compare fn?, 0/false
+ 160     break-if-=
+ 161     # turn (fn ...) into (litfn env ...)
+ 162     trace-text trace, "eval", "anonymous function"
+ 163     var rest-ah/eax: (addr handle cell) <- get in, right
+ 164     var tmp: (handle cell)
+ 165     var tmp-ah/edi: (addr handle cell) <- address tmp
+ 166     new-pair tmp-ah, env-h, *rest-ah
+ 167     var litfn: (handle cell)
+ 168     var litfn-ah/eax: (addr handle cell) <- address litfn
+ 169     new-symbol litfn-ah, "litfn"
+ 170     new-pair _out-ah, *litfn-ah, *tmp-ah
+ 171     trace-higher trace
+ 172     return
+ 173   }
+ 174   # builtins with "special" evaluation rules
+ 175   $evaluate:quote: {
+ 176     # trees starting with single quote create literals
+ 177     var expr/esi: (addr cell) <- copy in
+ 178     # if its first elem is not "'", break
+ 179     var first-ah/ecx: (addr handle cell) <- get in, left
+ 180     var rest-ah/edx: (addr handle cell) <- get in, right
+ 181     var first/eax: (addr cell) <- lookup *first-ah
+ 182     var quote?/eax: boolean <- symbol-equal? first, "'"
+ 183     compare quote?, 0/false
+ 184     break-if-=
+ 185     #
+ 186     trace-text trace, "eval", "quote"
+ 187     copy-object rest-ah, _out-ah
+ 188     trace-higher trace
+ 189     return
+ 190   }
+ 191   $evaluate:backquote: {
+ 192     # trees starting with single backquote create literals
+ 193     var expr/esi: (addr cell) <- copy in
+ 194     # if its first elem is not "'", break
+ 195     var first-ah/ecx: (addr handle cell) <- get in, left
+ 196     var rest-ah/edx: (addr handle cell) <- get in, right
+ 197     var first/eax: (addr cell) <- lookup *first-ah
+ 198     var backquote?/eax: boolean <- symbol-equal? first, "`"
+ 199     compare backquote?, 0/false
+ 200     break-if-=
+ 201     #
+ 202     trace-text trace, "eval", "backquote"
+ 203     debug-print "`(", 7/fg, 0/bg
+ 204     evaluate-backquote rest-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 205     debug-print ")", 7/fg, 0/bg
+ 206     trace-higher trace
+ 207     return
+ 208   }
+ 209   $evaluate:def: {
+ 210     # trees starting with "def" define globals
+ 211     var expr/esi: (addr cell) <- copy in
+ 212     # if its first elem is not "def", break
+ 213     var first-ah/ecx: (addr handle cell) <- get in, left
+ 214     var rest-ah/edx: (addr handle cell) <- get in, right
+ 215     var first/eax: (addr cell) <- lookup *first-ah
+ 216     var def?/eax: boolean <- symbol-equal? first, "def"
+ 217     compare def?, 0/false
+ 218     break-if-=
+ 219     #
+ 220     trace-text trace, "eval", "def"
+ 221     trace-text trace, "eval", "evaluating second arg"
+ 222     var rest/eax: (addr cell) <- lookup *rest-ah
+ 223     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
+ 224     {
+ 225       var first-arg/eax: (addr cell) <- lookup *first-arg-ah
+ 226       var first-arg-type/eax: (addr int) <- get first-arg, type
+ 227       compare *first-arg-type, 2/symbol
+ 228       break-if-=
+ 229       error trace, "first arg to def must be a symbol"
+ 230       trace-higher trace
+ 231       return
+ 232     }
+ 233     rest-ah <- get rest, right
+ 234     rest <- lookup *rest-ah
+ 235     var second-arg-ah/edx: (addr handle cell) <- get rest, left
+ 236     debug-print "P", 4/fg, 0/bg
+ 237     increment call-number
+ 238     evaluate second-arg-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 239     debug-print "Q", 4/fg, 0/bg
+ 240     trace-text trace, "eval", "saving global binding"
+ 241     var first-arg/eax: (addr cell) <- lookup *first-arg-ah
+ 242     var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
+ 243     var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
+ 244     var tmp-string: (handle array byte)
+ 245     var tmp-ah/edx: (addr handle array byte) <- address tmp-string
+ 246     rewind-stream first-arg-data
+ 247     stream-to-array first-arg-data, tmp-ah
+ 248     var first-arg-data-string/eax: (addr array byte) <- lookup *tmp-ah
+ 249     var out-ah/edi: (addr handle cell) <- copy _out-ah
+ 250     assign-or-create-global globals, first-arg-data-string, *out-ah, trace
+ 251     trace-higher trace
+ 252     return
+ 253   }
+ 254   $evaluate:set: {
+ 255     # trees starting with "set" mutate bindings
+ 256     var expr/esi: (addr cell) <- copy in
+ 257     # if its first elem is not "set", break
+ 258     var first-ah/ecx: (addr handle cell) <- get in, left
+ 259     var rest-ah/edx: (addr handle cell) <- get in, right
+ 260     var first/eax: (addr cell) <- lookup *first-ah
+ 261     var set?/eax: boolean <- symbol-equal? first, "set"
+ 262     compare set?, 0/false
+ 263     break-if-=
+ 264     #
+ 265     trace-text trace, "eval", "set"
+ 266     trace-text trace, "eval", "evaluating second arg"
+ 267     var rest/eax: (addr cell) <- lookup *rest-ah
+ 268     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
+ 269     {
+ 270       var first-arg/eax: (addr cell) <- lookup *first-arg-ah
+ 271       var first-arg-type/eax: (addr int) <- get first-arg, type
+ 272       compare *first-arg-type, 2/symbol
+ 273       break-if-=
+ 274       error trace, "first arg to set must be a symbol"
+ 275       trace-higher trace
+ 276       return
+ 277     }
+ 278     rest-ah <- get rest, right
+ 279     rest <- lookup *rest-ah
+ 280     var second-arg-ah/edx: (addr handle cell) <- get rest, left
+ 281     debug-print "P", 4/fg, 0/bg
+ 282     increment call-number
+ 283     evaluate second-arg-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 284     debug-print "Q", 4/fg, 0/bg
+ 285     trace-text trace, "eval", "mutating binding"
+ 286     var first-arg/eax: (addr cell) <- lookup *first-arg-ah
+ 287     var first-arg-data-ah/eax: (addr handle stream byte) <- get first-arg, text-data
+ 288     var first-arg-data/eax: (addr stream byte) <- lookup *first-arg-data-ah
+ 289     mutate-binding first-arg-data, _out-ah, env-h, globals, trace
+ 290     trace-higher trace
+ 291     return
+ 292   }
+ 293   $evaluate:and: {
+ 294     var expr/esi: (addr cell) <- copy in
+ 295     # if its first elem is not "and", break
+ 296     var first-ah/ecx: (addr handle cell) <- get in, left
+ 297     var rest-ah/edx: (addr handle cell) <- get in, right
+ 298     var first/eax: (addr cell) <- lookup *first-ah
+ 299     var and?/eax: boolean <- symbol-equal? first, "and"
+ 300     compare and?, 0/false
+ 301     break-if-=
+ 302     #
+ 303     trace-text trace, "eval", "and"
+ 304     trace-text trace, "eval", "evaluating first arg"
+ 305     var rest/eax: (addr cell) <- lookup *rest-ah
+ 306     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
+ 307     debug-print "R2", 4/fg, 0/bg
+ 308     increment call-number
+ 309     evaluate first-arg-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 310     debug-print "S2", 4/fg, 0/bg
+ 311     # if first arg is nil, short-circuit
+ 312     var out-ah/eax: (addr handle cell) <- copy _out-ah
+ 313     var out/eax: (addr cell) <- lookup *out-ah
+ 314     var nil?/eax: boolean <- nil? out
+ 315     compare nil?, 0/false
+ 316     {
+ 317       break-if-=
+ 318       return
+ 319     }
+ 320     var rest/eax: (addr cell) <- lookup *rest-ah
+ 321     rest-ah <- get rest, right
+ 322     rest <- lookup *rest-ah
+ 323     var second-ah/eax: (addr handle cell) <- get rest, left
+ 324     debug-print "T2", 4/fg, 0/bg
+ 325     increment call-number
+ 326     evaluate second-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 327     debug-print "U2", 4/fg, 0/bg
+ 328     trace-higher trace
+ 329     return
+ 330   }
+ 331   $evaluate:or: {
+ 332     var expr/esi: (addr cell) <- copy in
+ 333     # if its first elem is not "or", break
+ 334     var first-ah/ecx: (addr handle cell) <- get in, left
+ 335     var rest-ah/edx: (addr handle cell) <- get in, right
+ 336     var first/eax: (addr cell) <- lookup *first-ah
+ 337     var or?/eax: boolean <- symbol-equal? first, "or"
+ 338     compare or?, 0/false
+ 339     break-if-=
+ 340     #
+ 341     trace-text trace, "eval", "or"
+ 342     trace-text trace, "eval", "evaluating first arg"
+ 343     var rest/eax: (addr cell) <- lookup *rest-ah
+ 344     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
+ 345     debug-print "R2", 4/fg, 0/bg
+ 346     increment call-number
+ 347     evaluate first-arg-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 348     debug-print "S2", 4/fg, 0/bg
+ 349     # if first arg is not nil, short-circuit
+ 350     var out-ah/eax: (addr handle cell) <- copy _out-ah
+ 351     var out/eax: (addr cell) <- lookup *out-ah
+ 352     var nil?/eax: boolean <- nil? out
+ 353     compare nil?, 0/false
+ 354     {
+ 355       break-if-!=
+ 356       return
+ 357     }
+ 358     var rest/eax: (addr cell) <- lookup *rest-ah
+ 359     rest-ah <- get rest, right
+ 360     rest <- lookup *rest-ah
+ 361     var second-ah/eax: (addr handle cell) <- get rest, left
+ 362     debug-print "T2", 4/fg, 0/bg
+ 363     increment call-number
+ 364     evaluate second-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 365     debug-print "U2", 4/fg, 0/bg
+ 366     trace-higher trace
+ 367     return
+ 368   }
+ 369   $evaluate:if: {
+ 370     # trees starting with "if" are conditionals
+ 371     var expr/esi: (addr cell) <- copy in
+ 372     # if its first elem is not "if", break
+ 373     var first-ah/ecx: (addr handle cell) <- get in, left
+ 374     var rest-ah/edx: (addr handle cell) <- get in, right
+ 375     var first/eax: (addr cell) <- lookup *first-ah
+ 376     var if?/eax: boolean <- symbol-equal? first, "if"
+ 377     compare if?, 0/false
+ 378     break-if-=
+ 379     #
+ 380     trace-text trace, "eval", "if"
+ 381     trace-text trace, "eval", "evaluating first arg"
+ 382     var rest/eax: (addr cell) <- lookup *rest-ah
+ 383     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
+ 384     var guard-h: (handle cell)
+ 385     var guard-ah/esi: (addr handle cell) <- address guard-h
+ 386     debug-print "R", 4/fg, 0/bg
+ 387     increment call-number
+ 388     evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 389     debug-print "S", 4/fg, 0/bg
+ 390     rest-ah <- get rest, right
+ 391     rest <- lookup *rest-ah
+ 392     var branch-ah/edi: (addr handle cell) <- get rest, left
+ 393     var guard-a/eax: (addr cell) <- lookup *guard-ah
+ 394     var skip-to-third-arg?/eax: boolean <- nil? guard-a
+ 395     compare skip-to-third-arg?, 0/false
+ 396     {
+ 397       break-if-=
+ 398       trace-text trace, "eval", "skipping to third arg"
+ 399       var rest/eax: (addr cell) <- lookup *rest-ah
+ 400       rest-ah <- get rest, right
+ 401       rest <- lookup *rest-ah
+ 402       branch-ah <- get rest, left
+ 403     }
+ 404     debug-print "T", 4/fg, 0/bg
+ 405     increment call-number
+ 406     evaluate branch-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 407     debug-print "U", 4/fg, 0/bg
+ 408     trace-higher trace
+ 409     return
+ 410   }
+ 411   $evaluate:while: {
+ 412     # trees starting with "while" are loops
+ 413     var expr/esi: (addr cell) <- copy in
+ 414     # if its first elem is not "while", break
+ 415     var first-ah/ecx: (addr handle cell) <- get in, left
+ 416     var rest-ah/edx: (addr handle cell) <- get in, right
+ 417     var first/eax: (addr cell) <- lookup *first-ah
+ 418     var first-type/ecx: (addr int) <- get first, type
+ 419     compare *first-type, 2/symbol
  420     break-if-!=
- 421     # eval left
- 422     var curr-out/eax: (addr cell) <- lookup *curr-out-ah
- 423     var left-out-ah/edi: (addr handle cell) <- get curr-out, left
- 424     var left-ah/esi: (addr handle cell) <- get curr, left
- 425     debug-print "A", 4/fg, 0xc5/bg=blue-bg
- 426     increment call-number
- 427     evaluate left-ah, left-out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 428     debug-print "B", 4/fg, 0xc5/bg=blue-bg
- 429     #
- 430     curr-out-ah <- get curr-out, right
- 431     var right-ah/eax: (addr handle cell) <- get curr, right
- 432     var right/eax: (addr cell) <- lookup *right-ah
- 433     curr <- copy right
- 434     loop
- 435   }
- 436   trace-higher trace
- 437   var evaluated-list/eax: (addr cell) <- lookup *evaluated-list-ah
- 438   var function-ah/ecx: (addr handle cell) <- get evaluated-list, left
- 439   var args-ah/edx: (addr handle cell) <- get evaluated-list, right
- 440   debug-print "C", 4/fg, 0xc5/bg=blue-bg
- 441   apply function-ah, args-ah, out, globals, trace, screen-cell, keyboard-cell, call-number
- 442   debug-print "Y", 4/fg, 0xc5/bg=blue-bg
- 443   trace-higher trace
- 444 +-- 11 lines: # trace "=> " out ---------------------------------------------------------------------------------------------------------------------------------------------------------
- 455   debug-print "Z", 4/fg, 0xc5/bg=blue-bg
- 456 }
- 457 
- 458 fn apply _f-ah: (addr handle cell), args-ah: (addr handle cell), out: (addr handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
- 459   var f-ah/eax: (addr handle cell) <- copy _f-ah
- 460   var _f/eax: (addr cell) <- lookup *f-ah
- 461   var f/esi: (addr cell) <- copy _f
- 462   # call primitive functions
- 463   {
- 464     var f-type/eax: (addr int) <- get f, type
- 465     compare *f-type, 4/primitive-function
- 466     break-if-!=
- 467     apply-primitive f, args-ah, out, globals, trace
- 468     return
- 469   }
- 470   # if it's not a primitive function it must be an anonymous function
- 471 +-- 14 lines: # trace "apply anonymous function " f " in environment " env --------------------------------------------------------------------------------------------------------------
- 485   trace-lower trace
- 486   {
- 487     var f-type/ecx: (addr int) <- get f, type
- 488     compare *f-type, 0/pair
- 489     break-if-!=
- 490     var first-ah/eax: (addr handle cell) <- get f, left
- 491     var first/eax: (addr cell) <- lookup *first-ah
- 492     var fn?/eax: boolean <- fn? first
- 493     compare fn?, 0/false
- 494     break-if-=
- 495     var rest-ah/esi: (addr handle cell) <- get f, right
- 496     var rest/eax: (addr cell) <- lookup *rest-ah
- 497     var callee-env-ah/edx: (addr handle cell) <- get rest, left
- 498     rest-ah <- get rest, right
- 499     rest <- lookup *rest-ah
- 500     var params-ah/ecx: (addr handle cell) <- get rest, left
- 501     var body-ah/eax: (addr handle cell) <- get rest, right
- 502     debug-print "D", 7/fg, 0xc5/bg=blue-bg
- 503     apply-function params-ah, args-ah, body-ah, out, *callee-env-ah, globals, trace, screen-cell, keyboard-cell, call-number
- 504     debug-print "Y", 7/fg, 0xc5/bg=blue-bg
- 505     trace-higher trace
- 506     return
- 507   }
- 508   error trace, "unknown function"
- 509 }
- 510 
- 511 fn apply-function params-ah: (addr handle cell), args-ah: (addr handle cell), body-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
- 512   # push bindings for params to env
- 513   var new-env-h: (handle cell)
- 514   var new-env-ah/esi: (addr handle cell) <- address new-env-h
- 515   push-bindings params-ah, args-ah, env-h, new-env-ah, trace
- 516   #
- 517   evaluate-exprs body-ah, out, new-env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 518 }
- 519 
- 520 fn evaluate-exprs _exprs-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
- 521   # eval all exprs, writing result to `out` each time
- 522   var exprs-ah/ecx: (addr handle cell) <- copy _exprs-ah
- 523   $evaluate-exprs:loop: {
- 524     var exprs/eax: (addr cell) <- lookup *exprs-ah
- 525     # stop when exprs is nil
- 526     {
- 527       var exprs-nil?/eax: boolean <- nil? exprs
- 528       compare exprs-nil?, 0/false
- 529       break-if-!= $evaluate-exprs:loop
- 530     }
- 531     # evaluate each expression, writing result to `out`
- 532     {
- 533       var curr-ah/eax: (addr handle cell) <- get exprs, left
- 534       debug-print "E", 7/fg, 0xc5/bg=blue-bg
- 535       increment call-number
- 536       evaluate curr-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
- 537       debug-print "X", 7/fg, 0xc5/bg=blue-bg
- 538     }
- 539     #
- 540     exprs-ah <- get exprs, right
- 541     loop
- 542   }
- 543   # `out` contains result of evaluating final expression
- 544 }
- 545 
- 546 # Bind params to corresponding args and add the bindings to old-env. Return
- 547 # the result in env-ah.
- 548 #
- 549 # We never modify old-env, but we point to it. This way other parts of the
- 550 # interpreter can continue using old-env, and everything works harmoniously
- 551 # even though no cells are copied around.
- 552 #
- 553 # env should always be a DAG (ignoring internals of values). It doesn't have
- 554 # to be a tree (some values may be shared), but there are also no cycles.
- 555 #
- 556 # Learn more: https://en.wikipedia.org/wiki/Persistent_data_structure
- 557 fn push-bindings _params-ah: (addr handle cell), _args-ah: (addr handle cell), old-env-h: (handle cell), env-ah: (addr handle cell), trace: (addr trace) {
- 558   var params-ah/edx: (addr handle cell) <- copy _params-ah
- 559   var args-ah/ebx: (addr handle cell) <- copy _args-ah
- 560   var _params/eax: (addr cell) <- lookup *params-ah
- 561   var params/esi: (addr cell) <- copy _params
- 562   {
- 563     var params-nil?/eax: boolean <- nil? params
- 564     compare params-nil?, 0/false
- 565     break-if-=
- 566     # nil is a literal
- 567     trace-text trace, "eval", "done with push-bindings"
- 568     copy-handle old-env-h, env-ah
- 569     return
- 570   }
- 571   # Params can only be symbols or pairs. Args can be anything.
- 572 +-- 16 lines: # trace "pushing bindings from " params " to " args -----------------------------------------------------------------------------------------------------------------------
- 588   trace-lower trace
- 589   var params-type/eax: (addr int) <- get params, type
- 590   compare *params-type, 2/symbol
- 591   {
- 592     break-if-!=
- 593     trace-text trace, "eval", "symbol; binding to all remaining args"
- 594     # create a new binding
- 595     var new-binding-storage: (handle cell)
- 596     var new-binding-ah/eax: (addr handle cell) <- address new-binding-storage
- 597     new-pair new-binding-ah, *params-ah, *args-ah
- 598     # push it to env
- 599     new-pair env-ah, *new-binding-ah, old-env-h
- 600     trace-higher trace
- 601     return
- 602   }
- 603   compare *params-type, 0/pair
- 604   {
- 605     break-if-=
- 606     error trace, "cannot bind a non-symbol"
- 607     trace-higher trace
- 608     return
- 609   }
- 610   var _args/eax: (addr cell) <- lookup *args-ah
- 611   var args/edi: (addr cell) <- copy _args
- 612   # params is now a pair, so args must be also
- 613   var args-type/eax: (addr int) <- get args, type
- 614   compare *args-type, 0/pair
- 615   {
- 616     break-if-=
- 617     error trace, "args not in a proper list"
- 618     trace-higher trace
- 619     return
- 620   }
- 621   var intermediate-env-storage: (handle cell)
- 622   var intermediate-env-ah/edx: (addr handle cell) <- address intermediate-env-storage
- 623   var first-param-ah/eax: (addr handle cell) <- get params, left
- 624   var first-arg-ah/ecx: (addr handle cell) <- get args, left
- 625   push-bindings first-param-ah, first-arg-ah, old-env-h, intermediate-env-ah, trace
- 626   var remaining-params-ah/eax: (addr handle cell) <- get params, right
- 627   var remaining-args-ah/ecx: (addr handle cell) <- get args, right
- 628   push-bindings remaining-params-ah, remaining-args-ah, *intermediate-env-ah, env-ah, trace
- 629   trace-higher trace
- 630 }
- 631 
- 632 fn lookup-symbol sym: (addr cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
- 633   # trace sym
- 634   {
- 635     compare trace, 0
- 636     break-if-=
- 637     var stream-storage: (stream byte 0x800)  # pessimistically sized just for the large alist loaded from disk in `main`
- 638     var stream/ecx: (addr stream byte) <- address stream-storage
- 639     write stream, "look up "
- 640     var sym2/eax: (addr cell) <- copy sym
- 641     var sym-data-ah/eax: (addr handle stream byte) <- get sym2, text-data
- 642     var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
- 643     rewind-stream sym-data
- 644     write-stream stream, sym-data
- 645     write stream, " in "
- 646     var env-ah/eax: (addr handle cell) <- address env-h
- 647     print-cell env-ah, stream, 0/no-trace
- 648     trace trace, "eval", stream
- 649   }
- 650   trace-lower trace
- 651   var _env/eax: (addr cell) <- lookup env-h
- 652   var env/ebx: (addr cell) <- copy _env
- 653   # if env is not a list, abort
- 654   {
- 655     var env-type/ecx: (addr int) <- get env, type
- 656     compare *env-type, 0/pair
- 657     break-if-=
- 658     error trace, "eval found a non-list environment"
+ 421     var sym-data-ah/eax: (addr handle stream byte) <- get first, text-data
+ 422     var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
+ 423     var while?/eax: boolean <- stream-data-equal? sym-data, "while"
+ 424     compare while?, 0/false
+ 425     break-if-=
+ 426     #
+ 427     trace-text trace, "eval", "while"
+ 428     var rest/eax: (addr cell) <- lookup *rest-ah
+ 429     var first-arg-ah/ecx: (addr handle cell) <- get rest, left
+ 430     rest-ah <- get rest, right
+ 431     var guard-h: (handle cell)
+ 432     var guard-ah/esi: (addr handle cell) <- address guard-h
+ 433     $evaluate:while:loop-execution: {
+ 434       {
+ 435         compare trace, 0
+ 436         break-if-=
+ 437         var error?/eax: boolean <- has-errors? trace
+ 438         compare error?, 0/false
+ 439         break-if-!= $evaluate:while:loop-execution
+ 440       }
+ 441       trace-text trace, "eval", "loop termination check"
+ 442       debug-print "V", 4/fg, 0/bg
+ 443       increment call-number
+ 444       evaluate first-arg-ah, guard-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 445       debug-print "W", 4/fg, 0/bg
+ 446       var guard-a/eax: (addr cell) <- lookup *guard-ah
+ 447       var done?/eax: boolean <- nil? guard-a
+ 448       compare done?, 0/false
+ 449       break-if-!=
+ 450       evaluate-exprs rest-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 451       loop
+ 452     }
+ 453     trace-text trace, "eval", "loop terminated"
+ 454     trace-higher trace
+ 455     return
+ 456   }
+ 457   trace-text trace, "eval", "function call"
+ 458   trace-text trace, "eval", "evaluating list elements"
+ 459   trace-lower trace
+ 460   var evaluated-list-storage: (handle cell)
+ 461   var evaluated-list-ah/esi: (addr handle cell) <- address evaluated-list-storage
+ 462   var curr-out-ah/edx: (addr handle cell) <- copy evaluated-list-ah
+ 463   var curr/ecx: (addr cell) <- copy in
+ 464   $evaluate-list:loop: {
+ 465     allocate-pair curr-out-ah
+ 466     var nil?/eax: boolean <- nil? curr
+ 467     compare nil?, 0/false
+ 468     break-if-!=
+ 469     # eval left
+ 470     var curr-out/eax: (addr cell) <- lookup *curr-out-ah
+ 471     var left-out-ah/edi: (addr handle cell) <- get curr-out, left
+ 472     var left-ah/esi: (addr handle cell) <- get curr, left
+ 473     debug-print "A", 4/fg, 0/bg
+ 474     increment call-number
+ 475     evaluate left-ah, left-out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 476     debug-print "B", 4/fg, 0/bg
+ 477     # a trip wire in case we're running without a trace (e.g. when loading the initial state from disk)
+ 478     {
+ 479       compare trace, 0
+ 480       break-if-!=
+ 481       var left-out/eax: (addr cell) <- lookup *left-out-ah
+ 482       compare left-out, 0
+ 483       {
+ 484         break-if-!=
+ 485         abort "there was some error (likely in syntax): eval-list"
+ 486       }
+ 487     }
+ 488     #
+ 489     curr-out-ah <- get curr-out, right
+ 490     var right-ah/eax: (addr handle cell) <- get curr, right
+ 491     var right/eax: (addr cell) <- lookup *right-ah
+ 492     curr <- copy right
+ 493     loop
+ 494   }
+ 495   trace-higher trace
+ 496   var evaluated-list/eax: (addr cell) <- lookup *evaluated-list-ah
+ 497   var function-ah/ecx: (addr handle cell) <- get evaluated-list, left
+ 498   var args-ah/edx: (addr handle cell) <- get evaluated-list, right
+ 499   debug-print "C", 4/fg, 0/bg
+ 500   apply function-ah, args-ah, _out-ah, globals, trace, screen-cell, keyboard-cell, call-number
+ 501   debug-print "Y", 4/fg, 0/bg
+ 502   trace-higher trace
+ 503 +-- 11 lines: # trace "=> " _out-ah -----------------------------------------------------------------------------------------------------------------------------------------------------
+ 514   debug-print "Z", 4/fg, 0/bg
+ 515 }
+ 516 
+ 517 fn apply _f-ah: (addr handle cell), args-ah: (addr handle cell), out: (addr handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
+ 518   var f-ah/eax: (addr handle cell) <- copy _f-ah
+ 519   var _f/eax: (addr cell) <- lookup *f-ah
+ 520   var f/esi: (addr cell) <- copy _f
+ 521   # call primitive functions
+ 522   {
+ 523     var f-type/eax: (addr int) <- get f, type
+ 524     compare *f-type, 4/primitive-function
+ 525     break-if-!=
+ 526     apply-primitive f, args-ah, out, globals, trace
+ 527     return
+ 528   }
+ 529   # if it's not a primitive function it must be an anonymous function
+ 530 +-- 14 lines: # trace "apply anonymous function " f " in environment " env --------------------------------------------------------------------------------------------------------------
+ 544   trace-lower trace
+ 545   {
+ 546     var f-type/ecx: (addr int) <- get f, type
+ 547     compare *f-type, 0/pair
+ 548     break-if-!=
+ 549     var first-ah/eax: (addr handle cell) <- get f, left
+ 550     var first/eax: (addr cell) <- lookup *first-ah
+ 551     var litfn?/eax: boolean <- litfn? first
+ 552     compare litfn?, 0/false
+ 553     break-if-=
+ 554     var rest-ah/esi: (addr handle cell) <- get f, right
+ 555     var rest/eax: (addr cell) <- lookup *rest-ah
+ 556     var callee-env-ah/edx: (addr handle cell) <- get rest, left
+ 557     rest-ah <- get rest, right
+ 558     rest <- lookup *rest-ah
+ 559     var params-ah/ecx: (addr handle cell) <- get rest, left
+ 560     var body-ah/eax: (addr handle cell) <- get rest, right
+ 561     debug-print "D", 7/fg, 0/bg
+ 562     apply-function params-ah, args-ah, body-ah, out, *callee-env-ah, globals, trace, screen-cell, keyboard-cell, call-number
+ 563     debug-print "Y", 7/fg, 0/bg
+ 564     trace-higher trace
+ 565     return
+ 566   }
+ 567   error trace, "unknown function"
+ 568 }
+ 569 
+ 570 fn apply-function params-ah: (addr handle cell), args-ah: (addr handle cell), body-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
+ 571   # push bindings for params to env
+ 572   var new-env-h: (handle cell)
+ 573   var new-env-ah/esi: (addr handle cell) <- address new-env-h
+ 574   push-bindings params-ah, args-ah, env-h, new-env-ah, trace
+ 575   #
+ 576   evaluate-exprs body-ah, out, new-env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 577 }
+ 578 
+ 579 fn evaluate-exprs _exprs-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
+ 580   # eval all exprs, writing result to `out` each time
+ 581   var exprs-ah/ecx: (addr handle cell) <- copy _exprs-ah
+ 582   $evaluate-exprs:loop: {
+ 583     var exprs/eax: (addr cell) <- lookup *exprs-ah
+ 584     # stop when exprs is nil
+ 585     {
+ 586       var exprs-nil?/eax: boolean <- nil? exprs
+ 587       compare exprs-nil?, 0/false
+ 588       break-if-!= $evaluate-exprs:loop
+ 589     }
+ 590     # evaluate each expression, writing result to `out`
+ 591     {
+ 592       var curr-ah/eax: (addr handle cell) <- get exprs, left
+ 593       debug-print "E", 7/fg, 0/bg
+ 594       increment call-number
+ 595       evaluate curr-ah, out, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+ 596       debug-print "X", 7/fg, 0/bg
+ 597     }
+ 598     #
+ 599     exprs-ah <- get exprs, right
+ 600     loop
+ 601   }
+ 602   # `out` contains result of evaluating final expression
+ 603 }
+ 604 
+ 605 # Bind params to corresponding args and add the bindings to old-env. Return
+ 606 # the result in env-ah.
+ 607 #
+ 608 # We never modify old-env, but we point to it. This way other parts of the
+ 609 # interpreter can continue using old-env, and everything works harmoniously
+ 610 # even though no cells are copied around.
+ 611 #
+ 612 # env should always be a DAG (ignoring internals of values). It doesn't have
+ 613 # to be a tree (some values may be shared), but there are also no cycles.
+ 614 #
+ 615 # Learn more: https://en.wikipedia.org/wiki/Persistent_data_structure
+ 616 fn push-bindings _params-ah: (addr handle cell), _args-ah: (addr handle cell), old-env-h: (handle cell), env-ah: (addr handle cell), trace: (addr trace) {
+ 617   var params-ah/edx: (addr handle cell) <- copy _params-ah
+ 618   var args-ah/ebx: (addr handle cell) <- copy _args-ah
+ 619   var _params/eax: (addr cell) <- lookup *params-ah
+ 620   var params/esi: (addr cell) <- copy _params
+ 621   {
+ 622     var params-nil?/eax: boolean <- nil? params
+ 623     compare params-nil?, 0/false
+ 624     break-if-=
+ 625     # nil is a literal
+ 626     trace-text trace, "eval", "done with push-bindings"
+ 627     copy-handle old-env-h, env-ah
+ 628     return
+ 629   }
+ 630   # Params can only be symbols or pairs. Args can be anything.
+ 631 +-- 16 lines: # trace "pushing bindings from " params " to " args -----------------------------------------------------------------------------------------------------------------------
+ 647   trace-lower trace
+ 648   var params-type/eax: (addr int) <- get params, type
+ 649   compare *params-type, 2/symbol
+ 650   {
+ 651     break-if-!=
+ 652     trace-text trace, "eval", "symbol; binding to all remaining args"
+ 653     # create a new binding
+ 654     var new-binding-storage: (handle cell)
+ 655     var new-binding-ah/eax: (addr handle cell) <- address new-binding-storage
+ 656     new-pair new-binding-ah, *params-ah, *args-ah
+ 657     # push it to env
+ 658     new-pair env-ah, *new-binding-ah, old-env-h
  659     trace-higher trace
  660     return
  661   }
- 662   # if env is nil, look up in globals
+ 662   compare *params-type, 0/pair
  663   {
- 664     var env-nil?/eax: boolean <- nil? env
- 665     compare env-nil?, 0/false
- 666     break-if-=
- 667     debug-print "b", 7/fg, 0xc5/bg=blue-bg
- 668     lookup-symbol-in-globals sym, out, globals, trace, screen-cell, keyboard-cell
- 669     debug-print "x", 7/fg, 0xc5/bg=blue-bg
- 670     trace-higher trace
- 671 +-- 15 lines: # trace "=> " out " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
- 686     debug-print "y", 7/fg, 0xc5/bg=blue-bg
- 687     return
- 688   }
- 689   # check car
- 690   var env-head-storage: (handle cell)
- 691   var env-head-ah/eax: (addr handle cell) <- address env-head-storage
- 692   car env, env-head-ah, 0/no-trace
- 693   var _env-head/eax: (addr cell) <- lookup *env-head-ah
- 694   var env-head/ecx: (addr cell) <- copy _env-head
- 695   # if car is not a list, abort
- 696   {
- 697     var env-head-type/eax: (addr int) <- get env-head, type
- 698     compare *env-head-type, 0/pair
- 699     break-if-=
- 700     error trace, "environment is not a list of (key . value) pairs"
- 701     trace-higher trace
- 702     return
- 703   }
- 704   # check key
- 705   var curr-key-storage: (handle cell)
- 706   var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
- 707   car env-head, curr-key-ah, trace
- 708   var curr-key/eax: (addr cell) <- lookup *curr-key-ah
- 709   # if key is not a symbol, abort
- 710   {
- 711     var curr-key-type/eax: (addr int) <- get curr-key, type
- 712     compare *curr-key-type, 2/symbol
- 713     break-if-=
- 714     error trace, "environment contains a binding for a non-symbol"
- 715     trace-higher trace
- 716     return
- 717   }
- 718   # if key matches sym, return val
- 719   var match?/eax: boolean <- cell-isomorphic? curr-key, sym, trace
- 720   compare match?, 0/false
- 721   {
- 722     break-if-=
- 723     cdr env-head, out, 0/no-trace
- 724 +-- 15 lines: # trace "=> " out " (match)" ----------------------------------------------------------------------------------------------------------------------------------------------
- 739     trace-higher trace
- 740     return
- 741   }
- 742   # otherwise recurse
- 743   var env-tail-storage: (handle cell)
- 744   var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
- 745   cdr env, env-tail-ah, trace
- 746   lookup-symbol sym, out, *env-tail-ah, globals, trace, screen-cell, keyboard-cell
- 747   trace-higher trace
- 748 +-- 15 lines: # trace "=> " out " (recurse)" --------------------------------------------------------------------------------------------------------------------------------------------
- 763 }
- 764 
- 765 fn test-lookup-symbol-in-env {
- 766   # tmp = (a . 3)
- 767   var val-storage: (handle cell)
- 768   var val-ah/ecx: (addr handle cell) <- address val-storage
- 769   new-integer val-ah, 3
- 770   var key-storage: (handle cell)
- 771   var key-ah/edx: (addr handle cell) <- address key-storage
- 772   new-symbol key-ah, "a"
- 773   var env-storage: (handle cell)
- 774   var env-ah/ebx: (addr handle cell) <- address env-storage
- 775   new-pair env-ah, *key-ah, *val-ah
- 776   # env = ((a . 3))
- 777   var nil-storage: (handle cell)
- 778   var nil-ah/ecx: (addr handle cell) <- address nil-storage
- 779   allocate-pair nil-ah
- 780   new-pair env-ah, *env-ah, *nil-ah
- 781   # lookup sym(a) in env tmp
- 782   var tmp-storage: (handle cell)
- 783   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
- 784   new-symbol tmp-ah, "a"
- 785   var in/eax: (addr cell) <- lookup *tmp-ah
- 786   lookup-symbol in, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard
- 787   var result/eax: (addr cell) <- lookup *tmp-ah
- 788   var result-type/edx: (addr int) <- get result, type
- 789   check-ints-equal *result-type, 1/number, "F - test-lookup-symbol-in-env/0"
- 790   var result-value-addr/eax: (addr float) <- get result, number-data
- 791   var result-value/eax: int <- convert *result-value-addr
- 792   check-ints-equal result-value, 3, "F - test-lookup-symbol-in-env/1"
- 793 }
- 794 
- 795 fn test-lookup-symbol-in-globals {
- 796   var globals-storage: global-table
- 797   var globals/edi: (addr global-table) <- address globals-storage
- 798   initialize-globals globals
- 799   # env = nil
- 800   var nil-storage: (handle cell)
- 801   var nil-ah/ecx: (addr handle cell) <- address nil-storage
- 802   allocate-pair nil-ah
- 803   # lookup sym(a), env
- 804   var tmp-storage: (handle cell)
- 805   var tmp-ah/ebx: (addr handle cell) <- address tmp-storage
- 806   new-symbol tmp-ah, "+"
- 807   var in/eax: (addr cell) <- lookup *tmp-ah
- 808   lookup-symbol in, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard
- 809   var result/eax: (addr cell) <- lookup *tmp-ah
- 810   var result-type/edx: (addr int) <- get result, type
- 811   check-ints-equal *result-type, 4/primitive-function, "F - test-lookup-symbol-in-globals/0"
- 812   var result-value/eax: (addr int) <- get result, index-data
- 813   check-ints-equal *result-value, 1/add, "F - test-lookup-symbol-in-globals/1"
- 814 }
- 815 
- 816 fn mutate-binding name: (addr stream byte), val: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace) {
- 817   # trace name
- 818   {
- 819     compare trace, 0
- 820     break-if-=
- 821     var stream-storage: (stream byte 0x800)  # pessimistically sized just for the large alist loaded from disk in `main`
- 822     var stream/ecx: (addr stream byte) <- address stream-storage
- 823     write stream, "bind "
- 824     rewind-stream name
- 825     write-stream stream, name
- 826     write stream, " to "
- 827     print-cell val, stream, 0/no-trace
- 828     write stream, " in "
- 829     var env-ah/eax: (addr handle cell) <- address env-h
- 830     print-cell env-ah, stream, 0/no-trace
- 831     trace trace, "eval", stream
- 832   }
- 833   trace-lower trace
- 834   var _env/eax: (addr cell) <- lookup env-h
- 835   var env/ebx: (addr cell) <- copy _env
- 836   # if env is not a list, abort
- 837   {
- 838     var env-type/ecx: (addr int) <- get env, type
- 839     compare *env-type, 0/pair
- 840     break-if-=
- 841     error trace, "eval found a non-list environment"
- 842     trace-higher trace
- 843     return
- 844   }
- 845   # if env is nil, look in globals
- 846   {
- 847     var env-nil?/eax: boolean <- nil? env
- 848     compare env-nil?, 0/false
- 849     break-if-=
- 850     debug-print "b", 3/fg, 0xc5/bg=blue-bg
- 851     mutate-binding-in-globals name, val, globals, trace
- 852     debug-print "x", 3/fg, 0xc5/bg=blue-bg
- 853     trace-higher trace
- 854 +-- 15 lines: # trace "=> " val " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
- 869     debug-print "y", 3/fg, 0xc5/bg=blue-bg
- 870     return
- 871   }
- 872   # check car
- 873   var env-head-storage: (handle cell)
- 874   var env-head-ah/eax: (addr handle cell) <- address env-head-storage
- 875   car env, env-head-ah, 0/no-trace
- 876   var _env-head/eax: (addr cell) <- lookup *env-head-ah
- 877   var env-head/ecx: (addr cell) <- copy _env-head
- 878   # if car is not a list, abort
- 879   {
- 880     var env-head-type/eax: (addr int) <- get env-head, type
- 881     compare *env-head-type, 0/pair
- 882     break-if-=
- 883     error trace, "environment is not a list of (key . value) pairs"
- 884     trace-higher trace
- 885     return
- 886   }
- 887   # check key
- 888   var curr-key-storage: (handle cell)
- 889   var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
- 890   car env-head, curr-key-ah, trace
- 891   var curr-key/eax: (addr cell) <- lookup *curr-key-ah
- 892   # if key is not a symbol, abort
- 893   {
- 894     var curr-key-type/eax: (addr int) <- get curr-key, type
- 895     compare *curr-key-type, 2/symbol
- 896     break-if-=
- 897     error trace, "environment contains a binding for a non-symbol"
- 898     trace-higher trace
- 899     return
- 900   }
- 901   # if key matches name, return val
- 902   var curr-key-data-ah/eax: (addr handle stream byte) <- get curr-key, text-data
- 903   var curr-key-data/eax: (addr stream byte) <- lookup *curr-key-data-ah
- 904   var match?/eax: boolean <- streams-data-equal? curr-key-data, name
- 905   compare match?, 0/false
- 906   {
- 907     break-if-=
- 908     var dest/eax: (addr handle cell) <- get env-head, right
- 909     copy-object val, dest
- 910     trace-text trace, "eval", "=> done"
- 911     trace-higher trace
- 912     return
- 913   }
- 914   # otherwise recurse
- 915   var env-tail-storage: (handle cell)
- 916   var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
- 917   cdr env, env-tail-ah, trace
- 918   mutate-binding name, val, *env-tail-ah, globals, trace
- 919   trace-higher trace
- 920 }
- 921 
- 922 fn car _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
- 923   trace-text trace, "eval", "car"
- 924   trace-lower trace
- 925   var in/eax: (addr cell) <- copy _in
- 926   # if in is not a list, abort
- 927   {
- 928     var in-type/ecx: (addr int) <- get in, type
- 929     compare *in-type, 0/pair
- 930     break-if-=
- 931     error trace, "car on a non-list"
- 932     trace-higher trace
- 933     return
- 934   }
- 935   # if in is nil, abort
- 936   {
- 937     var in-nil?/eax: boolean <- nil? in
- 938     compare in-nil?, 0/false
- 939     break-if-=
- 940     error trace, "car on nil"
- 941     trace-higher trace
- 942     return
- 943   }
- 944   var in-left/eax: (addr handle cell) <- get in, left
- 945   copy-object in-left, out
- 946   trace-higher trace
- 947   return
- 948 }
- 949 
- 950 fn cdr _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
- 951   trace-text trace, "eval", "cdr"
- 952   trace-lower trace
- 953   var in/eax: (addr cell) <- copy _in
- 954   # if in is not a list, abort
- 955   {
- 956     var in-type/ecx: (addr int) <- get in, type
- 957     compare *in-type, 0/pair
- 958     break-if-=
- 959     error trace, "car on a non-list"
- 960     trace-higher trace
- 961     return
- 962   }
- 963   # if in is nil, abort
- 964   {
- 965     var in-nil?/eax: boolean <- nil? in
- 966     compare in-nil?, 0/false
- 967     break-if-=
- 968     error trace, "car on nil"
- 969     trace-higher trace
- 970     return
- 971   }
- 972   var in-right/eax: (addr handle cell) <- get in, right
- 973   copy-object in-right, out
- 974   trace-higher trace
- 975   return
- 976 }
- 977 
- 978 fn cell-isomorphic? _a: (addr cell), _b: (addr cell), trace: (addr trace) -> _/eax: boolean {
- 979   trace-text trace, "eval", "cell-isomorphic?"
- 980   trace-lower trace
- 981   var a/esi: (addr cell) <- copy _a
- 982   var b/edi: (addr cell) <- copy _b
- 983   # if types don't match, return false
- 984   var a-type-addr/eax: (addr int) <- get a, type
- 985   var b-type-addr/ecx: (addr int) <- get b, type
- 986   var b-type/ecx: int <- copy *b-type-addr
- 987   compare b-type, *a-type-addr
- 988   {
+ 664     break-if-=
+ 665     error trace, "cannot bind a non-symbol"
+ 666     trace-higher trace
+ 667     return
+ 668   }
+ 669   var _args/eax: (addr cell) <- lookup *args-ah
+ 670   var args/edi: (addr cell) <- copy _args
+ 671   # params is now a pair, so args must be also
+ 672   var args-type/eax: (addr int) <- get args, type
+ 673   compare *args-type, 0/pair
+ 674   {
+ 675     break-if-=
+ 676     error trace, "args not in a proper list"
+ 677     trace-higher trace
+ 678     return
+ 679   }
+ 680   var intermediate-env-storage: (handle cell)
+ 681   var intermediate-env-ah/edx: (addr handle cell) <- address intermediate-env-storage
+ 682   var first-param-ah/eax: (addr handle cell) <- get params, left
+ 683   var first-arg-ah/ecx: (addr handle cell) <- get args, left
+ 684   push-bindings first-param-ah, first-arg-ah, old-env-h, intermediate-env-ah, trace
+ 685   var remaining-params-ah/eax: (addr handle cell) <- get params, right
+ 686   var remaining-args-ah/ecx: (addr handle cell) <- get args, right
+ 687   push-bindings remaining-params-ah, remaining-args-ah, *intermediate-env-ah, env-ah, trace
+ 688   trace-higher trace
+ 689 }
+ 690 
+ 691 fn lookup-symbol sym: (addr cell), out: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) {
+ 692   # trace sym
+ 693   {
+ 694     compare trace, 0
+ 695     break-if-=
+ 696     var stream-storage: (stream byte 0x800)  # pessimistically sized just for the large alist loaded from disk in `main`
+ 697     var stream/ecx: (addr stream byte) <- address stream-storage
+ 698     write stream, "look up "
+ 699     var sym2/eax: (addr cell) <- copy sym
+ 700     var sym-data-ah/eax: (addr handle stream byte) <- get sym2, text-data
+ 701     var sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
+ 702     rewind-stream sym-data
+ 703     write-stream stream, sym-data
+ 704     write stream, " in "
+ 705     var env-ah/eax: (addr handle cell) <- address env-h
+ 706     print-cell env-ah, stream, 0/no-trace
+ 707     trace trace, "eval", stream
+ 708   }
+ 709   trace-lower trace
+ 710   var _env/eax: (addr cell) <- lookup env-h
+ 711   var env/ebx: (addr cell) <- copy _env
+ 712   # if env is not a list, abort
+ 713   {
+ 714     var env-type/ecx: (addr int) <- get env, type
+ 715     compare *env-type, 0/pair
+ 716     break-if-=
+ 717     error trace, "eval found a non-list environment"
+ 718     trace-higher trace
+ 719     return
+ 720   }
+ 721   # if env is nil, look up in globals
+ 722   {
+ 723     var env-nil?/eax: boolean <- nil? env
+ 724     compare env-nil?, 0/false
+ 725     break-if-=
+ 726     debug-print "b", 7/fg, 0/bg
+ 727     lookup-symbol-in-globals sym, out, globals, trace, screen-cell, keyboard-cell
+ 728     debug-print "x", 7/fg, 0/bg
+ 729     trace-higher trace
+ 730 +-- 15 lines: # trace "=> " out " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
+ 745     debug-print "y", 7/fg, 0/bg
+ 746     return
+ 747   }
+ 748   # check car
+ 749   var env-head-storage: (handle cell)
+ 750   var env-head-ah/eax: (addr handle cell) <- address env-head-storage
+ 751   car env, env-head-ah, 0/no-trace
+ 752   var _env-head/eax: (addr cell) <- lookup *env-head-ah
+ 753   var env-head/ecx: (addr cell) <- copy _env-head
+ 754   # if car is not a list, abort
+ 755   {
+ 756     var env-head-type/eax: (addr int) <- get env-head, type
+ 757     compare *env-head-type, 0/pair
+ 758     break-if-=
+ 759     error trace, "environment is not a list of (key . value) pairs"
+ 760     trace-higher trace
+ 761     return
+ 762   }
+ 763   # check key
+ 764   var curr-key-storage: (handle cell)
+ 765   var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
+ 766   car env-head, curr-key-ah, trace
+ 767   var curr-key/eax: (addr cell) <- lookup *curr-key-ah
+ 768   # if key is not a symbol, abort
+ 769   {
+ 770     var curr-key-type/eax: (addr int) <- get curr-key, type
+ 771     compare *curr-key-type, 2/symbol
+ 772     break-if-=
+ 773     error trace, "environment contains a binding for a non-symbol"
+ 774     trace-higher trace
+ 775     return
+ 776   }
+ 777   # if key matches sym, return val
+ 778   var match?/eax: boolean <- cell-isomorphic? curr-key, sym, trace
+ 779   compare match?, 0/false
+ 780   {
+ 781     break-if-=
+ 782     cdr env-head, out, 0/no-trace
+ 783 +-- 15 lines: # trace "=> " out " (match)" ----------------------------------------------------------------------------------------------------------------------------------------------
+ 798     trace-higher trace
+ 799     return
+ 800   }
+ 801   # otherwise recurse
+ 802   var env-tail-storage: (handle cell)
+ 803   var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
+ 804   cdr env, env-tail-ah, trace
+ 805   lookup-symbol sym, out, *env-tail-ah, globals, trace, screen-cell, keyboard-cell
+ 806   trace-higher trace
+ 807 +-- 15 lines: # trace "=> " out " (recurse)" --------------------------------------------------------------------------------------------------------------------------------------------
+ 822 }
+ 823 
+ 824 fn test-lookup-symbol-in-env {
+ 825   # tmp = (a . 3)
+ 826   var val-storage: (handle cell)
+ 827   var val-ah/ecx: (addr handle cell) <- address val-storage
+ 828   new-integer val-ah, 3
+ 829   var key-storage: (handle cell)
+ 830   var key-ah/edx: (addr handle cell) <- address key-storage
+ 831   new-symbol key-ah, "a"
+ 832   var env-storage: (handle cell)
+ 833   var env-ah/ebx: (addr handle cell) <- address env-storage
+ 834   new-pair env-ah, *key-ah, *val-ah
+ 835   # env = ((a . 3))
+ 836   var nil-storage: (handle cell)
+ 837   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+ 838   allocate-pair nil-ah
+ 839   new-pair env-ah, *env-ah, *nil-ah
+ 840   # lookup sym(a) in env tmp
+ 841   var tmp-storage: (handle cell)
+ 842   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
+ 843   new-symbol tmp-ah, "a"
+ 844   var in/eax: (addr cell) <- lookup *tmp-ah
+ 845   lookup-symbol in, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard
+ 846   var result/eax: (addr cell) <- lookup *tmp-ah
+ 847   var result-type/edx: (addr int) <- get result, type
+ 848   check-ints-equal *result-type, 1/number, "F - test-lookup-symbol-in-env/0"
+ 849   var result-value-addr/eax: (addr float) <- get result, number-data
+ 850   var result-value/eax: int <- convert *result-value-addr
+ 851   check-ints-equal result-value, 3, "F - test-lookup-symbol-in-env/1"
+ 852 }
+ 853 
+ 854 fn test-lookup-symbol-in-globals {
+ 855   var globals-storage: global-table
+ 856   var globals/edi: (addr global-table) <- address globals-storage
+ 857   initialize-globals globals
+ 858   # env = nil
+ 859   var nil-storage: (handle cell)
+ 860   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+ 861   allocate-pair nil-ah
+ 862   # lookup sym(a), env
+ 863   var tmp-storage: (handle cell)
+ 864   var tmp-ah/ebx: (addr handle cell) <- address tmp-storage
+ 865   new-symbol tmp-ah, "+"
+ 866   var in/eax: (addr cell) <- lookup *tmp-ah
+ 867   lookup-symbol in, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard
+ 868   var result/eax: (addr cell) <- lookup *tmp-ah
+ 869   var result-type/edx: (addr int) <- get result, type
+ 870   check-ints-equal *result-type, 4/primitive-function, "F - test-lookup-symbol-in-globals/0"
+ 871   var result-value/eax: (addr int) <- get result, index-data
+ 872   check-ints-equal *result-value, 1/add, "F - test-lookup-symbol-in-globals/1"
+ 873 }
+ 874 
+ 875 fn mutate-binding name: (addr stream byte), val: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace) {
+ 876   # trace name
+ 877   {
+ 878     compare trace, 0
+ 879     break-if-=
+ 880     var stream-storage: (stream byte 0x800)  # pessimistically sized just for the large alist loaded from disk in `main`
+ 881     var stream/ecx: (addr stream byte) <- address stream-storage
+ 882     write stream, "bind "
+ 883     rewind-stream name
+ 884     write-stream stream, name
+ 885     write stream, " to "
+ 886     print-cell val, stream, 0/no-trace
+ 887     write stream, " in "
+ 888     var env-ah/eax: (addr handle cell) <- address env-h
+ 889     print-cell env-ah, stream, 0/no-trace
+ 890     trace trace, "eval", stream
+ 891   }
+ 892   trace-lower trace
+ 893   var _env/eax: (addr cell) <- lookup env-h
+ 894   var env/ebx: (addr cell) <- copy _env
+ 895   # if env is not a list, abort
+ 896   {
+ 897     var env-type/ecx: (addr int) <- get env, type
+ 898     compare *env-type, 0/pair
+ 899     break-if-=
+ 900     error trace, "eval found a non-list environment"
+ 901     trace-higher trace
+ 902     return
+ 903   }
+ 904   # if env is nil, look in globals
+ 905   {
+ 906     var env-nil?/eax: boolean <- nil? env
+ 907     compare env-nil?, 0/false
+ 908     break-if-=
+ 909     debug-print "b", 3/fg, 0/bg
+ 910     mutate-binding-in-globals name, val, globals, trace
+ 911     debug-print "x", 3/fg, 0/bg
+ 912     trace-higher trace
+ 913 +-- 15 lines: # trace "=> " val " (global)" ---------------------------------------------------------------------------------------------------------------------------------------------
+ 928     debug-print "y", 3/fg, 0/bg
+ 929     return
+ 930   }
+ 931   # check car
+ 932   var env-head-storage: (handle cell)
+ 933   var env-head-ah/eax: (addr handle cell) <- address env-head-storage
+ 934   car env, env-head-ah, 0/no-trace
+ 935   var _env-head/eax: (addr cell) <- lookup *env-head-ah
+ 936   var env-head/ecx: (addr cell) <- copy _env-head
+ 937   # if car is not a list, abort
+ 938   {
+ 939     var env-head-type/eax: (addr int) <- get env-head, type
+ 940     compare *env-head-type, 0/pair
+ 941     break-if-=
+ 942     error trace, "environment is not a list of (key . value) pairs"
+ 943     trace-higher trace
+ 944     return
+ 945   }
+ 946   # check key
+ 947   var curr-key-storage: (handle cell)
+ 948   var curr-key-ah/eax: (addr handle cell) <- address curr-key-storage
+ 949   car env-head, curr-key-ah, trace
+ 950   var curr-key/eax: (addr cell) <- lookup *curr-key-ah
+ 951   # if key is not a symbol, abort
+ 952   {
+ 953     var curr-key-type/eax: (addr int) <- get curr-key, type
+ 954     compare *curr-key-type, 2/symbol
+ 955     break-if-=
+ 956     error trace, "environment contains a binding for a non-symbol"
+ 957     trace-higher trace
+ 958     return
+ 959   }
+ 960   # if key matches name, return val
+ 961   var curr-key-data-ah/eax: (addr handle stream byte) <- get curr-key, text-data
+ 962   var curr-key-data/eax: (addr stream byte) <- lookup *curr-key-data-ah
+ 963   var match?/eax: boolean <- streams-data-equal? curr-key-data, name
+ 964   compare match?, 0/false
+ 965   {
+ 966     break-if-=
+ 967     var dest/eax: (addr handle cell) <- get env-head, right
+ 968     copy-object val, dest
+ 969     trace-text trace, "eval", "=> done"
+ 970     trace-higher trace
+ 971     return
+ 972   }
+ 973   # otherwise recurse
+ 974   var env-tail-storage: (handle cell)
+ 975   var env-tail-ah/eax: (addr handle cell) <- address env-tail-storage
+ 976   cdr env, env-tail-ah, trace
+ 977   mutate-binding name, val, *env-tail-ah, globals, trace
+ 978   trace-higher trace
+ 979 }
+ 980 
+ 981 fn car _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
+ 982   trace-text trace, "eval", "car"
+ 983   trace-lower trace
+ 984   var in/eax: (addr cell) <- copy _in
+ 985   # if in is not a list, abort
+ 986   {
+ 987     var in-type/ecx: (addr int) <- get in, type
+ 988     compare *in-type, 0/pair
  989     break-if-=
- 990     trace-higher trace
- 991     trace-text trace, "eval", "=> false (type)"
- 992     return 0/false
+ 990     error trace, "car on a non-list"
+ 991     trace-higher trace
+ 992     return
  993   }
- 994   # if types are number, compare number-data
- 995   # TODO: exactly comparing floats is a bad idea
- 996   compare b-type, 1/number
- 997   {
- 998     break-if-!=
- 999     var a-val-addr/eax: (addr float) <- get a, number-data
-1000     var b-val-addr/ecx: (addr float) <- get b, number-data
-1001     var a-val/xmm0: float <- copy *a-val-addr
-1002     compare a-val, *b-val-addr
-1003     {
-1004       break-if-=
-1005       trace-higher trace
-1006       trace-text trace, "eval", "=> false (numbers)"
-1007       return 0/false
-1008     }
-1009     trace-higher trace
-1010     trace-text trace, "eval", "=> true (numbers)"
-1011     return 1/true
-1012   }
-1013   compare b-type, 2/symbol
+ 994   # if in is nil, abort
+ 995   {
+ 996     var in-nil?/eax: boolean <- nil? in
+ 997     compare in-nil?, 0/false
+ 998     break-if-=
+ 999     error trace, "car on nil"
+1000     trace-higher trace
+1001     return
+1002   }
+1003   var in-left/eax: (addr handle cell) <- get in, left
+1004   copy-object in-left, out
+1005   trace-higher trace
+1006   return
+1007 }
+1008 
+1009 fn cdr _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
+1010   trace-text trace, "eval", "cdr"
+1011   trace-lower trace
+1012   var in/eax: (addr cell) <- copy _in
+1013   # if in is not a list, abort
 1014   {
-1015     break-if-!=
-1016     var b-val-ah/eax: (addr handle stream byte) <- get b, text-data
-1017     var _b-val/eax: (addr stream byte) <- lookup *b-val-ah
-1018     var b-val/ecx: (addr stream byte) <- copy _b-val
-1019     var a-val-ah/eax: (addr handle stream byte) <- get a, text-data
-1020     var a-val/eax: (addr stream byte) <- lookup *a-val-ah
-1021     var tmp-array: (handle array byte)
-1022     var tmp-ah/edx: (addr handle array byte) <- address tmp-array
-1023     rewind-stream a-val
-1024     stream-to-array a-val, tmp-ah
-1025     var tmp/eax: (addr array byte) <- lookup *tmp-ah
-1026     var match?/eax: boolean <- stream-data-equal? b-val, tmp
-1027     trace-higher trace
-1028     {
-1029       compare match?, 0/false
-1030       break-if-=
-1031       trace-text trace, "eval", "=> true (symbols)"
-1032     }
-1033     {
-1034       compare match?, 0/false
-1035       break-if-!=
-1036       trace-text trace, "eval", "=> false (symbols)"
-1037     }
-1038     return match?
-1039   }
-1040   # if a is nil, b should be nil
-1041   {
-1042     # (assumes nil? returns 0 or 1)
-1043     var _b-nil?/eax: boolean <- nil? b
-1044     var b-nil?/ecx: boolean <- copy _b-nil?
-1045     var a-nil?/eax: boolean <- nil? a
-1046     # a == nil and b == nil => return true
-1047     {
-1048       compare a-nil?, 0/false
-1049       break-if-=
-1050       compare b-nil?, 0/false
-1051       break-if-=
-1052       trace-higher trace
-1053       trace-text trace, "eval", "=> true (nils)"
-1054       return 1/true
-1055     }
-1056     # a == nil => return false
-1057     {
-1058       compare a-nil?, 0/false
-1059       break-if-=
-1060       trace-higher trace
-1061       trace-text trace, "eval", "=> false (b != nil)"
-1062       return 0/false
-1063     }
-1064     # b == nil => return false
-1065     {
-1066       compare b-nil?, 0/false
-1067       break-if-=
-1068       trace-higher trace
-1069       trace-text trace, "eval", "=> false (a != nil)"
-1070       return 0/false
-1071     }
-1072   }
-1073   # a and b are pairs
-1074   var a-tmp-storage: (handle cell)
-1075   var a-tmp-ah/edx: (addr handle cell) <- address a-tmp-storage
-1076   var b-tmp-storage: (handle cell)
-1077   var b-tmp-ah/ebx: (addr handle cell) <- address b-tmp-storage
-1078   # if cars aren't equal, return false
-1079   car a, a-tmp-ah, trace
-1080   car b, b-tmp-ah, trace
-1081   {
-1082     var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
-1083     var a-tmp/ecx: (addr cell) <- copy _a-tmp
-1084     var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
-1085     var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
-1086     compare result, 0/false
-1087     break-if-!=
-1088     trace-higher trace
-1089     trace-text trace, "eval", "=> false (car mismatch)"
-1090     return 0/false
-1091   }
-1092   # recurse on cdrs
-1093   cdr a, a-tmp-ah, trace
-1094   cdr b, b-tmp-ah, trace
-1095   var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
-1096   var a-tmp/ecx: (addr cell) <- copy _a-tmp
-1097   var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
-1098   var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
-1099   trace-higher trace
-1100   return result
-1101 }
-1102 
-1103 fn fn? _x: (addr cell) -> _/eax: boolean {
-1104   var x/esi: (addr cell) <- copy _x
-1105   var type/eax: (addr int) <- get x, type
-1106   compare *type, 2/symbol
-1107   {
-1108     break-if-=
-1109     return 0/false
-1110   }
-1111   var contents-ah/eax: (addr handle stream byte) <- get x, text-data
-1112   var contents/eax: (addr stream byte) <- lookup *contents-ah
-1113   var result/eax: boolean <- stream-data-equal? contents, "fn"
-1114   return result
-1115 }
-1116 
-1117 fn test-evaluate-is-well-behaved {
-1118   var t-storage: trace
-1119   var t/esi: (addr trace) <- address t-storage
-1120   initialize-trace t, 0x10, 0/visible  # we don't use trace UI
-1121   # env = nil
-1122   var env-storage: (handle cell)
-1123   var env-ah/ecx: (addr handle cell) <- address env-storage
-1124   allocate-pair env-ah
-1125   # eval sym(a), nil env
-1126   var tmp-storage: (handle cell)
-1127   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-1128   new-symbol tmp-ah, "a"
-1129   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
-1130   # doesn't die
-1131   check-trace-contains t, "error", "unbound symbol: a", "F - test-evaluate-is-well-behaved"
-1132 }
-1133 
-1134 fn test-evaluate-number {
-1135   # env = nil
-1136   var env-storage: (handle cell)
-1137   var env-ah/ecx: (addr handle cell) <- address env-storage
-1138   allocate-pair env-ah
-1139   # tmp = 3
-1140   var tmp-storage: (handle cell)
-1141   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-1142   new-integer tmp-ah, 3
-1143   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
-1144   #
-1145   var result/eax: (addr cell) <- lookup *tmp-ah
-1146   var result-type/edx: (addr int) <- get result, type
-1147   check-ints-equal *result-type, 1/number, "F - test-evaluate-number/0"
-1148   var result-value-addr/eax: (addr float) <- get result, number-data
-1149   var result-value/eax: int <- convert *result-value-addr
-1150   check-ints-equal result-value, 3, "F - test-evaluate-number/1"
-1151 }
-1152 
-1153 fn test-evaluate-symbol {
-1154   # tmp = (a . 3)
-1155   var val-storage: (handle cell)
-1156   var val-ah/ecx: (addr handle cell) <- address val-storage
-1157   new-integer val-ah, 3
-1158   var key-storage: (handle cell)
-1159   var key-ah/edx: (addr handle cell) <- address key-storage
-1160   new-symbol key-ah, "a"
-1161   var env-storage: (handle cell)
-1162   var env-ah/ebx: (addr handle cell) <- address env-storage
-1163   new-pair env-ah, *key-ah, *val-ah
-1164   # env = ((a . 3))
-1165   var nil-storage: (handle cell)
-1166   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-1167   allocate-pair nil-ah
-1168   new-pair env-ah, *env-ah, *nil-ah
-1169   # eval sym(a), env
-1170   var tmp-storage: (handle cell)
-1171   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
-1172   new-symbol tmp-ah, "a"
-1173   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
-1174   var result/eax: (addr cell) <- lookup *tmp-ah
-1175   var result-type/edx: (addr int) <- get result, type
-1176   check-ints-equal *result-type, 1/number, "F - test-evaluate-symbol/0"
-1177   var result-value-addr/eax: (addr float) <- get result, number-data
-1178   var result-value/eax: int <- convert *result-value-addr
-1179   check-ints-equal result-value, 3, "F - test-evaluate-symbol/1"
-1180 }
-1181 
-1182 fn test-evaluate-primitive-function {
-1183   var globals-storage: global-table
-1184   var globals/edi: (addr global-table) <- address globals-storage
-1185   initialize-globals globals
-1186   var nil-storage: (handle cell)
-1187   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-1188   allocate-pair nil-ah
-1189   var add-storage: (handle cell)
-1190   var add-ah/ebx: (addr handle cell) <- address add-storage
-1191   new-symbol add-ah, "+"
-1192   # eval +, nil env
-1193   var tmp-storage: (handle cell)
-1194   var tmp-ah/esi: (addr handle cell) <- address tmp-storage
-1195   evaluate add-ah, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
-1196   #
-1197   var result/eax: (addr cell) <- lookup *tmp-ah
-1198   var result-type/edx: (addr int) <- get result, type
-1199   check-ints-equal *result-type, 4/primitive-function, "F - test-evaluate-primitive-function/0"
-1200   var result-value/eax: (addr int) <- get result, index-data
-1201   check-ints-equal *result-value, 1/add, "F - test-evaluate-primitive-function/1"
-1202 }
-1203 
-1204 fn test-evaluate-primitive-function-call {
-1205   var t-storage: trace
-1206   var t/edi: (addr trace) <- address t-storage
-1207   initialize-trace t, 0x100, 0/visible  # we don't use trace UI
-1208   #
-1209   var nil-storage: (handle cell)
-1210   var nil-ah/ecx: (addr handle cell) <- address nil-storage
-1211   allocate-pair nil-ah
-1212   var one-storage: (handle cell)
-1213   var one-ah/edx: (addr handle cell) <- address one-storage
-1214   new-integer one-ah, 1
-1215   var add-storage: (handle cell)
-1216   var add-ah/ebx: (addr handle cell) <- address add-storage
-1217   new-symbol add-ah, "+"
-1218   # input is (+ 1 1)
-1219   var tmp-storage: (handle cell)
-1220   var tmp-ah/esi: (addr handle cell) <- address tmp-storage
-1221   new-pair tmp-ah, *one-ah, *nil-ah
-1222   new-pair tmp-ah, *one-ah, *tmp-ah
-1223   new-pair tmp-ah, *add-ah, *tmp-ah
-1224 #?   dump-cell tmp-ah
-1225   #
-1226   var globals-storage: global-table
-1227   var globals/edx: (addr global-table) <- address globals-storage
-1228   initialize-globals globals
-1229   #
-1230   evaluate tmp-ah, tmp-ah, *nil-ah, globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
-1231 #?   dump-trace t
-1232   #
-1233   var result/eax: (addr cell) <- lookup *tmp-ah
-1234   var result-type/edx: (addr int) <- get result, type
-1235   check-ints-equal *result-type, 1/number, "F - test-evaluate-primitive-function-call/0"
-1236   var result-value-addr/eax: (addr float) <- get result, number-data
-1237   var result-value/eax: int <- convert *result-value-addr
-1238   check-ints-equal result-value, 2, "F - test-evaluate-primitive-function-call/1"
-1239 }
+1015     var in-type/ecx: (addr int) <- get in, type
+1016     compare *in-type, 0/pair
+1017     break-if-=
+1018     error trace, "car on a non-list"
+1019     trace-higher trace
+1020     return
+1021   }
+1022   # if in is nil, abort
+1023   {
+1024     var in-nil?/eax: boolean <- nil? in
+1025     compare in-nil?, 0/false
+1026     break-if-=
+1027     error trace, "car on nil"
+1028     trace-higher trace
+1029     return
+1030   }
+1031   var in-right/eax: (addr handle cell) <- get in, right
+1032   copy-object in-right, out
+1033   trace-higher trace
+1034   return
+1035 }
+1036 
+1037 fn cell-isomorphic? _a: (addr cell), _b: (addr cell), trace: (addr trace) -> _/eax: boolean {
+1038   trace-text trace, "eval", "cell-isomorphic?"
+1039   trace-lower trace
+1040   var a/esi: (addr cell) <- copy _a
+1041   var b/edi: (addr cell) <- copy _b
+1042   # if types don't match, return false
+1043   var a-type-addr/eax: (addr int) <- get a, type
+1044   var b-type-addr/ecx: (addr int) <- get b, type
+1045   var b-type/ecx: int <- copy *b-type-addr
+1046   compare b-type, *a-type-addr
+1047   {
+1048     break-if-=
+1049     trace-higher trace
+1050     trace-text trace, "eval", "=> false (type)"
+1051     return 0/false
+1052   }
+1053   # if types are number, compare number-data
+1054   # TODO: exactly comparing floats is a bad idea
+1055   compare b-type, 1/number
+1056   {
+1057     break-if-!=
+1058     var a-val-addr/eax: (addr float) <- get a, number-data
+1059     var b-val-addr/ecx: (addr float) <- get b, number-data
+1060     var a-val/xmm0: float <- copy *a-val-addr
+1061     compare a-val, *b-val-addr
+1062     {
+1063       break-if-=
+1064       trace-higher trace
+1065       trace-text trace, "eval", "=> false (numbers)"
+1066       return 0/false
+1067     }
+1068     trace-higher trace
+1069     trace-text trace, "eval", "=> true (numbers)"
+1070     return 1/true
+1071   }
+1072   $cell-isomorphic?:text-data: {
+1073     {
+1074       compare b-type, 2/symbol
+1075       break-if-=
+1076       compare b-type, 3/stream
+1077       break-if-=
+1078       break $cell-isomorphic?:text-data
+1079     }
+1080     var b-val-ah/eax: (addr handle stream byte) <- get b, text-data
+1081     var _b-val/eax: (addr stream byte) <- lookup *b-val-ah
+1082     var b-val/ecx: (addr stream byte) <- copy _b-val
+1083     var a-val-ah/eax: (addr handle stream byte) <- get a, text-data
+1084     var a-val/eax: (addr stream byte) <- lookup *a-val-ah
+1085     var tmp-array: (handle array byte)
+1086     var tmp-ah/edx: (addr handle array byte) <- address tmp-array
+1087     rewind-stream a-val
+1088     stream-to-array a-val, tmp-ah
+1089     var tmp/eax: (addr array byte) <- lookup *tmp-ah
+1090     var match?/eax: boolean <- stream-data-equal? b-val, tmp
+1091     trace-higher trace
+1092     {
+1093       compare match?, 0/false
+1094       break-if-=
+1095       trace-text trace, "eval", "=> true (symbols)"
+1096     }
+1097     {
+1098       compare match?, 0/false
+1099       break-if-!=
+1100       trace-text trace, "eval", "=> false (symbols)"
+1101     }
+1102     return match?
+1103   }
+1104   # if objects are primitive functions, compare index-data
+1105   compare b-type, 4/primitive
+1106   {
+1107     break-if-!=
+1108     var a-val-addr/eax: (addr int) <- get a, index-data
+1109     var b-val-addr/ecx: (addr int) <- get b, index-data
+1110     var a-val/eax: int <- copy *a-val-addr
+1111     compare a-val, *b-val-addr
+1112     {
+1113       break-if-=
+1114       trace-higher trace
+1115       trace-text trace, "eval", "=> false (primitives)"
+1116       return 0/false
+1117     }
+1118     trace-higher trace
+1119     trace-text trace, "eval", "=> true (primitives)"
+1120     return 1/true
+1121   }
+1122   # if objects are screens, check if they're the same object
+1123   compare b-type, 5/screen
+1124   {
+1125     break-if-!=
+1126     var a-val-addr/eax: (addr handle screen) <- get a, screen-data
+1127     var b-val-addr/ecx: (addr handle screen) <- get b, screen-data
+1128     var result/eax: boolean <- handle-equal? *a-val-addr, *b-val-addr
+1129     compare result, 0/false
+1130     return result
+1131   }
+1132   # if objects are keyboards, check if they have the same contents
+1133   compare b-type, 6/keyboard
+1134   {
+1135     break-if-!=
+1136     var a-val-addr/ecx: (addr handle gap-buffer) <- get a, keyboard-data
+1137     var _a/eax: (addr gap-buffer) <- lookup *a-val-addr
+1138     var a/ecx: (addr gap-buffer) <- copy _a
+1139     var b-val-addr/eax: (addr handle gap-buffer) <- get b, keyboard-data
+1140     var b/eax: (addr gap-buffer) <- lookup *b-val-addr
+1141     var result/eax: boolean <- gap-buffers-equal? a, b
+1142     return result
+1143   }
+1144   # if a is nil, b should be nil
+1145   {
+1146     # (assumes nil? returns 0 or 1)
+1147     var _b-nil?/eax: boolean <- nil? b
+1148     var b-nil?/ecx: boolean <- copy _b-nil?
+1149     var a-nil?/eax: boolean <- nil? a
+1150     # a == nil and b == nil => return true
+1151     {
+1152       compare a-nil?, 0/false
+1153       break-if-=
+1154       compare b-nil?, 0/false
+1155       break-if-=
+1156       trace-higher trace
+1157       trace-text trace, "eval", "=> true (nils)"
+1158       return 1/true
+1159     }
+1160     # a == nil => return false
+1161     {
+1162       compare a-nil?, 0/false
+1163       break-if-=
+1164       trace-higher trace
+1165       trace-text trace, "eval", "=> false (b != nil)"
+1166       return 0/false
+1167     }
+1168     # b == nil => return false
+1169     {
+1170       compare b-nil?, 0/false
+1171       break-if-=
+1172       trace-higher trace
+1173       trace-text trace, "eval", "=> false (a != nil)"
+1174       return 0/false
+1175     }
+1176   }
+1177   # a and b are pairs
+1178   var a-tmp-storage: (handle cell)
+1179   var a-tmp-ah/edx: (addr handle cell) <- address a-tmp-storage
+1180   var b-tmp-storage: (handle cell)
+1181   var b-tmp-ah/ebx: (addr handle cell) <- address b-tmp-storage
+1182   # if cars aren't equal, return false
+1183   car a, a-tmp-ah, trace
+1184   car b, b-tmp-ah, trace
+1185   {
+1186     var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
+1187     var a-tmp/ecx: (addr cell) <- copy _a-tmp
+1188     var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
+1189     var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
+1190     compare result, 0/false
+1191     break-if-!=
+1192     trace-higher trace
+1193     trace-text trace, "eval", "=> false (car mismatch)"
+1194     return 0/false
+1195   }
+1196   # recurse on cdrs
+1197   cdr a, a-tmp-ah, trace
+1198   cdr b, b-tmp-ah, trace
+1199   var _a-tmp/eax: (addr cell) <- lookup *a-tmp-ah
+1200   var a-tmp/ecx: (addr cell) <- copy _a-tmp
+1201   var b-tmp/eax: (addr cell) <- lookup *b-tmp-ah
+1202   var result/eax: boolean <- cell-isomorphic? a-tmp, b-tmp, trace
+1203   trace-higher trace
+1204   return result
+1205 }
+1206 
+1207 fn fn? _x: (addr cell) -> _/eax: boolean {
+1208   var x/esi: (addr cell) <- copy _x
+1209   var type/eax: (addr int) <- get x, type
+1210   compare *type, 2/symbol
+1211   {
+1212     break-if-=
+1213     return 0/false
+1214   }
+1215   var contents-ah/eax: (addr handle stream byte) <- get x, text-data
+1216   var contents/eax: (addr stream byte) <- lookup *contents-ah
+1217   var result/eax: boolean <- stream-data-equal? contents, "fn"
+1218   return result
+1219 }
+1220 
+1221 fn litfn? _x: (addr cell) -> _/eax: boolean {
+1222   var x/esi: (addr cell) <- copy _x
+1223   var type/eax: (addr int) <- get x, type
+1224   compare *type, 2/symbol
+1225   {
+1226     break-if-=
+1227     return 0/false
+1228   }
+1229   var contents-ah/eax: (addr handle stream byte) <- get x, text-data
+1230   var contents/eax: (addr stream byte) <- lookup *contents-ah
+1231   var result/eax: boolean <- stream-data-equal? contents, "litfn"
+1232   return result
+1233 }
+1234 
+1235 fn litmac? _x: (addr cell) -> _/eax: boolean {
+1236   var x/esi: (addr cell) <- copy _x
+1237   var type/eax: (addr int) <- get x, type
+1238   compare *type, 2/symbol
+1239   {
+1240     break-if-=
+1241     return 0/false
+1242   }
+1243   var contents-ah/eax: (addr handle stream byte) <- get x, text-data
+1244   var contents/eax: (addr stream byte) <- lookup *contents-ah
+1245   var result/eax: boolean <- stream-data-equal? contents, "litmac"
+1246   return result
+1247 }
+1248 
+1249 fn test-evaluate-is-well-behaved {
+1250   var t-storage: trace
+1251   var t/esi: (addr trace) <- address t-storage
+1252   initialize-trace t, 0x10, 0/visible  # we don't use trace UI
+1253   # env = nil
+1254   var env-storage: (handle cell)
+1255   var env-ah/ecx: (addr handle cell) <- address env-storage
+1256   allocate-pair env-ah
+1257   # eval sym(a), nil env
+1258   var tmp-storage: (handle cell)
+1259   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
+1260   new-symbol tmp-ah, "a"
+1261   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
+1262   # doesn't die
+1263   check-trace-contains t, "error", "unbound symbol: a", "F - test-evaluate-is-well-behaved"
+1264 }
+1265 
+1266 fn test-evaluate-number {
+1267   # env = nil
+1268   var env-storage: (handle cell)
+1269   var env-ah/ecx: (addr handle cell) <- address env-storage
+1270   allocate-pair env-ah
+1271   # tmp = 3
+1272   var tmp-storage: (handle cell)
+1273   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
+1274   new-integer tmp-ah, 3
+1275   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1276   #
+1277   var result/eax: (addr cell) <- lookup *tmp-ah
+1278   var result-type/edx: (addr int) <- get result, type
+1279   check-ints-equal *result-type, 1/number, "F - test-evaluate-number/0"
+1280   var result-value-addr/eax: (addr float) <- get result, number-data
+1281   var result-value/eax: int <- convert *result-value-addr
+1282   check-ints-equal result-value, 3, "F - test-evaluate-number/1"
+1283 }
+1284 
+1285 fn test-evaluate-symbol {
+1286   # tmp = (a . 3)
+1287   var val-storage: (handle cell)
+1288   var val-ah/ecx: (addr handle cell) <- address val-storage
+1289   new-integer val-ah, 3
+1290   var key-storage: (handle cell)
+1291   var key-ah/edx: (addr handle cell) <- address key-storage
+1292   new-symbol key-ah, "a"
+1293   var env-storage: (handle cell)
+1294   var env-ah/ebx: (addr handle cell) <- address env-storage
+1295   new-pair env-ah, *key-ah, *val-ah
+1296   # env = ((a . 3))
+1297   var nil-storage: (handle cell)
+1298   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+1299   allocate-pair nil-ah
+1300   new-pair env-ah, *env-ah, *nil-ah
+1301   # eval sym(a), env
+1302   var tmp-storage: (handle cell)
+1303   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
+1304   new-symbol tmp-ah, "a"
+1305   evaluate tmp-ah, tmp-ah, *env-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1306   var result/eax: (addr cell) <- lookup *tmp-ah
+1307   var result-type/edx: (addr int) <- get result, type
+1308   check-ints-equal *result-type, 1/number, "F - test-evaluate-symbol/0"
+1309   var result-value-addr/eax: (addr float) <- get result, number-data
+1310   var result-value/eax: int <- convert *result-value-addr
+1311   check-ints-equal result-value, 3, "F - test-evaluate-symbol/1"
+1312 }
+1313 
+1314 fn test-evaluate-quote {
+1315   # env = nil
+1316   var nil-storage: (handle cell)
+1317   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+1318   allocate-pair nil-ah
+1319   # eval `a, env
+1320   var tmp-storage: (handle cell)
+1321   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
+1322   new-symbol tmp-ah, "'"
+1323   var tmp2-storage: (handle cell)
+1324   var tmp2-ah/ebx: (addr handle cell) <- address tmp2-storage
+1325   new-symbol tmp2-ah, "a"
+1326   new-pair tmp-ah, *tmp-ah, *tmp2-ah
+1327   evaluate tmp-ah, tmp-ah, *nil-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1328   var result/eax: (addr cell) <- lookup *tmp-ah
+1329   var result-type/edx: (addr int) <- get result, type
+1330   check-ints-equal *result-type, 2/symbol, "F - test-evaluate-quote/0"
+1331   var sym?/eax: boolean <- symbol-equal? result, "a"
+1332   check sym?, "F - test-evaluate-quote/1"
+1333 }
+1334 
+1335 fn test-evaluate-primitive-function {
+1336   var globals-storage: global-table
+1337   var globals/edi: (addr global-table) <- address globals-storage
+1338   initialize-globals globals
+1339   var nil-storage: (handle cell)
+1340   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+1341   allocate-pair nil-ah
+1342   var add-storage: (handle cell)
+1343   var add-ah/ebx: (addr handle cell) <- address add-storage
+1344   new-symbol add-ah, "+"
+1345   # eval +, nil env
+1346   var tmp-storage: (handle cell)
+1347   var tmp-ah/esi: (addr handle cell) <- address tmp-storage
+1348   evaluate add-ah, tmp-ah, *nil-ah, globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1349   #
+1350   var result/eax: (addr cell) <- lookup *tmp-ah
+1351   var result-type/edx: (addr int) <- get result, type
+1352   check-ints-equal *result-type, 4/primitive-function, "F - test-evaluate-primitive-function/0"
+1353   var result-value/eax: (addr int) <- get result, index-data
+1354   check-ints-equal *result-value, 1/add, "F - test-evaluate-primitive-function/1"
+1355 }
+1356 
+1357 fn test-evaluate-primitive-function-call {
+1358   var t-storage: trace
+1359   var t/edi: (addr trace) <- address t-storage
+1360   initialize-trace t, 0x100, 0/visible  # we don't use trace UI
+1361   #
+1362   var nil-storage: (handle cell)
+1363   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+1364   allocate-pair nil-ah
+1365   var one-storage: (handle cell)
+1366   var one-ah/edx: (addr handle cell) <- address one-storage
+1367   new-integer one-ah, 1
+1368   var add-storage: (handle cell)
+1369   var add-ah/ebx: (addr handle cell) <- address add-storage
+1370   new-symbol add-ah, "+"
+1371   # input is (+ 1 1)
+1372   var tmp-storage: (handle cell)
+1373   var tmp-ah/esi: (addr handle cell) <- address tmp-storage
+1374   new-pair tmp-ah, *one-ah, *nil-ah
+1375   new-pair tmp-ah, *one-ah, *tmp-ah
+1376   new-pair tmp-ah, *add-ah, *tmp-ah
+1377 #?   dump-cell tmp-ah
+1378   #
+1379   var globals-storage: global-table
+1380   var globals/edx: (addr global-table) <- address globals-storage
+1381   initialize-globals globals
+1382   #
+1383   evaluate tmp-ah, tmp-ah, *nil-ah, globals, t, 0/no-screen, 0/no-keyboard, 0/call-number
+1384 #?   dump-trace t
+1385   #
+1386   var result/eax: (addr cell) <- lookup *tmp-ah
+1387   var result-type/edx: (addr int) <- get result, type
+1388   check-ints-equal *result-type, 1/number, "F - test-evaluate-primitive-function-call/0"
+1389   var result-value-addr/eax: (addr float) <- get result, number-data
+1390   var result-value/eax: int <- convert *result-value-addr
+1391   check-ints-equal result-value, 2, "F - test-evaluate-primitive-function-call/1"
+1392 }
+1393 
+1394 fn test-evaluate-backquote {
+1395   # env = nil
+1396   var nil-storage: (handle cell)
+1397   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+1398   allocate-pair nil-ah
+1399   # eval `a, env
+1400   var tmp-storage: (handle cell)
+1401   var tmp-ah/edx: (addr handle cell) <- address tmp-storage
+1402   new-symbol tmp-ah, "`"
+1403   var tmp2-storage: (handle cell)
+1404   var tmp2-ah/ebx: (addr handle cell) <- address tmp2-storage
+1405   new-symbol tmp2-ah, "a"
+1406   new-pair tmp-ah, *tmp-ah, *tmp2-ah
+1407   clear-object tmp2-ah
+1408   evaluate tmp-ah, tmp2-ah, *nil-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1409   var result/eax: (addr cell) <- lookup *tmp2-ah
+1410   var result-type/edx: (addr int) <- get result, type
+1411   check-ints-equal *result-type, 2/symbol, "F - test-evaluate-backquote/0"
+1412   var sym?/eax: boolean <- symbol-equal? result, "a"
+1413   check sym?, "F - test-evaluate-backquote/1"
+1414 }
+1415 
+1416 fn evaluate-backquote _in-ah: (addr handle cell), _out-ah: (addr handle cell), env-h: (handle cell), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell), call-number: int {
+1417   # stack overflow?   # disable when enabling Really-debug-print
+1418 #?   dump-cell-from-cursor-over-full-screen _in-ah
+1419   check-stack
+1420   {
+1421     var screen-cell/eax: (addr handle cell) <- copy screen-cell
+1422     compare screen-cell, 0
+1423     break-if-=
+1424     var screen-cell-addr/eax: (addr cell) <- lookup *screen-cell
+1425     compare screen-cell-addr, 0
+1426     break-if-=
+1427     # if screen-cell exists, we're probably not in a test
+1428     show-stack-state
+1429   }
+1430   # errors? skip
+1431   {
+1432     compare trace, 0
+1433     break-if-=
+1434     var error?/eax: boolean <- has-errors? trace
+1435     compare error?, 0/false
+1436     break-if-=
+1437     return
+1438   }
+1439   var in-ah/esi: (addr handle cell) <- copy _in-ah
+1440   var in/eax: (addr cell) <- lookup *in-ah
+1441   {
+1442     var nil?/eax: boolean <- nil? in
+1443     compare nil?, 0/false
+1444     break-if-=
+1445     # nil is a literal
+1446     trace-text trace, "eval", "backquote nil"
+1447     copy-object _in-ah, _out-ah
+1448     trace-higher trace
+1449     return
+1450   }
+1451   var in-type/ecx: (addr int) <- get in, type
+1452   compare *in-type, 0/pair
+1453   {
+1454     break-if-=
+1455     # copy non-pairs directly
+1456     # TODO: streams might need to be copied
+1457     trace-text trace, "eval", "backquote atom"
+1458     copy-object _in-ah, _out-ah
+1459     trace-higher trace
+1460     return
+1461   }
+1462   # 'in' is a pair
+1463   debug-print "()", 4/fg, 0/bg
+1464   var in-ah/esi: (addr handle cell) <- copy _in-ah
+1465   var _in/eax: (addr cell) <- lookup *in-ah
+1466   var in/ebx: (addr cell) <- copy _in
+1467   var in-left-ah/ecx: (addr handle cell) <- get in, left
+1468   debug-print "10", 4/fg, 0/bg
+1469   # check for unquote
+1470   $macroexpand-iter:unquote: {
+1471     var in-left/eax: (addr cell) <- lookup *in-left-ah
+1472     var unquote?/eax: boolean <- symbol-equal? in-left, ","
+1473     compare unquote?, 0/false
+1474     break-if-=
+1475     trace-text trace, "eval", "unquote"
+1476     var rest-ah/eax: (addr handle cell) <- get in, right
+1477     increment call-number
+1478     debug-print ",", 3/fg, 0/bg
+1479     evaluate rest-ah, _out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+1480     debug-print ",)", 3/fg, 0/bg
+1481     return
+1482   }
+1483   # check for unquote-splice in in-left
+1484   debug-print "11", 4/fg, 0/bg
+1485   var out-ah/edi: (addr handle cell) <- copy _out-ah
+1486   $macroexpand-iter:unquote-splice: {
+1487 #?     dump-cell-from-cursor-over-full-screen in-left-ah
+1488     var in-left/eax: (addr cell) <- lookup *in-left-ah
+1489     {
+1490       debug-print "12", 4/fg, 0/bg
+1491       {
+1492         var in-left-is-nil?/eax: boolean <- nil? in-left
+1493         compare in-left-is-nil?, 0/false
+1494       }
+1495       break-if-!= $macroexpand-iter:unquote-splice
+1496       var in-left-type/ecx: (addr int) <- get in-left, type
+1497       debug-print "13", 4/fg, 0/bg
+1498       compare *in-left-type, 0/pair
+1499       break-if-!= $macroexpand-iter:unquote-splice
+1500       var in-left-left-ah/eax: (addr handle cell) <- get in-left, left
+1501       debug-print "14", 4/fg, 0/bg
+1502       var in-left-left/eax: (addr cell) <- lookup *in-left-left-ah
+1503       debug-print "15", 4/fg, 0/bg
+1504       var in-left-left-type/ecx: (addr int) <- get in-left-left, type
+1505       var left-is-unquote-splice?/eax: boolean <- symbol-equal? in-left-left, ",@"
+1506       debug-print "16", 4/fg, 0/bg
+1507       compare left-is-unquote-splice?, 0/false
+1508     }
+1509     break-if-=
+1510     debug-print "17", 4/fg, 0/bg
+1511     trace-text trace, "eval", "unquote-splice"
+1512     var in-unquote-payload-ah/eax: (addr handle cell) <- get in-left, right
+1513     increment call-number
+1514     evaluate in-unquote-payload-ah, out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+1515     # while (*out-ah != null) out-ah = cdr(out-ah)
+1516     {
+1517       var out/eax: (addr cell) <- lookup *out-ah
+1518       {
+1519         var done?/eax: boolean <- nil? out
+1520         compare done?, 0/false
+1521       }
+1522       break-if-!=
+1523       out-ah <- get out, right
+1524       loop
+1525     }
+1526     # append result of in-right
+1527     var in-right-ah/ecx: (addr handle cell) <- get in, right
+1528     evaluate-backquote in-right-ah, out-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+1529     return
+1530   }
+1531   debug-print "19", 4/fg, 0/bg
+1532   # otherwise continue copying
+1533   trace-text trace, "eval", "backquote: copy"
+1534   var out-ah/edi: (addr handle cell) <- copy _out-ah
+1535   allocate-pair out-ah
+1536   debug-print "20", 7/fg, 0/bg
+1537 #?   dump-cell-from-cursor-over-full-screen out-ah
+1538   var out/eax: (addr cell) <- lookup *out-ah
+1539   var out-left-ah/edx: (addr handle cell) <- get out, left
+1540   debug-print "`(l", 3/fg, 0/bg
+1541   evaluate-backquote in-left-ah, out-left-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+1542   debug-print "`r)", 3/fg, 0/bg
+1543   var in-right-ah/ecx: (addr handle cell) <- get in, right
+1544   var out-right-ah/edx: (addr handle cell) <- get out, right
+1545   debug-print "`r(", 3/fg, 0/bg
+1546   evaluate-backquote in-right-ah, out-right-ah, env-h, globals, trace, screen-cell, keyboard-cell, call-number
+1547   debug-print "`r)", 3/fg, 0/bg
+1548 }
+1549 
+1550 fn test-evaluate-backquote-list {
+1551   var nil-storage: (handle cell)
+1552   var nil-ah/ecx: (addr handle cell) <- address nil-storage
+1553   allocate-pair nil-ah
+1554   var backquote-storage: (handle cell)
+1555   var backquote-ah/edx: (addr handle cell) <- address backquote-storage
+1556   new-symbol backquote-ah, "`"
+1557   # input is `(a b)
+1558   var a-storage: (handle cell)
+1559   var a-ah/ebx: (addr handle cell) <- address a-storage
+1560   new-symbol a-ah, "a"
+1561   var b-storage: (handle cell)
+1562   var b-ah/esi: (addr handle cell) <- address b-storage
+1563   new-symbol b-ah, "b"
+1564   var tmp-storage: (handle cell)
+1565   var tmp-ah/eax: (addr handle cell) <- address tmp-storage
+1566   new-pair tmp-ah, *b-ah, *nil-ah
+1567   new-pair tmp-ah, *a-ah, *tmp-ah
+1568   new-pair tmp-ah, *backquote-ah, *tmp-ah
+1569   #
+1570   evaluate tmp-ah, tmp-ah, *nil-ah, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1571   # result is (a b)
+1572   var result/eax: (addr cell) <- lookup *tmp-ah
+1573   {
+1574     var result-type/eax: (addr int) <- get result, type
+1575     check-ints-equal *result-type, 0/pair, "F - test-evaluate-backquote-list/0"
+1576   }
+1577   {
+1578     var a1-ah/eax: (addr handle cell) <- get result, left
+1579     var a1/eax: (addr cell) <- lookup *a1-ah
+1580     var check1/eax: boolean <- symbol-equal? a1, "a"
+1581     check check1, "F - test-evaluate-backquote-list/1"
+1582   }
+1583   var rest-ah/eax: (addr handle cell) <- get result, right
+1584   var rest/eax: (addr cell) <- lookup *rest-ah
+1585   {
+1586     var a2-ah/eax: (addr handle cell) <- get rest, left
+1587     var a2/eax: (addr cell) <- lookup *a2-ah
+1588     var check2/eax: boolean <- symbol-equal? a2, "b"
+1589     check check2, "F - test-evaluate-backquote-list/2"
+1590   }
+1591   var rest-ah/eax: (addr handle cell) <- get rest, right
+1592   var rest/eax: (addr cell) <- lookup *rest-ah
+1593   var check3/eax: boolean <- nil? rest
+1594   check check3, "F - test-evaluate-backquote-list/3"
+1595 }
+1596 
+1597 fn test-evaluate-backquote-list-with-unquote {
+1598   var nil-h: (handle cell)
+1599   var nil-ah/eax: (addr handle cell) <- address nil-h
+1600   allocate-pair nil-ah
+1601   var backquote-h: (handle cell)
+1602   var backquote-ah/eax: (addr handle cell) <- address backquote-h
+1603   new-symbol backquote-ah, "`"
+1604   var unquote-h: (handle cell)
+1605   var unquote-ah/eax: (addr handle cell) <- address unquote-h
+1606   new-symbol unquote-ah, ","
+1607   var a-h: (handle cell)
+1608   var a-ah/eax: (addr handle cell) <- address a-h
+1609   new-symbol a-ah, "a"
+1610   var b-h: (handle cell)
+1611   var b-ah/eax: (addr handle cell) <- address b-h
+1612   new-symbol b-ah, "b"
+1613   # env = ((b . 3))
+1614   var val-h: (handle cell)
+1615   var val-ah/eax: (addr handle cell) <- address val-h
+1616   new-integer val-ah, 3
+1617   var env-h: (handle cell)
+1618   var env-ah/eax: (addr handle cell) <- address env-h
+1619   new-pair env-ah, b-h, val-h
+1620   new-pair env-ah, env-h, nil-h
+1621   # input is `(a ,b)
+1622   var tmp-h: (handle cell)
+1623   var tmp-ah/eax: (addr handle cell) <- address tmp-h
+1624   # tmp = cons(unquote, b)
+1625   new-pair tmp-ah, unquote-h, b-h
+1626   # tmp = cons(tmp, nil)
+1627   new-pair tmp-ah, tmp-h, nil-h
+1628   # tmp = cons(a, tmp)
+1629   new-pair tmp-ah, a-h, tmp-h
+1630   # tmp = cons(backquote, tmp)
+1631   new-pair tmp-ah, backquote-h, tmp-h
+1632   #
+1633   evaluate tmp-ah, tmp-ah, env-h, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1634   # result is (a 3)
+1635   var result/eax: (addr cell) <- lookup *tmp-ah
+1636   {
+1637     var result-type/eax: (addr int) <- get result, type
+1638     check-ints-equal *result-type, 0/pair, "F - test-evaluate-backquote-list-with-unquote/0"
+1639   }
+1640   {
+1641     var a1-ah/eax: (addr handle cell) <- get result, left
+1642     var a1/eax: (addr cell) <- lookup *a1-ah
+1643     var check1/eax: boolean <- symbol-equal? a1, "a"
+1644     check check1, "F - test-evaluate-backquote-list-with-unquote/1"
+1645   }
+1646   var rest-ah/eax: (addr handle cell) <- get result, right
+1647   var rest/eax: (addr cell) <- lookup *rest-ah
+1648   {
+1649     var a2-ah/eax: (addr handle cell) <- get rest, left
+1650     var a2/eax: (addr cell) <- lookup *a2-ah
+1651     var a2-value-addr/eax: (addr float) <- get a2, number-data
+1652     var a2-value/eax: int <- convert *a2-value-addr
+1653     check-ints-equal a2-value, 3, "F - test-evaluate-backquote-list-with-unquote/2"
+1654   }
+1655   var rest-ah/eax: (addr handle cell) <- get rest, right
+1656   var rest/eax: (addr cell) <- lookup *rest-ah
+1657   var check3/eax: boolean <- nil? rest
+1658   check check3, "F - test-evaluate-backquote-list-with-unquote/3"
+1659 }
+1660 
+1661 fn test-evaluate-backquote-list-with-unquote-splice {
+1662   var nil-h: (handle cell)
+1663   var nil-ah/eax: (addr handle cell) <- address nil-h
+1664   allocate-pair nil-ah
+1665   var backquote-h: (handle cell)
+1666   var backquote-ah/eax: (addr handle cell) <- address backquote-h
+1667   new-symbol backquote-ah, "`"
+1668   var unquote-splice-h: (handle cell)
+1669   var unquote-splice-ah/eax: (addr handle cell) <- address unquote-splice-h
+1670   new-symbol unquote-splice-ah, ",@"
+1671   var a-h: (handle cell)
+1672   var a-ah/eax: (addr handle cell) <- address a-h
+1673   new-symbol a-ah, "a"
+1674   var b-h: (handle cell)
+1675   var b-ah/eax: (addr handle cell) <- address b-h
+1676   new-symbol b-ah, "b"
+1677   # env = ((b . (a 3)))
+1678   var val-h: (handle cell)
+1679   var val-ah/eax: (addr handle cell) <- address val-h
+1680   new-integer val-ah, 3
+1681   new-pair val-ah, val-h, nil-h
+1682   new-pair val-ah, a-h, val-h
+1683   var env-h: (handle cell)
+1684   var env-ah/eax: (addr handle cell) <- address env-h
+1685   new-pair env-ah, b-h, val-h
+1686   new-pair env-ah, env-h, nil-h
+1687   # input is `(a ,@b b)
+1688   var tmp-h: (handle cell)
+1689   var tmp-ah/eax: (addr handle cell) <- address tmp-h
+1690   # tmp = cons(b, nil)
+1691   new-pair tmp-ah, b-h, nil-h
+1692   # tmp2 = cons(unquote-splice, b)
+1693   var tmp2-h: (handle cell)
+1694   var tmp2-ah/ecx: (addr handle cell) <- address tmp2-h
+1695   new-pair tmp2-ah, unquote-splice-h, b-h
+1696   # tmp = cons(tmp2, tmp)
+1697   new-pair tmp-ah, tmp2-h, tmp-h
+1698   # tmp = cons(a, tmp)
+1699   new-pair tmp-ah, a-h, tmp-h
+1700   # tmp = cons(backquote, tmp)
+1701   new-pair tmp-ah, backquote-h, tmp-h
+1702 #?   dump-cell-from-cursor-over-full-screen tmp-ah
+1703   #
+1704   evaluate tmp-ah, tmp-ah, env-h, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard, 0/call-number
+1705   # result is (a a 3 b)
+1706 #?   dump-cell-from-cursor-over-full-screen tmp-ah
+1707   var result/eax: (addr cell) <- lookup *tmp-ah
+1708   {
+1709     var result-type/eax: (addr int) <- get result, type
+1710     check-ints-equal *result-type, 0/pair, "F - test-evaluate-backquote-list-with-unquote-splice/0"
+1711   }
+1712   {
+1713     var a1-ah/eax: (addr handle cell) <- get result, left
+1714     var a1/eax: (addr cell) <- lookup *a1-ah
+1715     var check1/eax: boolean <- symbol-equal? a1, "a"
+1716     check check1, "F - test-evaluate-backquote-list-with-unquote-splice/1"
+1717   }
+1718   var rest-ah/eax: (addr handle cell) <- get result, right
+1719   var rest/eax: (addr cell) <- lookup *rest-ah
+1720   {
+1721     var a2-ah/eax: (addr handle cell) <- get rest, left
+1722     var a2/eax: (addr cell) <- lookup *a2-ah
+1723     var check2/eax: boolean <- symbol-equal? a2, "a"
+1724     check check2, "F - test-evaluate-backquote-list-with-unquote-splice/2"
+1725   }
+1726   var rest-ah/eax: (addr handle cell) <- get rest, right
+1727   var rest/eax: (addr cell) <- lookup *rest-ah
+1728   {
+1729     var a3-ah/eax: (addr handle cell) <- get rest, left
+1730     var a3/eax: (addr cell) <- lookup *a3-ah
+1731     var a3-value-addr/eax: (addr float) <- get a3, number-data
+1732     var a3-value/eax: int <- convert *a3-value-addr
+1733     check-ints-equal a3-value, 3, "F - test-evaluate-backquote-list-with-unquote-splice/3"
+1734   }
+1735   var rest-ah/eax: (addr handle cell) <- get rest, right
+1736   var rest/eax: (addr cell) <- lookup *rest-ah
+1737   {
+1738     var a4-ah/eax: (addr handle cell) <- get rest, left
+1739     var a4/eax: (addr cell) <- lookup *a4-ah
+1740     var check4/eax: boolean <- symbol-equal? a4, "b"
+1741     check check4, "F - test-evaluate-backquote-list-with-unquote-splice/4"
+1742   }
+1743   var rest-ah/eax: (addr handle cell) <- get rest, right
+1744   var rest/eax: (addr cell) <- lookup *rest-ah
+1745   var check5/eax: boolean <- nil? rest
+1746   check check5, "F - test-evaluate-backquote-list-with-unquote-splice/5"
+1747 }
 
diff --git a/html/shell/gap-buffer.mu.html b/html/shell/gap-buffer.mu.html index 9fae1381..29e58b75 100644 --- a/html/shell/gap-buffer.mu.html +++ b/html/shell/gap-buffer.mu.html @@ -87,15 +87,15 @@ if ('onhashchange' in window) { 28 var gap/esi: (addr gap-buffer) <- copy _gap 29 var left/eax: (addr grapheme-stack) <- get gap, left 30 var left-data-ah/eax: (addr handle array grapheme) <- get left, data - 31 var left-data/eax: (addr array grapheme) <- lookup *left-data-ah + 31 var left-data/eax: (addr array grapheme) <- lookup *left-data-ah 32 var result/eax: int <- length left-data 33 return result 34 } 35 36 # just for tests 37 fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) { - 38 initialize-gap-buffer self, 0x10/capacity - 39 var stream-storage: (stream byte 0x10/capacity) + 38 initialize-gap-buffer self, 0x40/capacity + 39 var stream-storage: (stream byte 0x40/capacity) 40 var stream/ecx: (addr stream byte) <- address stream-storage 41 write stream, s 42 { @@ -144,7 +144,7 @@ if ('onhashchange' in window) { 85 fn emit-stack-from-bottom _self: (addr grapheme-stack), out: (addr stream byte) { 86 var self/esi: (addr grapheme-stack) <- copy _self 87 var data-ah/edi: (addr handle array grapheme) <- get self, data - 88 var _data/eax: (addr array grapheme) <- lookup *data-ah + 88 var _data/eax: (addr array grapheme) <- lookup *data-ah 89 var data/edi: (addr array grapheme) <- copy _data 90 var top-addr/ecx: (addr int) <- get self, top 91 var i/eax: int <- copy 0 @@ -162,7 +162,7 @@ if ('onhashchange' in window) { 103 fn emit-stack-from-top _self: (addr grapheme-stack), out: (addr stream byte) { 104 var self/esi: (addr grapheme-stack) <- copy _self 105 var data-ah/edi: (addr handle array grapheme) <- get self, data - 106 var _data/eax: (addr array grapheme) <- lookup *data-ah + 106 var _data/eax: (addr array grapheme) <- lookup *data-ah 107 var data/edi: (addr array grapheme) <- copy _data 108 var top-addr/ecx: (addr int) <- get self, top 109 var i/eax: int <- copy *top-addr @@ -319,7 +319,7 @@ if ('onhashchange' in window) { 260 { 261 break-if-<= 262 var data-ah/eax: (addr handle array grapheme) <- get left, data - 263 var data/eax: (addr array grapheme) <- lookup *data-ah + 263 var data/eax: (addr array grapheme) <- lookup *data-ah 264 var result-addr/eax: (addr grapheme) <- index data, 0 265 return *result-addr 266 } @@ -330,7 +330,7 @@ if ('onhashchange' in window) { 271 { 272 break-if-<= 273 var data-ah/eax: (addr handle array grapheme) <- get right, data - 274 var data/eax: (addr array grapheme) <- lookup *data-ah + 274 var data/eax: (addr array grapheme) <- lookup *data-ah 275 var top/ecx: int <- copy *top-addr 276 top <- decrement 277 var result-addr/eax: (addr grapheme) <- index data, top @@ -491,7 +491,7 @@ if ('onhashchange' in window) { 432 { 433 break-if->= 434 var data-ah/eax: (addr handle array grapheme) <- get left, data - 435 var data/eax: (addr array grapheme) <- lookup *data-ah + 435 var data/eax: (addr array grapheme) <- lookup *data-ah 436 var result/eax: (addr grapheme) <- index data, n 437 return *result 438 } @@ -504,7 +504,7 @@ if ('onhashchange' in window) { 445 { 446 break-if->= 447 var data-ah/eax: (addr handle array grapheme) <- get right, data - 448 var data/eax: (addr array grapheme) <- lookup *data-ah + 448 var data/eax: (addr array grapheme) <- lookup *data-ah 449 # idx = right->len - n - 1 450 var idx/ebx: int <- copy n 451 idx <- subtract *right-len-a @@ -514,7 +514,7 @@ if ('onhashchange' in window) { 455 return *result 456 } 457 # error - 458 abort "gap-index: out of bounds" + 458 abort "gap-index: out of bounds" 459 return 0 460 } 461 @@ -577,10 +577,10 @@ if ('onhashchange' in window) { 518 fn copy-gap-buffer _src-ah: (addr handle gap-buffer), _dest-ah: (addr handle gap-buffer) { 519 # obtain src-a, dest-a 520 var src-ah/eax: (addr handle gap-buffer) <- copy _src-ah - 521 var _src-a/eax: (addr gap-buffer) <- lookup *src-ah + 521 var _src-a/eax: (addr gap-buffer) <- lookup *src-ah 522 var src-a/esi: (addr gap-buffer) <- copy _src-a 523 var dest-ah/eax: (addr handle gap-buffer) <- copy _dest-ah - 524 var _dest-a/eax: (addr gap-buffer) <- lookup *dest-ah + 524 var _dest-a/eax: (addr gap-buffer) <- lookup *dest-ah 525 var dest-a/edi: (addr gap-buffer) <- copy _dest-a 526 # copy left grapheme-stack 527 var src/ecx: (addr grapheme-stack) <- get src-a, left @@ -758,7 +758,7 @@ if ('onhashchange' in window) { 699 } 700 top-index <- decrement 701 var data-ah/eax: (addr handle array grapheme) <- get stack, data - 702 var data/eax: (addr array grapheme) <- lookup *data-ah + 702 var data/eax: (addr array grapheme) <- lookup *data-ah 703 var g/eax: (addr grapheme) <- index data, top-index 704 compare *g, 0x29/close-paren 705 { @@ -770,7 +770,7 @@ if ('onhashchange' in window) { 711 # cursor is not at end; return (char at cursor == ')') 712 top-index <- decrement 713 var data-ah/eax: (addr handle array grapheme) <- get stack, data - 714 var data/eax: (addr array grapheme) <- lookup *data-ah + 714 var data/eax: (addr array grapheme) <- lookup *data-ah 715 var g/eax: (addr grapheme) <- index data, top-index 716 compare *g, 0x29/close-paren 717 { @@ -847,7 +847,7 @@ if ('onhashchange' in window) { 788 { 789 break-if->= 790 var left-data-ah/eax: (addr handle array grapheme) <- get left, data - 791 var left-data/eax: (addr array grapheme) <- lookup *left-data-ah + 791 var left-data/eax: (addr array grapheme) <- lookup *left-data-ah 792 var left-read-index/ecx: int <- copy *left-read-index-a 793 var result/eax: (addr grapheme) <- index left-data, left-read-index 794 return *result @@ -862,7 +862,7 @@ if ('onhashchange' in window) { 803 break-if->= 804 # read the right from reverse 805 var right-data-ah/eax: (addr handle array grapheme) <- get right, data - 806 var right-data/eax: (addr array grapheme) <- lookup *right-data-ah + 806 var right-data/eax: (addr array grapheme) <- lookup *right-data-ah 807 var right-read-index/ebx: int <- copy right-size 808 right-read-index <- subtract *right-read-index-a 809 right-read-index <- subtract 1 @@ -883,7 +883,7 @@ if ('onhashchange' in window) { 824 { 825 break-if->= 826 var left-data-ah/eax: (addr handle array grapheme) <- get left, data - 827 var left-data/eax: (addr array grapheme) <- lookup *left-data-ah + 827 var left-data/eax: (addr array grapheme) <- lookup *left-data-ah 828 var left-read-index/ecx: int <- copy *left-read-index-a 829 var result/eax: (addr grapheme) <- index left-data, left-read-index 830 increment *left-read-index-a @@ -899,7 +899,7 @@ if ('onhashchange' in window) { 840 break-if->= 841 # read the right from reverse 842 var right-data-ah/eax: (addr handle array grapheme) <- get right, data - 843 var right-data/eax: (addr array grapheme) <- lookup *right-data-ah + 843 var right-data/eax: (addr array grapheme) <- lookup *right-data-ah 844 var right-read-index/ebx: int <- copy right-size 845 right-read-index <- subtract *right-read-index-a 846 right-read-index <- subtract 1 diff --git a/html/shell/global.mu.html b/html/shell/global.mu.html index 6ddc349d..db15c53f 100644 --- a/html/shell/global.mu.html +++ b/html/shell/global.mu.html @@ -70,1955 +70,2073 @@ if ('onhashchange' in window) { 11 12 fn initialize-globals _self: (addr global-table) { 13 var self/esi: (addr global-table) <- copy _self - 14 var data-ah/eax: (addr handle array global) <- get self, data - 15 populate data-ah, 0x40 - 16 # for numbers - 17 append-primitive self, "+" - 18 append-primitive self, "-" - 19 append-primitive self, "*" - 20 append-primitive self, "/" - 21 append-primitive self, "sqrt" - 22 append-primitive self, "abs" - 23 append-primitive self, "sgn" - 24 append-primitive self, "<" - 25 append-primitive self, ">" - 26 append-primitive self, "<=" - 27 append-primitive self, ">=" - 28 # generic - 29 append-primitive self, "=" - 30 append-primitive self, "no" - 31 append-primitive self, "not" - 32 # for pairs - 33 append-primitive self, "car" - 34 append-primitive self, "cdr" - 35 append-primitive self, "cons" - 36 # for screens - 37 append-primitive self, "print" - 38 append-primitive self, "clear" - 39 append-primitive self, "lines" - 40 append-primitive self, "columns" - 41 append-primitive self, "up" - 42 append-primitive self, "down" - 43 append-primitive self, "left" - 44 append-primitive self, "right" - 45 append-primitive self, "cr" - 46 append-primitive self, "pixel" - 47 append-primitive self, "width" - 48 append-primitive self, "height" - 49 # for keyboards - 50 append-primitive self, "key" - 51 # for streams - 52 append-primitive self, "stream" - 53 append-primitive self, "write" - 54 # misc - 55 append-primitive self, "abort" - 56 # keep sync'd with render-primitives - 57 } - 58 - 59 fn load-globals in: (addr handle cell), self: (addr global-table) { - 60 var remaining-ah/esi: (addr handle cell) <- copy in - 61 { - 62 var _remaining/eax: (addr cell) <- lookup *remaining-ah - 63 var remaining/ecx: (addr cell) <- copy _remaining - 64 var done?/eax: boolean <- nil? remaining - 65 compare done?, 0/false - 66 break-if-!= - 67 var curr-ah/eax: (addr handle cell) <- get remaining, left - 68 var curr/eax: (addr cell) <- lookup *curr-ah - 69 remaining-ah <- get remaining, right - 70 var value-ah/eax: (addr handle cell) <- get curr, right - 71 var value/eax: (addr cell) <- lookup *value-ah - 72 var value-data-ah/eax: (addr handle stream byte) <- get value, text-data - 73 var _value-data/eax: (addr stream byte) <- lookup *value-data-ah - 74 var value-data/ecx: (addr stream byte) <- copy _value-data - 75 var value-gap-buffer-storage: (handle gap-buffer) - 76 var value-gap-buffer-ah/edx: (addr handle gap-buffer) <- address value-gap-buffer-storage - 77 allocate value-gap-buffer-ah - 78 var value-gap-buffer/eax: (addr gap-buffer) <- lookup *value-gap-buffer-ah - 79 initialize-gap-buffer value-gap-buffer, 0x1000/4KB - 80 load-gap-buffer-from-stream value-gap-buffer, value-data - 81 read-evaluate-and-move-to-globals value-gap-buffer-ah, self - 82 loop - 83 } - 84 } - 85 - 86 fn write-globals out: (addr stream byte), _self: (addr global-table) { - 87 var self/esi: (addr global-table) <- copy _self - 88 write out, " (globals . (\n" - 89 var data-ah/eax: (addr handle array global) <- get self, data - 90 var data/eax: (addr array global) <- lookup *data-ah - 91 var final-index/edx: (addr int) <- get self, final-index - 92 var curr-index/ecx: int <- copy 1/skip-0 - 93 { - 94 compare curr-index, *final-index - 95 break-if-> - 96 var curr-offset/ebx: (offset global) <- compute-offset data, curr-index - 97 var curr/ebx: (addr global) <- index data, curr-offset - 98 var curr-value-ah/edx: (addr handle cell) <- get curr, value - 99 var curr-value/eax: (addr cell) <- lookup *curr-value-ah - 100 var curr-type/eax: (addr int) <- get curr-value, type - 101 { - 102 compare *curr-type, 4/primitive-function - 103 break-if-= - 104 compare *curr-type, 5/screen - 105 break-if-= - 106 compare *curr-type, 6/keyboard - 107 break-if-= - 108 compare *curr-type, 3/stream # not implemented yet - 109 break-if-= - 110 write out, " (" - 111 var curr-name-ah/eax: (addr handle array byte) <- get curr, name - 112 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah - 113 write out, curr-name - 114 write out, " . [" - 115 var curr-input-ah/eax: (addr handle gap-buffer) <- get curr, input - 116 var curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah - 117 append-gap-buffer curr-input, out - 118 write out, "])\n" - 119 } - 120 curr-index <- increment - 121 loop - 122 } - 123 write out, " ))\n" - 124 } - 125 - 126 # globals layout: 1 char padding, 41 code, 1 padding, 41 code, 1 padding = 85 chars - 127 fn render-globals screen: (addr screen), _self: (addr global-table) { - 128 clear-rect screen, 0/xmin, 0/ymin, 0x55/xmax, 0x2f/ymax=screen-height-without-menu, 0xdc/bg=green-bg - 129 var self/esi: (addr global-table) <- copy _self - 130 # render primitives - 131 render-primitives screen, 1/xmin=padding-left, 0x55/xmax, 0x2f/ymax - 132 var data-ah/eax: (addr handle array global) <- get self, data - 133 var data/eax: (addr array global) <- lookup *data-ah - 134 var curr-index/edx: int <- copy 1 - 135 { - 136 var curr-offset/ebx: (offset global) <- compute-offset data, curr-index - 137 var curr/ebx: (addr global) <- index data, curr-offset - 138 var continue?/eax: boolean <- primitive-global? curr - 139 compare continue?, 0/false - 140 break-if-= - 141 curr-index <- increment - 142 loop - 143 } - 144 var lowest-index/edi: int <- copy curr-index - 145 var final-index/edx: (addr int) <- get self, final-index - 146 var curr-index/edx: int <- copy *final-index - 147 var y1: int - 148 copy-to y1, 1/padding-top - 149 var y2: int - 150 copy-to y2, 1/padding-top - 151 $render-globals:loop: { - 152 compare curr-index, lowest-index - 153 break-if-< - 154 { - 155 compare y1, 0x2f/ymax - 156 break-if-< - 157 compare y2, 0x2f/ymax - 158 break-if-< - 159 break $render-globals:loop - 160 } - 161 { - 162 var curr-offset/edx: (offset global) <- compute-offset data, curr-index - 163 var curr/edx: (addr global) <- index data, curr-offset - 164 var curr-input-ah/edx: (addr handle gap-buffer) <- get curr, input - 165 var _curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah - 166 var curr-input/ebx: (addr gap-buffer) <- copy _curr-input - 167 compare curr-input, 0 - 168 break-if-= - 169 $render-globals:render-global: { - 170 var x/eax: int <- copy 0 - 171 var y/ecx: int <- copy y1 - 172 compare y, y2 - 173 { - 174 break-if->= - 175 x, y <- render-gap-buffer-wrapping-right-then-down screen, curr-input, 1/padding-left, y1, 0x2a/xmax, 0x2f/ymax, 0/no-cursor, 7/fg=definition, 0xc5/bg=blue-bg - 176 y <- add 2 - 177 copy-to y1, y - 178 break $render-globals:render-global - 179 } - 180 x, y <- render-gap-buffer-wrapping-right-then-down screen, curr-input, 0x2b/xmin, y2, 0x54/xmax, 0x2f/ymax, 0/no-cursor, 7/fg=definition, 0xc5/bg=blue-bg - 181 y <- add 2 - 182 copy-to y2, y - 183 } - 184 } - 185 curr-index <- decrement - 186 loop - 187 } - 188 } - 189 - 190 fn render-primitives screen: (addr screen), xmin: int, xmax: int, ymax: int { - 191 var y/ecx: int <- copy ymax - 192 y <- subtract 0xf - 193 var tmpx/eax: int <- copy xmin - 194 tmpx <- draw-text-rightward screen, "cursor graphics", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 195 y <- increment - 196 var tmpx/eax: int <- copy xmin - 197 tmpx <- draw-text-rightward screen, " print", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 198 tmpx <- draw-text-rightward screen, ": screen a -> a", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 199 y <- increment - 200 var tmpx/eax: int <- copy xmin - 201 tmpx <- draw-text-rightward screen, " lines columns", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 202 tmpx <- draw-text-rightward screen, ": screen -> number", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 203 y <- increment - 204 var tmpx/eax: int <- copy xmin - 205 tmpx <- draw-text-rightward screen, " up down left right", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 206 tmpx <- draw-text-rightward screen, ": screen", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 207 y <- increment - 208 var tmpx/eax: int <- copy xmin - 209 tmpx <- draw-text-rightward screen, " cr", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 210 tmpx <- draw-text-rightward screen, ": screen ", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 211 tmpx <- draw-text-rightward screen, "# move cursor down and to left margin", tmpx, xmax, y, 0x38/fg=trace, 0xdc/bg=green-bg - 212 y <- increment - 213 var tmpx/eax: int <- copy xmin - 214 tmpx <- draw-text-rightward screen, "pixel graphics", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 215 y <- increment - 216 var tmpx/eax: int <- copy xmin - 217 tmpx <- draw-text-rightward screen, " width height", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 218 tmpx <- draw-text-rightward screen, ": screen -> number", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 219 y <- increment - 220 var tmpx/eax: int <- copy xmin - 221 tmpx <- draw-text-rightward screen, " pixel", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 222 tmpx <- draw-text-rightward screen, ": screen x y color", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 223 y <- increment - 224 var tmpx/eax: int <- copy xmin - 225 tmpx <- draw-text-rightward screen, "screen/keyboard", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 226 y <- increment - 227 var tmpx/eax: int <- copy xmin - 228 tmpx <- draw-text-rightward screen, " clear", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 229 tmpx <- draw-text-rightward screen, ": screen", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 14 compare self, 0 + 15 { + 16 break-if-!= + 17 abort "initialize globals" + 18 return + 19 } + 20 var data-ah/eax: (addr handle array global) <- get self, data + 21 populate data-ah, 0x40 + 22 # for numbers + 23 append-primitive self, "+" + 24 append-primitive self, "-" + 25 append-primitive self, "*" + 26 append-primitive self, "/" + 27 append-primitive self, "sqrt" + 28 append-primitive self, "abs" + 29 append-primitive self, "sgn" + 30 append-primitive self, "<" + 31 append-primitive self, ">" + 32 append-primitive self, "<=" + 33 append-primitive self, ">=" + 34 # generic + 35 append-primitive self, "=" + 36 append-primitive self, "no" + 37 append-primitive self, "not" + 38 append-primitive self, "dbg" + 39 # for pairs + 40 append-primitive self, "car" + 41 append-primitive self, "cdr" + 42 append-primitive self, "cons" + 43 # for screens + 44 append-primitive self, "print" + 45 append-primitive self, "clear" + 46 append-primitive self, "lines" + 47 append-primitive self, "columns" + 48 append-primitive self, "up" + 49 append-primitive self, "down" + 50 append-primitive self, "left" + 51 append-primitive self, "right" + 52 append-primitive self, "cr" + 53 append-primitive self, "pixel" + 54 append-primitive self, "width" + 55 append-primitive self, "height" + 56 # for keyboards + 57 append-primitive self, "key" + 58 # for streams + 59 append-primitive self, "stream" + 60 append-primitive self, "write" + 61 # misc + 62 append-primitive self, "abort" + 63 # keep sync'd with render-primitives + 64 } + 65 + 66 fn load-globals in: (addr handle cell), self: (addr global-table) { + 67 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading globals:", 3/fg, 0/bg + 68 var remaining-ah/esi: (addr handle cell) <- copy in + 69 { + 70 var _remaining/eax: (addr cell) <- lookup *remaining-ah + 71 var remaining/ecx: (addr cell) <- copy _remaining + 72 var done?/eax: boolean <- nil? remaining + 73 compare done?, 0/false + 74 break-if-!= + 75 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "b", 2/fg 0/bg + 76 var curr-ah/eax: (addr handle cell) <- get remaining, left + 77 var curr/eax: (addr cell) <- lookup *curr-ah + 78 remaining-ah <- get remaining, right + 79 { + 80 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " ", 2/fg 0/bg + 81 var name-ah/ecx: (addr handle cell) <- get curr, left + 82 var name/eax: (addr cell) <- lookup *name-ah + 83 var name-data-ah/eax: (addr handle stream byte) <- get name, text-data + 84 var name-data/eax: (addr stream byte) <- lookup *name-data-ah + 85 rewind-stream name-data + 86 draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, name-data, 3/fg, 0/bg + 87 } + 88 var value-ah/eax: (addr handle cell) <- get curr, right + 89 var value/eax: (addr cell) <- lookup *value-ah + 90 var value-data-ah/eax: (addr handle stream byte) <- get value, text-data + 91 var _value-data/eax: (addr stream byte) <- lookup *value-data-ah + 92 var value-data/ecx: (addr stream byte) <- copy _value-data + 93 var value-gap-buffer-storage: (handle gap-buffer) + 94 var value-gap-buffer-ah/edx: (addr handle gap-buffer) <- address value-gap-buffer-storage + 95 allocate value-gap-buffer-ah + 96 var value-gap-buffer/eax: (addr gap-buffer) <- lookup *value-gap-buffer-ah + 97 initialize-gap-buffer value-gap-buffer, 0x1000/4KB + 98 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "w", 2/fg 0/bg + 99 load-gap-buffer-from-stream value-gap-buffer, value-data + 100 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "x", 2/fg 0/bg + 101 read-evaluate-and-move-to-globals value-gap-buffer-ah, self + 102 #? draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "y", 2/fg 0/bg + 103 loop + 104 } + 105 move-cursor-to-left-margin-of-next-line 0/screen + 106 #? abort "zz" + 107 } + 108 + 109 fn write-globals out: (addr stream byte), _self: (addr global-table) { + 110 var self/esi: (addr global-table) <- copy _self + 111 compare self, 0 + 112 { + 113 break-if-!= + 114 abort "write globals" + 115 return + 116 } + 117 write out, " (globals . (\n" + 118 var data-ah/eax: (addr handle array global) <- get self, data + 119 var data/eax: (addr array global) <- lookup *data-ah + 120 var final-index/edx: (addr int) <- get self, final-index + 121 var curr-index/ecx: int <- copy 1/skip-0 + 122 { + 123 compare curr-index, *final-index + 124 break-if-> + 125 var curr-offset/ebx: (offset global) <- compute-offset data, curr-index + 126 var curr/ebx: (addr global) <- index data, curr-offset + 127 var curr-value-ah/edx: (addr handle cell) <- get curr, value + 128 var curr-value/eax: (addr cell) <- lookup *curr-value-ah + 129 var curr-type/eax: (addr int) <- get curr-value, type + 130 { + 131 compare *curr-type, 4/primitive-function + 132 break-if-= + 133 compare *curr-type, 5/screen + 134 break-if-= + 135 compare *curr-type, 6/keyboard + 136 break-if-= + 137 compare *curr-type, 3/stream # not implemented yet + 138 break-if-= + 139 write out, " (" + 140 var curr-name-ah/eax: (addr handle array byte) <- get curr, name + 141 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah + 142 write out, curr-name + 143 write out, " . [" + 144 var curr-input-ah/eax: (addr handle gap-buffer) <- get curr, input + 145 var curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah + 146 append-gap-buffer curr-input, out + 147 write out, "])\n" + 148 } + 149 curr-index <- increment + 150 loop + 151 } + 152 write out, " ))\n" + 153 } + 154 + 155 # globals layout: 1 char padding, 41 code, 1 padding, 41 code, 1 padding = 85 chars + 156 fn render-globals screen: (addr screen), _self: (addr global-table) { + 157 clear-rect screen, 0/xmin, 0/ymin, 0x55/xmax, 0x2f/ymax=screen-height-without-menu, 0xdc/bg=green-bg + 158 var self/esi: (addr global-table) <- copy _self + 159 compare self, 0 + 160 { + 161 break-if-!= + 162 abort "render globals" + 163 return + 164 } + 165 # render primitives + 166 render-primitives screen, 1/xmin=padding-left, 0x55/xmax, 0x2f/ymax + 167 var data-ah/eax: (addr handle array global) <- get self, data + 168 var data/eax: (addr array global) <- lookup *data-ah + 169 var curr-index/edx: int <- copy 1 + 170 { + 171 var curr-offset/ebx: (offset global) <- compute-offset data, curr-index + 172 var curr/ebx: (addr global) <- index data, curr-offset + 173 var continue?/eax: boolean <- primitive-global? curr + 174 compare continue?, 0/false + 175 break-if-= + 176 curr-index <- increment + 177 loop + 178 } + 179 var lowest-index/edi: int <- copy curr-index + 180 var final-index/edx: (addr int) <- get self, final-index + 181 var curr-index/edx: int <- copy *final-index + 182 var y1: int + 183 copy-to y1, 1/padding-top + 184 var y2: int + 185 copy-to y2, 1/padding-top + 186 $render-globals:loop: { + 187 compare curr-index, lowest-index + 188 break-if-< + 189 { + 190 compare y1, 0x2f/ymax + 191 break-if-< + 192 compare y2, 0x2f/ymax + 193 break-if-< + 194 break $render-globals:loop + 195 } + 196 { + 197 var curr-offset/edx: (offset global) <- compute-offset data, curr-index + 198 var curr/edx: (addr global) <- index data, curr-offset + 199 var curr-input-ah/edx: (addr handle gap-buffer) <- get curr, input + 200 var _curr-input/eax: (addr gap-buffer) <- lookup *curr-input-ah + 201 var curr-input/ebx: (addr gap-buffer) <- copy _curr-input + 202 compare curr-input, 0 + 203 break-if-= + 204 $render-globals:render-global: { + 205 var x/eax: int <- copy 0 + 206 var y/ecx: int <- copy y1 + 207 compare y, y2 + 208 { + 209 break-if->= + 210 x, y <- render-gap-buffer-wrapping-right-then-down screen, curr-input, 1/padding-left, y1, 0x2a/xmax, 0x2f/ymax, 0/no-cursor, 7/fg=definition, 0xc5/bg=blue-bg + 211 y <- add 2 + 212 copy-to y1, y + 213 break $render-globals:render-global + 214 } + 215 x, y <- render-gap-buffer-wrapping-right-then-down screen, curr-input, 0x2b/xmin, y2, 0x54/xmax, 0x2f/ymax, 0/no-cursor, 7/fg=definition, 0xc5/bg=blue-bg + 216 y <- add 2 + 217 copy-to y2, y + 218 } + 219 } + 220 curr-index <- decrement + 221 loop + 222 } + 223 } + 224 + 225 fn render-primitives screen: (addr screen), xmin: int, xmax: int, ymax: int { + 226 var y/ecx: int <- copy ymax + 227 y <- subtract 0xf + 228 var tmpx/eax: int <- copy xmin + 229 tmpx <- draw-text-rightward screen, "cursor graphics", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg 230 y <- increment 231 var tmpx/eax: int <- copy xmin - 232 tmpx <- draw-text-rightward screen, " key", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 233 tmpx <- draw-text-rightward screen, ": () -> grapheme?", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 232 tmpx <- draw-text-rightward screen, " print", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 233 tmpx <- draw-text-rightward screen, ": screen a -> a", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg 234 y <- increment 235 var tmpx/eax: int <- copy xmin - 236 tmpx <- draw-text-rightward screen, "streams", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 237 y <- increment - 238 var tmpx/eax: int <- copy xmin - 239 tmpx <- draw-text-rightward screen, " stream", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 240 tmpx <- draw-text-rightward screen, ": () -> stream ", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 241 y <- increment - 242 var tmpx/eax: int <- copy xmin - 243 tmpx <- draw-text-rightward screen, " write", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 244 tmpx <- draw-text-rightward screen, ": stream grapheme -> stream", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 245 y <- increment - 246 var tmpx/eax: int <- copy xmin - 247 tmpx <- draw-text-rightward screen, "fn def set if while = no(t) car cdr cons ", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 248 tmpx <- draw-text-rightward screen, "num: ", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg - 249 tmpx <- draw-text-rightward screen, "+ - * / sqrt abs sgn < > <= >= ", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg - 250 } - 251 - 252 fn primitive-global? _x: (addr global) -> _/eax: boolean { - 253 var x/eax: (addr global) <- copy _x - 254 var value-ah/eax: (addr handle cell) <- get x, value - 255 var value/eax: (addr cell) <- lookup *value-ah - 256 compare value, 0/null - 257 { - 258 break-if-!= - 259 return 0/false - 260 } - 261 var value-type/eax: (addr int) <- get value, type - 262 compare *value-type, 4/primitive - 263 { - 264 break-if-= - 265 return 0/false - 266 } - 267 return 1/true - 268 } - 269 - 270 fn append-primitive _self: (addr global-table), name: (addr array byte) { - 271 var self/esi: (addr global-table) <- copy _self - 272 var final-index-addr/ecx: (addr int) <- get self, final-index - 273 increment *final-index-addr - 274 var curr-index/ecx: int <- copy *final-index-addr - 275 var data-ah/eax: (addr handle array global) <- get self, data - 276 var data/eax: (addr array global) <- lookup *data-ah - 277 var curr-offset/esi: (offset global) <- compute-offset data, curr-index - 278 var curr/esi: (addr global) <- index data, curr-offset - 279 var curr-name-ah/eax: (addr handle array byte) <- get curr, name - 280 copy-array-object name, curr-name-ah - 281 var curr-value-ah/eax: (addr handle cell) <- get curr, value - 282 new-primitive-function curr-value-ah, curr-index - 283 } - 284 - 285 fn assign-or-create-global _self: (addr global-table), name: (addr array byte), value: (handle cell), trace: (addr trace) { - 286 var self/esi: (addr global-table) <- copy _self - 287 var curr-index/ecx: int <- find-symbol-name-in-globals self, name - 288 { - 289 compare curr-index, -1/not-found - 290 break-if-!= - 291 var final-index-addr/eax: (addr int) <- get self, final-index - 292 increment *final-index-addr - 293 curr-index <- copy *final-index-addr - 294 } - 295 var data-ah/eax: (addr handle array global) <- get self, data - 296 var data/eax: (addr array global) <- lookup *data-ah - 297 var curr-offset/esi: (offset global) <- compute-offset data, curr-index - 298 var curr/esi: (addr global) <- index data, curr-offset - 299 var curr-name-ah/eax: (addr handle array byte) <- get curr, name - 300 copy-array-object name, curr-name-ah - 301 var curr-value-ah/eax: (addr handle cell) <- get curr, value - 302 copy-handle value, curr-value-ah + 236 tmpx <- draw-text-rightward screen, " lines columns", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 237 tmpx <- draw-text-rightward screen, ": screen -> number", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 238 y <- increment + 239 var tmpx/eax: int <- copy xmin + 240 tmpx <- draw-text-rightward screen, " up down left right", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 241 tmpx <- draw-text-rightward screen, ": screen", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 242 y <- increment + 243 var tmpx/eax: int <- copy xmin + 244 tmpx <- draw-text-rightward screen, " cr", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 245 tmpx <- draw-text-rightward screen, ": screen ", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 246 tmpx <- draw-text-rightward screen, "# move cursor down and to left margin", tmpx, xmax, y, 0x38/fg=trace, 0xdc/bg=green-bg + 247 y <- increment + 248 var tmpx/eax: int <- copy xmin + 249 tmpx <- draw-text-rightward screen, "pixel graphics", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 250 y <- increment + 251 var tmpx/eax: int <- copy xmin + 252 tmpx <- draw-text-rightward screen, " width height", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 253 tmpx <- draw-text-rightward screen, ": screen -> number", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 254 y <- increment + 255 var tmpx/eax: int <- copy xmin + 256 tmpx <- draw-text-rightward screen, " pixel", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 257 tmpx <- draw-text-rightward screen, ": screen x y color", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 258 y <- increment + 259 var tmpx/eax: int <- copy xmin + 260 tmpx <- draw-text-rightward screen, "screen/keyboard", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 261 y <- increment + 262 var tmpx/eax: int <- copy xmin + 263 tmpx <- draw-text-rightward screen, " clear", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 264 tmpx <- draw-text-rightward screen, ": screen", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 265 y <- increment + 266 var tmpx/eax: int <- copy xmin + 267 tmpx <- draw-text-rightward screen, " key", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 268 tmpx <- draw-text-rightward screen, ": () -> grapheme?", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 269 y <- increment + 270 var tmpx/eax: int <- copy xmin + 271 tmpx <- draw-text-rightward screen, "streams", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 272 y <- increment + 273 var tmpx/eax: int <- copy xmin + 274 tmpx <- draw-text-rightward screen, " stream", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 275 tmpx <- draw-text-rightward screen, ": () -> stream ", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 276 y <- increment + 277 var tmpx/eax: int <- copy xmin + 278 tmpx <- draw-text-rightward screen, " write", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 279 tmpx <- draw-text-rightward screen, ": stream grapheme -> stream", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 280 y <- increment + 281 var tmpx/eax: int <- copy xmin + 282 tmpx <- draw-text-rightward screen, "fn def set if while = no(t) car cdr cons ", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 283 tmpx <- draw-text-rightward screen, "num: ", tmpx, xmax, y, 7/fg=grey, 0xdc/bg=green-bg + 284 tmpx <- draw-text-rightward screen, "+ - * / sqrt abs sgn < > <= >= ", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + 285 } + 286 + 287 fn primitive-global? _x: (addr global) -> _/eax: boolean { + 288 var x/eax: (addr global) <- copy _x + 289 var value-ah/eax: (addr handle cell) <- get x, value + 290 var value/eax: (addr cell) <- lookup *value-ah + 291 compare value, 0/null + 292 { + 293 break-if-!= + 294 return 0/false + 295 } + 296 var value-type/eax: (addr int) <- get value, type + 297 compare *value-type, 4/primitive + 298 { + 299 break-if-= + 300 return 0/false + 301 } + 302 return 1/true 303 } 304 - 305 fn lookup-symbol-in-globals _sym: (addr cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) { - 306 var sym/eax: (addr cell) <- copy _sym - 307 var sym-name-ah/eax: (addr handle stream byte) <- get sym, text-data - 308 var _sym-name/eax: (addr stream byte) <- lookup *sym-name-ah - 309 var sym-name/edx: (addr stream byte) <- copy _sym-name - 310 var globals/esi: (addr global-table) <- copy _globals - 311 { - 312 compare globals, 0 - 313 break-if-= - 314 var curr-index/ecx: int <- find-symbol-in-globals globals, sym-name - 315 compare curr-index, -1/not-found - 316 break-if-= - 317 var global-data-ah/eax: (addr handle array global) <- get globals, data - 318 var global-data/eax: (addr array global) <- lookup *global-data-ah - 319 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index - 320 var curr/ebx: (addr global) <- index global-data, curr-offset - 321 var curr-value/eax: (addr handle cell) <- get curr, value - 322 copy-object curr-value, out - 323 return - 324 } - 325 # if sym is "screen" and screen-cell exists, return it - 326 { - 327 var sym-is-screen?/eax: boolean <- stream-data-equal? sym-name, "screen" - 328 compare sym-is-screen?, 0/false - 329 break-if-= - 330 compare screen-cell, 0 - 331 break-if-= - 332 copy-object screen-cell, out - 333 return - 334 } - 335 # if sym is "keyboard" and keyboard-cell exists, return it - 336 { - 337 var sym-is-keyboard?/eax: boolean <- stream-data-equal? sym-name, "keyboard" - 338 compare sym-is-keyboard?, 0/false - 339 break-if-= - 340 compare keyboard-cell, 0 - 341 break-if-= - 342 copy-object keyboard-cell, out - 343 return - 344 } - 345 # otherwise error "unbound symbol: ", sym - 346 var stream-storage: (stream byte 0x40) - 347 var stream/ecx: (addr stream byte) <- address stream-storage - 348 write stream, "unbound symbol: " - 349 rewind-stream sym-name - 350 write-stream stream, sym-name - 351 trace trace, "error", stream - 352 } - 353 - 354 # return the index in globals containing 'sym' - 355 # or -1 if not found - 356 fn find-symbol-in-globals _globals: (addr global-table), sym-name: (addr stream byte) -> _/ecx: int { + 305 fn append-primitive _self: (addr global-table), name: (addr array byte) { + 306 var self/esi: (addr global-table) <- copy _self + 307 compare self, 0 + 308 { + 309 break-if-!= + 310 abort "append primitive" + 311 return + 312 } + 313 var final-index-addr/ecx: (addr int) <- get self, final-index + 314 increment *final-index-addr + 315 var curr-index/ecx: int <- copy *final-index-addr + 316 var data-ah/eax: (addr handle array global) <- get self, data + 317 var data/eax: (addr array global) <- lookup *data-ah + 318 var curr-offset/esi: (offset global) <- compute-offset data, curr-index + 319 var curr/esi: (addr global) <- index data, curr-offset + 320 var curr-name-ah/eax: (addr handle array byte) <- get curr, name + 321 copy-array-object name, curr-name-ah + 322 var curr-value-ah/eax: (addr handle cell) <- get curr, value + 323 new-primitive-function curr-value-ah, curr-index + 324 } + 325 + 326 fn assign-or-create-global _self: (addr global-table), name: (addr array byte), value: (handle cell), trace: (addr trace) { + 327 var self/esi: (addr global-table) <- copy _self + 328 compare self, 0 + 329 { + 330 break-if-!= + 331 abort "assign global" + 332 return + 333 } + 334 var curr-index/ecx: int <- find-symbol-name-in-globals self, name + 335 { + 336 compare curr-index, -1/not-found + 337 break-if-!= + 338 var final-index-addr/eax: (addr int) <- get self, final-index + 339 increment *final-index-addr + 340 curr-index <- copy *final-index-addr + 341 } + 342 var data-ah/eax: (addr handle array global) <- get self, data + 343 var data/eax: (addr array global) <- lookup *data-ah + 344 var curr-offset/esi: (offset global) <- compute-offset data, curr-index + 345 var curr/esi: (addr global) <- index data, curr-offset + 346 var curr-name-ah/eax: (addr handle array byte) <- get curr, name + 347 copy-array-object name, curr-name-ah + 348 var curr-value-ah/eax: (addr handle cell) <- get curr, value + 349 copy-handle value, curr-value-ah + 350 } + 351 + 352 fn lookup-symbol-in-globals _sym: (addr cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) { + 353 var sym/eax: (addr cell) <- copy _sym + 354 var sym-name-ah/eax: (addr handle stream byte) <- get sym, text-data + 355 var _sym-name/eax: (addr stream byte) <- lookup *sym-name-ah + 356 var sym-name/edx: (addr stream byte) <- copy _sym-name 357 var globals/esi: (addr global-table) <- copy _globals - 358 compare globals, 0 - 359 { - 360 break-if-!= - 361 return -1/not-found - 362 } - 363 var global-data-ah/eax: (addr handle array global) <- get globals, data - 364 var global-data/eax: (addr array global) <- lookup *global-data-ah - 365 var final-index/ecx: (addr int) <- get globals, final-index - 366 var curr-index/ecx: int <- copy *final-index - 367 { - 368 compare curr-index, 0 - 369 break-if-< - 370 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index - 371 var curr/ebx: (addr global) <- index global-data, curr-offset - 372 var curr-name-ah/eax: (addr handle array byte) <- get curr, name - 373 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah - 374 var found?/eax: boolean <- stream-data-equal? sym-name, curr-name - 375 compare found?, 0/false - 376 { - 377 break-if-= - 378 return curr-index - 379 } - 380 curr-index <- decrement - 381 loop - 382 } - 383 return -1/not-found - 384 } - 385 - 386 # return the index in globals containing 'sym' - 387 # or -1 if not found - 388 fn find-symbol-name-in-globals _globals: (addr global-table), sym-name: (addr array byte) -> _/ecx: int { - 389 var globals/esi: (addr global-table) <- copy _globals - 390 compare globals, 0 - 391 { - 392 break-if-!= - 393 return -1/not-found - 394 } - 395 var global-data-ah/eax: (addr handle array global) <- get globals, data - 396 var global-data/eax: (addr array global) <- lookup *global-data-ah - 397 var final-index/ecx: (addr int) <- get globals, final-index - 398 var curr-index/ecx: int <- copy *final-index - 399 { - 400 compare curr-index, 0 - 401 break-if-< - 402 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index - 403 var curr/ebx: (addr global) <- index global-data, curr-offset - 404 var curr-name-ah/eax: (addr handle array byte) <- get curr, name - 405 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah - 406 var found?/eax: boolean <- string-equal? sym-name, curr-name - 407 compare found?, 0/false - 408 { - 409 break-if-= - 410 return curr-index - 411 } - 412 curr-index <- decrement - 413 loop - 414 } - 415 return -1/not-found - 416 } - 417 - 418 fn mutate-binding-in-globals name: (addr stream byte), val: (addr handle cell), _globals: (addr global-table), trace: (addr trace) { - 419 var globals/esi: (addr global-table) <- copy _globals - 420 { - 421 compare globals, 0 - 422 break-if-= - 423 var curr-index/ecx: int <- find-symbol-in-globals globals, name - 424 compare curr-index, -1/not-found - 425 break-if-= - 426 var global-data-ah/eax: (addr handle array global) <- get globals, data - 427 var global-data/eax: (addr array global) <- lookup *global-data-ah - 428 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index - 429 var curr/ebx: (addr global) <- index global-data, curr-offset - 430 var dest/eax: (addr handle cell) <- get curr, value - 431 copy-object val, dest - 432 return - 433 } - 434 # otherwise error "unbound symbol: ", sym - 435 var stream-storage: (stream byte 0x40) - 436 var stream/ecx: (addr stream byte) <- address stream-storage - 437 write stream, "unbound symbol: " - 438 rewind-stream name - 439 write-stream stream, name - 440 trace trace, "error", stream - 441 } - 442 - 443 # a little strange; goes from value to name and selects primitive based on name - 444 fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace) { - 445 var f/esi: (addr cell) <- copy _f - 446 var f-index-a/ecx: (addr int) <- get f, index-data - 447 var f-index/ecx: int <- copy *f-index-a - 448 var globals/eax: (addr global-table) <- copy _globals - 449 var global-data-ah/eax: (addr handle array global) <- get globals, data - 450 var global-data/eax: (addr array global) <- lookup *global-data-ah - 451 var f-offset/ecx: (offset global) <- compute-offset global-data, f-index - 452 var f-value/ecx: (addr global) <- index global-data, f-offset - 453 var f-name-ah/ecx: (addr handle array byte) <- get f-value, name - 454 var f-name/eax: (addr array byte) <- lookup *f-name-ah - 455 { - 456 var add?/eax: boolean <- string-equal? f-name, "+" - 457 compare add?, 0/false - 458 break-if-= - 459 apply-add args-ah, out, trace - 460 return - 461 } - 462 { - 463 var subtract?/eax: boolean <- string-equal? f-name, "-" - 464 compare subtract?, 0/false - 465 break-if-= - 466 apply-subtract args-ah, out, trace - 467 return - 468 } - 469 { - 470 var multiply?/eax: boolean <- string-equal? f-name, "*" - 471 compare multiply?, 0/false - 472 break-if-= - 473 apply-multiply args-ah, out, trace - 474 return - 475 } - 476 { - 477 var divide?/eax: boolean <- string-equal? f-name, "/" - 478 compare divide?, 0/false - 479 break-if-= - 480 apply-divide args-ah, out, trace - 481 return - 482 } - 483 { - 484 var square-root?/eax: boolean <- string-equal? f-name, "sqrt" - 485 compare square-root?, 0/false - 486 break-if-= - 487 apply-square-root args-ah, out, trace - 488 return - 489 } - 490 { - 491 var abs?/eax: boolean <- string-equal? f-name, "abs" - 492 compare abs?, 0/false - 493 break-if-= - 494 apply-abs args-ah, out, trace - 495 return - 496 } - 497 { - 498 var sgn?/eax: boolean <- string-equal? f-name, "sgn" - 499 compare sgn?, 0/false - 500 break-if-= - 501 apply-sgn args-ah, out, trace - 502 return - 503 } - 504 { - 505 var car?/eax: boolean <- string-equal? f-name, "car" - 506 compare car?, 0/false - 507 break-if-= - 508 apply-car args-ah, out, trace - 509 return - 510 } - 511 { - 512 var cdr?/eax: boolean <- string-equal? f-name, "cdr" - 513 compare cdr?, 0/false - 514 break-if-= - 515 apply-cdr args-ah, out, trace - 516 return - 517 } - 518 { - 519 var cons?/eax: boolean <- string-equal? f-name, "cons" - 520 compare cons?, 0/false - 521 break-if-= - 522 apply-cons args-ah, out, trace - 523 return - 524 } - 525 { - 526 var structurally-equal?/eax: boolean <- string-equal? f-name, "=" - 527 compare structurally-equal?, 0/false - 528 break-if-= - 529 apply-structurally-equal args-ah, out, trace - 530 return - 531 } - 532 { - 533 var not?/eax: boolean <- string-equal? f-name, "no" - 534 compare not?, 0/false - 535 break-if-= - 536 apply-not args-ah, out, trace - 537 return - 538 } - 539 { - 540 var not?/eax: boolean <- string-equal? f-name, "not" - 541 compare not?, 0/false - 542 break-if-= - 543 apply-not args-ah, out, trace - 544 return - 545 } - 546 { - 547 var lesser?/eax: boolean <- string-equal? f-name, "<" - 548 compare lesser?, 0/false - 549 break-if-= - 550 apply-< args-ah, out, trace - 551 return - 552 } - 553 { - 554 var greater?/eax: boolean <- string-equal? f-name, ">" - 555 compare greater?, 0/false - 556 break-if-= - 557 apply-> args-ah, out, trace - 558 return - 559 } - 560 { - 561 var lesser-or-equal?/eax: boolean <- string-equal? f-name, "<=" - 562 compare lesser-or-equal?, 0/false - 563 break-if-= - 564 apply-<= args-ah, out, trace - 565 return - 566 } - 567 { - 568 var greater-or-equal?/eax: boolean <- string-equal? f-name, ">=" - 569 compare greater-or-equal?, 0/false - 570 break-if-= - 571 apply->= args-ah, out, trace - 572 return - 573 } - 574 { - 575 var print?/eax: boolean <- string-equal? f-name, "print" - 576 compare print?, 0/false - 577 break-if-= - 578 apply-print args-ah, out, trace - 579 return - 580 } - 581 { - 582 var clear?/eax: boolean <- string-equal? f-name, "clear" - 583 compare clear?, 0/false - 584 break-if-= - 585 apply-clear args-ah, out, trace - 586 return - 587 } - 588 { - 589 var lines?/eax: boolean <- string-equal? f-name, "lines" - 590 compare lines?, 0/false - 591 break-if-= - 592 apply-lines args-ah, out, trace - 593 return - 594 } - 595 { - 596 var columns?/eax: boolean <- string-equal? f-name, "columns" - 597 compare columns?, 0/false - 598 break-if-= - 599 apply-columns args-ah, out, trace - 600 return - 601 } - 602 { - 603 var up?/eax: boolean <- string-equal? f-name, "up" - 604 compare up?, 0/false - 605 break-if-= - 606 apply-up args-ah, out, trace - 607 return - 608 } - 609 { - 610 var down?/eax: boolean <- string-equal? f-name, "down" - 611 compare down?, 0/false - 612 break-if-= - 613 apply-down args-ah, out, trace - 614 return - 615 } - 616 { - 617 var left?/eax: boolean <- string-equal? f-name, "left" - 618 compare left?, 0/false - 619 break-if-= - 620 apply-left args-ah, out, trace - 621 return - 622 } - 623 { - 624 var right?/eax: boolean <- string-equal? f-name, "right" - 625 compare right?, 0/false - 626 break-if-= - 627 apply-right args-ah, out, trace - 628 return - 629 } - 630 { - 631 var cr?/eax: boolean <- string-equal? f-name, "cr" - 632 compare cr?, 0/false - 633 break-if-= - 634 apply-cr args-ah, out, trace - 635 return - 636 } - 637 { - 638 var pixel?/eax: boolean <- string-equal? f-name, "pixel" - 639 compare pixel?, 0/false - 640 break-if-= - 641 apply-pixel args-ah, out, trace - 642 return - 643 } - 644 { - 645 var width?/eax: boolean <- string-equal? f-name, "width" - 646 compare width?, 0/false - 647 break-if-= - 648 apply-width args-ah, out, trace - 649 return - 650 } - 651 { - 652 var height?/eax: boolean <- string-equal? f-name, "height" - 653 compare height?, 0/false - 654 break-if-= - 655 apply-height args-ah, out, trace - 656 return - 657 } - 658 { - 659 var wait-for-key?/eax: boolean <- string-equal? f-name, "key" - 660 compare wait-for-key?, 0/false - 661 break-if-= - 662 apply-wait-for-key args-ah, out, trace - 663 return - 664 } - 665 { - 666 var stream?/eax: boolean <- string-equal? f-name, "stream" - 667 compare stream?, 0/false - 668 break-if-= - 669 apply-stream args-ah, out, trace - 670 return - 671 } - 672 { - 673 var write?/eax: boolean <- string-equal? f-name, "write" - 674 compare write?, 0/false - 675 break-if-= - 676 apply-write args-ah, out, trace - 677 return - 678 } - 679 { - 680 var abort?/eax: boolean <- string-equal? f-name, "abort" - 681 compare abort?, 0/false - 682 break-if-= - 683 apply-abort args-ah, out, trace - 684 return - 685 } - 686 abort "unknown primitive function" - 687 } - 688 - 689 fn apply-add _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 690 trace-text trace, "eval", "apply +" - 691 var args-ah/eax: (addr handle cell) <- copy _args-ah - 692 var _args/eax: (addr cell) <- lookup *args-ah - 693 var args/esi: (addr cell) <- copy _args - 694 # TODO: check that args is a pair - 695 var empty-args?/eax: boolean <- nil? args - 696 compare empty-args?, 0/false - 697 { - 698 break-if-= - 699 error trace, "+ needs 2 args but got 0" - 700 return - 701 } - 702 # args->left->value - 703 var first-ah/eax: (addr handle cell) <- get args, left - 704 var first/eax: (addr cell) <- lookup *first-ah - 705 var first-type/ecx: (addr int) <- get first, type - 706 compare *first-type, 1/number - 707 { + 358 { + 359 compare globals, 0 + 360 break-if-= + 361 var curr-index/ecx: int <- find-symbol-in-globals globals, sym-name + 362 compare curr-index, -1/not-found + 363 break-if-= + 364 var global-data-ah/eax: (addr handle array global) <- get globals, data + 365 var global-data/eax: (addr array global) <- lookup *global-data-ah + 366 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index + 367 var curr/ebx: (addr global) <- index global-data, curr-offset + 368 var curr-value/eax: (addr handle cell) <- get curr, value + 369 copy-object curr-value, out + 370 return + 371 } + 372 # if sym is "screen" and screen-cell exists, return it + 373 { + 374 var sym-is-screen?/eax: boolean <- stream-data-equal? sym-name, "screen" + 375 compare sym-is-screen?, 0/false + 376 break-if-= + 377 compare screen-cell, 0 + 378 break-if-= + 379 copy-object screen-cell, out + 380 return + 381 } + 382 # if sym is "keyboard" and keyboard-cell exists, return it + 383 { + 384 var sym-is-keyboard?/eax: boolean <- stream-data-equal? sym-name, "keyboard" + 385 compare sym-is-keyboard?, 0/false + 386 break-if-= + 387 compare keyboard-cell, 0 + 388 break-if-= + 389 copy-object keyboard-cell, out + 390 return + 391 } + 392 # otherwise error "unbound symbol: ", sym + 393 var stream-storage: (stream byte 0x40) + 394 var stream/ecx: (addr stream byte) <- address stream-storage + 395 write stream, "unbound symbol: " + 396 rewind-stream sym-name + 397 write-stream stream, sym-name + 398 trace trace, "error", stream + 399 } + 400 + 401 fn maybe-lookup-symbol-in-globals _sym: (addr cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace) { + 402 var sym/eax: (addr cell) <- copy _sym + 403 var sym-name-ah/eax: (addr handle stream byte) <- get sym, text-data + 404 var _sym-name/eax: (addr stream byte) <- lookup *sym-name-ah + 405 var sym-name/edx: (addr stream byte) <- copy _sym-name + 406 var globals/esi: (addr global-table) <- copy _globals + 407 { + 408 compare globals, 0 + 409 break-if-= + 410 var curr-index/ecx: int <- find-symbol-in-globals globals, sym-name + 411 compare curr-index, -1/not-found + 412 break-if-= + 413 var global-data-ah/eax: (addr handle array global) <- get globals, data + 414 var global-data/eax: (addr array global) <- lookup *global-data-ah + 415 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index + 416 var curr/ebx: (addr global) <- index global-data, curr-offset + 417 var curr-value/eax: (addr handle cell) <- get curr, value + 418 copy-object curr-value, out + 419 return + 420 } + 421 } + 422 + 423 # return the index in globals containing 'sym' + 424 # or -1 if not found + 425 fn find-symbol-in-globals _globals: (addr global-table), sym-name: (addr stream byte) -> _/ecx: int { + 426 var globals/esi: (addr global-table) <- copy _globals + 427 compare globals, 0 + 428 { + 429 break-if-!= + 430 return -1/not-found + 431 } + 432 var global-data-ah/eax: (addr handle array global) <- get globals, data + 433 var global-data/eax: (addr array global) <- lookup *global-data-ah + 434 var final-index/ecx: (addr int) <- get globals, final-index + 435 var curr-index/ecx: int <- copy *final-index + 436 { + 437 compare curr-index, 0 + 438 break-if-< + 439 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index + 440 var curr/ebx: (addr global) <- index global-data, curr-offset + 441 var curr-name-ah/eax: (addr handle array byte) <- get curr, name + 442 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah + 443 var found?/eax: boolean <- stream-data-equal? sym-name, curr-name + 444 compare found?, 0/false + 445 { + 446 break-if-= + 447 return curr-index + 448 } + 449 curr-index <- decrement + 450 loop + 451 } + 452 return -1/not-found + 453 } + 454 + 455 # return the index in globals containing 'sym' + 456 # or -1 if not found + 457 fn find-symbol-name-in-globals _globals: (addr global-table), sym-name: (addr array byte) -> _/ecx: int { + 458 var globals/esi: (addr global-table) <- copy _globals + 459 compare globals, 0 + 460 { + 461 break-if-!= + 462 return -1/not-found + 463 } + 464 var global-data-ah/eax: (addr handle array global) <- get globals, data + 465 var global-data/eax: (addr array global) <- lookup *global-data-ah + 466 var final-index/ecx: (addr int) <- get globals, final-index + 467 var curr-index/ecx: int <- copy *final-index + 468 { + 469 compare curr-index, 0 + 470 break-if-< + 471 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index + 472 var curr/ebx: (addr global) <- index global-data, curr-offset + 473 var curr-name-ah/eax: (addr handle array byte) <- get curr, name + 474 var curr-name/eax: (addr array byte) <- lookup *curr-name-ah + 475 var found?/eax: boolean <- string-equal? sym-name, curr-name + 476 compare found?, 0/false + 477 { + 478 break-if-= + 479 return curr-index + 480 } + 481 curr-index <- decrement + 482 loop + 483 } + 484 return -1/not-found + 485 } + 486 + 487 fn mutate-binding-in-globals name: (addr stream byte), val: (addr handle cell), _globals: (addr global-table), trace: (addr trace) { + 488 var globals/esi: (addr global-table) <- copy _globals + 489 { + 490 compare globals, 0 + 491 break-if-= + 492 var curr-index/ecx: int <- find-symbol-in-globals globals, name + 493 compare curr-index, -1/not-found + 494 break-if-= + 495 var global-data-ah/eax: (addr handle array global) <- get globals, data + 496 var global-data/eax: (addr array global) <- lookup *global-data-ah + 497 var curr-offset/ebx: (offset global) <- compute-offset global-data, curr-index + 498 var curr/ebx: (addr global) <- index global-data, curr-offset + 499 var dest/eax: (addr handle cell) <- get curr, value + 500 copy-object val, dest + 501 return + 502 } + 503 # otherwise error "unbound symbol: ", sym + 504 var stream-storage: (stream byte 0x40) + 505 var stream/ecx: (addr stream byte) <- address stream-storage + 506 write stream, "unbound symbol: " + 507 rewind-stream name + 508 write-stream stream, name + 509 trace trace, "error", stream + 510 } + 511 + 512 # a little strange; goes from value to name and selects primitive based on name + 513 fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr handle cell), _globals: (addr global-table), trace: (addr trace) { + 514 var f/esi: (addr cell) <- copy _f + 515 var f-index-a/ecx: (addr int) <- get f, index-data + 516 var f-index/ecx: int <- copy *f-index-a + 517 var globals/eax: (addr global-table) <- copy _globals + 518 compare globals, 0 + 519 { + 520 break-if-!= + 521 abort "apply primitive" + 522 return + 523 } + 524 var global-data-ah/eax: (addr handle array global) <- get globals, data + 525 var global-data/eax: (addr array global) <- lookup *global-data-ah + 526 var f-offset/ecx: (offset global) <- compute-offset global-data, f-index + 527 var f-value/ecx: (addr global) <- index global-data, f-offset + 528 var f-name-ah/ecx: (addr handle array byte) <- get f-value, name + 529 var f-name/eax: (addr array byte) <- lookup *f-name-ah + 530 { + 531 var add?/eax: boolean <- string-equal? f-name, "+" + 532 compare add?, 0/false + 533 break-if-= + 534 apply-add args-ah, out, trace + 535 return + 536 } + 537 { + 538 var subtract?/eax: boolean <- string-equal? f-name, "-" + 539 compare subtract?, 0/false + 540 break-if-= + 541 apply-subtract args-ah, out, trace + 542 return + 543 } + 544 { + 545 var multiply?/eax: boolean <- string-equal? f-name, "*" + 546 compare multiply?, 0/false + 547 break-if-= + 548 apply-multiply args-ah, out, trace + 549 return + 550 } + 551 { + 552 var divide?/eax: boolean <- string-equal? f-name, "/" + 553 compare divide?, 0/false + 554 break-if-= + 555 apply-divide args-ah, out, trace + 556 return + 557 } + 558 { + 559 var square-root?/eax: boolean <- string-equal? f-name, "sqrt" + 560 compare square-root?, 0/false + 561 break-if-= + 562 apply-square-root args-ah, out, trace + 563 return + 564 } + 565 { + 566 var abs?/eax: boolean <- string-equal? f-name, "abs" + 567 compare abs?, 0/false + 568 break-if-= + 569 apply-abs args-ah, out, trace + 570 return + 571 } + 572 { + 573 var sgn?/eax: boolean <- string-equal? f-name, "sgn" + 574 compare sgn?, 0/false + 575 break-if-= + 576 apply-sgn args-ah, out, trace + 577 return + 578 } + 579 { + 580 var car?/eax: boolean <- string-equal? f-name, "car" + 581 compare car?, 0/false + 582 break-if-= + 583 apply-car args-ah, out, trace + 584 return + 585 } + 586 { + 587 var cdr?/eax: boolean <- string-equal? f-name, "cdr" + 588 compare cdr?, 0/false + 589 break-if-= + 590 apply-cdr args-ah, out, trace + 591 return + 592 } + 593 { + 594 var cons?/eax: boolean <- string-equal? f-name, "cons" + 595 compare cons?, 0/false + 596 break-if-= + 597 apply-cons args-ah, out, trace + 598 return + 599 } + 600 { + 601 var structurally-equal?/eax: boolean <- string-equal? f-name, "=" + 602 compare structurally-equal?, 0/false + 603 break-if-= + 604 apply-structurally-equal args-ah, out, trace + 605 return + 606 } + 607 { + 608 var not?/eax: boolean <- string-equal? f-name, "no" + 609 compare not?, 0/false + 610 break-if-= + 611 apply-not args-ah, out, trace + 612 return + 613 } + 614 { + 615 var not?/eax: boolean <- string-equal? f-name, "not" + 616 compare not?, 0/false + 617 break-if-= + 618 apply-not args-ah, out, trace + 619 return + 620 } + 621 { + 622 var debug?/eax: boolean <- string-equal? f-name, "dbg" + 623 compare debug?, 0/false + 624 break-if-= + 625 apply-debug args-ah, out, trace + 626 return + 627 } + 628 { + 629 var lesser?/eax: boolean <- string-equal? f-name, "<" + 630 compare lesser?, 0/false + 631 break-if-= + 632 apply-< args-ah, out, trace + 633 return + 634 } + 635 { + 636 var greater?/eax: boolean <- string-equal? f-name, ">" + 637 compare greater?, 0/false + 638 break-if-= + 639 apply-> args-ah, out, trace + 640 return + 641 } + 642 { + 643 var lesser-or-equal?/eax: boolean <- string-equal? f-name, "<=" + 644 compare lesser-or-equal?, 0/false + 645 break-if-= + 646 apply-<= args-ah, out, trace + 647 return + 648 } + 649 { + 650 var greater-or-equal?/eax: boolean <- string-equal? f-name, ">=" + 651 compare greater-or-equal?, 0/false + 652 break-if-= + 653 apply->= args-ah, out, trace + 654 return + 655 } + 656 { + 657 var print?/eax: boolean <- string-equal? f-name, "print" + 658 compare print?, 0/false + 659 break-if-= + 660 apply-print args-ah, out, trace + 661 return + 662 } + 663 { + 664 var clear?/eax: boolean <- string-equal? f-name, "clear" + 665 compare clear?, 0/false + 666 break-if-= + 667 apply-clear args-ah, out, trace + 668 return + 669 } + 670 { + 671 var lines?/eax: boolean <- string-equal? f-name, "lines" + 672 compare lines?, 0/false + 673 break-if-= + 674 apply-lines args-ah, out, trace + 675 return + 676 } + 677 { + 678 var columns?/eax: boolean <- string-equal? f-name, "columns" + 679 compare columns?, 0/false + 680 break-if-= + 681 apply-columns args-ah, out, trace + 682 return + 683 } + 684 { + 685 var up?/eax: boolean <- string-equal? f-name, "up" + 686 compare up?, 0/false + 687 break-if-= + 688 apply-up args-ah, out, trace + 689 return + 690 } + 691 { + 692 var down?/eax: boolean <- string-equal? f-name, "down" + 693 compare down?, 0/false + 694 break-if-= + 695 apply-down args-ah, out, trace + 696 return + 697 } + 698 { + 699 var left?/eax: boolean <- string-equal? f-name, "left" + 700 compare left?, 0/false + 701 break-if-= + 702 apply-left args-ah, out, trace + 703 return + 704 } + 705 { + 706 var right?/eax: boolean <- string-equal? f-name, "right" + 707 compare right?, 0/false 708 break-if-= - 709 error trace, "first arg for + is not a number" + 709 apply-right args-ah, out, trace 710 return 711 } - 712 var first-value/ecx: (addr float) <- get first, number-data - 713 # args->right->left->value - 714 var right-ah/eax: (addr handle cell) <- get args, right - 715 #? dump-cell right-ah - 716 #? abort "aaa" - 717 var right/eax: (addr cell) <- lookup *right-ah - 718 # TODO: check that right is a pair - 719 var second-ah/eax: (addr handle cell) <- get right, left - 720 var second/eax: (addr cell) <- lookup *second-ah - 721 var second-type/edx: (addr int) <- get second, type - 722 compare *second-type, 1/number - 723 { - 724 break-if-= - 725 error trace, "second arg for + is not a number" - 726 return - 727 } - 728 var second-value/edx: (addr float) <- get second, number-data - 729 # add - 730 var result/xmm0: float <- copy *first-value - 731 result <- add *second-value - 732 new-float out, result - 733 } - 734 - 735 fn apply-subtract _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 736 trace-text trace, "eval", "apply -" - 737 var args-ah/eax: (addr handle cell) <- copy _args-ah - 738 var _args/eax: (addr cell) <- lookup *args-ah - 739 var args/esi: (addr cell) <- copy _args - 740 # TODO: check that args is a pair - 741 var empty-args?/eax: boolean <- nil? args - 742 compare empty-args?, 0/false - 743 { - 744 break-if-= - 745 error trace, "- needs 2 args but got 0" - 746 return - 747 } - 748 # args->left->value - 749 var first-ah/eax: (addr handle cell) <- get args, left - 750 var first/eax: (addr cell) <- lookup *first-ah - 751 var first-type/ecx: (addr int) <- get first, type - 752 compare *first-type, 1/number - 753 { - 754 break-if-= - 755 error trace, "first arg for - is not a number" - 756 return - 757 } - 758 var first-value/ecx: (addr float) <- get first, number-data - 759 # args->right->left->value - 760 var right-ah/eax: (addr handle cell) <- get args, right - 761 var right/eax: (addr cell) <- lookup *right-ah - 762 # TODO: check that right is a pair - 763 var second-ah/eax: (addr handle cell) <- get right, left - 764 var second/eax: (addr cell) <- lookup *second-ah - 765 var second-type/edx: (addr int) <- get second, type - 766 compare *second-type, 1/number - 767 { - 768 break-if-= - 769 error trace, "second arg for - is not a number" - 770 return - 771 } - 772 var second-value/edx: (addr float) <- get second, number-data - 773 # subtract - 774 var result/xmm0: float <- copy *first-value - 775 result <- subtract *second-value - 776 new-float out, result - 777 } - 778 - 779 fn apply-multiply _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 780 trace-text trace, "eval", "apply *" - 781 var args-ah/eax: (addr handle cell) <- copy _args-ah - 782 var _args/eax: (addr cell) <- lookup *args-ah - 783 var args/esi: (addr cell) <- copy _args - 784 # TODO: check that args is a pair - 785 var empty-args?/eax: boolean <- nil? args - 786 compare empty-args?, 0/false - 787 { - 788 break-if-= - 789 error trace, "* needs 2 args but got 0" - 790 return - 791 } - 792 # args->left->value - 793 var first-ah/eax: (addr handle cell) <- get args, left - 794 var first/eax: (addr cell) <- lookup *first-ah - 795 var first-type/ecx: (addr int) <- get first, type - 796 compare *first-type, 1/number - 797 { - 798 break-if-= - 799 error trace, "first arg for * is not a number" - 800 return - 801 } - 802 var first-value/ecx: (addr float) <- get first, number-data - 803 # args->right->left->value - 804 var right-ah/eax: (addr handle cell) <- get args, right - 805 var right/eax: (addr cell) <- lookup *right-ah - 806 # TODO: check that right is a pair - 807 var second-ah/eax: (addr handle cell) <- get right, left - 808 var second/eax: (addr cell) <- lookup *second-ah - 809 var second-type/edx: (addr int) <- get second, type - 810 compare *second-type, 1/number - 811 { - 812 break-if-= - 813 error trace, "second arg for * is not a number" - 814 return - 815 } - 816 var second-value/edx: (addr float) <- get second, number-data - 817 # multiply - 818 var result/xmm0: float <- copy *first-value - 819 result <- multiply *second-value - 820 new-float out, result - 821 } - 822 - 823 fn apply-divide _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 824 trace-text trace, "eval", "apply /" - 825 var args-ah/eax: (addr handle cell) <- copy _args-ah - 826 var _args/eax: (addr cell) <- lookup *args-ah - 827 var args/esi: (addr cell) <- copy _args - 828 # TODO: check that args is a pair - 829 var empty-args?/eax: boolean <- nil? args - 830 compare empty-args?, 0/false - 831 { - 832 break-if-= - 833 error trace, "/ needs 2 args but got 0" - 834 return - 835 } - 836 # args->left->value - 837 var first-ah/eax: (addr handle cell) <- get args, left - 838 var first/eax: (addr cell) <- lookup *first-ah - 839 var first-type/ecx: (addr int) <- get first, type - 840 compare *first-type, 1/number - 841 { - 842 break-if-= - 843 error trace, "first arg for / is not a number" - 844 return - 845 } - 846 var first-value/ecx: (addr float) <- get first, number-data - 847 # args->right->left->value - 848 var right-ah/eax: (addr handle cell) <- get args, right - 849 var right/eax: (addr cell) <- lookup *right-ah - 850 # TODO: check that right is a pair - 851 var second-ah/eax: (addr handle cell) <- get right, left - 852 var second/eax: (addr cell) <- lookup *second-ah - 853 var second-type/edx: (addr int) <- get second, type - 854 compare *second-type, 1/number - 855 { - 856 break-if-= - 857 error trace, "second arg for / is not a number" - 858 return - 859 } - 860 var second-value/edx: (addr float) <- get second, number-data - 861 # divide - 862 var result/xmm0: float <- copy *first-value - 863 result <- divide *second-value - 864 new-float out, result - 865 } - 866 - 867 fn apply-square-root _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 868 trace-text trace, "eval", "apply sqrt" - 869 var args-ah/eax: (addr handle cell) <- copy _args-ah - 870 var _args/eax: (addr cell) <- lookup *args-ah - 871 var args/esi: (addr cell) <- copy _args - 872 # TODO: check that args is a pair - 873 var empty-args?/eax: boolean <- nil? args - 874 compare empty-args?, 0/false - 875 { - 876 break-if-= - 877 error trace, "sqrt needs 1 args but got 0" - 878 return - 879 } - 880 # args->left->value - 881 var first-ah/eax: (addr handle cell) <- get args, left - 882 var first/eax: (addr cell) <- lookup *first-ah - 883 var first-type/ecx: (addr int) <- get first, type - 884 compare *first-type, 1/number - 885 { - 886 break-if-= - 887 error trace, "arg for sqrt is not a number" - 888 return - 889 } - 890 var first-value/ecx: (addr float) <- get first, number-data - 891 # square-root - 892 var result/xmm0: float <- square-root *first-value - 893 new-float out, result - 894 } - 895 - 896 fn apply-abs _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 897 trace-text trace, "eval", "apply abs" - 898 var args-ah/eax: (addr handle cell) <- copy _args-ah - 899 var _args/eax: (addr cell) <- lookup *args-ah - 900 var args/esi: (addr cell) <- copy _args - 901 # TODO: check that args is a pair - 902 var empty-args?/eax: boolean <- nil? args - 903 compare empty-args?, 0/false - 904 { - 905 break-if-= - 906 error trace, "abs needs 1 args but got 0" - 907 return - 908 } - 909 # args->left->value - 910 var first-ah/eax: (addr handle cell) <- get args, left - 911 var first/eax: (addr cell) <- lookup *first-ah - 912 var first-type/ecx: (addr int) <- get first, type - 913 compare *first-type, 1/number - 914 { - 915 break-if-= - 916 error trace, "arg for abs is not a number" - 917 return - 918 } - 919 var first-value/ecx: (addr float) <- get first, number-data - 920 # - 921 var result/xmm0: float <- copy *first-value - 922 var zero: float - 923 compare result, zero - 924 { - 925 break-if-float>= - 926 var neg1/eax: int <- copy -1 - 927 var neg1-f/xmm1: float <- convert neg1 - 928 result <- multiply neg1-f - 929 } - 930 new-float out, result - 931 } - 932 - 933 fn apply-sgn _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 934 trace-text trace, "eval", "apply sgn" - 935 var args-ah/eax: (addr handle cell) <- copy _args-ah - 936 var _args/eax: (addr cell) <- lookup *args-ah - 937 var args/esi: (addr cell) <- copy _args - 938 # TODO: check that args is a pair - 939 var empty-args?/eax: boolean <- nil? args - 940 compare empty-args?, 0/false - 941 { - 942 break-if-= - 943 error trace, "sgn needs 1 args but got 0" - 944 return - 945 } - 946 # args->left->value - 947 var first-ah/eax: (addr handle cell) <- get args, left - 948 var first/eax: (addr cell) <- lookup *first-ah - 949 var first-type/ecx: (addr int) <- get first, type - 950 compare *first-type, 1/number - 951 { - 952 break-if-= - 953 error trace, "arg for sgn is not a number" - 954 return - 955 } - 956 var first-value/ecx: (addr float) <- get first, number-data - 957 # - 958 var result/xmm0: float <- copy *first-value - 959 var zero: float - 960 $apply-sgn:core: { - 961 compare result, zero - 962 break-if-= - 963 { - 964 break-if-float> - 965 var neg1/eax: int <- copy -1 - 966 result <- convert neg1 - 967 break $apply-sgn:core - 968 } - 969 { - 970 break-if-float< - 971 var one/eax: int <- copy 1 - 972 result <- convert one - 973 break $apply-sgn:core - 974 } - 975 } - 976 new-float out, result - 977 } - 978 - 979 fn apply-car _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { - 980 trace-text trace, "eval", "apply car" - 981 var args-ah/eax: (addr handle cell) <- copy _args-ah - 982 var _args/eax: (addr cell) <- lookup *args-ah - 983 var args/esi: (addr cell) <- copy _args - 984 # TODO: check that args is a pair - 985 var empty-args?/eax: boolean <- nil? args - 986 compare empty-args?, 0/false - 987 { - 988 break-if-= - 989 error trace, "car needs 1 args but got 0" - 990 return - 991 } - 992 # args->left - 993 var first-ah/eax: (addr handle cell) <- get args, left - 994 var first/eax: (addr cell) <- lookup *first-ah - 995 var first-type/ecx: (addr int) <- get first, type - 996 compare *first-type, 0/pair - 997 { - 998 break-if-= - 999 error trace, "arg for car is not a pair" -1000 return -1001 } -1002 # car -1003 var result/eax: (addr handle cell) <- get first, left -1004 copy-object result, out -1005 } -1006 -1007 fn apply-cdr _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1008 trace-text trace, "eval", "apply cdr" -1009 var args-ah/eax: (addr handle cell) <- copy _args-ah -1010 var _args/eax: (addr cell) <- lookup *args-ah -1011 var args/esi: (addr cell) <- copy _args -1012 # TODO: check that args is a pair -1013 var empty-args?/eax: boolean <- nil? args -1014 compare empty-args?, 0/false -1015 { -1016 break-if-= -1017 error trace, "cdr needs 1 args but got 0" -1018 return -1019 } -1020 # args->left -1021 var first-ah/eax: (addr handle cell) <- get args, left -1022 var first/eax: (addr cell) <- lookup *first-ah -1023 var first-type/ecx: (addr int) <- get first, type -1024 compare *first-type, 0/pair -1025 { -1026 break-if-= -1027 error trace, "arg for cdr is not a pair" -1028 return -1029 } -1030 # cdr -1031 var result/eax: (addr handle cell) <- get first, right -1032 copy-object result, out -1033 } -1034 -1035 fn apply-cons _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1036 trace-text trace, "eval", "apply cons" -1037 var args-ah/eax: (addr handle cell) <- copy _args-ah -1038 var _args/eax: (addr cell) <- lookup *args-ah -1039 var args/esi: (addr cell) <- copy _args -1040 # TODO: check that args is a pair -1041 var empty-args?/eax: boolean <- nil? args -1042 compare empty-args?, 0/false -1043 { + 712 { + 713 var cr?/eax: boolean <- string-equal? f-name, "cr" + 714 compare cr?, 0/false + 715 break-if-= + 716 apply-cr args-ah, out, trace + 717 return + 718 } + 719 { + 720 var pixel?/eax: boolean <- string-equal? f-name, "pixel" + 721 compare pixel?, 0/false + 722 break-if-= + 723 apply-pixel args-ah, out, trace + 724 return + 725 } + 726 { + 727 var width?/eax: boolean <- string-equal? f-name, "width" + 728 compare width?, 0/false + 729 break-if-= + 730 apply-width args-ah, out, trace + 731 return + 732 } + 733 { + 734 var height?/eax: boolean <- string-equal? f-name, "height" + 735 compare height?, 0/false + 736 break-if-= + 737 apply-height args-ah, out, trace + 738 return + 739 } + 740 { + 741 var wait-for-key?/eax: boolean <- string-equal? f-name, "key" + 742 compare wait-for-key?, 0/false + 743 break-if-= + 744 apply-wait-for-key args-ah, out, trace + 745 return + 746 } + 747 { + 748 var stream?/eax: boolean <- string-equal? f-name, "stream" + 749 compare stream?, 0/false + 750 break-if-= + 751 apply-stream args-ah, out, trace + 752 return + 753 } + 754 { + 755 var write?/eax: boolean <- string-equal? f-name, "write" + 756 compare write?, 0/false + 757 break-if-= + 758 apply-write args-ah, out, trace + 759 return + 760 } + 761 { + 762 var abort?/eax: boolean <- string-equal? f-name, "abort" + 763 compare abort?, 0/false + 764 break-if-= + 765 apply-abort args-ah, out, trace + 766 return + 767 } + 768 abort "unknown primitive function" + 769 } + 770 + 771 fn apply-add _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + 772 trace-text trace, "eval", "apply +" + 773 var args-ah/eax: (addr handle cell) <- copy _args-ah + 774 var _args/eax: (addr cell) <- lookup *args-ah + 775 var args/esi: (addr cell) <- copy _args + 776 # TODO: check that args is a pair + 777 var empty-args?/eax: boolean <- nil? args + 778 compare empty-args?, 0/false + 779 { + 780 break-if-= + 781 error trace, "+ needs 2 args but got 0" + 782 return + 783 } + 784 # args->left->value + 785 var first-ah/eax: (addr handle cell) <- get args, left + 786 var first/eax: (addr cell) <- lookup *first-ah + 787 var first-type/ecx: (addr int) <- get first, type + 788 compare *first-type, 1/number + 789 { + 790 break-if-= + 791 error trace, "first arg for + is not a number" + 792 return + 793 } + 794 var first-value/ecx: (addr float) <- get first, number-data + 795 # args->right->left->value + 796 var right-ah/eax: (addr handle cell) <- get args, right + 797 #? dump-cell right-ah + 798 #? abort "aaa" + 799 var right/eax: (addr cell) <- lookup *right-ah + 800 # TODO: check that right is a pair + 801 var second-ah/eax: (addr handle cell) <- get right, left + 802 var second/eax: (addr cell) <- lookup *second-ah + 803 var second-type/edx: (addr int) <- get second, type + 804 compare *second-type, 1/number + 805 { + 806 break-if-= + 807 error trace, "second arg for + is not a number" + 808 return + 809 } + 810 var second-value/edx: (addr float) <- get second, number-data + 811 # add + 812 var result/xmm0: float <- copy *first-value + 813 result <- add *second-value + 814 new-float out, result + 815 } + 816 + 817 fn apply-subtract _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + 818 trace-text trace, "eval", "apply -" + 819 var args-ah/eax: (addr handle cell) <- copy _args-ah + 820 var _args/eax: (addr cell) <- lookup *args-ah + 821 var args/esi: (addr cell) <- copy _args + 822 # TODO: check that args is a pair + 823 var empty-args?/eax: boolean <- nil? args + 824 compare empty-args?, 0/false + 825 { + 826 break-if-= + 827 error trace, "- needs 2 args but got 0" + 828 return + 829 } + 830 # args->left->value + 831 var first-ah/eax: (addr handle cell) <- get args, left + 832 var first/eax: (addr cell) <- lookup *first-ah + 833 var first-type/ecx: (addr int) <- get first, type + 834 compare *first-type, 1/number + 835 { + 836 break-if-= + 837 error trace, "first arg for - is not a number" + 838 return + 839 } + 840 var first-value/ecx: (addr float) <- get first, number-data + 841 # args->right->left->value + 842 var right-ah/eax: (addr handle cell) <- get args, right + 843 var right/eax: (addr cell) <- lookup *right-ah + 844 # TODO: check that right is a pair + 845 var second-ah/eax: (addr handle cell) <- get right, left + 846 var second/eax: (addr cell) <- lookup *second-ah + 847 var second-type/edx: (addr int) <- get second, type + 848 compare *second-type, 1/number + 849 { + 850 break-if-= + 851 error trace, "second arg for - is not a number" + 852 return + 853 } + 854 var second-value/edx: (addr float) <- get second, number-data + 855 # subtract + 856 var result/xmm0: float <- copy *first-value + 857 result <- subtract *second-value + 858 new-float out, result + 859 } + 860 + 861 fn apply-multiply _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + 862 trace-text trace, "eval", "apply *" + 863 var args-ah/eax: (addr handle cell) <- copy _args-ah + 864 var _args/eax: (addr cell) <- lookup *args-ah + 865 var args/esi: (addr cell) <- copy _args + 866 # TODO: check that args is a pair + 867 var empty-args?/eax: boolean <- nil? args + 868 compare empty-args?, 0/false + 869 { + 870 break-if-= + 871 error trace, "* needs 2 args but got 0" + 872 return + 873 } + 874 # args->left->value + 875 var first-ah/eax: (addr handle cell) <- get args, left + 876 var first/eax: (addr cell) <- lookup *first-ah + 877 var first-type/ecx: (addr int) <- get first, type + 878 compare *first-type, 1/number + 879 { + 880 break-if-= + 881 error trace, "first arg for * is not a number" + 882 return + 883 } + 884 var first-value/ecx: (addr float) <- get first, number-data + 885 # args->right->left->value + 886 var right-ah/eax: (addr handle cell) <- get args, right + 887 var right/eax: (addr cell) <- lookup *right-ah + 888 # TODO: check that right is a pair + 889 var second-ah/eax: (addr handle cell) <- get right, left + 890 var second/eax: (addr cell) <- lookup *second-ah + 891 var second-type/edx: (addr int) <- get second, type + 892 compare *second-type, 1/number + 893 { + 894 break-if-= + 895 error trace, "second arg for * is not a number" + 896 return + 897 } + 898 var second-value/edx: (addr float) <- get second, number-data + 899 # multiply + 900 var result/xmm0: float <- copy *first-value + 901 result <- multiply *second-value + 902 new-float out, result + 903 } + 904 + 905 fn apply-divide _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + 906 trace-text trace, "eval", "apply /" + 907 var args-ah/eax: (addr handle cell) <- copy _args-ah + 908 var _args/eax: (addr cell) <- lookup *args-ah + 909 var args/esi: (addr cell) <- copy _args + 910 # TODO: check that args is a pair + 911 var empty-args?/eax: boolean <- nil? args + 912 compare empty-args?, 0/false + 913 { + 914 break-if-= + 915 error trace, "/ needs 2 args but got 0" + 916 return + 917 } + 918 # args->left->value + 919 var first-ah/eax: (addr handle cell) <- get args, left + 920 var first/eax: (addr cell) <- lookup *first-ah + 921 var first-type/ecx: (addr int) <- get first, type + 922 compare *first-type, 1/number + 923 { + 924 break-if-= + 925 error trace, "first arg for / is not a number" + 926 return + 927 } + 928 var first-value/ecx: (addr float) <- get first, number-data + 929 # args->right->left->value + 930 var right-ah/eax: (addr handle cell) <- get args, right + 931 var right/eax: (addr cell) <- lookup *right-ah + 932 # TODO: check that right is a pair + 933 var second-ah/eax: (addr handle cell) <- get right, left + 934 var second/eax: (addr cell) <- lookup *second-ah + 935 var second-type/edx: (addr int) <- get second, type + 936 compare *second-type, 1/number + 937 { + 938 break-if-= + 939 error trace, "second arg for / is not a number" + 940 return + 941 } + 942 var second-value/edx: (addr float) <- get second, number-data + 943 # divide + 944 var result/xmm0: float <- copy *first-value + 945 result <- divide *second-value + 946 new-float out, result + 947 } + 948 + 949 fn apply-square-root _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + 950 trace-text trace, "eval", "apply sqrt" + 951 var args-ah/eax: (addr handle cell) <- copy _args-ah + 952 var _args/eax: (addr cell) <- lookup *args-ah + 953 var args/esi: (addr cell) <- copy _args + 954 # TODO: check that args is a pair + 955 var empty-args?/eax: boolean <- nil? args + 956 compare empty-args?, 0/false + 957 { + 958 break-if-= + 959 error trace, "sqrt needs 1 arg but got 0" + 960 return + 961 } + 962 # args->left->value + 963 var first-ah/eax: (addr handle cell) <- get args, left + 964 var first/eax: (addr cell) <- lookup *first-ah + 965 var first-type/ecx: (addr int) <- get first, type + 966 compare *first-type, 1/number + 967 { + 968 break-if-= + 969 error trace, "arg for sqrt is not a number" + 970 return + 971 } + 972 var first-value/ecx: (addr float) <- get first, number-data + 973 # square-root + 974 var result/xmm0: float <- square-root *first-value + 975 new-float out, result + 976 } + 977 + 978 fn apply-abs _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + 979 trace-text trace, "eval", "apply abs" + 980 var args-ah/eax: (addr handle cell) <- copy _args-ah + 981 var _args/eax: (addr cell) <- lookup *args-ah + 982 var args/esi: (addr cell) <- copy _args + 983 # TODO: check that args is a pair + 984 var empty-args?/eax: boolean <- nil? args + 985 compare empty-args?, 0/false + 986 { + 987 break-if-= + 988 error trace, "abs needs 1 arg but got 0" + 989 return + 990 } + 991 # args->left->value + 992 var first-ah/eax: (addr handle cell) <- get args, left + 993 var first/eax: (addr cell) <- lookup *first-ah + 994 var first-type/ecx: (addr int) <- get first, type + 995 compare *first-type, 1/number + 996 { + 997 break-if-= + 998 error trace, "arg for abs is not a number" + 999 return +1000 } +1001 var first-value/ecx: (addr float) <- get first, number-data +1002 # +1003 var result/xmm0: float <- copy *first-value +1004 var zero: float +1005 compare result, zero +1006 { +1007 break-if-float>= +1008 var neg1/eax: int <- copy -1 +1009 var neg1-f/xmm1: float <- convert neg1 +1010 result <- multiply neg1-f +1011 } +1012 new-float out, result +1013 } +1014 +1015 fn apply-sgn _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1016 trace-text trace, "eval", "apply sgn" +1017 var args-ah/eax: (addr handle cell) <- copy _args-ah +1018 var _args/eax: (addr cell) <- lookup *args-ah +1019 var args/esi: (addr cell) <- copy _args +1020 # TODO: check that args is a pair +1021 var empty-args?/eax: boolean <- nil? args +1022 compare empty-args?, 0/false +1023 { +1024 break-if-= +1025 error trace, "sgn needs 1 arg but got 0" +1026 return +1027 } +1028 # args->left->value +1029 var first-ah/eax: (addr handle cell) <- get args, left +1030 var first/eax: (addr cell) <- lookup *first-ah +1031 var first-type/ecx: (addr int) <- get first, type +1032 compare *first-type, 1/number +1033 { +1034 break-if-= +1035 error trace, "arg for sgn is not a number" +1036 return +1037 } +1038 var first-value/ecx: (addr float) <- get first, number-data +1039 # +1040 var result/xmm0: float <- copy *first-value +1041 var zero: float +1042 $apply-sgn:core: { +1043 compare result, zero 1044 break-if-= -1045 error trace, "cons needs 2 args but got 0" -1046 return -1047 } -1048 # args->left -1049 var first-ah/ecx: (addr handle cell) <- get args, left -1050 # args->right->left -1051 var right-ah/eax: (addr handle cell) <- get args, right -1052 var right/eax: (addr cell) <- lookup *right-ah -1053 # TODO: check that right is a pair -1054 var second-ah/eax: (addr handle cell) <- get right, left -1055 # cons -1056 new-pair out, *first-ah, *second-ah -1057 } -1058 -1059 fn apply-structurally-equal _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1060 trace-text trace, "eval", "apply '='" -1061 var args-ah/eax: (addr handle cell) <- copy _args-ah -1062 var _args/eax: (addr cell) <- lookup *args-ah -1063 var args/esi: (addr cell) <- copy _args -1064 # TODO: check that args is a pair -1065 var empty-args?/eax: boolean <- nil? args -1066 compare empty-args?, 0/false -1067 { -1068 break-if-= -1069 error trace, "'=' needs 2 args but got 0" -1070 return -1071 } -1072 # args->left -1073 var first-ah/ecx: (addr handle cell) <- get args, left -1074 # args->right->left -1075 var right-ah/eax: (addr handle cell) <- get args, right -1076 var right/eax: (addr cell) <- lookup *right-ah -1077 # TODO: check that right is a pair -1078 var second-ah/edx: (addr handle cell) <- get right, left -1079 # compare -1080 var _first/eax: (addr cell) <- lookup *first-ah -1081 var first/ecx: (addr cell) <- copy _first -1082 var second/eax: (addr cell) <- lookup *second-ah -1083 var match?/eax: boolean <- cell-isomorphic? first, second, trace -1084 compare match?, 0/false -1085 { -1086 break-if-!= -1087 nil out -1088 return -1089 } -1090 new-integer out, 1/true -1091 } -1092 -1093 fn apply-not _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1094 trace-text trace, "eval", "apply not" -1095 var args-ah/eax: (addr handle cell) <- copy _args-ah -1096 var _args/eax: (addr cell) <- lookup *args-ah -1097 var args/esi: (addr cell) <- copy _args -1098 # TODO: check that args is a pair -1099 var empty-args?/eax: boolean <- nil? args -1100 compare empty-args?, 0/false -1101 { -1102 break-if-= -1103 error trace, "not needs 1 args but got 0" -1104 return -1105 } -1106 # args->left -1107 var first-ah/eax: (addr handle cell) <- get args, left -1108 var first/eax: (addr cell) <- lookup *first-ah -1109 # not -1110 var nil?/eax: boolean <- nil? first -1111 compare nil?, 0/false -1112 { -1113 break-if-!= -1114 nil out -1115 return -1116 } -1117 new-integer out, 1 -1118 } -1119 -1120 fn apply-< _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1121 trace-text trace, "eval", "apply '<'" -1122 var args-ah/eax: (addr handle cell) <- copy _args-ah -1123 var _args/eax: (addr cell) <- lookup *args-ah -1124 var args/esi: (addr cell) <- copy _args -1125 # TODO: check that args is a pair -1126 var empty-args?/eax: boolean <- nil? args -1127 compare empty-args?, 0/false -1128 { -1129 break-if-= -1130 error trace, "'<' needs 2 args but got 0" -1131 return -1132 } -1133 # args->left -1134 var first-ah/ecx: (addr handle cell) <- get args, left -1135 # args->right->left -1136 var right-ah/eax: (addr handle cell) <- get args, right -1137 var right/eax: (addr cell) <- lookup *right-ah -1138 # TODO: check that right is a pair -1139 var second-ah/edx: (addr handle cell) <- get right, left -1140 # compare -1141 var _first/eax: (addr cell) <- lookup *first-ah -1142 var first/ecx: (addr cell) <- copy _first -1143 var first-type/eax: (addr int) <- get first, type -1144 compare *first-type, 1/number -1145 { -1146 break-if-= -1147 error trace, "first arg for '<' is not a number" -1148 return -1149 } -1150 var first-value/ecx: (addr float) <- get first, number-data -1151 var first-float/xmm0: float <- copy *first-value -1152 var second/eax: (addr cell) <- lookup *second-ah -1153 var second-type/edx: (addr int) <- get second, type -1154 compare *second-type, 1/number -1155 { -1156 break-if-= -1157 error trace, "first arg for '<' is not a number" -1158 return -1159 } -1160 var second-value/eax: (addr float) <- get second, number-data -1161 compare first-float, *second-value -1162 { -1163 break-if-float< -1164 nil out -1165 return -1166 } -1167 new-integer out, 1/true -1168 } -1169 -1170 fn apply-> _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1171 trace-text trace, "eval", "apply '>'" -1172 var args-ah/eax: (addr handle cell) <- copy _args-ah -1173 var _args/eax: (addr cell) <- lookup *args-ah -1174 var args/esi: (addr cell) <- copy _args -1175 # TODO: check that args is a pair -1176 var empty-args?/eax: boolean <- nil? args -1177 compare empty-args?, 0/false -1178 { -1179 break-if-= -1180 error trace, "'>' needs 2 args but got 0" -1181 return -1182 } -1183 # args->left -1184 var first-ah/ecx: (addr handle cell) <- get args, left -1185 # args->right->left -1186 var right-ah/eax: (addr handle cell) <- get args, right -1187 var right/eax: (addr cell) <- lookup *right-ah -1188 # TODO: check that right is a pair -1189 var second-ah/edx: (addr handle cell) <- get right, left -1190 # compare -1191 var _first/eax: (addr cell) <- lookup *first-ah -1192 var first/ecx: (addr cell) <- copy _first -1193 var first-type/eax: (addr int) <- get first, type -1194 compare *first-type, 1/number -1195 { -1196 break-if-= -1197 error trace, "first arg for '>' is not a number" -1198 return -1199 } -1200 var first-value/ecx: (addr float) <- get first, number-data -1201 var first-float/xmm0: float <- copy *first-value -1202 var second/eax: (addr cell) <- lookup *second-ah -1203 var second-type/edx: (addr int) <- get second, type -1204 compare *second-type, 1/number -1205 { -1206 break-if-= -1207 error trace, "first arg for '>' is not a number" -1208 return -1209 } -1210 var second-value/eax: (addr float) <- get second, number-data -1211 compare first-float, *second-value -1212 { -1213 break-if-float> -1214 nil out -1215 return -1216 } -1217 new-integer out, 1/true -1218 } -1219 -1220 fn apply-<= _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1221 trace-text trace, "eval", "apply '<='" -1222 var args-ah/eax: (addr handle cell) <- copy _args-ah -1223 var _args/eax: (addr cell) <- lookup *args-ah -1224 var args/esi: (addr cell) <- copy _args -1225 # TODO: check that args is a pair -1226 var empty-args?/eax: boolean <- nil? args -1227 compare empty-args?, 0/false -1228 { -1229 break-if-= -1230 error trace, "'<=' needs 2 args but got 0" -1231 return -1232 } -1233 # args->left -1234 var first-ah/ecx: (addr handle cell) <- get args, left -1235 # args->right->left -1236 var right-ah/eax: (addr handle cell) <- get args, right -1237 var right/eax: (addr cell) <- lookup *right-ah -1238 # TODO: check that right is a pair -1239 var second-ah/edx: (addr handle cell) <- get right, left -1240 # compare -1241 var _first/eax: (addr cell) <- lookup *first-ah -1242 var first/ecx: (addr cell) <- copy _first -1243 var first-type/eax: (addr int) <- get first, type -1244 compare *first-type, 1/number -1245 { -1246 break-if-= -1247 error trace, "first arg for '<=' is not a number" -1248 return -1249 } -1250 var first-value/ecx: (addr float) <- get first, number-data -1251 var first-float/xmm0: float <- copy *first-value -1252 var second/eax: (addr cell) <- lookup *second-ah -1253 var second-type/edx: (addr int) <- get second, type -1254 compare *second-type, 1/number -1255 { -1256 break-if-= -1257 error trace, "first arg for '<=' is not a number" -1258 return -1259 } -1260 var second-value/eax: (addr float) <- get second, number-data -1261 compare first-float, *second-value -1262 { -1263 break-if-float<= -1264 nil out -1265 return -1266 } -1267 new-integer out, 1/true -1268 } -1269 -1270 fn apply->= _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1271 trace-text trace, "eval", "apply '>='" -1272 var args-ah/eax: (addr handle cell) <- copy _args-ah -1273 var _args/eax: (addr cell) <- lookup *args-ah -1274 var args/esi: (addr cell) <- copy _args -1275 # TODO: check that args is a pair -1276 var empty-args?/eax: boolean <- nil? args -1277 compare empty-args?, 0/false -1278 { -1279 break-if-= -1280 error trace, "'>=' needs 2 args but got 0" -1281 return -1282 } -1283 # args->left -1284 var first-ah/ecx: (addr handle cell) <- get args, left -1285 # args->right->left -1286 var right-ah/eax: (addr handle cell) <- get args, right -1287 var right/eax: (addr cell) <- lookup *right-ah -1288 # TODO: check that right is a pair -1289 var second-ah/edx: (addr handle cell) <- get right, left -1290 # compare -1291 var _first/eax: (addr cell) <- lookup *first-ah -1292 var first/ecx: (addr cell) <- copy _first -1293 var first-type/eax: (addr int) <- get first, type -1294 compare *first-type, 1/number -1295 { -1296 break-if-= -1297 error trace, "first arg for '>=' is not a number" -1298 return -1299 } -1300 var first-value/ecx: (addr float) <- get first, number-data -1301 var first-float/xmm0: float <- copy *first-value -1302 var second/eax: (addr cell) <- lookup *second-ah -1303 var second-type/edx: (addr int) <- get second, type -1304 compare *second-type, 1/number -1305 { -1306 break-if-= -1307 error trace, "first arg for '>=' is not a number" -1308 return -1309 } -1310 var second-value/eax: (addr float) <- get second, number-data -1311 compare first-float, *second-value -1312 { -1313 break-if-float>= -1314 nil out -1315 return -1316 } -1317 new-integer out, 1/true -1318 } -1319 -1320 fn apply-print _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1321 trace-text trace, "eval", "apply print" -1322 var args-ah/eax: (addr handle cell) <- copy _args-ah -1323 var _args/eax: (addr cell) <- lookup *args-ah -1324 var args/esi: (addr cell) <- copy _args -1325 # TODO: check that args is a pair -1326 var empty-args?/eax: boolean <- nil? args -1327 compare empty-args?, 0/false -1328 { -1329 break-if-= -1330 error trace, "print needs 2 args but got 0" -1331 return -1332 } -1333 # screen = args->left -1334 var first-ah/eax: (addr handle cell) <- get args, left -1335 var first/eax: (addr cell) <- lookup *first-ah -1336 var first-type/ecx: (addr int) <- get first, type -1337 compare *first-type, 5/screen -1338 { -1339 break-if-= -1340 error trace, "first arg for 'print' is not a screen" -1341 return -1342 } -1343 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1344 var _screen/eax: (addr screen) <- lookup *screen-ah -1345 var screen/ecx: (addr screen) <- copy _screen -1346 # args->right->left -1347 var right-ah/eax: (addr handle cell) <- get args, right -1348 var right/eax: (addr cell) <- lookup *right-ah -1349 # TODO: check that right is a pair -1350 var second-ah/eax: (addr handle cell) <- get right, left -1351 var stream-storage: (stream byte 0x100) -1352 var stream/edi: (addr stream byte) <- address stream-storage -1353 print-cell second-ah, stream, trace -1354 draw-stream-wrapping-right-then-down-from-cursor-over-full-screen screen, stream, 7/fg, 0/bg -1355 # return what was printed -1356 copy-object second-ah, out -1357 } -1358 -1359 fn apply-clear _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1360 trace-text trace, "eval", "apply clear" -1361 var args-ah/eax: (addr handle cell) <- copy _args-ah -1362 var _args/eax: (addr cell) <- lookup *args-ah -1363 var args/esi: (addr cell) <- copy _args -1364 # TODO: check that args is a pair -1365 var empty-args?/eax: boolean <- nil? args -1366 compare empty-args?, 0/false -1367 { -1368 break-if-= -1369 error trace, "'clear' needs 1 arg but got 0" -1370 return -1371 } -1372 # screen = args->left -1373 var first-ah/eax: (addr handle cell) <- get args, left -1374 var first/eax: (addr cell) <- lookup *first-ah -1375 var first-type/ecx: (addr int) <- get first, type -1376 compare *first-type, 5/screen -1377 { -1378 break-if-= -1379 error trace, "first arg for 'clear' is not a screen" -1380 return -1381 } -1382 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1383 var _screen/eax: (addr screen) <- lookup *screen-ah -1384 var screen/ecx: (addr screen) <- copy _screen -1385 # -1386 clear-screen screen -1387 } -1388 -1389 fn apply-up _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1390 trace-text trace, "eval", "apply up" -1391 var args-ah/eax: (addr handle cell) <- copy _args-ah -1392 var _args/eax: (addr cell) <- lookup *args-ah -1393 var args/esi: (addr cell) <- copy _args -1394 # TODO: check that args is a pair -1395 var empty-args?/eax: boolean <- nil? args -1396 compare empty-args?, 0/false -1397 { -1398 break-if-= -1399 error trace, "'up' needs 1 arg but got 0" -1400 return -1401 } -1402 # screen = args->left -1403 var first-ah/eax: (addr handle cell) <- get args, left -1404 var first/eax: (addr cell) <- lookup *first-ah -1405 var first-type/ecx: (addr int) <- get first, type -1406 compare *first-type, 5/screen -1407 { -1408 break-if-= -1409 error trace, "first arg for 'up' is not a screen" -1410 return -1411 } -1412 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1413 var _screen/eax: (addr screen) <- lookup *screen-ah -1414 var screen/ecx: (addr screen) <- copy _screen -1415 # -1416 move-cursor-up screen -1417 } -1418 -1419 fn apply-down _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1420 trace-text trace, "eval", "apply 'down'" -1421 var args-ah/eax: (addr handle cell) <- copy _args-ah -1422 var _args/eax: (addr cell) <- lookup *args-ah -1423 var args/esi: (addr cell) <- copy _args -1424 # TODO: check that args is a pair -1425 var empty-args?/eax: boolean <- nil? args -1426 compare empty-args?, 0/false -1427 { -1428 break-if-= -1429 error trace, "'down' needs 1 arg but got 0" -1430 return -1431 } -1432 # screen = args->left -1433 var first-ah/eax: (addr handle cell) <- get args, left -1434 var first/eax: (addr cell) <- lookup *first-ah -1435 var first-type/ecx: (addr int) <- get first, type -1436 compare *first-type, 5/screen -1437 { -1438 break-if-= -1439 error trace, "first arg for 'down' is not a screen" -1440 return -1441 } -1442 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1443 var _screen/eax: (addr screen) <- lookup *screen-ah -1444 var screen/ecx: (addr screen) <- copy _screen -1445 # -1446 move-cursor-down screen -1447 } -1448 -1449 fn apply-left _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1450 trace-text trace, "eval", "apply 'left'" -1451 var args-ah/eax: (addr handle cell) <- copy _args-ah -1452 var _args/eax: (addr cell) <- lookup *args-ah -1453 var args/esi: (addr cell) <- copy _args -1454 # TODO: check that args is a pair -1455 var empty-args?/eax: boolean <- nil? args -1456 compare empty-args?, 0/false -1457 { -1458 break-if-= -1459 error trace, "'left' needs 1 arg but got 0" -1460 return -1461 } -1462 # screen = args->left -1463 var first-ah/eax: (addr handle cell) <- get args, left -1464 var first/eax: (addr cell) <- lookup *first-ah -1465 var first-type/ecx: (addr int) <- get first, type -1466 compare *first-type, 5/screen -1467 { -1468 break-if-= -1469 error trace, "first arg for 'left' is not a screen" -1470 return -1471 } -1472 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1473 var _screen/eax: (addr screen) <- lookup *screen-ah -1474 var screen/ecx: (addr screen) <- copy _screen -1475 # -1476 move-cursor-left screen -1477 } -1478 -1479 fn apply-right _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1480 trace-text trace, "eval", "apply 'right'" -1481 var args-ah/eax: (addr handle cell) <- copy _args-ah -1482 var _args/eax: (addr cell) <- lookup *args-ah -1483 var args/esi: (addr cell) <- copy _args -1484 # TODO: check that args is a pair -1485 var empty-args?/eax: boolean <- nil? args -1486 compare empty-args?, 0/false -1487 { -1488 break-if-= -1489 error trace, "'right' needs 1 arg but got 0" -1490 return -1491 } -1492 # screen = args->left -1493 var first-ah/eax: (addr handle cell) <- get args, left -1494 var first/eax: (addr cell) <- lookup *first-ah -1495 var first-type/ecx: (addr int) <- get first, type -1496 compare *first-type, 5/screen -1497 { -1498 break-if-= -1499 error trace, "first arg for 'right' is not a screen" -1500 return -1501 } -1502 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1503 var _screen/eax: (addr screen) <- lookup *screen-ah -1504 var screen/ecx: (addr screen) <- copy _screen -1505 # -1506 move-cursor-right screen -1507 } -1508 -1509 fn apply-cr _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1510 trace-text trace, "eval", "apply 'cr'" -1511 var args-ah/eax: (addr handle cell) <- copy _args-ah -1512 var _args/eax: (addr cell) <- lookup *args-ah -1513 var args/esi: (addr cell) <- copy _args -1514 # TODO: check that args is a pair -1515 var empty-args?/eax: boolean <- nil? args -1516 compare empty-args?, 0/false -1517 { -1518 break-if-= -1519 error trace, "'cr' needs 1 arg but got 0" -1520 return -1521 } -1522 # screen = args->left -1523 var first-ah/eax: (addr handle cell) <- get args, left -1524 var first/eax: (addr cell) <- lookup *first-ah -1525 var first-type/ecx: (addr int) <- get first, type -1526 compare *first-type, 5/screen -1527 { -1528 break-if-= -1529 error trace, "first arg for 'cr' is not a screen" -1530 return -1531 } -1532 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1533 var _screen/eax: (addr screen) <- lookup *screen-ah -1534 var screen/ecx: (addr screen) <- copy _screen -1535 # -1536 move-cursor-to-left-margin-of-next-line screen -1537 } -1538 -1539 fn apply-pixel _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1540 trace-text trace, "eval", "apply pixel" -1541 var args-ah/eax: (addr handle cell) <- copy _args-ah -1542 var _args/eax: (addr cell) <- lookup *args-ah -1543 var args/esi: (addr cell) <- copy _args -1544 # TODO: check that args is a pair -1545 var empty-args?/eax: boolean <- nil? args -1546 compare empty-args?, 0/false -1547 { -1548 break-if-= -1549 error trace, "pixel needs 4 args but got 0" -1550 return -1551 } -1552 # screen = args->left -1553 var first-ah/eax: (addr handle cell) <- get args, left -1554 var first/eax: (addr cell) <- lookup *first-ah -1555 var first-type/ecx: (addr int) <- get first, type -1556 compare *first-type, 5/screen -1557 { -1558 break-if-= -1559 error trace, "first arg for 'pixel' is not a screen" -1560 return -1561 } -1562 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1563 var _screen/eax: (addr screen) <- lookup *screen-ah -1564 var screen/edi: (addr screen) <- copy _screen -1565 # x = args->right->left->value -1566 var rest-ah/eax: (addr handle cell) <- get args, right -1567 var _rest/eax: (addr cell) <- lookup *rest-ah -1568 var rest/esi: (addr cell) <- copy _rest -1569 # TODO: check that rest is a pair -1570 var second-ah/eax: (addr handle cell) <- get rest, left -1571 var second/eax: (addr cell) <- lookup *second-ah -1572 var second-type/ecx: (addr int) <- get second, type -1573 compare *second-type, 1/number -1574 { -1575 break-if-= -1576 error trace, "second arg for 'pixel' is not an int (x coordinate)" -1577 return -1578 } -1579 var second-value/eax: (addr float) <- get second, number-data -1580 var x/edx: int <- convert *second-value -1581 # y = rest->right->left->value -1582 var rest-ah/eax: (addr handle cell) <- get rest, right -1583 var _rest/eax: (addr cell) <- lookup *rest-ah -1584 rest <- copy _rest -1585 # TODO: check that rest is a pair -1586 var third-ah/eax: (addr handle cell) <- get rest, left -1587 var third/eax: (addr cell) <- lookup *third-ah -1588 var third-type/ecx: (addr int) <- get third, type -1589 compare *third-type, 1/number -1590 { -1591 break-if-= -1592 error trace, "third arg for 'pixel' is not an int (y coordinate)" -1593 return -1594 } -1595 var third-value/eax: (addr float) <- get third, number-data -1596 var y/ebx: int <- convert *third-value -1597 # color = rest->right->left->value -1598 var rest-ah/eax: (addr handle cell) <- get rest, right -1599 var _rest/eax: (addr cell) <- lookup *rest-ah -1600 rest <- copy _rest -1601 # TODO: check that rest is a pair -1602 var fourth-ah/eax: (addr handle cell) <- get rest, left -1603 var fourth/eax: (addr cell) <- lookup *fourth-ah -1604 var fourth-type/ecx: (addr int) <- get fourth, type -1605 compare *fourth-type, 1/number -1606 { -1607 break-if-= -1608 error trace, "fourth arg for 'pixel' is not an int (color; 0..0xff)" -1609 return -1610 } -1611 var fourth-value/eax: (addr float) <- get fourth, number-data -1612 var color/eax: int <- convert *fourth-value -1613 pixel screen, x, y, color -1614 # return nothing -1615 } -1616 -1617 fn apply-wait-for-key _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1618 trace-text trace, "eval", "apply key" -1619 var args-ah/eax: (addr handle cell) <- copy _args-ah -1620 var _args/eax: (addr cell) <- lookup *args-ah -1621 var args/esi: (addr cell) <- copy _args -1622 # TODO: check that args is a pair -1623 var empty-args?/eax: boolean <- nil? args -1624 compare empty-args?, 0/false -1625 { -1626 break-if-= -1627 error trace, "key needs 1 arg but got 0" -1628 return -1629 } -1630 # keyboard = args->left -1631 var first-ah/eax: (addr handle cell) <- get args, left -1632 var first/eax: (addr cell) <- lookup *first-ah -1633 var first-type/ecx: (addr int) <- get first, type -1634 compare *first-type, 6/keyboard -1635 { -1636 break-if-= -1637 error trace, "first arg for 'key' is not a keyboard" -1638 return -1639 } -1640 var keyboard-ah/eax: (addr handle gap-buffer) <- get first, keyboard-data -1641 var _keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah -1642 var keyboard/ecx: (addr gap-buffer) <- copy _keyboard -1643 var result/eax: int <- wait-for-key keyboard -1644 # return key typed -1645 new-integer out, result -1646 } -1647 -1648 fn wait-for-key keyboard: (addr gap-buffer) -> _/eax: int { -1649 # if keyboard is 0, use real keyboard -1650 { -1651 compare keyboard, 0/real-keyboard -1652 break-if-!= -1653 var key/eax: byte <- read-key 0/real-keyboard -1654 var result/eax: int <- copy key -1655 return result -1656 } -1657 # otherwise read from fake keyboard -1658 var g/eax: grapheme <- read-from-gap-buffer keyboard -1659 var result/eax: int <- copy g -1660 return result -1661 } -1662 -1663 fn apply-stream _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1664 trace-text trace, "eval", "apply stream" -1665 allocate-stream out -1666 } -1667 -1668 fn apply-write _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1669 trace-text trace, "eval", "apply write" -1670 var args-ah/eax: (addr handle cell) <- copy _args-ah -1671 var _args/eax: (addr cell) <- lookup *args-ah -1672 var args/esi: (addr cell) <- copy _args -1673 # TODO: check that args is a pair -1674 var empty-args?/eax: boolean <- nil? args -1675 compare empty-args?, 0/false -1676 { -1677 break-if-= -1678 error trace, "write needs 2 args but got 0" -1679 return -1680 } -1681 # stream = args->left -1682 var first-ah/edx: (addr handle cell) <- get args, left -1683 var first/eax: (addr cell) <- lookup *first-ah -1684 var first-type/ecx: (addr int) <- get first, type -1685 compare *first-type, 3/stream -1686 { -1687 break-if-= -1688 error trace, "first arg for 'write' is not a stream" -1689 return -1690 } -1691 var stream-data-ah/eax: (addr handle stream byte) <- get first, text-data -1692 var _stream-data/eax: (addr stream byte) <- lookup *stream-data-ah -1693 var stream-data/ebx: (addr stream byte) <- copy _stream-data -1694 # args->right->left -1695 var right-ah/eax: (addr handle cell) <- get args, right -1696 var right/eax: (addr cell) <- lookup *right-ah -1697 # TODO: check that right is a pair -1698 var second-ah/eax: (addr handle cell) <- get right, left -1699 var second/eax: (addr cell) <- lookup *second-ah -1700 var second-type/ecx: (addr int) <- get second, type -1701 compare *second-type, 1/number -1702 { -1703 break-if-= -1704 error trace, "second arg for stream is not a number/grapheme" -1705 return -1706 } -1707 var second-value/eax: (addr float) <- get second, number-data -1708 var x-float/xmm0: float <- copy *second-value -1709 var x/eax: int <- convert x-float -1710 var x-grapheme/eax: grapheme <- copy x -1711 write-grapheme stream-data, x-grapheme -1712 # return the stream -1713 copy-object first-ah, out -1714 } -1715 -1716 fn apply-lines _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1717 trace-text trace, "eval", "apply lines" -1718 var args-ah/eax: (addr handle cell) <- copy _args-ah -1719 var _args/eax: (addr cell) <- lookup *args-ah -1720 var args/esi: (addr cell) <- copy _args -1721 # TODO: check that args is a pair -1722 var empty-args?/eax: boolean <- nil? args -1723 compare empty-args?, 0/false -1724 { -1725 break-if-= -1726 error trace, "lines needs 1 arg but got 0" -1727 return -1728 } -1729 # screen = args->left -1730 var first-ah/eax: (addr handle cell) <- get args, left -1731 var first/eax: (addr cell) <- lookup *first-ah -1732 var first-type/ecx: (addr int) <- get first, type -1733 compare *first-type, 5/screen -1734 { -1735 break-if-= -1736 error trace, "first arg for 'lines' is not a screen" -1737 return -1738 } -1739 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1740 var _screen/eax: (addr screen) <- lookup *screen-ah -1741 var screen/edx: (addr screen) <- copy _screen -1742 # compute dimensions -1743 var dummy/eax: int <- copy 0 -1744 var height/ecx: int <- copy 0 -1745 dummy, height <- screen-size screen -1746 var result/xmm0: float <- convert height -1747 new-float out, result -1748 } -1749 -1750 fn apply-abort _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1751 abort "aa" +1045 { +1046 break-if-float> +1047 var neg1/eax: int <- copy -1 +1048 result <- convert neg1 +1049 break $apply-sgn:core +1050 } +1051 { +1052 break-if-float< +1053 var one/eax: int <- copy 1 +1054 result <- convert one +1055 break $apply-sgn:core +1056 } +1057 } +1058 new-float out, result +1059 } +1060 +1061 fn apply-car _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1062 trace-text trace, "eval", "apply car" +1063 var args-ah/eax: (addr handle cell) <- copy _args-ah +1064 var _args/eax: (addr cell) <- lookup *args-ah +1065 var args/esi: (addr cell) <- copy _args +1066 # TODO: check that args is a pair +1067 var empty-args?/eax: boolean <- nil? args +1068 compare empty-args?, 0/false +1069 { +1070 break-if-= +1071 error trace, "car needs 1 arg but got 0" +1072 return +1073 } +1074 # args->left +1075 var first-ah/eax: (addr handle cell) <- get args, left +1076 var first/eax: (addr cell) <- lookup *first-ah +1077 var first-type/ecx: (addr int) <- get first, type +1078 compare *first-type, 0/pair +1079 { +1080 break-if-= +1081 error trace, "arg for car is not a pair" +1082 return +1083 } +1084 # car +1085 var result/eax: (addr handle cell) <- get first, left +1086 copy-object result, out +1087 } +1088 +1089 fn apply-cdr _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1090 trace-text trace, "eval", "apply cdr" +1091 var args-ah/eax: (addr handle cell) <- copy _args-ah +1092 var _args/eax: (addr cell) <- lookup *args-ah +1093 var args/esi: (addr cell) <- copy _args +1094 # TODO: check that args is a pair +1095 var empty-args?/eax: boolean <- nil? args +1096 compare empty-args?, 0/false +1097 { +1098 break-if-= +1099 error trace, "cdr needs 1 arg but got 0" +1100 return +1101 } +1102 # args->left +1103 var first-ah/eax: (addr handle cell) <- get args, left +1104 var first/eax: (addr cell) <- lookup *first-ah +1105 var first-type/ecx: (addr int) <- get first, type +1106 compare *first-type, 0/pair +1107 { +1108 break-if-= +1109 error trace, "arg for cdr is not a pair" +1110 return +1111 } +1112 # cdr +1113 var result/eax: (addr handle cell) <- get first, right +1114 copy-object result, out +1115 } +1116 +1117 fn apply-cons _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1118 trace-text trace, "eval", "apply cons" +1119 var args-ah/eax: (addr handle cell) <- copy _args-ah +1120 var _args/eax: (addr cell) <- lookup *args-ah +1121 var args/esi: (addr cell) <- copy _args +1122 # TODO: check that args is a pair +1123 var empty-args?/eax: boolean <- nil? args +1124 compare empty-args?, 0/false +1125 { +1126 break-if-= +1127 error trace, "cons needs 2 args but got 0" +1128 return +1129 } +1130 # args->left +1131 var first-ah/ecx: (addr handle cell) <- get args, left +1132 # args->right->left +1133 var right-ah/eax: (addr handle cell) <- get args, right +1134 var right/eax: (addr cell) <- lookup *right-ah +1135 # TODO: check that right is a pair +1136 var second-ah/eax: (addr handle cell) <- get right, left +1137 # cons +1138 new-pair out, *first-ah, *second-ah +1139 } +1140 +1141 fn apply-structurally-equal _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1142 trace-text trace, "eval", "apply '='" +1143 var args-ah/eax: (addr handle cell) <- copy _args-ah +1144 var _args/eax: (addr cell) <- lookup *args-ah +1145 var args/esi: (addr cell) <- copy _args +1146 # TODO: check that args is a pair +1147 var empty-args?/eax: boolean <- nil? args +1148 compare empty-args?, 0/false +1149 { +1150 break-if-= +1151 error trace, "'=' needs 2 args but got 0" +1152 return +1153 } +1154 # args->left +1155 var first-ah/ecx: (addr handle cell) <- get args, left +1156 # args->right->left +1157 var right-ah/eax: (addr handle cell) <- get args, right +1158 var right/eax: (addr cell) <- lookup *right-ah +1159 # TODO: check that right is a pair +1160 var second-ah/edx: (addr handle cell) <- get right, left +1161 # compare +1162 var _first/eax: (addr cell) <- lookup *first-ah +1163 var first/ecx: (addr cell) <- copy _first +1164 var second/eax: (addr cell) <- lookup *second-ah +1165 var match?/eax: boolean <- cell-isomorphic? first, second, trace +1166 compare match?, 0/false +1167 { +1168 break-if-!= +1169 nil out +1170 return +1171 } +1172 new-integer out, 1/true +1173 } +1174 +1175 fn apply-not _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1176 trace-text trace, "eval", "apply not" +1177 var args-ah/eax: (addr handle cell) <- copy _args-ah +1178 var _args/eax: (addr cell) <- lookup *args-ah +1179 var args/esi: (addr cell) <- copy _args +1180 # TODO: check that args is a pair +1181 var empty-args?/eax: boolean <- nil? args +1182 compare empty-args?, 0/false +1183 { +1184 break-if-= +1185 error trace, "not needs 1 arg but got 0" +1186 return +1187 } +1188 # args->left +1189 var first-ah/eax: (addr handle cell) <- get args, left +1190 var first/eax: (addr cell) <- lookup *first-ah +1191 # not +1192 var nil?/eax: boolean <- nil? first +1193 compare nil?, 0/false +1194 { +1195 break-if-!= +1196 nil out +1197 return +1198 } +1199 new-integer out, 1 +1200 } +1201 +1202 fn apply-debug _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1203 trace-text trace, "eval", "apply debug" +1204 var args-ah/eax: (addr handle cell) <- copy _args-ah +1205 var _args/eax: (addr cell) <- lookup *args-ah +1206 var args/esi: (addr cell) <- copy _args +1207 # TODO: check that args is a pair +1208 var empty-args?/eax: boolean <- nil? args +1209 compare empty-args?, 0/false +1210 { +1211 break-if-= +1212 error trace, "not needs 1 arg but got 0" +1213 return +1214 } +1215 # dump args->left uglily to screen and wait for a keypress +1216 var first-ah/eax: (addr handle cell) <- get args, left +1217 dump-cell-from-cursor-over-full-screen first-ah +1218 { +1219 var foo/eax: byte <- read-key 0/keyboard +1220 compare foo, 0 +1221 loop-if-= +1222 } +1223 # return nothing +1224 } +1225 +1226 fn apply-< _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1227 trace-text trace, "eval", "apply '<'" +1228 var args-ah/eax: (addr handle cell) <- copy _args-ah +1229 var _args/eax: (addr cell) <- lookup *args-ah +1230 var args/esi: (addr cell) <- copy _args +1231 # TODO: check that args is a pair +1232 var empty-args?/eax: boolean <- nil? args +1233 compare empty-args?, 0/false +1234 { +1235 break-if-= +1236 error trace, "'<' needs 2 args but got 0" +1237 return +1238 } +1239 # args->left +1240 var first-ah/ecx: (addr handle cell) <- get args, left +1241 # args->right->left +1242 var right-ah/eax: (addr handle cell) <- get args, right +1243 var right/eax: (addr cell) <- lookup *right-ah +1244 # TODO: check that right is a pair +1245 var second-ah/edx: (addr handle cell) <- get right, left +1246 # compare +1247 var _first/eax: (addr cell) <- lookup *first-ah +1248 var first/ecx: (addr cell) <- copy _first +1249 var first-type/eax: (addr int) <- get first, type +1250 compare *first-type, 1/number +1251 { +1252 break-if-= +1253 error trace, "first arg for '<' is not a number" +1254 return +1255 } +1256 var first-value/ecx: (addr float) <- get first, number-data +1257 var first-float/xmm0: float <- copy *first-value +1258 var second/eax: (addr cell) <- lookup *second-ah +1259 var second-type/edx: (addr int) <- get second, type +1260 compare *second-type, 1/number +1261 { +1262 break-if-= +1263 error trace, "first arg for '<' is not a number" +1264 return +1265 } +1266 var second-value/eax: (addr float) <- get second, number-data +1267 compare first-float, *second-value +1268 { +1269 break-if-float< +1270 nil out +1271 return +1272 } +1273 new-integer out, 1/true +1274 } +1275 +1276 fn apply-> _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1277 trace-text trace, "eval", "apply '>'" +1278 var args-ah/eax: (addr handle cell) <- copy _args-ah +1279 var _args/eax: (addr cell) <- lookup *args-ah +1280 var args/esi: (addr cell) <- copy _args +1281 # TODO: check that args is a pair +1282 var empty-args?/eax: boolean <- nil? args +1283 compare empty-args?, 0/false +1284 { +1285 break-if-= +1286 error trace, "'>' needs 2 args but got 0" +1287 return +1288 } +1289 # args->left +1290 var first-ah/ecx: (addr handle cell) <- get args, left +1291 # args->right->left +1292 var right-ah/eax: (addr handle cell) <- get args, right +1293 var right/eax: (addr cell) <- lookup *right-ah +1294 # TODO: check that right is a pair +1295 var second-ah/edx: (addr handle cell) <- get right, left +1296 # compare +1297 var _first/eax: (addr cell) <- lookup *first-ah +1298 var first/ecx: (addr cell) <- copy _first +1299 var first-type/eax: (addr int) <- get first, type +1300 compare *first-type, 1/number +1301 { +1302 break-if-= +1303 error trace, "first arg for '>' is not a number" +1304 return +1305 } +1306 var first-value/ecx: (addr float) <- get first, number-data +1307 var first-float/xmm0: float <- copy *first-value +1308 var second/eax: (addr cell) <- lookup *second-ah +1309 var second-type/edx: (addr int) <- get second, type +1310 compare *second-type, 1/number +1311 { +1312 break-if-= +1313 error trace, "first arg for '>' is not a number" +1314 return +1315 } +1316 var second-value/eax: (addr float) <- get second, number-data +1317 compare first-float, *second-value +1318 { +1319 break-if-float> +1320 nil out +1321 return +1322 } +1323 new-integer out, 1/true +1324 } +1325 +1326 fn apply-<= _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1327 trace-text trace, "eval", "apply '<='" +1328 var args-ah/eax: (addr handle cell) <- copy _args-ah +1329 var _args/eax: (addr cell) <- lookup *args-ah +1330 var args/esi: (addr cell) <- copy _args +1331 # TODO: check that args is a pair +1332 var empty-args?/eax: boolean <- nil? args +1333 compare empty-args?, 0/false +1334 { +1335 break-if-= +1336 error trace, "'<=' needs 2 args but got 0" +1337 return +1338 } +1339 # args->left +1340 var first-ah/ecx: (addr handle cell) <- get args, left +1341 # args->right->left +1342 var right-ah/eax: (addr handle cell) <- get args, right +1343 var right/eax: (addr cell) <- lookup *right-ah +1344 # TODO: check that right is a pair +1345 var second-ah/edx: (addr handle cell) <- get right, left +1346 # compare +1347 var _first/eax: (addr cell) <- lookup *first-ah +1348 var first/ecx: (addr cell) <- copy _first +1349 var first-type/eax: (addr int) <- get first, type +1350 compare *first-type, 1/number +1351 { +1352 break-if-= +1353 error trace, "first arg for '<=' is not a number" +1354 return +1355 } +1356 var first-value/ecx: (addr float) <- get first, number-data +1357 var first-float/xmm0: float <- copy *first-value +1358 var second/eax: (addr cell) <- lookup *second-ah +1359 var second-type/edx: (addr int) <- get second, type +1360 compare *second-type, 1/number +1361 { +1362 break-if-= +1363 error trace, "first arg for '<=' is not a number" +1364 return +1365 } +1366 var second-value/eax: (addr float) <- get second, number-data +1367 compare first-float, *second-value +1368 { +1369 break-if-float<= +1370 nil out +1371 return +1372 } +1373 new-integer out, 1/true +1374 } +1375 +1376 fn apply->= _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1377 trace-text trace, "eval", "apply '>='" +1378 var args-ah/eax: (addr handle cell) <- copy _args-ah +1379 var _args/eax: (addr cell) <- lookup *args-ah +1380 var args/esi: (addr cell) <- copy _args +1381 # TODO: check that args is a pair +1382 var empty-args?/eax: boolean <- nil? args +1383 compare empty-args?, 0/false +1384 { +1385 break-if-= +1386 error trace, "'>=' needs 2 args but got 0" +1387 return +1388 } +1389 # args->left +1390 var first-ah/ecx: (addr handle cell) <- get args, left +1391 # args->right->left +1392 var right-ah/eax: (addr handle cell) <- get args, right +1393 var right/eax: (addr cell) <- lookup *right-ah +1394 # TODO: check that right is a pair +1395 var second-ah/edx: (addr handle cell) <- get right, left +1396 # compare +1397 var _first/eax: (addr cell) <- lookup *first-ah +1398 var first/ecx: (addr cell) <- copy _first +1399 var first-type/eax: (addr int) <- get first, type +1400 compare *first-type, 1/number +1401 { +1402 break-if-= +1403 error trace, "first arg for '>=' is not a number" +1404 return +1405 } +1406 var first-value/ecx: (addr float) <- get first, number-data +1407 var first-float/xmm0: float <- copy *first-value +1408 var second/eax: (addr cell) <- lookup *second-ah +1409 var second-type/edx: (addr int) <- get second, type +1410 compare *second-type, 1/number +1411 { +1412 break-if-= +1413 error trace, "first arg for '>=' is not a number" +1414 return +1415 } +1416 var second-value/eax: (addr float) <- get second, number-data +1417 compare first-float, *second-value +1418 { +1419 break-if-float>= +1420 nil out +1421 return +1422 } +1423 new-integer out, 1/true +1424 } +1425 +1426 fn apply-print _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1427 trace-text trace, "eval", "apply print" +1428 var args-ah/eax: (addr handle cell) <- copy _args-ah +1429 var _args/eax: (addr cell) <- lookup *args-ah +1430 var args/esi: (addr cell) <- copy _args +1431 # TODO: check that args is a pair +1432 var empty-args?/eax: boolean <- nil? args +1433 compare empty-args?, 0/false +1434 { +1435 break-if-= +1436 error trace, "print needs 2 args but got 0" +1437 return +1438 } +1439 # screen = args->left +1440 var first-ah/eax: (addr handle cell) <- get args, left +1441 var first/eax: (addr cell) <- lookup *first-ah +1442 var first-type/ecx: (addr int) <- get first, type +1443 compare *first-type, 5/screen +1444 { +1445 break-if-= +1446 error trace, "first arg for 'print' is not a screen" +1447 return +1448 } +1449 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1450 var _screen/eax: (addr screen) <- lookup *screen-ah +1451 var screen/ecx: (addr screen) <- copy _screen +1452 # args->right->left +1453 var right-ah/eax: (addr handle cell) <- get args, right +1454 var right/eax: (addr cell) <- lookup *right-ah +1455 # TODO: check that right is a pair +1456 var second-ah/eax: (addr handle cell) <- get right, left +1457 var stream-storage: (stream byte 0x100) +1458 var stream/edi: (addr stream byte) <- address stream-storage +1459 print-cell second-ah, stream, trace +1460 draw-stream-wrapping-right-then-down-from-cursor-over-full-screen screen, stream, 7/fg, 0/bg +1461 # return what was printed +1462 copy-object second-ah, out +1463 } +1464 +1465 fn apply-clear _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1466 trace-text trace, "eval", "apply clear" +1467 var args-ah/eax: (addr handle cell) <- copy _args-ah +1468 var _args/eax: (addr cell) <- lookup *args-ah +1469 var args/esi: (addr cell) <- copy _args +1470 # TODO: check that args is a pair +1471 var empty-args?/eax: boolean <- nil? args +1472 compare empty-args?, 0/false +1473 { +1474 break-if-= +1475 error trace, "'clear' needs 1 arg but got 0" +1476 return +1477 } +1478 # screen = args->left +1479 var first-ah/eax: (addr handle cell) <- get args, left +1480 var first/eax: (addr cell) <- lookup *first-ah +1481 var first-type/ecx: (addr int) <- get first, type +1482 compare *first-type, 5/screen +1483 { +1484 break-if-= +1485 error trace, "first arg for 'clear' is not a screen" +1486 return +1487 } +1488 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1489 var _screen/eax: (addr screen) <- lookup *screen-ah +1490 var screen/ecx: (addr screen) <- copy _screen +1491 # +1492 clear-screen screen +1493 } +1494 +1495 fn apply-up _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1496 trace-text trace, "eval", "apply up" +1497 var args-ah/eax: (addr handle cell) <- copy _args-ah +1498 var _args/eax: (addr cell) <- lookup *args-ah +1499 var args/esi: (addr cell) <- copy _args +1500 # TODO: check that args is a pair +1501 var empty-args?/eax: boolean <- nil? args +1502 compare empty-args?, 0/false +1503 { +1504 break-if-= +1505 error trace, "'up' needs 1 arg but got 0" +1506 return +1507 } +1508 # screen = args->left +1509 var first-ah/eax: (addr handle cell) <- get args, left +1510 var first/eax: (addr cell) <- lookup *first-ah +1511 var first-type/ecx: (addr int) <- get first, type +1512 compare *first-type, 5/screen +1513 { +1514 break-if-= +1515 error trace, "first arg for 'up' is not a screen" +1516 return +1517 } +1518 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1519 var _screen/eax: (addr screen) <- lookup *screen-ah +1520 var screen/ecx: (addr screen) <- copy _screen +1521 # +1522 move-cursor-up screen +1523 } +1524 +1525 fn apply-down _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1526 trace-text trace, "eval", "apply 'down'" +1527 var args-ah/eax: (addr handle cell) <- copy _args-ah +1528 var _args/eax: (addr cell) <- lookup *args-ah +1529 var args/esi: (addr cell) <- copy _args +1530 # TODO: check that args is a pair +1531 var empty-args?/eax: boolean <- nil? args +1532 compare empty-args?, 0/false +1533 { +1534 break-if-= +1535 error trace, "'down' needs 1 arg but got 0" +1536 return +1537 } +1538 # screen = args->left +1539 var first-ah/eax: (addr handle cell) <- get args, left +1540 var first/eax: (addr cell) <- lookup *first-ah +1541 var first-type/ecx: (addr int) <- get first, type +1542 compare *first-type, 5/screen +1543 { +1544 break-if-= +1545 error trace, "first arg for 'down' is not a screen" +1546 return +1547 } +1548 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1549 var _screen/eax: (addr screen) <- lookup *screen-ah +1550 var screen/ecx: (addr screen) <- copy _screen +1551 # +1552 move-cursor-down screen +1553 } +1554 +1555 fn apply-left _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1556 trace-text trace, "eval", "apply 'left'" +1557 var args-ah/eax: (addr handle cell) <- copy _args-ah +1558 var _args/eax: (addr cell) <- lookup *args-ah +1559 var args/esi: (addr cell) <- copy _args +1560 # TODO: check that args is a pair +1561 var empty-args?/eax: boolean <- nil? args +1562 compare empty-args?, 0/false +1563 { +1564 break-if-= +1565 error trace, "'left' needs 1 arg but got 0" +1566 return +1567 } +1568 # screen = args->left +1569 var first-ah/eax: (addr handle cell) <- get args, left +1570 var first/eax: (addr cell) <- lookup *first-ah +1571 var first-type/ecx: (addr int) <- get first, type +1572 compare *first-type, 5/screen +1573 { +1574 break-if-= +1575 error trace, "first arg for 'left' is not a screen" +1576 return +1577 } +1578 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1579 var _screen/eax: (addr screen) <- lookup *screen-ah +1580 var screen/ecx: (addr screen) <- copy _screen +1581 # +1582 move-cursor-left screen +1583 } +1584 +1585 fn apply-right _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1586 trace-text trace, "eval", "apply 'right'" +1587 var args-ah/eax: (addr handle cell) <- copy _args-ah +1588 var _args/eax: (addr cell) <- lookup *args-ah +1589 var args/esi: (addr cell) <- copy _args +1590 # TODO: check that args is a pair +1591 var empty-args?/eax: boolean <- nil? args +1592 compare empty-args?, 0/false +1593 { +1594 break-if-= +1595 error trace, "'right' needs 1 arg but got 0" +1596 return +1597 } +1598 # screen = args->left +1599 var first-ah/eax: (addr handle cell) <- get args, left +1600 var first/eax: (addr cell) <- lookup *first-ah +1601 var first-type/ecx: (addr int) <- get first, type +1602 compare *first-type, 5/screen +1603 { +1604 break-if-= +1605 error trace, "first arg for 'right' is not a screen" +1606 return +1607 } +1608 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1609 var _screen/eax: (addr screen) <- lookup *screen-ah +1610 var screen/ecx: (addr screen) <- copy _screen +1611 # +1612 move-cursor-right screen +1613 } +1614 +1615 fn apply-cr _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1616 trace-text trace, "eval", "apply 'cr'" +1617 var args-ah/eax: (addr handle cell) <- copy _args-ah +1618 var _args/eax: (addr cell) <- lookup *args-ah +1619 var args/esi: (addr cell) <- copy _args +1620 # TODO: check that args is a pair +1621 var empty-args?/eax: boolean <- nil? args +1622 compare empty-args?, 0/false +1623 { +1624 break-if-= +1625 error trace, "'cr' needs 1 arg but got 0" +1626 return +1627 } +1628 # screen = args->left +1629 var first-ah/eax: (addr handle cell) <- get args, left +1630 var first/eax: (addr cell) <- lookup *first-ah +1631 var first-type/ecx: (addr int) <- get first, type +1632 compare *first-type, 5/screen +1633 { +1634 break-if-= +1635 error trace, "first arg for 'cr' is not a screen" +1636 return +1637 } +1638 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1639 var _screen/eax: (addr screen) <- lookup *screen-ah +1640 var screen/ecx: (addr screen) <- copy _screen +1641 # +1642 move-cursor-to-left-margin-of-next-line screen +1643 } +1644 +1645 fn apply-pixel _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1646 trace-text trace, "eval", "apply pixel" +1647 var args-ah/eax: (addr handle cell) <- copy _args-ah +1648 var _args/eax: (addr cell) <- lookup *args-ah +1649 var args/esi: (addr cell) <- copy _args +1650 # TODO: check that args is a pair +1651 var empty-args?/eax: boolean <- nil? args +1652 compare empty-args?, 0/false +1653 { +1654 break-if-= +1655 error trace, "pixel needs 4 args but got 0" +1656 return +1657 } +1658 # screen = args->left +1659 var first-ah/eax: (addr handle cell) <- get args, left +1660 var first/eax: (addr cell) <- lookup *first-ah +1661 var first-type/ecx: (addr int) <- get first, type +1662 compare *first-type, 5/screen +1663 { +1664 break-if-= +1665 error trace, "first arg for 'pixel' is not a screen" +1666 return +1667 } +1668 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1669 var _screen/eax: (addr screen) <- lookup *screen-ah +1670 var screen/edi: (addr screen) <- copy _screen +1671 # x = args->right->left->value +1672 var rest-ah/eax: (addr handle cell) <- get args, right +1673 var _rest/eax: (addr cell) <- lookup *rest-ah +1674 var rest/esi: (addr cell) <- copy _rest +1675 # TODO: check that rest is a pair +1676 var second-ah/eax: (addr handle cell) <- get rest, left +1677 var second/eax: (addr cell) <- lookup *second-ah +1678 var second-type/ecx: (addr int) <- get second, type +1679 compare *second-type, 1/number +1680 { +1681 break-if-= +1682 error trace, "second arg for 'pixel' is not an int (x coordinate)" +1683 return +1684 } +1685 var second-value/eax: (addr float) <- get second, number-data +1686 var x/edx: int <- convert *second-value +1687 # y = rest->right->left->value +1688 var rest-ah/eax: (addr handle cell) <- get rest, right +1689 var _rest/eax: (addr cell) <- lookup *rest-ah +1690 rest <- copy _rest +1691 # TODO: check that rest is a pair +1692 var third-ah/eax: (addr handle cell) <- get rest, left +1693 var third/eax: (addr cell) <- lookup *third-ah +1694 var third-type/ecx: (addr int) <- get third, type +1695 compare *third-type, 1/number +1696 { +1697 break-if-= +1698 error trace, "third arg for 'pixel' is not an int (y coordinate)" +1699 return +1700 } +1701 var third-value/eax: (addr float) <- get third, number-data +1702 var y/ebx: int <- convert *third-value +1703 # color = rest->right->left->value +1704 var rest-ah/eax: (addr handle cell) <- get rest, right +1705 var _rest/eax: (addr cell) <- lookup *rest-ah +1706 rest <- copy _rest +1707 # TODO: check that rest is a pair +1708 var fourth-ah/eax: (addr handle cell) <- get rest, left +1709 var fourth/eax: (addr cell) <- lookup *fourth-ah +1710 var fourth-type/ecx: (addr int) <- get fourth, type +1711 compare *fourth-type, 1/number +1712 { +1713 break-if-= +1714 error trace, "fourth arg for 'pixel' is not an int (color; 0..0xff)" +1715 return +1716 } +1717 var fourth-value/eax: (addr float) <- get fourth, number-data +1718 var color/eax: int <- convert *fourth-value +1719 pixel screen, x, y, color +1720 # return nothing +1721 } +1722 +1723 fn apply-wait-for-key _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1724 trace-text trace, "eval", "apply key" +1725 var args-ah/eax: (addr handle cell) <- copy _args-ah +1726 var _args/eax: (addr cell) <- lookup *args-ah +1727 var args/esi: (addr cell) <- copy _args +1728 # TODO: check that args is a pair +1729 var empty-args?/eax: boolean <- nil? args +1730 compare empty-args?, 0/false +1731 { +1732 break-if-= +1733 error trace, "key needs 1 arg but got 0" +1734 return +1735 } +1736 # keyboard = args->left +1737 var first-ah/eax: (addr handle cell) <- get args, left +1738 var first/eax: (addr cell) <- lookup *first-ah +1739 var first-type/ecx: (addr int) <- get first, type +1740 compare *first-type, 6/keyboard +1741 { +1742 break-if-= +1743 error trace, "first arg for 'key' is not a keyboard" +1744 return +1745 } +1746 var keyboard-ah/eax: (addr handle gap-buffer) <- get first, keyboard-data +1747 var _keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah +1748 var keyboard/ecx: (addr gap-buffer) <- copy _keyboard +1749 var result/eax: int <- wait-for-key keyboard +1750 # return key typed +1751 new-integer out, result 1752 } 1753 -1754 fn apply-columns _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1755 trace-text trace, "eval", "apply columns" -1756 var args-ah/eax: (addr handle cell) <- copy _args-ah -1757 var _args/eax: (addr cell) <- lookup *args-ah -1758 var args/esi: (addr cell) <- copy _args -1759 # TODO: check that args is a pair -1760 var empty-args?/eax: boolean <- nil? args -1761 compare empty-args?, 0/false -1762 { -1763 break-if-= -1764 error trace, "columns needs 1 arg but got 0" -1765 return -1766 } -1767 # screen = args->left -1768 var first-ah/eax: (addr handle cell) <- get args, left -1769 var first/eax: (addr cell) <- lookup *first-ah -1770 var first-type/ecx: (addr int) <- get first, type -1771 compare *first-type, 5/screen -1772 { -1773 break-if-= -1774 error trace, "first arg for 'columns' is not a screen" -1775 return -1776 } -1777 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1778 var _screen/eax: (addr screen) <- lookup *screen-ah -1779 var screen/edx: (addr screen) <- copy _screen -1780 # compute dimensions -1781 var width/eax: int <- copy 0 -1782 var dummy/ecx: int <- copy 0 -1783 width, dummy <- screen-size screen -1784 var result/xmm0: float <- convert width -1785 new-float out, result -1786 } -1787 -1788 fn apply-width _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1789 trace-text trace, "eval", "apply width" -1790 var args-ah/eax: (addr handle cell) <- copy _args-ah -1791 var _args/eax: (addr cell) <- lookup *args-ah -1792 var args/esi: (addr cell) <- copy _args -1793 # TODO: check that args is a pair -1794 var empty-args?/eax: boolean <- nil? args -1795 compare empty-args?, 0/false -1796 { -1797 break-if-= -1798 error trace, "width needs 1 arg but got 0" -1799 return -1800 } -1801 # screen = args->left -1802 var first-ah/eax: (addr handle cell) <- get args, left -1803 var first/eax: (addr cell) <- lookup *first-ah -1804 var first-type/ecx: (addr int) <- get first, type -1805 compare *first-type, 5/screen -1806 { -1807 break-if-= -1808 error trace, "first arg for 'width' is not a screen" -1809 return -1810 } -1811 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1812 var _screen/eax: (addr screen) <- lookup *screen-ah -1813 var screen/edx: (addr screen) <- copy _screen -1814 # compute dimensions -1815 var width/eax: int <- copy 0 -1816 var dummy/ecx: int <- copy 0 -1817 width, dummy <- screen-size screen -1818 width <- shift-left 3/log2-font-width -1819 var result/xmm0: float <- convert width -1820 new-float out, result -1821 } -1822 -1823 fn apply-height _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { -1824 trace-text trace, "eval", "apply height" -1825 var args-ah/eax: (addr handle cell) <- copy _args-ah -1826 var _args/eax: (addr cell) <- lookup *args-ah -1827 var args/esi: (addr cell) <- copy _args -1828 # TODO: check that args is a pair -1829 var empty-args?/eax: boolean <- nil? args -1830 compare empty-args?, 0/false -1831 { -1832 break-if-= -1833 error trace, "height needs 1 arg but got 0" -1834 return -1835 } -1836 # screen = args->left -1837 var first-ah/eax: (addr handle cell) <- get args, left -1838 var first/eax: (addr cell) <- lookup *first-ah -1839 var first-type/ecx: (addr int) <- get first, type -1840 compare *first-type, 5/screen -1841 { -1842 break-if-= -1843 error trace, "first arg for 'height' is not a screen" -1844 return -1845 } -1846 var screen-ah/eax: (addr handle screen) <- get first, screen-data -1847 var _screen/eax: (addr screen) <- lookup *screen-ah -1848 var screen/edx: (addr screen) <- copy _screen -1849 # compute dimensions -1850 var dummy/eax: int <- copy 0 -1851 var height/ecx: int <- copy 0 -1852 dummy, height <- screen-size screen -1853 height <- shift-left 4/log2-font-height -1854 var result/xmm0: float <- convert height -1855 new-float out, result -1856 } -1857 -1858 # Accepts an input s-expression, naively checks if it is a definition, and if -1859 # so saves the gap-buffer to the appropriate global, spinning up a new empty -1860 # one to replace it with. -1861 fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) { -1862 # if 'definition' is not a pair, return -1863 var definition-ah/eax: (addr handle cell) <- copy _definition-ah -1864 var _definition/eax: (addr cell) <- lookup *definition-ah -1865 var definition/esi: (addr cell) <- copy _definition -1866 var definition-type/eax: (addr int) <- get definition, type -1867 compare *definition-type, 0/pair +1754 fn wait-for-key keyboard: (addr gap-buffer) -> _/eax: int { +1755 # if keyboard is 0, use real keyboard +1756 { +1757 compare keyboard, 0/real-keyboard +1758 break-if-!= +1759 var key/eax: byte <- read-key 0/real-keyboard +1760 var result/eax: int <- copy key +1761 return result +1762 } +1763 # otherwise read from fake keyboard +1764 var g/eax: grapheme <- read-from-gap-buffer keyboard +1765 var result/eax: int <- copy g +1766 return result +1767 } +1768 +1769 fn apply-stream _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1770 trace-text trace, "eval", "apply stream" +1771 allocate-stream out +1772 } +1773 +1774 fn apply-write _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1775 trace-text trace, "eval", "apply write" +1776 var args-ah/eax: (addr handle cell) <- copy _args-ah +1777 var _args/eax: (addr cell) <- lookup *args-ah +1778 var args/esi: (addr cell) <- copy _args +1779 # TODO: check that args is a pair +1780 var empty-args?/eax: boolean <- nil? args +1781 compare empty-args?, 0/false +1782 { +1783 break-if-= +1784 error trace, "write needs 2 args but got 0" +1785 return +1786 } +1787 # stream = args->left +1788 var first-ah/edx: (addr handle cell) <- get args, left +1789 var first/eax: (addr cell) <- lookup *first-ah +1790 var first-type/ecx: (addr int) <- get first, type +1791 compare *first-type, 3/stream +1792 { +1793 break-if-= +1794 error trace, "first arg for 'write' is not a stream" +1795 return +1796 } +1797 var stream-data-ah/eax: (addr handle stream byte) <- get first, text-data +1798 var _stream-data/eax: (addr stream byte) <- lookup *stream-data-ah +1799 var stream-data/ebx: (addr stream byte) <- copy _stream-data +1800 # args->right->left +1801 var right-ah/eax: (addr handle cell) <- get args, right +1802 var right/eax: (addr cell) <- lookup *right-ah +1803 # TODO: check that right is a pair +1804 var second-ah/eax: (addr handle cell) <- get right, left +1805 var second/eax: (addr cell) <- lookup *second-ah +1806 var second-type/ecx: (addr int) <- get second, type +1807 compare *second-type, 1/number +1808 { +1809 break-if-= +1810 error trace, "second arg for stream is not a number/grapheme" +1811 return +1812 } +1813 var second-value/eax: (addr float) <- get second, number-data +1814 var x-float/xmm0: float <- copy *second-value +1815 var x/eax: int <- convert x-float +1816 var x-grapheme/eax: grapheme <- copy x +1817 write-grapheme stream-data, x-grapheme +1818 # return the stream +1819 copy-object first-ah, out +1820 } +1821 +1822 fn apply-lines _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1823 trace-text trace, "eval", "apply lines" +1824 var args-ah/eax: (addr handle cell) <- copy _args-ah +1825 var _args/eax: (addr cell) <- lookup *args-ah +1826 var args/esi: (addr cell) <- copy _args +1827 # TODO: check that args is a pair +1828 var empty-args?/eax: boolean <- nil? args +1829 compare empty-args?, 0/false +1830 { +1831 break-if-= +1832 error trace, "lines needs 1 arg but got 0" +1833 return +1834 } +1835 # screen = args->left +1836 var first-ah/eax: (addr handle cell) <- get args, left +1837 var first/eax: (addr cell) <- lookup *first-ah +1838 var first-type/ecx: (addr int) <- get first, type +1839 compare *first-type, 5/screen +1840 { +1841 break-if-= +1842 error trace, "first arg for 'lines' is not a screen" +1843 return +1844 } +1845 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1846 var _screen/eax: (addr screen) <- lookup *screen-ah +1847 var screen/edx: (addr screen) <- copy _screen +1848 # compute dimensions +1849 var dummy/eax: int <- copy 0 +1850 var height/ecx: int <- copy 0 +1851 dummy, height <- screen-size screen +1852 var result/xmm0: float <- convert height +1853 new-float out, result +1854 } +1855 +1856 fn apply-abort _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1857 abort "aa" +1858 } +1859 +1860 fn apply-columns _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1861 trace-text trace, "eval", "apply columns" +1862 var args-ah/eax: (addr handle cell) <- copy _args-ah +1863 var _args/eax: (addr cell) <- lookup *args-ah +1864 var args/esi: (addr cell) <- copy _args +1865 # TODO: check that args is a pair +1866 var empty-args?/eax: boolean <- nil? args +1867 compare empty-args?, 0/false 1868 { 1869 break-if-= -1870 return -1871 } -1872 # if definition->left is neither "def" nor "set", return -1873 var left-ah/eax: (addr handle cell) <- get definition, left -1874 var _left/eax: (addr cell) <- lookup *left-ah -1875 var left/ecx: (addr cell) <- copy _left -1876 { -1877 var def?/eax: boolean <- symbol-equal? left, "def" -1878 compare def?, 0/false -1879 break-if-!= -1880 var set?/eax: boolean <- symbol-equal? left, "set" -1881 compare set?, 0/false -1882 break-if-!= -1883 return -1884 } -1885 # locate the global for definition->right->left -1886 var right-ah/eax: (addr handle cell) <- get definition, right -1887 var right/eax: (addr cell) <- lookup *right-ah -1888 var defined-symbol-ah/eax: (addr handle cell) <- get right, left -1889 var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah -1890 var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data -1891 var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah -1892 var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name -1893 { -1894 compare index, -1/not-found -1895 break-if-!= -1896 return -1897 } -1898 # stash 'gap' to it -1899 var globals/eax: (addr global-table) <- copy _globals -1900 var global-data-ah/eax: (addr handle array global) <- get globals, data -1901 var global-data/eax: (addr array global) <- lookup *global-data-ah -1902 var offset/ebx: (offset global) <- compute-offset global-data, index -1903 var dest-global/eax: (addr global) <- index global-data, offset -1904 var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input -1905 copy-object gap, dest-ah -1906 # initialize a new gap-buffer in 'gap' -1907 var dest/eax: (addr gap-buffer) <- lookup *dest-ah -1908 var capacity/ecx: int <- gap-buffer-capacity dest -1909 var gap2/eax: (addr handle gap-buffer) <- copy gap -1910 allocate gap2 -1911 var gap-addr/eax: (addr gap-buffer) <- lookup *gap2 -1912 initialize-gap-buffer gap-addr, capacity -1913 } -1914 -1915 # Accepts an input s-expression, naively checks if it is a definition, and if -1916 # so saves the gap-buffer to the appropriate global. -1917 fn move-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) { -1918 # if 'definition' is not a pair, return -1919 var definition-ah/eax: (addr handle cell) <- copy _definition-ah -1920 var _definition/eax: (addr cell) <- lookup *definition-ah -1921 var definition/esi: (addr cell) <- copy _definition -1922 var definition-type/eax: (addr int) <- get definition, type -1923 compare *definition-type, 0/pair -1924 { -1925 break-if-= -1926 return -1927 } -1928 # if definition->left is neither "def" nor "set", return -1929 var left-ah/eax: (addr handle cell) <- get definition, left -1930 var _left/eax: (addr cell) <- lookup *left-ah -1931 var left/ecx: (addr cell) <- copy _left -1932 { -1933 var def?/eax: boolean <- symbol-equal? left, "def" -1934 compare def?, 0/false -1935 break-if-!= -1936 var set?/eax: boolean <- symbol-equal? left, "set" -1937 compare set?, 0/false -1938 break-if-!= -1939 return -1940 } -1941 # locate the global for definition->right->left -1942 var right-ah/eax: (addr handle cell) <- get definition, right -1943 var right/eax: (addr cell) <- lookup *right-ah -1944 var defined-symbol-ah/eax: (addr handle cell) <- get right, left -1945 var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah -1946 var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data -1947 var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah -1948 var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name -1949 { -1950 compare index, -1/not-found -1951 break-if-!= -1952 return -1953 } -1954 # move 'gap' to it -1955 var globals/eax: (addr global-table) <- copy _globals -1956 var global-data-ah/eax: (addr handle array global) <- get globals, data -1957 var global-data/eax: (addr array global) <- lookup *global-data-ah -1958 var offset/ebx: (offset global) <- compute-offset global-data, index -1959 var dest-global/eax: (addr global) <- index global-data, offset -1960 var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input -1961 copy-object gap, dest-ah +1870 error trace, "columns needs 1 arg but got 0" +1871 return +1872 } +1873 # screen = args->left +1874 var first-ah/eax: (addr handle cell) <- get args, left +1875 var first/eax: (addr cell) <- lookup *first-ah +1876 var first-type/ecx: (addr int) <- get first, type +1877 compare *first-type, 5/screen +1878 { +1879 break-if-= +1880 error trace, "first arg for 'columns' is not a screen" +1881 return +1882 } +1883 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1884 var _screen/eax: (addr screen) <- lookup *screen-ah +1885 var screen/edx: (addr screen) <- copy _screen +1886 # compute dimensions +1887 var width/eax: int <- copy 0 +1888 var dummy/ecx: int <- copy 0 +1889 width, dummy <- screen-size screen +1890 var result/xmm0: float <- convert width +1891 new-float out, result +1892 } +1893 +1894 fn apply-width _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1895 trace-text trace, "eval", "apply width" +1896 var args-ah/eax: (addr handle cell) <- copy _args-ah +1897 var _args/eax: (addr cell) <- lookup *args-ah +1898 var args/esi: (addr cell) <- copy _args +1899 # TODO: check that args is a pair +1900 var empty-args?/eax: boolean <- nil? args +1901 compare empty-args?, 0/false +1902 { +1903 break-if-= +1904 error trace, "width needs 1 arg but got 0" +1905 return +1906 } +1907 # screen = args->left +1908 var first-ah/eax: (addr handle cell) <- get args, left +1909 var first/eax: (addr cell) <- lookup *first-ah +1910 var first-type/ecx: (addr int) <- get first, type +1911 compare *first-type, 5/screen +1912 { +1913 break-if-= +1914 error trace, "first arg for 'width' is not a screen" +1915 return +1916 } +1917 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1918 var _screen/eax: (addr screen) <- lookup *screen-ah +1919 var screen/edx: (addr screen) <- copy _screen +1920 # compute dimensions +1921 var width/eax: int <- copy 0 +1922 var dummy/ecx: int <- copy 0 +1923 width, dummy <- screen-size screen +1924 width <- shift-left 3/log2-font-width +1925 var result/xmm0: float <- convert width +1926 new-float out, result +1927 } +1928 +1929 fn apply-height _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { +1930 trace-text trace, "eval", "apply height" +1931 var args-ah/eax: (addr handle cell) <- copy _args-ah +1932 var _args/eax: (addr cell) <- lookup *args-ah +1933 var args/esi: (addr cell) <- copy _args +1934 # TODO: check that args is a pair +1935 var empty-args?/eax: boolean <- nil? args +1936 compare empty-args?, 0/false +1937 { +1938 break-if-= +1939 error trace, "height needs 1 arg but got 0" +1940 return +1941 } +1942 # screen = args->left +1943 var first-ah/eax: (addr handle cell) <- get args, left +1944 var first/eax: (addr cell) <- lookup *first-ah +1945 var first-type/ecx: (addr int) <- get first, type +1946 compare *first-type, 5/screen +1947 { +1948 break-if-= +1949 error trace, "first arg for 'height' is not a screen" +1950 return +1951 } +1952 var screen-ah/eax: (addr handle screen) <- get first, screen-data +1953 var _screen/eax: (addr screen) <- lookup *screen-ah +1954 var screen/edx: (addr screen) <- copy _screen +1955 # compute dimensions +1956 var dummy/eax: int <- copy 0 +1957 var height/ecx: int <- copy 0 +1958 dummy, height <- screen-size screen +1959 height <- shift-left 4/log2-font-height +1960 var result/xmm0: float <- convert height +1961 new-float out, result 1962 } +1963 +1964 # Accepts an input s-expression, naively checks if it is a definition, and if +1965 # so saves the gap-buffer to the appropriate global, spinning up a new empty +1966 # one to replace it with. +1967 fn maybe-stash-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) { +1968 # if 'definition' is not a pair, return +1969 var definition-ah/eax: (addr handle cell) <- copy _definition-ah +1970 var _definition/eax: (addr cell) <- lookup *definition-ah +1971 var definition/esi: (addr cell) <- copy _definition +1972 var definition-type/eax: (addr int) <- get definition, type +1973 compare *definition-type, 0/pair +1974 { +1975 break-if-= +1976 return +1977 } +1978 # if definition->left is neither "def" nor "set", return +1979 var left-ah/eax: (addr handle cell) <- get definition, left +1980 var _left/eax: (addr cell) <- lookup *left-ah +1981 var left/ecx: (addr cell) <- copy _left +1982 { +1983 var def?/eax: boolean <- symbol-equal? left, "def" +1984 compare def?, 0/false +1985 break-if-!= +1986 var set?/eax: boolean <- symbol-equal? left, "set" +1987 compare set?, 0/false +1988 break-if-!= +1989 return +1990 } +1991 # locate the global for definition->right->left +1992 var right-ah/eax: (addr handle cell) <- get definition, right +1993 var right/eax: (addr cell) <- lookup *right-ah +1994 var defined-symbol-ah/eax: (addr handle cell) <- get right, left +1995 var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah +1996 var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data +1997 var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah +1998 var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name +1999 { +2000 compare index, -1/not-found +2001 break-if-!= +2002 return +2003 } +2004 # stash 'gap' to it +2005 var globals/eax: (addr global-table) <- copy _globals +2006 compare globals, 0 +2007 { +2008 break-if-!= +2009 abort "stash to globals" +2010 return +2011 } +2012 var global-data-ah/eax: (addr handle array global) <- get globals, data +2013 var global-data/eax: (addr array global) <- lookup *global-data-ah +2014 var offset/ebx: (offset global) <- compute-offset global-data, index +2015 var dest-global/eax: (addr global) <- index global-data, offset +2016 var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input +2017 copy-object gap, dest-ah +2018 # initialize a new gap-buffer in 'gap' +2019 var dest/eax: (addr gap-buffer) <- lookup *dest-ah +2020 var capacity/ecx: int <- gap-buffer-capacity dest +2021 var gap2/eax: (addr handle gap-buffer) <- copy gap +2022 allocate gap2 +2023 var gap-addr/eax: (addr gap-buffer) <- lookup *gap2 +2024 initialize-gap-buffer gap-addr, capacity +2025 } +2026 +2027 # Accepts an input s-expression, naively checks if it is a definition, and if +2028 # so saves the gap-buffer to the appropriate global. +2029 fn move-gap-buffer-to-global _globals: (addr global-table), _definition-ah: (addr handle cell), gap: (addr handle gap-buffer) { +2030 # if 'definition' is not a pair, return +2031 var definition-ah/eax: (addr handle cell) <- copy _definition-ah +2032 var _definition/eax: (addr cell) <- lookup *definition-ah +2033 var definition/esi: (addr cell) <- copy _definition +2034 var definition-type/eax: (addr int) <- get definition, type +2035 compare *definition-type, 0/pair +2036 { +2037 break-if-= +2038 return +2039 } +2040 # if definition->left is neither "def" nor "set", return +2041 var left-ah/eax: (addr handle cell) <- get definition, left +2042 var _left/eax: (addr cell) <- lookup *left-ah +2043 var left/ecx: (addr cell) <- copy _left +2044 { +2045 var def?/eax: boolean <- symbol-equal? left, "def" +2046 compare def?, 0/false +2047 break-if-!= +2048 var set?/eax: boolean <- symbol-equal? left, "set" +2049 compare set?, 0/false +2050 break-if-!= +2051 return +2052 } +2053 # locate the global for definition->right->left +2054 var right-ah/eax: (addr handle cell) <- get definition, right +2055 var right/eax: (addr cell) <- lookup *right-ah +2056 var defined-symbol-ah/eax: (addr handle cell) <- get right, left +2057 var defined-symbol/eax: (addr cell) <- lookup *defined-symbol-ah +2058 var defined-symbol-name-ah/eax: (addr handle stream byte) <- get defined-symbol, text-data +2059 var defined-symbol-name/eax: (addr stream byte) <- lookup *defined-symbol-name-ah +2060 var index/ecx: int <- find-symbol-in-globals _globals, defined-symbol-name +2061 { +2062 compare index, -1/not-found +2063 break-if-!= +2064 return +2065 } +2066 # move 'gap' to it +2067 var globals/eax: (addr global-table) <- copy _globals +2068 compare globals, 0 +2069 { +2070 break-if-!= +2071 abort "move to globals" +2072 return +2073 } +2074 var global-data-ah/eax: (addr handle array global) <- get globals, data +2075 var global-data/eax: (addr array global) <- lookup *global-data-ah +2076 var offset/ebx: (offset global) <- compute-offset global-data, index +2077 var dest-global/eax: (addr global) <- index global-data, offset +2078 var dest-ah/eax: (addr handle gap-buffer) <- get dest-global, input +2079 copy-object gap, dest-ah +2080 } diff --git a/html/shell/grapheme-stack.mu.html b/html/shell/grapheme-stack.mu.html index 1ebdfe9a..a4e0719d 100644 --- a/html/shell/grapheme-stack.mu.html +++ b/html/shell/grapheme-stack.mu.html @@ -99,7 +99,7 @@ if ('onhashchange' in window) { 40 var self/esi: (addr grapheme-stack) <- copy _self 41 var top-addr/ecx: (addr int) <- get self, top 42 var data-ah/edx: (addr handle array grapheme) <- get self, data - 43 var data/eax: (addr array grapheme) <- lookup *data-ah + 43 var data/eax: (addr array grapheme) <- lookup *data-ah 44 var top/edx: int <- copy *top-addr 45 var dest-addr/edx: (addr grapheme) <- index data, top 46 var val/eax: grapheme <- copy _val @@ -117,7 +117,7 @@ if ('onhashchange' in window) { 58 } 59 subtract-from *top-addr, 1 60 var data-ah/edx: (addr handle array grapheme) <- get self, data - 61 var data/eax: (addr array grapheme) <- lookup *data-ah + 61 var data/eax: (addr array grapheme) <- lookup *data-ah 62 var top/edx: int <- copy *top-addr 63 var result-addr/eax: (addr grapheme) <- index data, top 64 return *result-addr @@ -126,7 +126,7 @@ if ('onhashchange' in window) { 67 fn copy-grapheme-stack _src: (addr grapheme-stack), dest: (addr grapheme-stack) { 68 var src/esi: (addr grapheme-stack) <- copy _src 69 var data-ah/edi: (addr handle array grapheme) <- get src, data - 70 var _data/eax: (addr array grapheme) <- lookup *data-ah + 70 var _data/eax: (addr array grapheme) <- lookup *data-ah 71 var data/edi: (addr array grapheme) <- copy _data 72 var top-addr/ecx: (addr int) <- get src, top 73 var i/eax: int <- copy 0 @@ -147,7 +147,7 @@ if ('onhashchange' in window) { 88 var self/esi: (addr grapheme-stack) <- copy _self 89 var matching-open-paren-index/edx: int <- get-matching-open-paren-index self, highlight-matching-open-paren?, open-paren-depth 90 var data-ah/edi: (addr handle array grapheme) <- get self, data - 91 var _data/eax: (addr array grapheme) <- lookup *data-ah + 91 var _data/eax: (addr array grapheme) <- lookup *data-ah 92 var data/edi: (addr array grapheme) <- copy _data 93 var x/eax: int <- copy _x 94 var y/ecx: int <- copy _y @@ -198,7 +198,7 @@ if ('onhashchange' in window) { 139 var self/esi: (addr grapheme-stack) <- copy _self 140 var matching-close-paren-index/edx: int <- get-matching-close-paren-index self, render-cursor? 141 var data-ah/eax: (addr handle array grapheme) <- get self, data -142 var _data/eax: (addr array grapheme) <- lookup *data-ah +142 var _data/eax: (addr array grapheme) <- lookup *data-ah 143 var data/edi: (addr array grapheme) <- copy _data 144 var x/eax: int <- copy _x 145 var y/ecx: int <- copy _y @@ -444,7 +444,7 @@ if ('onhashchange' in window) { 385 return *top-addr 386 } 387 var data-ah/eax: (addr handle array grapheme) <- get self, data -388 var data/eax: (addr array grapheme) <- lookup *data-ah +388 var data/eax: (addr array grapheme) <- lookup *data-ah 389 var i/ecx: int <- copy *top-addr 390 # if stack is empty, return 391 compare i, 0 @@ -500,7 +500,7 @@ if ('onhashchange' in window) { 441 return *top-addr 442 } 443 var data-ah/eax: (addr handle array grapheme) <- get self, data -444 var data/eax: (addr array grapheme) <- lookup *data-ah +444 var data/eax: (addr array grapheme) <- lookup *data-ah 445 var i/ecx: int <- copy *top-addr 446 # if stack is empty, return 447 compare i, 0 @@ -541,7 +541,7 @@ if ('onhashchange' in window) { 482 fn prefix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean { 483 var self/esi: (addr grapheme-stack) <- copy _self 484 var data-ah/edi: (addr handle array grapheme) <- get self, data -485 var _data/eax: (addr array grapheme) <- lookup *data-ah +485 var _data/eax: (addr array grapheme) <- lookup *data-ah 486 var data/edi: (addr array grapheme) <- copy _data 487 var top-addr/ecx: (addr int) <- get self, top 488 var i/ebx: int <- copy 0 @@ -569,7 +569,7 @@ if ('onhashchange' in window) { 510 fn suffix-match? _self: (addr grapheme-stack), s: (addr stream byte) -> _/eax: boolean { 511 var self/esi: (addr grapheme-stack) <- copy _self 512 var data-ah/edi: (addr handle array grapheme) <- get self, data -513 var _data/eax: (addr array grapheme) <- lookup *data-ah +513 var _data/eax: (addr array grapheme) <- lookup *data-ah 514 var data/edi: (addr array grapheme) <- copy _data 515 var top-addr/eax: (addr int) <- get self, top 516 var i/ebx: int <- copy *top-addr @@ -596,7 +596,7 @@ if ('onhashchange' in window) { 537 fn grapheme-stack-is-decimal-integer? _self: (addr grapheme-stack) -> _/eax: boolean { 538 var self/esi: (addr grapheme-stack) <- copy _self 539 var data-ah/eax: (addr handle array grapheme) <- get self, data -540 var _data/eax: (addr array grapheme) <- lookup *data-ah +540 var _data/eax: (addr array grapheme) <- lookup *data-ah 541 var data/edx: (addr array grapheme) <- copy _data 542 var top-addr/ecx: (addr int) <- get self, top 543 var i/ebx: int <- copy 0 @@ -605,7 +605,7 @@ if ('onhashchange' in window) { 546 compare i, *top-addr 547 break-if->= 548 var g/edx: (addr grapheme) <- index data, i -549 result <- decimal-digit? *g +549 result <- decimal-digit? *g 550 compare result, 0/false 551 break-if-= 552 i <- increment diff --git a/html/shell/macroexpand.mu.html b/html/shell/macroexpand.mu.html new file mode 100644 index 00000000..4dfb34e4 --- /dev/null +++ b/html/shell/macroexpand.mu.html @@ -0,0 +1,428 @@ + + + + +Mu - shell/macroexpand.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/shell/macroexpand.mu +
+  1 fn macroexpand expr-ah: (addr handle cell), globals: (addr global-table), trace: (addr trace) {
+  2 +-- 11 lines: # trace "macroexpand " expr-ah --------------------------------------------------------------------------------------------------------------------------------------------
+ 13   # loop until convergence
+ 14   {
+ 15     var expanded?/eax: boolean <- macroexpand-iter expr-ah, globals, trace
+ 16     compare expanded?, 0/false
+ 17     loop-if-!=
+ 18   }
+ 19 +-- 11 lines: # trace "=> " expr-ah -----------------------------------------------------------------------------------------------------------------------------------------------------
+ 30 }
+ 31 
+ 32 # return true if we found any macros
+ 33 fn macroexpand-iter _expr-ah: (addr handle cell), globals: (addr global-table), trace: (addr trace) -> _/eax: boolean {
+ 34   var expr-ah/esi: (addr handle cell) <- copy _expr-ah
+ 35 +-- 11 lines: # trace "macroexpand-iter " expr ------------------------------------------------------------------------------------------------------------------------------------------
+ 46   # if expr is a non-pair, return
+ 47   var expr/eax: (addr cell) <- lookup *expr-ah
+ 48   {
+ 49     var nil?/eax: boolean <- nil? expr
+ 50     compare nil?, 0/false
+ 51     break-if-=
+ 52     # nil is a literal
+ 53     trace-text trace, "mac", "nil"
+ 54     trace-higher trace
+ 55     return 0/false
+ 56   }
+ 57   {
+ 58     var expr-type/eax: (addr int) <- get expr, type
+ 59     compare *expr-type, 0/pair
+ 60     break-if-=
+ 61     # non-pairs are literals
+ 62     trace-text trace, "mac", "non-pair"
+ 63     trace-higher trace
+ 64     return 0/false
+ 65   }
+ 66   # if expr is a literal pair, return
+ 67   var first-ah/ebx: (addr handle cell) <- get expr, left
+ 68   var rest-ah/ecx: (addr handle cell) <- get expr, right
+ 69   var first/eax: (addr cell) <- lookup *first-ah
+ 70   {
+ 71     var litfn?/eax: boolean <- litfn? first
+ 72     compare litfn?, 0/false
+ 73     break-if-=
+ 74     # litfn is a literal
+ 75     trace-text trace, "mac", "literal function"
+ 76     trace-higher trace
+ 77     return 0/false
+ 78   }
+ 79   {
+ 80     var litmac?/eax: boolean <- litmac? first
+ 81     compare litmac?, 0/false
+ 82     break-if-=
+ 83     # litmac is a literal
+ 84     trace-text trace, "mac", "literal macro"
+ 85     trace-higher trace
+ 86     return 0/false
+ 87   }
+ 88   var result/edi: boolean <- copy 0/false
+ 89   # for each builtin, expand only what will later be evaluated
+ 90   $macroexpand-iter:anonymous-function: {
+ 91     var fn?/eax: boolean <- fn? first
+ 92     compare fn?, 0/false
+ 93     break-if-=
+ 94     # fn: expand every expression in the body
+ 95     trace-text trace, "mac", "anonymous function"
+ 96     # skip parameters
+ 97     var rest/eax: (addr cell) <- lookup *rest-ah
+ 98     {
+ 99       rest-ah <- get rest, right
+100       rest <- lookup *rest-ah
+101       {
+102         var done?/eax: boolean <- nil? rest
+103         compare done?, 0/false
+104       }
+105       break-if-!=
+106       var curr-ah/eax: (addr handle cell) <- get rest, left
+107       var macro-found?/eax: boolean <- macroexpand-iter curr-ah, globals, trace
+108       result <- or macro-found?
+109       loop
+110     }
+111     trace-higher trace
+112     return result
+113   }
+114   # builtins with "special" evaluation rules
+115   $macroexpand-iter:quote: {
+116     # trees starting with single quote create literals
+117     var quote?/eax: boolean <- symbol-equal? first, "'"
+118     compare quote?, 0/false
+119     break-if-=
+120     #
+121     trace-text trace, "mac", "quote"
+122     trace-higher trace
+123     return 0/false
+124   }
+125   $macroexpand-iter:backquote: {
+126     # nested backquote not supported for now
+127     var backquote?/eax: boolean <- symbol-equal? first, "`"
+128     compare backquote?, 0/false
+129     break-if-=
+130     #
+131     error trace, "nested backquote not supported yet"
+132     trace-higher trace
+133     return 0/false
+134   }
+135   $macroexpand-iter:def: {
+136     # trees starting with "def" define globals
+137     var def?/eax: boolean <- symbol-equal? first, "def"
+138     compare def?, 0/false
+139     break-if-=
+140     #
+141     trace-text trace, "mac", "def"
+142     var rest/eax: (addr cell) <- lookup *rest-ah
+143     rest-ah <- get rest, right  # skip name
+144     rest <- lookup *rest-ah
+145     var val-ah/edx: (addr handle cell) <- get rest, left
+146     var macro-found?/eax: boolean <- macroexpand-iter val-ah, globals, trace
+147     trace-higher trace
+148     return macro-found?
+149   }
+150   $macroexpand-iter:set: {
+151     # trees starting with "set" mutate bindings
+152     var set?/eax: boolean <- symbol-equal? first, "set"
+153     compare set?, 0/false
+154     break-if-=
+155     #
+156     trace-text trace, "mac", "set"
+157     var rest/eax: (addr cell) <- lookup *rest-ah
+158     rest-ah <- get rest, right  # skip name
+159     rest <- lookup *rest-ah
+160     var val-ah/edx: (addr handle cell) <- get rest, left
+161     var macro-found?/eax: boolean <- macroexpand-iter val-ah, globals, trace
+162     trace-higher trace
+163     return macro-found?
+164   }
+165   # 'and' is like a function for macroexpansion purposes
+166   # 'or' is like a function for macroexpansion purposes
+167   # 'if' is like a function for macroexpansion purposes
+168   # 'while' is like a function for macroexpansion purposes
+169   # if car(expr) is a symbol defined as a macro, expand it
+170   {
+171     var definition-h: (handle cell)
+172     var definition-ah/edx: (addr handle cell) <- address definition-h
+173     maybe-lookup-symbol-in-globals first, definition-ah, globals, trace
+174     var definition/eax: (addr cell) <- lookup *definition-ah
+175     compare definition, 0
+176     break-if-=
+177     # definition found
+178     {
+179       var definition-type/eax: (addr int) <- get definition, type
+180       compare *definition-type, 0/pair
+181     }
+182     break-if-!=
+183     # definition is a pair
+184     {
+185       var definition-car-ah/eax: (addr handle cell) <- get definition, left
+186       var definition-car/eax: (addr cell) <- lookup *definition-car-ah
+187       var macro?/eax: boolean <- litmac? definition-car
+188       compare macro?, 0/false
+189     }
+190     break-if-=
+191     # definition is a macro
+192     var macro-definition-ah/eax: (addr handle cell) <- get definition, right
+193     # TODO: check car(macro-definition) is litfn
+194 #?     turn-on-debug-print
+195     apply macro-definition-ah, rest-ah, expr-ah, globals, trace, 0/no-screen, 0/no-keyboard, 0/call-number
+196     return 1/true
+197   }
+198   # no macro found; process any macros within args
+199   trace-text trace, "mac", "recursing into function definition"
+200   var curr-ah/ebx: (addr handle cell) <- copy first-ah
+201   $macroexpand-iter:loop: {
+202 #?     clear-screen 0/screen
+203 #?     dump-trace trace
+204     var macro-found?/eax: boolean <- macroexpand-iter curr-ah, globals, trace
+205     result <- or macro-found?
+206     var rest/eax: (addr cell) <- lookup *rest-ah
+207     {
+208       var nil?/eax: boolean <- nil? rest
+209       compare nil?, 0/false
+210     }
+211     break-if-!=
+212     curr-ah <- get rest, left
+213     rest-ah <- get rest, right
+214     loop
+215   }
+216   return result
+217 }
+218 
+219 fn test-macroexpand {
+220   var globals-storage: global-table
+221   var globals/edx: (addr global-table) <- address globals-storage
+222   initialize-globals globals
+223   # new macro: m
+224   var sandbox-storage: sandbox
+225   var sandbox/esi: (addr sandbox) <- address sandbox-storage
+226   initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
+227   edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
+228   var trace-ah/eax: (addr handle trace) <- get sandbox, trace
+229   var trace/eax: (addr trace) <- lookup *trace-ah
+230   # invoke macro
+231   initialize-sandbox-with sandbox, "(m 3 4)"
+232   var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+233   var gap/eax: (addr gap-buffer) <- lookup *gap-ah
+234   var result-h: (handle cell)
+235   var result-ah/ebx: (addr handle cell) <- address result-h
+236   read-cell gap, result-ah, 0/no-trace
+237   var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
+238 #?   dump-cell-from-cursor-over-full-screen result-ah
+239   var _result/eax: (addr cell) <- lookup *result-ah
+240   var result/edi: (addr cell) <- copy _result
+241   # expected
+242   initialize-sandbox-with sandbox, "(+ 3 4)"
+243   var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+244   var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
+245   var expected-h: (handle cell)
+246   var expected-ah/ecx: (addr handle cell) <- address expected-h
+247   read-cell expected-gap, expected-ah, 0/no-trace
+248 #?   dump-cell-from-cursor-over-full-screen expected-ah
+249   var expected/eax: (addr cell) <- lookup *expected-ah
+250   #
+251   var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
+252   check assertion, "F - test-macroexpand"
+253 }
+254 
+255 fn test-macroexpand-inside-anonymous-fn {
+256   var globals-storage: global-table
+257   var globals/edx: (addr global-table) <- address globals-storage
+258   initialize-globals globals
+259   # new macro: m
+260   var sandbox-storage: sandbox
+261   var sandbox/esi: (addr sandbox) <- address sandbox-storage
+262   initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
+263   edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
+264   var trace-ah/eax: (addr handle trace) <- get sandbox, trace
+265   var trace/eax: (addr trace) <- lookup *trace-ah
+266   # invoke macro
+267   initialize-sandbox-with sandbox, "(fn() (m 3 4))"
+268   var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+269   var gap/eax: (addr gap-buffer) <- lookup *gap-ah
+270   var result-h: (handle cell)
+271   var result-ah/ebx: (addr handle cell) <- address result-h
+272   read-cell gap, result-ah, 0/no-trace
+273   var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
+274 #?   dump-cell-from-cursor-over-full-screen result-ah
+275   var _result/eax: (addr cell) <- lookup *result-ah
+276   var result/edi: (addr cell) <- copy _result
+277   # expected
+278   initialize-sandbox-with sandbox, "(fn() (+ 3 4))"
+279   var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+280   var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
+281   var expected-h: (handle cell)
+282   var expected-ah/ecx: (addr handle cell) <- address expected-h
+283   read-cell expected-gap, expected-ah, 0/no-trace
+284 #?   dump-cell-from-cursor-over-full-screen expected-ah
+285   var expected/eax: (addr cell) <- lookup *expected-ah
+286   #
+287   var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
+288   check assertion, "F - test-macroexpand-inside-anonymous-fn"
+289 }
+290 
+291 fn test-macroexpand-inside-fn-call {
+292   var globals-storage: global-table
+293   var globals/edx: (addr global-table) <- address globals-storage
+294   initialize-globals globals
+295   # new macro: m
+296   var sandbox-storage: sandbox
+297   var sandbox/esi: (addr sandbox) <- address sandbox-storage
+298   initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
+299   edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
+300   # invoke macro
+301   initialize-sandbox-with sandbox, "((fn() (m 3 4)))"
+302   var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+303   var gap/eax: (addr gap-buffer) <- lookup *gap-ah
+304   var result-h: (handle cell)
+305   var result-ah/ebx: (addr handle cell) <- address result-h
+306   read-cell gap, result-ah, 0/no-trace
+307   var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
+308 #?   dump-cell-from-cursor-over-full-screen result-ah
+309   var _result/eax: (addr cell) <- lookup *result-ah
+310   var result/edi: (addr cell) <- copy _result
+311   # expected
+312   initialize-sandbox-with sandbox, "((fn() (+ 3 4)))"
+313   var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+314   var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
+315   var expected-h: (handle cell)
+316   var expected-ah/ecx: (addr handle cell) <- address expected-h
+317   read-cell expected-gap, expected-ah, 0/no-trace
+318 #?   dump-cell-from-cursor-over-full-screen expected-ah
+319   var expected/eax: (addr cell) <- lookup *expected-ah
+320   #
+321   var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
+322   check assertion, "F - test-macroexpand-inside-fn-call"
+323 }
+324 
+325 fn pending-test-macroexpand-inside-backquote-unquote {
+326   var globals-storage: global-table
+327   var globals/edx: (addr global-table) <- address globals-storage
+328   initialize-globals globals
+329   # new macro: m
+330   var sandbox-storage: sandbox
+331   var sandbox/esi: (addr sandbox) <- address sandbox-storage
+332   initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
+333   edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
+334   # invoke macro
+335   initialize-sandbox-with sandbox, "`(print [result is ] ,(m 3 4)))"
+336   var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+337   var gap/eax: (addr gap-buffer) <- lookup *gap-ah
+338   var result-h: (handle cell)
+339   var result-ah/ebx: (addr handle cell) <- address result-h
+340   read-cell gap, result-ah, 0/no-trace
+341   var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
+342   dump-cell-from-cursor-over-full-screen result-ah
+343   var _result/eax: (addr cell) <- lookup *result-ah
+344   var result/edi: (addr cell) <- copy _result
+345   # expected
+346   initialize-sandbox-with sandbox, "`(print [result is ] ,(+ 3 4)))"
+347   var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+348   var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
+349   var expected-h: (handle cell)
+350   var expected-ah/ecx: (addr handle cell) <- address expected-h
+351   read-cell expected-gap, expected-ah, 0/no-trace
+352   dump-cell-from-cursor-over-full-screen expected-ah
+353   var expected/eax: (addr cell) <- lookup *expected-ah
+354   #
+355   var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
+356   check assertion, "F - test-macroexpand-inside-backquote-unquote"
+357 }
+358 
+359 fn pending-test-macroexpand-inside-nested-backquote-unquote {
+360   var globals-storage: global-table
+361   var globals/edx: (addr global-table) <- address globals-storage
+362   initialize-globals globals
+363   # new macro: m
+364   var sandbox-storage: sandbox
+365   var sandbox/esi: (addr sandbox) <- address sandbox-storage
+366   initialize-sandbox-with sandbox, "(def m (litmac litfn () (a b) `(+ ,a ,b)))"
+367   edit-sandbox sandbox, 0x13/ctrl-s, globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen
+368   # invoke macro
+369   initialize-sandbox-with sandbox, "`(a ,(m 3 4) `(b ,(m 3 4) ,,(m 3 4)))"
+370   var gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+371   var gap/eax: (addr gap-buffer) <- lookup *gap-ah
+372   var result-h: (handle cell)
+373   var result-ah/ebx: (addr handle cell) <- address result-h
+374   read-cell gap, result-ah, 0/no-trace
+375   var dummy/eax: boolean <- macroexpand-iter result-ah, globals, 0/no-trace
+376   dump-cell-from-cursor-over-full-screen result-ah
+377   var _result/eax: (addr cell) <- lookup *result-ah
+378   var result/edi: (addr cell) <- copy _result
+379   # expected
+380   initialize-sandbox-with sandbox, "`(a ,(+ 3 4) `(b ,(m 3 4) ,,(+ 3 4)))"
+381   var expected-gap-ah/ecx: (addr handle gap-buffer) <- get sandbox, data
+382   var expected-gap/eax: (addr gap-buffer) <- lookup *expected-gap-ah
+383   var expected-h: (handle cell)
+384   var expected-ah/ecx: (addr handle cell) <- address expected-h
+385   read-cell expected-gap, expected-ah, 0/no-trace
+386   dump-cell-from-cursor-over-full-screen expected-ah
+387   var expected/eax: (addr cell) <- lookup *expected-ah
+388   #
+389   var assertion/eax: boolean <- cell-isomorphic? result, expected, 0/no-trace
+390   check assertion, "F - test-macroexpand-inside-nested-backquote-unquote"
+391 }
+392 
+393 # TODO: unquote-splice, nested and unnested
+
+ + + diff --git a/html/shell/main.mu.html b/html/shell/main.mu.html index aff6ec88..d606c1b5 100644 --- a/html/shell/main.mu.html +++ b/html/shell/main.mu.html @@ -72,7 +72,7 @@ if ('onhashchange' in window) { 13 # globals layout: 1 char padding, 41 code, 1 padding, 41 code, 1 padding = 85 14 # sandbox layout: 1 padding, 41 code, 1 padding = 43 15 # total = 128 chars - 16 render-globals screen, globals + 16 render-globals screen, globals 17 render-sandbox screen, sandbox, 0x55/sandbox-left-margin, 0/sandbox-top-margin, 0x80/screen-width, 0x2f/screen-height-without-menu 18 { 19 var key/eax: byte <- read-key keyboard @@ -83,39 +83,39 @@ if ('onhashchange' in window) { 24 compare key, 0x12/ctrl-r 25 break-if-!= 26 var tmp/eax: (addr handle cell) <- copy 0 - 27 var nil: (handle cell) - 28 tmp <- address nil - 29 allocate-pair tmp + 27 var nil: (handle cell) + 28 tmp <- address nil + 29 allocate-pair tmp 30 # (main 0/real-screen 0/real-keyboard) 31 # We're using the fact that 'screen' and 'keyboard' in this function are always 0. 32 var real-keyboard: (handle cell) 33 tmp <- address real-keyboard - 34 allocate-keyboard tmp + 34 allocate-keyboard tmp 35 # args = cons(real-keyboard, nil) 36 var args: (handle cell) 37 tmp <- address args - 38 new-pair tmp, real-keyboard, nil + 38 new-pair tmp, real-keyboard, nil 39 # 40 var real-screen: (handle cell) 41 tmp <- address real-screen - 42 allocate-screen tmp + 42 allocate-screen tmp 43 # args = cons(real-screen, args) 44 tmp <- address args - 45 new-pair tmp, real-screen, *tmp + 45 new-pair tmp, real-screen, *tmp 46 # 47 var main: (handle cell) 48 tmp <- address main - 49 new-symbol tmp, "main" + 49 new-symbol tmp, "main" 50 # args = cons(main, args) 51 tmp <- address args - 52 new-pair tmp, main, *tmp + 52 new-pair tmp, main, *tmp 53 # clear real screen 54 clear-screen screen 55 set-cursor-position screen, 0, 0 56 # run 57 var out: (handle cell) 58 var out-ah/ecx: (addr handle cell) <- address out - 59 evaluate tmp, out-ah, nil, globals, 0/trace, 0/no-fake-screen, 0/no-fake-keyboard, 0/call-number + 59 evaluate tmp, out-ah, nil, globals, 0/trace, 0/no-fake-screen, 0/no-fake-keyboard, 0/call-number 60 { 61 var tmp/eax: byte <- read-key keyboard 62 compare tmp, 0 @@ -135,79 +135,88 @@ if ('onhashchange' in window) { 76 fn load-state data-disk: (addr disk), _sandbox: (addr sandbox), globals: (addr global-table) { 77 var sandbox/eax: (addr sandbox) <- copy _sandbox 78 var data-ah/eax: (addr handle gap-buffer) <- get sandbox, data - 79 var _data/eax: (addr gap-buffer) <- lookup *data-ah + 79 var _data/eax: (addr gap-buffer) <- lookup *data-ah 80 var data/esi: (addr gap-buffer) <- copy _data 81 # data-disk -> stream 82 var s-storage: (stream byte 0x1000) # space for 8/sectors 83 var s/ebx: (addr stream byte) <- address s-storage - 84 load-sectors data-disk, 0/lba, 8/sectors, s - 85 #? draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg, 0xc5/bg=blue-bg - 86 # stream -> gap-buffer - 87 load-gap-buffer-from-stream data, s - 88 clear-stream s - 89 # read: gap-buffer -> cell - 90 var initial-root-storage: (handle cell) - 91 var initial-root/ecx: (addr handle cell) <- address initial-root-storage - 92 read-cell data, initial-root, 0/no-trace - 93 clear-gap-buffer data - 94 # - 95 { - 96 var initial-root-addr/eax: (addr cell) <- lookup *initial-root - 97 compare initial-root-addr, 0 - 98 break-if-!= - 99 return -100 } -101 # load globals from assoc(initial-root, 'globals) -102 var globals-literal-storage: (handle cell) -103 var globals-literal-ah/eax: (addr handle cell) <- address globals-literal-storage -104 new-symbol globals-literal-ah, "globals" -105 var globals-literal/eax: (addr cell) <- lookup *globals-literal-ah -106 var globals-cell-storage: (handle cell) -107 var globals-cell-ah/edx: (addr handle cell) <- address globals-cell-storage -108 lookup-symbol globals-literal, globals-cell-ah, *initial-root, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard -109 var globals-cell/eax: (addr cell) <- lookup *globals-cell-ah -110 { -111 compare globals-cell, 0 -112 break-if-= -113 load-globals globals-cell-ah, globals -114 } -115 # sandbox = assoc(initial-root, 'sandbox) -116 var sandbox-literal-storage: (handle cell) -117 var sandbox-literal-ah/eax: (addr handle cell) <- address sandbox-literal-storage -118 new-symbol sandbox-literal-ah, "sandbox" -119 var sandbox-literal/eax: (addr cell) <- lookup *sandbox-literal-ah -120 var sandbox-cell-storage: (handle cell) -121 var sandbox-cell-ah/edx: (addr handle cell) <- address sandbox-cell-storage -122 lookup-symbol sandbox-literal, sandbox-cell-ah, *initial-root, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard -123 var sandbox-cell/eax: (addr cell) <- lookup *sandbox-cell-ah -124 { -125 compare sandbox-cell, 0 -126 break-if-= -127 # print: cell -> stream -128 print-cell sandbox-cell-ah, s, 0/no-trace -129 # stream -> gap-buffer -130 load-gap-buffer-from-stream data, s -131 } -132 } -133 -134 # Save state as an alist of alists: -135 # ((globals . ((a . (fn ...)) -136 # ...)) -137 # (sandbox . ...)) -138 fn store-state data-disk: (addr disk), sandbox: (addr sandbox), globals: (addr global-table) { -139 compare data-disk, 0/no-disk -140 { -141 break-if-!= -142 return -143 } -144 var stream-storage: (stream byte 0x1000) # space enough for 8/sectors -145 var stream/edi: (addr stream byte) <- address stream-storage -146 write stream, "(\n" -147 write-globals stream, globals -148 write-sandbox stream, sandbox -149 write stream, ")\n" -150 store-sectors data-disk, 0/lba, 8/sectors, stream -151 } + 84 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sectors from data disk", 3/fg, 0/bg + 85 move-cursor-to-left-margin-of-next-line 0/screen + 86 load-sectors data-disk, 0/lba, 8/sectors, s + 87 #? draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, s, 7/fg, 0xc5/bg=blue-bg + 88 # stream -> gap-buffer + 89 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "parsing", 3/fg, 0/bg + 90 move-cursor-to-left-margin-of-next-line 0/screen + 91 load-gap-buffer-from-stream data, s + 92 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " into gap buffer", 3/fg, 0/bg + 93 move-cursor-to-left-margin-of-next-line 0/screen + 94 clear-stream s + 95 # read: gap-buffer -> cell + 96 var initial-root-storage: (handle cell) + 97 var initial-root/ecx: (addr handle cell) <- address initial-root-storage + 98 read-cell data, initial-root, 0/no-trace + 99 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, " into s-expressions", 3/fg, 0/bg +100 move-cursor-to-left-margin-of-next-line 0/screen +101 clear-gap-buffer data +102 # +103 { +104 var initial-root-addr/eax: (addr cell) <- lookup *initial-root +105 compare initial-root-addr, 0 +106 break-if-!= +107 return +108 } +109 # load globals from assoc(initial-root, 'globals) +110 var globals-literal-storage: (handle cell) +111 var globals-literal-ah/eax: (addr handle cell) <- address globals-literal-storage +112 new-symbol globals-literal-ah, "globals" +113 var globals-literal/eax: (addr cell) <- lookup *globals-literal-ah +114 var globals-cell-storage: (handle cell) +115 var globals-cell-ah/edx: (addr handle cell) <- address globals-cell-storage +116 lookup-symbol globals-literal, globals-cell-ah, *initial-root, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard +117 var globals-cell/eax: (addr cell) <- lookup *globals-cell-ah +118 { +119 compare globals-cell, 0 +120 break-if-= +121 load-globals globals-cell-ah, globals +122 } +123 # sandbox = assoc(initial-root, 'sandbox) +124 draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "loading sandbox", 3/fg, 0/bg +125 var sandbox-literal-storage: (handle cell) +126 var sandbox-literal-ah/eax: (addr handle cell) <- address sandbox-literal-storage +127 new-symbol sandbox-literal-ah, "sandbox" +128 var sandbox-literal/eax: (addr cell) <- lookup *sandbox-literal-ah +129 var sandbox-cell-storage: (handle cell) +130 var sandbox-cell-ah/edx: (addr handle cell) <- address sandbox-cell-storage +131 lookup-symbol sandbox-literal, sandbox-cell-ah, *initial-root, 0/no-globals, 0/no-trace, 0/no-screen, 0/no-keyboard +132 var sandbox-cell/eax: (addr cell) <- lookup *sandbox-cell-ah +133 { +134 compare sandbox-cell, 0 +135 break-if-= +136 # print: cell -> stream +137 print-cell sandbox-cell-ah, s, 0/no-trace +138 # stream -> gap-buffer +139 load-gap-buffer-from-stream data, s +140 } +141 } +142 +143 # Save state as an alist of alists: +144 # ((globals . ((a . (fn ...)) +145 # ...)) +146 # (sandbox . ...)) +147 fn store-state data-disk: (addr disk), sandbox: (addr sandbox), globals: (addr global-table) { +148 compare data-disk, 0/no-disk +149 { +150 break-if-!= +151 return +152 } +153 var stream-storage: (stream byte 0x1000) # space enough for 8/sectors +154 var stream/edi: (addr stream byte) <- address stream-storage +155 write stream, "(\n" +156 write-globals stream, globals +157 write-sandbox stream, sandbox +158 write stream, ")\n" +159 store-sectors data-disk, 0/lba, 8/sectors, stream +160 } diff --git a/html/shell/parse.mu.html b/html/shell/parse.mu.html index 673f9466..8e01546d 100644 --- a/html/shell/parse.mu.html +++ b/html/shell/parse.mu.html @@ -86,7 +86,7 @@ if ('onhashchange' in window) { 28 # unmatched close-paren encountered? 29 # dot encountered? (only used internally by recursive calls) 30 fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) -> _/eax: boolean, _/ecx: boolean { - 31 trace-text trace, "read", "parse" + 31 trace-text trace, "parse", "parse" 32 trace-lower trace 33 var curr-token-storage: cell 34 var curr-token/ecx: (addr cell) <- address curr-token-storage @@ -97,204 +97,252 @@ if ('onhashchange' in window) { 39 error trace, "end of stream; never found a balancing ')'" 40 return 1/true, 0/false 41 } - 42 read-from-stream tokens, curr-token + 42 read-from-stream tokens, curr-token 43 $parse-sexpression:type-check: { 44 # single quote -> parse as list with a special car - 45 var quote-token?/eax: boolean <- quote-token? curr-token - 46 compare quote-token?, 0/false + 45 var quote-token?/eax: boolean <- quote-token? curr-token + 46 compare quote-token?, 0/false 47 { 48 break-if-= 49 var out/edi: (addr handle cell) <- copy _out - 50 allocate-pair out - 51 var out-addr/eax: (addr cell) <- lookup *out + 50 allocate-pair out + 51 var out-addr/eax: (addr cell) <- lookup *out 52 var left-ah/edx: (addr handle cell) <- get out-addr, left - 53 new-symbol left-ah, "'" + 53 new-symbol left-ah, "'" 54 var right-ah/edx: (addr handle cell) <- get out-addr, right 55 var close-paren?/eax: boolean <- copy 0/false 56 var dot?/ecx: boolean <- copy 0/false 57 close-paren?, dot? <- parse-sexpression tokens, right-ah, trace 58 return close-paren?, dot? 59 } - 60 # dot -> return - 61 var dot?/eax: boolean <- dot-token? curr-token - 62 compare dot?, 0/false + 60 # backquote quote -> parse as list with a special car + 61 var backquote-token?/eax: boolean <- backquote-token? curr-token + 62 compare backquote-token?, 0/false 63 { 64 break-if-= - 65 trace-higher trace - 66 return 0/false, 1/true - 67 } - 68 # not bracket -> parse atom - 69 var bracket-token?/eax: boolean <- bracket-token? curr-token - 70 compare bracket-token?, 0/false - 71 { - 72 break-if-!= - 73 parse-atom curr-token, _out, trace - 74 break $parse-sexpression:type-check + 65 var out/edi: (addr handle cell) <- copy _out + 66 allocate-pair out + 67 var out-addr/eax: (addr cell) <- lookup *out + 68 var left-ah/edx: (addr handle cell) <- get out-addr, left + 69 new-symbol left-ah, "`" + 70 var right-ah/edx: (addr handle cell) <- get out-addr, right + 71 var close-paren?/eax: boolean <- copy 0/false + 72 var dot?/ecx: boolean <- copy 0/false + 73 close-paren?, dot? <- parse-sexpression tokens, right-ah, trace + 74 return close-paren?, dot? 75 } - 76 # open paren -> parse list - 77 var open-paren?/eax: boolean <- open-paren-token? curr-token - 78 compare open-paren?, 0/false + 76 # unquote -> parse as list with a special car + 77 var unquote-token?/eax: boolean <- unquote-token? curr-token + 78 compare unquote-token?, 0/false 79 { 80 break-if-= - 81 var curr/esi: (addr handle cell) <- copy _out - 82 allocate-pair curr - 83 var curr-addr/eax: (addr cell) <- lookup *curr - 84 var left/edx: (addr handle cell) <- get curr-addr, left - 85 { - 86 var close-paren?/eax: boolean <- copy 0/false - 87 var dot?/ecx: boolean <- copy 0/false - 88 close-paren?, dot? <- parse-sexpression tokens, left, trace - 89 { - 90 compare dot?, 0/false - 91 break-if-= - 92 error trace, "'.' cannot be at the start of a list" - 93 return 1/true, dot? - 94 } - 95 compare close-paren?, 0/false - 96 break-if-!= - 97 var curr-addr/eax: (addr cell) <- lookup *curr - 98 curr <- get curr-addr, right - 99 var tmp-storage: (handle cell) -100 var tmp/edx: (addr handle cell) <- address tmp-storage -101 $parse-sexpression:list-loop: { -102 var close-paren?/eax: boolean <- copy 0/false -103 var dot?/ecx: boolean <- copy 0/false -104 close-paren?, dot? <- parse-sexpression tokens, tmp, trace -105 # '.' -> clean up right here and return -106 compare dot?, 0/false -107 { -108 break-if-= -109 parse-dot-tail tokens, curr, trace -110 return 0/false, 0/false -111 } -112 allocate-pair curr -113 # ')' -> return -114 compare close-paren?, 0/false -115 break-if-!= -116 var curr-addr/eax: (addr cell) <- lookup *curr -117 var left/ecx: (addr handle cell) <- get curr-addr, left -118 copy-object tmp, left -119 # -120 curr <- get curr-addr, right -121 loop -122 } -123 } -124 break $parse-sexpression:type-check -125 } -126 # close paren -> return -127 var close-paren?/eax: boolean <- close-paren-token? curr-token -128 compare close-paren?, 0/false -129 { -130 break-if-= -131 trace-higher trace -132 return 1/true, 0/false -133 } -134 # otherwise abort -135 var stream-storage: (stream byte 0x40) -136 var stream/edx: (addr stream byte) <- address stream-storage -137 write stream, "unexpected token " -138 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data -139 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah -140 rewind-stream curr-token-data -141 write-stream stream, curr-token-data -142 trace trace, "error", stream -143 } -144 trace-higher trace -145 return 0/false, 0/false -146 } -147 -148 fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr trace) { -149 trace-text trace, "read", "parse atom" -150 var curr-token/ecx: (addr cell) <- copy _curr-token -151 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data -152 var _curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah -153 var curr-token-data/esi: (addr stream byte) <- copy _curr-token-data -154 trace trace, "read", curr-token-data -155 # number -156 var number-token?/eax: boolean <- number-token? curr-token -157 compare number-token?, 0/false -158 { -159 break-if-= -160 rewind-stream curr-token-data -161 var _val/eax: int <- parse-decimal-int-from-stream curr-token-data -162 var val/ecx: int <- copy _val -163 var val-float/xmm0: float <- convert val -164 allocate-number _out -165 var out/eax: (addr handle cell) <- copy _out -166 var out-addr/eax: (addr cell) <- lookup *out -167 var dest/edi: (addr float) <- get out-addr, number-data -168 copy-to *dest, val-float -169 { -170 var stream-storage: (stream byte 0x40) -171 var stream/ecx: (addr stream byte) <- address stream-storage -172 write stream, "=> number " -173 print-number out-addr, stream, 0/no-trace -174 trace trace, "read", stream -175 } -176 return -177 } -178 # default: copy either to a symbol or a stream -179 # stream token -> literal -180 var stream-token?/eax: boolean <- stream-token? curr-token -181 compare stream-token?, 0/false -182 { -183 break-if-= -184 allocate-stream _out -185 } -186 compare stream-token?, 0/false -187 { -188 break-if-!= -189 allocate-symbol _out -190 } -191 # copy token data -192 var out/eax: (addr handle cell) <- copy _out -193 var out-addr/eax: (addr cell) <- lookup *out -194 var curr-token-data-ah/ecx: (addr handle stream byte) <- get curr-token, text-data -195 var dest-ah/edx: (addr handle stream byte) <- get out-addr, text-data -196 copy-object curr-token-data-ah, dest-ah -197 { -198 var stream-storage: (stream byte 0x40) -199 var stream/ecx: (addr stream byte) <- address stream-storage -200 write stream, "=> symbol " -201 print-symbol out-addr, stream, 0/no-trace -202 trace trace, "read", stream -203 } -204 } -205 -206 fn parse-dot-tail tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) { -207 var out/edi: (addr handle cell) <- copy _out -208 var close-paren?/eax: boolean <- copy 0/false -209 var dot?/ecx: boolean <- copy 0/false -210 close-paren?, dot? <- parse-sexpression tokens, out, trace -211 compare close-paren?, 0/false -212 { -213 break-if-= -214 error trace, "'. )' makes no sense" -215 return -216 } -217 compare dot?, 0/false -218 { -219 break-if-= -220 error trace, "'. .' makes no sense" -221 return -222 } -223 # -224 var dummy: (handle cell) -225 var dummy-ah/edi: (addr handle cell) <- address dummy -226 close-paren?, dot? <- parse-sexpression tokens, dummy-ah, trace -227 compare close-paren?, 0/false -228 { -229 break-if-!= -230 error trace, "cannot have multiple expressions between '.' and ')'" -231 return -232 } -233 compare dot?, 0/false -234 { -235 break-if-= -236 error trace, "cannot have two dots in a single list" -237 return + 81 var out/edi: (addr handle cell) <- copy _out + 82 allocate-pair out + 83 var out-addr/eax: (addr cell) <- lookup *out + 84 var left-ah/edx: (addr handle cell) <- get out-addr, left + 85 new-symbol left-ah, "," + 86 var right-ah/edx: (addr handle cell) <- get out-addr, right + 87 var close-paren?/eax: boolean <- copy 0/false + 88 var dot?/ecx: boolean <- copy 0/false + 89 close-paren?, dot? <- parse-sexpression tokens, right-ah, trace + 90 return close-paren?, dot? + 91 } + 92 # unquote-splice -> parse as list with a special car + 93 var unquote-splice-token?/eax: boolean <- unquote-splice-token? curr-token + 94 compare unquote-splice-token?, 0/false + 95 { + 96 break-if-= + 97 var out/edi: (addr handle cell) <- copy _out + 98 allocate-pair out + 99 var out-addr/eax: (addr cell) <- lookup *out +100 var left-ah/edx: (addr handle cell) <- get out-addr, left +101 new-symbol left-ah, ",@" +102 var right-ah/edx: (addr handle cell) <- get out-addr, right +103 var close-paren?/eax: boolean <- copy 0/false +104 var dot?/ecx: boolean <- copy 0/false +105 close-paren?, dot? <- parse-sexpression tokens, right-ah, trace +106 return close-paren?, dot? +107 } +108 # dot -> return +109 var dot?/eax: boolean <- dot-token? curr-token +110 compare dot?, 0/false +111 { +112 break-if-= +113 trace-higher trace +114 return 0/false, 1/true +115 } +116 # not bracket -> parse atom +117 var bracket-token?/eax: boolean <- bracket-token? curr-token +118 compare bracket-token?, 0/false +119 { +120 break-if-!= +121 parse-atom curr-token, _out, trace +122 break $parse-sexpression:type-check +123 } +124 # open paren -> parse list +125 var open-paren?/eax: boolean <- open-paren-token? curr-token +126 compare open-paren?, 0/false +127 { +128 break-if-= +129 var curr/esi: (addr handle cell) <- copy _out +130 allocate-pair curr +131 var curr-addr/eax: (addr cell) <- lookup *curr +132 var left/edx: (addr handle cell) <- get curr-addr, left +133 { +134 var close-paren?/eax: boolean <- copy 0/false +135 var dot?/ecx: boolean <- copy 0/false +136 close-paren?, dot? <- parse-sexpression tokens, left, trace +137 { +138 compare dot?, 0/false +139 break-if-= +140 error trace, "'.' cannot be at the start of a list" +141 return 1/true, dot? +142 } +143 compare close-paren?, 0/false +144 break-if-!= +145 var curr-addr/eax: (addr cell) <- lookup *curr +146 curr <- get curr-addr, right +147 var tmp-storage: (handle cell) +148 var tmp/edx: (addr handle cell) <- address tmp-storage +149 $parse-sexpression:list-loop: { +150 var close-paren?/eax: boolean <- copy 0/false +151 var dot?/ecx: boolean <- copy 0/false +152 close-paren?, dot? <- parse-sexpression tokens, tmp, trace +153 # '.' -> clean up right here and return +154 compare dot?, 0/false +155 { +156 break-if-= +157 parse-dot-tail tokens, curr, trace +158 return 0/false, 0/false +159 } +160 allocate-pair curr +161 # ')' -> return +162 compare close-paren?, 0/false +163 break-if-!= +164 var curr-addr/eax: (addr cell) <- lookup *curr +165 var left/ecx: (addr handle cell) <- get curr-addr, left +166 copy-object tmp, left +167 # +168 curr <- get curr-addr, right +169 loop +170 } +171 } +172 break $parse-sexpression:type-check +173 } +174 # close paren -> return +175 var close-paren?/eax: boolean <- close-paren-token? curr-token +176 compare close-paren?, 0/false +177 { +178 break-if-= +179 trace-higher trace +180 return 1/true, 0/false +181 } +182 # otherwise abort +183 var stream-storage: (stream byte 0x400) +184 var stream/edx: (addr stream byte) <- address stream-storage +185 write stream, "unexpected token " +186 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data +187 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah +188 rewind-stream curr-token-data +189 write-stream stream, curr-token-data +190 trace trace, "error", stream +191 } +192 trace-higher trace +193 return 0/false, 0/false +194 } +195 +196 fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr trace) { +197 trace-text trace, "parse", "parse atom" +198 var curr-token/ecx: (addr cell) <- copy _curr-token +199 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data +200 var _curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah +201 var curr-token-data/esi: (addr stream byte) <- copy _curr-token-data +202 trace trace, "parse", curr-token-data +203 # number +204 var number-token?/eax: boolean <- number-token? curr-token +205 compare number-token?, 0/false +206 { +207 break-if-= +208 rewind-stream curr-token-data +209 var _val/eax: int <- parse-decimal-int-from-stream curr-token-data +210 var val/ecx: int <- copy _val +211 var val-float/xmm0: float <- convert val +212 allocate-number _out +213 var out/eax: (addr handle cell) <- copy _out +214 var out-addr/eax: (addr cell) <- lookup *out +215 var dest/edi: (addr float) <- get out-addr, number-data +216 copy-to *dest, val-float +217 { +218 var stream-storage: (stream byte 0x400) +219 var stream/ecx: (addr stream byte) <- address stream-storage +220 write stream, "=> number " +221 print-number out-addr, stream, 0/no-trace +222 trace trace, "parse", stream +223 } +224 return +225 } +226 # default: copy either to a symbol or a stream +227 # stream token -> literal +228 var stream-token?/eax: boolean <- stream-token? curr-token +229 compare stream-token?, 0/false +230 { +231 break-if-= +232 allocate-stream _out +233 } +234 compare stream-token?, 0/false +235 { +236 break-if-!= +237 allocate-symbol _out 238 } -239 } +239 # copy token data +240 var out/eax: (addr handle cell) <- copy _out +241 var out-addr/eax: (addr cell) <- lookup *out +242 var curr-token-data-ah/ecx: (addr handle stream byte) <- get curr-token, text-data +243 var dest-ah/edx: (addr handle stream byte) <- get out-addr, text-data +244 copy-object curr-token-data-ah, dest-ah +245 { +246 var stream-storage: (stream byte 0x400) +247 var stream/ecx: (addr stream byte) <- address stream-storage +248 write stream, "=> symbol " +249 print-symbol out-addr, stream, 0/no-trace +250 trace trace, "parse", stream +251 } +252 } +253 +254 fn parse-dot-tail tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) { +255 var out/edi: (addr handle cell) <- copy _out +256 var close-paren?/eax: boolean <- copy 0/false +257 var dot?/ecx: boolean <- copy 0/false +258 close-paren?, dot? <- parse-sexpression tokens, out, trace +259 compare close-paren?, 0/false +260 { +261 break-if-= +262 error trace, "'. )' makes no sense" +263 return +264 } +265 compare dot?, 0/false +266 { +267 break-if-= +268 error trace, "'. .' makes no sense" +269 return +270 } +271 # +272 var dummy: (handle cell) +273 var dummy-ah/edi: (addr handle cell) <- address dummy +274 close-paren?, dot? <- parse-sexpression tokens, dummy-ah, trace +275 compare close-paren?, 0/false +276 { +277 break-if-!= +278 error trace, "cannot have multiple expressions between '.' and ')'" +279 return +280 } +281 compare dot?, 0/false +282 { +283 break-if-= +284 error trace, "cannot have two dots in a single list" +285 return +286 } +287 } diff --git a/html/shell/print.mu.html b/html/shell/print.mu.html index 18c90801..e880b03c 100644 --- a/html/shell/print.mu.html +++ b/html/shell/print.mu.html @@ -62,7 +62,7 @@ if ('onhashchange' in window) { 3 trace-text trace, "print", "print" 4 trace-lower trace 5 var in/eax: (addr handle cell) <- copy _in - 6 var in-addr/eax: (addr cell) <- lookup *in + 6 var in-addr/eax: (addr cell) <- lookup *in 7 { 8 compare in-addr, 0 9 break-if-!= @@ -71,8 +71,8 @@ if ('onhashchange' in window) { 12 return 13 } 14 { - 15 var nil?/eax: boolean <- nil? in-addr - 16 compare nil?, 0/false + 15 var nil?/eax: boolean <- nil? in-addr + 16 compare nil?, 0/false 17 break-if-= 18 write out, "()" 19 trace-higher trace @@ -82,7 +82,7 @@ if ('onhashchange' in window) { 23 compare *in-type, 0/pair 24 { 25 break-if-!= - 26 print-list in-addr, out, trace + 26 print-pair in-addr, out, trace 27 trace-higher trace 28 return 29 } @@ -119,7 +119,7 @@ if ('onhashchange' in window) { 60 break-if-!= 61 write out, "[screen " 62 var screen-ah/eax: (addr handle screen) <- get in-addr, screen-data - 63 var screen/eax: (addr screen) <- lookup *screen-ah + 63 var screen/eax: (addr screen) <- lookup *screen-ah 64 var screen-addr/eax: int <- copy screen 65 write-int32-hex out, screen-addr 66 write out, "]" @@ -131,7 +131,7 @@ if ('onhashchange' in window) { 72 break-if-!= 73 write out, "[keyboard " 74 var keyboard-ah/eax: (addr handle gap-buffer) <- get in-addr, keyboard-data - 75 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah + 75 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah 76 var keyboard-addr/eax: int <- copy keyboard 77 write-int32-hex out, keyboard-addr 78 write out, "]" @@ -142,7 +142,7 @@ if ('onhashchange' in window) { 83 84 # debug helper 85 fn dump-cell-at-top-right in-ah: (addr handle cell) { - 86 var stream-storage: (stream byte 0x200) + 86 var stream-storage: (stream byte 0x1000) 87 var stream/edx: (addr stream byte) <- address stream-storage 88 print-cell in-ah, stream, 0/no-trace 89 var d1/eax: int <- copy 0 @@ -154,14 +154,14 @@ if ('onhashchange' in window) { 95 var stream-storage: (stream byte 0x200) 96 var stream/edx: (addr stream byte) <- address stream-storage 97 print-cell in-ah, stream, 0/no-trace - 98 draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, stream, 7/fg, 0xc5/bg=blue-bg + 98 draw-stream-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, stream, 7/fg, 0/bg 99 } 100 101 fn print-symbol _in: (addr cell), out: (addr stream byte), trace: (addr trace) { 102 trace-text trace, "print", "symbol" 103 var in/esi: (addr cell) <- copy _in 104 var data-ah/eax: (addr handle stream byte) <- get in, text-data -105 var _data/eax: (addr stream byte) <- lookup *data-ah +105 var _data/eax: (addr stream byte) <- lookup *data-ah 106 var data/esi: (addr stream byte) <- copy _data 107 rewind-stream data 108 write-stream out, data @@ -180,7 +180,7 @@ if ('onhashchange' in window) { 121 trace-text trace, "print", "stream" 122 var in/esi: (addr cell) <- copy _in 123 var data-ah/eax: (addr handle stream byte) <- get in, text-data -124 var _data/eax: (addr stream byte) <- lookup *data-ah +124 var _data/eax: (addr stream byte) <- lookup *data-ah 125 var data/esi: (addr stream byte) <- copy _data 126 rewind-stream data 127 write out, "[" @@ -211,211 +211,253 @@ if ('onhashchange' in window) { 152 trace trace, "print", stream 153 } 154 -155 fn print-list _in: (addr cell), out: (addr stream byte), trace: (addr trace) { -156 var curr/esi: (addr cell) <- copy _in -157 write out, "(" -158 $print-list:loop: { -159 var left/ecx: (addr handle cell) <- get curr, left -160 print-cell left, out, trace -161 var right/ecx: (addr handle cell) <- get curr, right -162 var right-addr/eax: (addr cell) <- lookup *right -163 { -164 compare right-addr, 0 -165 break-if-!= -166 abort "null encountered" -167 } -168 { -169 var right-nil?/eax: boolean <- nil? right-addr -170 compare right-nil?, 0/false -171 { -172 break-if-= -173 trace-text trace, "print", "right is nil" -174 break $print-list:loop -175 } -176 } -177 write out, " " -178 var right-type-addr/edx: (addr int) <- get right-addr, type -179 { -180 compare *right-type-addr, 0/pair -181 break-if-= -182 write out, ". " -183 print-cell right, out, trace -184 break $print-list:loop -185 } -186 curr <- copy right-addr -187 loop -188 } -189 write out, ")" -190 } -191 -192 # Most lisps intern nil, but we don't really have globals yet, so we'll be -193 # less efficient for now. -194 fn nil? _in: (addr cell) -> _/eax: boolean { -195 var in/esi: (addr cell) <- copy _in -196 # if type != pair, return false -197 var type/eax: (addr int) <- get in, type -198 compare *type, 0/pair -199 { -200 break-if-= -201 return 0/false -202 } -203 # if left != null, return false -204 var left-ah/eax: (addr handle cell) <- get in, left -205 var left/eax: (addr cell) <- lookup *left-ah -206 compare left, 0 -207 { -208 break-if-= -209 return 0/false -210 } -211 # if right != null, return false -212 var right-ah/eax: (addr handle cell) <- get in, right -213 var right/eax: (addr cell) <- lookup *right-ah -214 compare right, 0 -215 { -216 break-if-= -217 return 0/false -218 } -219 return 1/true -220 } -221 -222 fn test-print-cell-zero { -223 var num-storage: (handle cell) -224 var num/esi: (addr handle cell) <- address num-storage -225 new-integer num, 0 -226 var out-storage: (stream byte 0x40) -227 var out/edi: (addr stream byte) <- address out-storage -228 print-cell num, out, 0/no-trace -229 check-stream-equal out, "0", "F - test-print-cell-zero" -230 } -231 -232 fn test-print-cell-integer { -233 var num-storage: (handle cell) -234 var num/esi: (addr handle cell) <- address num-storage -235 new-integer num, 1 -236 var out-storage: (stream byte 0x40) -237 var out/edi: (addr stream byte) <- address out-storage -238 print-cell num, out, 0/no-trace -239 check-stream-equal out, "1", "F - test-print-cell-integer" -240 } -241 -242 fn test-print-cell-integer-2 { -243 var num-storage: (handle cell) -244 var num/esi: (addr handle cell) <- address num-storage -245 new-integer num, 0x30 -246 var out-storage: (stream byte 0x40) -247 var out/edi: (addr stream byte) <- address out-storage -248 print-cell num, out, 0/no-trace -249 check-stream-equal out, "48", "F - test-print-cell-integer-2" -250 } -251 -252 fn test-print-cell-fraction { -253 var num-storage: (handle cell) -254 var num/esi: (addr handle cell) <- address num-storage -255 var val/xmm0: float <- rational 1, 2 -256 new-float num, val -257 var out-storage: (stream byte 0x40) -258 var out/edi: (addr stream byte) <- address out-storage -259 print-cell num, out, 0/no-trace -260 check-stream-equal out, "0.5", "F - test-print-cell-fraction" -261 } -262 -263 fn test-print-cell-symbol { -264 var sym-storage: (handle cell) -265 var sym/esi: (addr handle cell) <- address sym-storage -266 new-symbol sym, "abc" -267 var out-storage: (stream byte 0x40) -268 var out/edi: (addr stream byte) <- address out-storage -269 print-cell sym, out, 0/no-trace -270 check-stream-equal out, "abc", "F - test-print-cell-symbol" -271 } -272 -273 fn test-print-cell-nil-list { -274 var nil-storage: (handle cell) -275 var nil/esi: (addr handle cell) <- address nil-storage -276 allocate-pair nil -277 var out-storage: (stream byte 0x40) -278 var out/edi: (addr stream byte) <- address out-storage -279 print-cell nil, out, 0/no-trace -280 check-stream-equal out, "()", "F - test-print-cell-nil-list" -281 } -282 -283 fn test-print-cell-singleton-list { -284 # list -285 var left-storage: (handle cell) -286 var left/ecx: (addr handle cell) <- address left-storage -287 new-symbol left, "abc" -288 var nil-storage: (handle cell) -289 var nil/edx: (addr handle cell) <- address nil-storage -290 allocate-pair nil -291 var list-storage: (handle cell) -292 var list/esi: (addr handle cell) <- address list-storage -293 new-pair list, *left, *nil -294 # -295 var out-storage: (stream byte 0x40) -296 var out/edi: (addr stream byte) <- address out-storage -297 print-cell list, out, 0/no-trace -298 check-stream-equal out, "(abc)", "F - test-print-cell-singleton-list" -299 } -300 -301 fn test-print-cell-list { -302 # list = cons "abc", nil -303 var left-storage: (handle cell) -304 var left/ecx: (addr handle cell) <- address left-storage -305 new-symbol left, "abc" -306 var nil-storage: (handle cell) -307 var nil/edx: (addr handle cell) <- address nil-storage -308 allocate-pair nil -309 var list-storage: (handle cell) -310 var list/esi: (addr handle cell) <- address list-storage -311 new-pair list, *left, *nil -312 # list = cons 64, list -313 new-integer left, 0x40 -314 new-pair list, *left, *list -315 # -316 var out-storage: (stream byte 0x40) -317 var out/edi: (addr stream byte) <- address out-storage -318 print-cell list, out, 0/no-trace -319 check-stream-equal out, "(64 abc)", "F - test-print-cell-list" -320 } -321 -322 fn test-print-cell-list-of-nil { -323 # list = cons "abc", nil -324 var left-storage: (handle cell) -325 var left/ecx: (addr handle cell) <- address left-storage -326 allocate-pair left -327 var nil-storage: (handle cell) -328 var nil/edx: (addr handle cell) <- address nil-storage -329 allocate-pair nil -330 var list-storage: (handle cell) -331 var list/esi: (addr handle cell) <- address list-storage -332 new-pair list, *left, *nil -333 # list = cons 64, list -334 new-integer left, 0x40 -335 new-pair list, *left, *list +155 fn print-pair _in: (addr cell), out: (addr stream byte), trace: (addr trace) { +156 # if in starts with a quote, print the quote outside the expression +157 var in/esi: (addr cell) <- copy _in +158 var left-ah/eax: (addr handle cell) <- get in, left +159 var _left/eax: (addr cell) <- lookup *left-ah +160 var left/ecx: (addr cell) <- copy _left +161 var is-quote?/eax: boolean <- symbol-equal? left, "'" +162 compare is-quote?, 0/false +163 { +164 break-if-= +165 write out, "'" +166 var right-ah/eax: (addr handle cell) <- get in, right +167 print-cell right-ah, out, trace +168 return +169 } +170 var is-backquote?/eax: boolean <- symbol-equal? left, "`" +171 compare is-backquote?, 0/false +172 { +173 break-if-= +174 write out, "`" +175 var right-ah/eax: (addr handle cell) <- get in, right +176 print-cell right-ah, out, trace +177 return +178 } +179 var is-unquote?/eax: boolean <- symbol-equal? left, "," +180 compare is-unquote?, 0/false +181 { +182 break-if-= +183 write out, "," +184 var right-ah/eax: (addr handle cell) <- get in, right +185 print-cell right-ah, out, trace +186 return +187 } +188 var is-unquote-splice?/eax: boolean <- symbol-equal? left, ",@" +189 compare is-unquote-splice?, 0/false +190 { +191 break-if-= +192 write out, ",@" +193 var right-ah/eax: (addr handle cell) <- get in, right +194 print-cell right-ah, out, trace +195 return +196 } +197 # +198 var curr/esi: (addr cell) <- copy _in +199 write out, "(" +200 $print-pair:loop: { +201 var left/ecx: (addr handle cell) <- get curr, left +202 print-cell left, out, trace +203 var right/ecx: (addr handle cell) <- get curr, right +204 var right-addr/eax: (addr cell) <- lookup *right +205 { +206 compare right-addr, 0 +207 break-if-!= +208 abort "null encountered" +209 } +210 { +211 var right-nil?/eax: boolean <- nil? right-addr +212 compare right-nil?, 0/false +213 { +214 break-if-= +215 trace-text trace, "print", "right is nil" +216 break $print-pair:loop +217 } +218 } +219 write out, " " +220 var right-type-addr/edx: (addr int) <- get right-addr, type +221 { +222 compare *right-type-addr, 0/pair +223 break-if-= +224 write out, ". " +225 print-cell right, out, trace +226 break $print-pair:loop +227 } +228 curr <- copy right-addr +229 loop +230 } +231 write out, ")" +232 } +233 +234 # Most lisps intern nil, but we don't really have globals yet, so we'll be +235 # less efficient for now. +236 fn nil? _in: (addr cell) -> _/eax: boolean { +237 var in/esi: (addr cell) <- copy _in +238 # if type != pair, return false +239 var type/eax: (addr int) <- get in, type +240 compare *type, 0/pair +241 { +242 break-if-= +243 return 0/false +244 } +245 # if left != null, return false +246 var left-ah/eax: (addr handle cell) <- get in, left +247 var left/eax: (addr cell) <- lookup *left-ah +248 compare left, 0 +249 { +250 break-if-= +251 return 0/false +252 } +253 # if right != null, return false +254 var right-ah/eax: (addr handle cell) <- get in, right +255 var right/eax: (addr cell) <- lookup *right-ah +256 compare right, 0 +257 { +258 break-if-= +259 return 0/false +260 } +261 return 1/true +262 } +263 +264 fn test-print-cell-zero { +265 var num-storage: (handle cell) +266 var num/esi: (addr handle cell) <- address num-storage +267 new-integer num, 0 +268 var out-storage: (stream byte 0x40) +269 var out/edi: (addr stream byte) <- address out-storage +270 print-cell num, out, 0/no-trace +271 check-stream-equal out, "0", "F - test-print-cell-zero" +272 } +273 +274 fn test-print-cell-integer { +275 var num-storage: (handle cell) +276 var num/esi: (addr handle cell) <- address num-storage +277 new-integer num, 1 +278 var out-storage: (stream byte 0x40) +279 var out/edi: (addr stream byte) <- address out-storage +280 print-cell num, out, 0/no-trace +281 check-stream-equal out, "1", "F - test-print-cell-integer" +282 } +283 +284 fn test-print-cell-integer-2 { +285 var num-storage: (handle cell) +286 var num/esi: (addr handle cell) <- address num-storage +287 new-integer num, 0x30 +288 var out-storage: (stream byte 0x40) +289 var out/edi: (addr stream byte) <- address out-storage +290 print-cell num, out, 0/no-trace +291 check-stream-equal out, "48", "F - test-print-cell-integer-2" +292 } +293 +294 fn test-print-cell-fraction { +295 var num-storage: (handle cell) +296 var num/esi: (addr handle cell) <- address num-storage +297 var val/xmm0: float <- rational 1, 2 +298 new-float num, val +299 var out-storage: (stream byte 0x40) +300 var out/edi: (addr stream byte) <- address out-storage +301 print-cell num, out, 0/no-trace +302 check-stream-equal out, "0.5", "F - test-print-cell-fraction" +303 } +304 +305 fn test-print-cell-symbol { +306 var sym-storage: (handle cell) +307 var sym/esi: (addr handle cell) <- address sym-storage +308 new-symbol sym, "abc" +309 var out-storage: (stream byte 0x40) +310 var out/edi: (addr stream byte) <- address out-storage +311 print-cell sym, out, 0/no-trace +312 check-stream-equal out, "abc", "F - test-print-cell-symbol" +313 } +314 +315 fn test-print-cell-nil-list { +316 var nil-storage: (handle cell) +317 var nil/esi: (addr handle cell) <- address nil-storage +318 allocate-pair nil +319 var out-storage: (stream byte 0x40) +320 var out/edi: (addr stream byte) <- address out-storage +321 print-cell nil, out, 0/no-trace +322 check-stream-equal out, "()", "F - test-print-cell-nil-list" +323 } +324 +325 fn test-print-cell-singleton-list { +326 # list +327 var left-storage: (handle cell) +328 var left/ecx: (addr handle cell) <- address left-storage +329 new-symbol left, "abc" +330 var nil-storage: (handle cell) +331 var nil/edx: (addr handle cell) <- address nil-storage +332 allocate-pair nil +333 var list-storage: (handle cell) +334 var list/esi: (addr handle cell) <- address list-storage +335 new-pair list, *left, *nil 336 # 337 var out-storage: (stream byte 0x40) 338 var out/edi: (addr stream byte) <- address out-storage 339 print-cell list, out, 0/no-trace -340 check-stream-equal out, "(64 ())", "F - test-print-cell-list-nil" +340 check-stream-equal out, "(abc)", "F - test-print-cell-singleton-list" 341 } 342 -343 fn test-print-dotted-list { -344 # list = cons 64, "abc" +343 fn test-print-cell-list { +344 # list = cons "abc", nil 345 var left-storage: (handle cell) 346 var left/ecx: (addr handle cell) <- address left-storage -347 new-symbol left, "abc" -348 var right-storage: (handle cell) -349 var right/edx: (addr handle cell) <- address right-storage -350 new-integer right, 0x40 +347 new-symbol left, "abc" +348 var nil-storage: (handle cell) +349 var nil/edx: (addr handle cell) <- address nil-storage +350 allocate-pair nil 351 var list-storage: (handle cell) 352 var list/esi: (addr handle cell) <- address list-storage -353 new-pair list, *left, *right -354 # -355 var out-storage: (stream byte 0x40) -356 var out/edi: (addr stream byte) <- address out-storage -357 print-cell list, out, 0/no-trace -358 check-stream-equal out, "(abc . 64)", "F - test-print-dotted-list" -359 } +353 new-pair list, *left, *nil +354 # list = cons 64, list +355 new-integer left, 0x40 +356 new-pair list, *left, *list +357 # +358 var out-storage: (stream byte 0x40) +359 var out/edi: (addr stream byte) <- address out-storage +360 print-cell list, out, 0/no-trace +361 check-stream-equal out, "(64 abc)", "F - test-print-cell-list" +362 } +363 +364 fn test-print-cell-list-of-nil { +365 # list = cons "abc", nil +366 var left-storage: (handle cell) +367 var left/ecx: (addr handle cell) <- address left-storage +368 allocate-pair left +369 var nil-storage: (handle cell) +370 var nil/edx: (addr handle cell) <- address nil-storage +371 allocate-pair nil +372 var list-storage: (handle cell) +373 var list/esi: (addr handle cell) <- address list-storage +374 new-pair list, *left, *nil +375 # list = cons 64, list +376 new-integer left, 0x40 +377 new-pair list, *left, *list +378 # +379 var out-storage: (stream byte 0x40) +380 var out/edi: (addr stream byte) <- address out-storage +381 print-cell list, out, 0/no-trace +382 check-stream-equal out, "(64 ())", "F - test-print-cell-list-nil" +383 } +384 +385 fn test-print-dotted-list { +386 # list = cons 64, "abc" +387 var left-storage: (handle cell) +388 var left/ecx: (addr handle cell) <- address left-storage +389 new-symbol left, "abc" +390 var right-storage: (handle cell) +391 var right/edx: (addr handle cell) <- address right-storage +392 new-integer right, 0x40 +393 var list-storage: (handle cell) +394 var list/esi: (addr handle cell) <- address list-storage +395 new-pair list, *left, *right +396 # +397 var out-storage: (stream byte 0x40) +398 var out/edi: (addr stream byte) <- address out-storage +399 print-cell list, out, 0/no-trace +400 check-stream-equal out, "(abc . 64)", "F - test-print-dotted-list" +401 } diff --git a/html/shell/sandbox.mu.html b/html/shell/sandbox.mu.html index 4d2be852..cbdc7c9f 100644 --- a/html/shell/sandbox.mu.html +++ b/html/shell/sandbox.mu.html @@ -16,6 +16,7 @@ a { color:inherit; } * { font-size:12pt; font-size: 1em; } .PreProc { color: #c000c0; } .LineNr { } +.CommentedCode { color: #8a8a8a; } .Constant { color: #008787; } .muComment { color: #005faf; } .Delimiter { color: #c000c0; } @@ -72,7 +73,7 @@ if ('onhashchange' in window) { 13 var self/esi: (addr sandbox) <- copy _self 14 var data-ah/eax: (addr handle gap-buffer) <- get self, data 15 allocate data-ah - 16 var data/eax: (addr gap-buffer) <- lookup *data-ah + 16 var data/eax: (addr gap-buffer) <- lookup *data-ah 17 initialize-gap-buffer data, 0x1000/4KB 18 # 19 var value-ah/eax: (addr handle stream byte) <- get self, value @@ -82,14 +83,14 @@ if ('onhashchange' in window) { 23 compare fake-screen-and-keyboard?, 0/false 24 break-if-= 25 var screen-ah/eax: (addr handle cell) <- get self, screen-var - 26 new-fake-screen screen-ah, 8/width, 3/height, 1/enable-pixel-graphics + 26 new-fake-screen screen-ah, 8/width, 3/height, 1/enable-pixel-graphics 27 var keyboard-ah/eax: (addr handle cell) <- get self, keyboard-var - 28 new-fake-keyboard keyboard-ah, 0x10/keyboard-capacity + 28 new-fake-keyboard keyboard-ah, 0x10/keyboard-capacity 29 } 30 # 31 var trace-ah/eax: (addr handle trace) <- get self, trace 32 allocate trace-ah - 33 var trace/eax: (addr trace) <- lookup *trace-ah + 33 var trace/eax: (addr trace) <- lookup *trace-ah 34 initialize-trace trace, 0x8000/lines, 0x80/visible-lines 35 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data? 36 copy-to *cursor-in-data?, 1/true @@ -101,13 +102,13 @@ if ('onhashchange' in window) { 42 var self/esi: (addr sandbox) <- copy _self 43 var data-ah/eax: (addr handle gap-buffer) <- get self, data 44 allocate data-ah - 45 var data/eax: (addr gap-buffer) <- lookup *data-ah + 45 var data/eax: (addr gap-buffer) <- lookup *data-ah 46 initialize-gap-buffer-with data, s 47 var value-ah/eax: (addr handle stream byte) <- get self, value 48 populate-stream value-ah, 0x1000/4KB 49 var trace-ah/eax: (addr handle trace) <- get self, trace 50 allocate trace-ah - 51 var trace/eax: (addr trace) <- lookup *trace-ah + 51 var trace/eax: (addr trace) <- lookup *trace-ah 52 initialize-trace trace, 0x8000/lines, 0x80/visible-lines 53 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data? 54 copy-to *cursor-in-data?, 1/true @@ -116,14 +117,14 @@ if ('onhashchange' in window) { 57 fn allocate-sandbox-with _out: (addr handle sandbox), s: (addr array byte) { 58 var out/eax: (addr handle sandbox) <- copy _out 59 allocate out - 60 var out-addr/eax: (addr sandbox) <- lookup *out + 60 var out-addr/eax: (addr sandbox) <- lookup *out 61 initialize-sandbox-with out-addr, s 62 } 63 64 fn write-sandbox out: (addr stream byte), _self: (addr sandbox) { 65 var self/eax: (addr sandbox) <- copy _self 66 var data-ah/eax: (addr handle gap-buffer) <- get self, data - 67 var data/eax: (addr gap-buffer) <- lookup *data-ah + 67 var data/eax: (addr gap-buffer) <- lookup *data-ah 68 { 69 var len/eax: int <- gap-buffer-length data 70 compare len, 0 @@ -145,7 +146,7 @@ if ('onhashchange' in window) { 86 var self/esi: (addr sandbox) <- copy _self 87 # data 88 var data-ah/eax: (addr handle gap-buffer) <- get self, data - 89 var _data/eax: (addr gap-buffer) <- lookup *data-ah + 89 var _data/eax: (addr gap-buffer) <- lookup *data-ah 90 var data/edx: (addr gap-buffer) <- copy _data 91 var x/eax: int <- copy xmin 92 var y/ecx: int <- copy ymin @@ -156,14 +157,14 @@ if ('onhashchange' in window) { 97 y <- increment 98 # trace 99 var trace-ah/eax: (addr handle trace) <- get self, trace -100 var _trace/eax: (addr trace) <- lookup *trace-ah +100 var _trace/eax: (addr trace) <- lookup *trace-ah 101 var trace/edx: (addr trace) <- copy _trace 102 var cursor-in-trace?/eax: (addr boolean) <- get self, cursor-in-trace? -103 y <- render-trace screen, trace, xmin, y, xmax, ymax, *cursor-in-trace? +103 y <- render-trace screen, trace, xmin, y, xmax, ymax, *cursor-in-trace? 104 # value 105 $render-sandbox:value: { 106 var value-ah/eax: (addr handle stream byte) <- get self, value -107 var _value/eax: (addr stream byte) <- lookup *value-ah +107 var _value/eax: (addr stream byte) <- lookup *value-ah 108 var value/esi: (addr stream byte) <- copy _value 109 rewind-stream value 110 var done?/eax: boolean <- stream-empty? value @@ -188,7 +189,7 @@ if ('onhashchange' in window) { 129 compare *cursor-in-trace?, 0/false 130 { 131 break-if-= -132 render-trace-menu screen +132 render-trace-menu screen 133 return 134 } 135 var cursor-in-keyboard?/eax: (addr boolean) <- get self, cursor-in-keyboard? @@ -204,7 +205,7 @@ if ('onhashchange' in window) { 145 # render just enough of the sandbox to figure out what to erase 146 var self/esi: (addr sandbox) <- copy _self 147 var data-ah/eax: (addr handle gap-buffer) <- get self, data -148 var _data/eax: (addr gap-buffer) <- lookup *data-ah +148 var _data/eax: (addr gap-buffer) <- lookup *data-ah 149 var data/edx: (addr gap-buffer) <- copy _data 150 var x/eax: int <- copy xmin 151 var y/ecx: int <- copy ymin @@ -219,7 +220,7 @@ if ('onhashchange' in window) { 160 fn maybe-render-empty-screen screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int { 161 var self/esi: (addr sandbox) <- copy _self 162 var screen-obj-cell-ah/eax: (addr handle cell) <- get self, screen-var -163 var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah +163 var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah 164 compare screen-obj-cell, 0 165 { 166 break-if-!= @@ -233,9 +234,9 @@ if ('onhashchange' in window) { 174 } 175 var y/ecx: int <- copy ymin 176 var screen-obj-ah/eax: (addr handle screen) <- get screen-obj-cell, screen-data -177 var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah +177 var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah 178 var screen-obj/edx: (addr screen) <- copy _screen-obj -179 var x/eax: int <- draw-text-rightward screen, "screen: ", xmin, 0x99/xmax, y, 7/fg, 0xc5/bg=blue-bg +179 var x/eax: int <- draw-text-rightward screen, "screen: ", xmin, 0x99/xmax, y, 0x17/fg, 0xc5/bg=blue-bg 180 y <- render-empty-screen screen, screen-obj, x, y 181 return y 182 } @@ -243,7 +244,7 @@ if ('onhashchange' in window) { 184 fn maybe-render-screen screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int { 185 var self/esi: (addr sandbox) <- copy _self 186 var screen-obj-cell-ah/eax: (addr handle cell) <- get self, screen-var -187 var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah +187 var screen-obj-cell/eax: (addr cell) <- lookup *screen-obj-cell-ah 188 compare screen-obj-cell, 0 189 { 190 break-if-!= @@ -256,7 +257,7 @@ if ('onhashchange' in window) { 197 return ymin # silently give up on rendering the screen 198 } 199 var screen-obj-ah/eax: (addr handle screen) <- get screen-obj-cell, screen-data -200 var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah +200 var _screen-obj/eax: (addr screen) <- lookup *screen-obj-ah 201 var screen-obj/edx: (addr screen) <- copy _screen-obj 202 { 203 var screen-empty?/eax: boolean <- fake-screen-empty? screen-obj @@ -264,7 +265,7 @@ if ('onhashchange' in window) { 205 break-if-= 206 return ymin 207 } -208 var x/eax: int <- draw-text-rightward screen, "screen: ", xmin, 0x99/xmax, ymin, 7/fg, 0xc5/bg=blue-bg +208 var x/eax: int <- draw-text-rightward screen, "screen: ", xmin, 0x99/xmax, ymin, 0x17/fg, 0xc5/bg=blue-bg 209 var y/ecx: int <- copy ymin 210 y <- render-screen screen, screen-obj, x, y 211 return y @@ -335,7 +336,7 @@ if ('onhashchange' in window) { 276 var top: int 277 copy-to top, tmp 278 var pixels-ah/eax: (addr handle array byte) <- get target-screen, pixels -279 var _pixels/eax: (addr array byte) <- lookup *pixels-ah +279 var _pixels/eax: (addr array byte) <- lookup *pixels-ah 280 var pixels/edi: (addr array byte) <- copy _pixels 281 compare pixels, 0 282 break-if-= @@ -379,7 +380,7 @@ if ('onhashchange' in window) { 320 fn has-keyboard? _self: (addr sandbox) -> _/eax: boolean { 321 var self/esi: (addr sandbox) <- copy _self 322 var keyboard-obj-cell-ah/eax: (addr handle cell) <- get self, keyboard-var -323 var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah +323 var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah 324 compare keyboard-obj-cell, 0 325 { 326 break-if-!= @@ -392,7 +393,7 @@ if ('onhashchange' in window) { 333 return 0/false 334 } 335 var keyboard-obj-ah/eax: (addr handle gap-buffer) <- get keyboard-obj-cell, keyboard-data -336 var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah +336 var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah 337 var keyboard-obj/edx: (addr gap-buffer) <- copy _keyboard-obj 338 compare keyboard-obj, 0 339 { @@ -405,7 +406,7 @@ if ('onhashchange' in window) { 346 fn maybe-render-keyboard screen: (addr screen), _self: (addr sandbox), xmin: int, ymin: int -> _/ecx: int { 347 var self/esi: (addr sandbox) <- copy _self 348 var keyboard-obj-cell-ah/eax: (addr handle cell) <- get self, keyboard-var -349 var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah +349 var keyboard-obj-cell/eax: (addr cell) <- lookup *keyboard-obj-cell-ah 350 compare keyboard-obj-cell, 0 351 { 352 break-if-!= @@ -418,11 +419,11 @@ if ('onhashchange' in window) { 359 return ymin # silently give up on rendering the keyboard 360 } 361 var keyboard-obj-ah/eax: (addr handle gap-buffer) <- get keyboard-obj-cell, keyboard-data -362 var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah +362 var _keyboard-obj/eax: (addr gap-buffer) <- lookup *keyboard-obj-ah 363 var keyboard-obj/edx: (addr gap-buffer) <- copy _keyboard-obj 364 var y/ecx: int <- copy ymin 365 y <- increment # padding -366 var x/eax: int <- draw-text-rightward screen, "keyboard: ", xmin, 0x99/xmax, y, 7/fg, 0xc5/bg=blue-bg +366 var x/eax: int <- draw-text-rightward screen, "keyboard: ", xmin, 0x99/xmax, y, 0x17/fg, 0xc5/bg=blue-bg 367 var cursor-in-keyboard?/esi: (addr boolean) <- get self, cursor-in-keyboard? 368 y <- render-keyboard screen, keyboard-obj, x, y, *cursor-in-keyboard? 369 y <- increment # padding @@ -448,7 +449,7 @@ if ('onhashchange' in window) { 389 fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen), x: int, y: int { 390 var target/ecx: (addr screen) <- copy _target 391 var data-ah/eax: (addr handle array screen-cell) <- get target, data -392 var data/eax: (addr array screen-cell) <- lookup *data-ah +392 var data/eax: (addr array screen-cell) <- lookup *data-ah 393 var index/ecx: int <- screen-cell-index target, x, y 394 var offset/ecx: (offset screen-cell) <- compute-offset data, index 395 var src-cell/esi: (addr screen-cell) <- index data, offset @@ -476,8 +477,8 @@ if ('onhashchange' in window) { 417 draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0xc5/bg=blue-bg 418 $render-sandbox-menu:render-ctrl-m: { 419 var self/eax: (addr sandbox) <- copy _self -420 var has-trace?/eax: boolean <- has-trace? self -421 compare has-trace?, 0/false +420 var has-trace?/eax: boolean <- has-trace? self +421 compare has-trace?, 0/false 422 { 423 break-if-= 424 draw-text-rightward-from-cursor screen, " m ", width, 0/fg, 0x38/bg=trace @@ -525,14 +526,14 @@ if ('onhashchange' in window) { 466 break-if-!= 467 # minor gotcha here: any bindings created later in this iteration won't be 468 # persisted until the next call to ctrl-s. -469 store-state data-disk, self, globals +469 store-state data-disk, self, globals 470 # run sandbox 471 var data-ah/ecx: (addr handle gap-buffer) <- get self, data 472 var value-ah/eax: (addr handle stream byte) <- get self, value -473 var _value/eax: (addr stream byte) <- lookup *value-ah +473 var _value/eax: (addr stream byte) <- lookup *value-ah 474 var value/edx: (addr stream byte) <- copy _value 475 var trace-ah/eax: (addr handle trace) <- get self, trace -476 var _trace/eax: (addr trace) <- lookup *trace-ah +476 var _trace/eax: (addr trace) <- lookup *trace-ah 477 var trace/ebx: (addr trace) <- copy _trace 478 clear-trace trace 479 { @@ -541,9 +542,9 @@ if ('onhashchange' in window) { 482 clear-sandbox-output real-screen, self, 0x56/sandbox-left-margin, 1/y, 0x80/screen-width, 0x2f/screen-height-without-menu 483 } 484 var screen-cell/eax: (addr handle cell) <- get self, screen-var -485 clear-screen-cell screen-cell +485 clear-screen-cell screen-cell 486 var keyboard-cell/esi: (addr handle cell) <- get self, keyboard-var -487 rewind-keyboard-cell keyboard-cell # don't clear keys from before +487 rewind-keyboard-cell keyboard-cell # don't clear keys from before 488 { 489 compare tweak-real-screen?, 0/false 490 break-if-= @@ -561,8 +562,8 @@ if ('onhashchange' in window) { 502 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data? 503 compare *cursor-in-data?, 0/false 504 break-if-= -505 var has-trace?/eax: boolean <- has-trace? self -506 compare has-trace?, 0/false +505 var has-trace?/eax: boolean <- has-trace? self +506 compare has-trace?, 0/false 507 { 508 break-if-= 509 var cursor-in-data?/eax: (addr boolean) <- get self, cursor-in-data? @@ -617,7 +618,7 @@ if ('onhashchange' in window) { 558 compare *cursor-in-data?, 0/false 559 break-if-= 560 var data-ah/eax: (addr handle gap-buffer) <- get self, data -561 var data/eax: (addr gap-buffer) <- lookup *data-ah +561 var data/eax: (addr gap-buffer) <- lookup *data-ah 562 edit-gap-buffer data, g 563 return 564 } @@ -627,7 +628,7 @@ if ('onhashchange' in window) { 568 compare *cursor-in-keyboard?, 0/false 569 break-if-= 570 var keyboard-cell-ah/eax: (addr handle cell) <- get self, keyboard-var -571 var keyboard-cell/eax: (addr cell) <- lookup *keyboard-cell-ah +571 var keyboard-cell/eax: (addr cell) <- lookup *keyboard-cell-ah 572 compare keyboard-cell, 0 573 { 574 break-if-!= @@ -640,7 +641,7 @@ if ('onhashchange' in window) { 581 return 582 } 583 var keyboard-ah/eax: (addr handle gap-buffer) <- get keyboard-cell, keyboard-data -584 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah +584 var keyboard/eax: (addr gap-buffer) <- lookup *keyboard-ah 585 edit-gap-buffer keyboard, g 586 return 587 } @@ -650,15 +651,15 @@ if ('onhashchange' in window) { 591 compare *cursor-in-trace?, 0/false 592 break-if-= 593 var trace-ah/eax: (addr handle trace) <- get self, trace -594 var trace/eax: (addr trace) <- lookup *trace-ah -595 edit-trace trace, g +594 var trace/eax: (addr trace) <- lookup *trace-ah +595 edit-trace trace, g 596 return 597 } 598 } 599 600 fn run _in-ah: (addr handle gap-buffer), out: (addr stream byte), globals: (addr global-table), trace: (addr trace), screen-cell: (addr handle cell), keyboard-cell: (addr handle cell) { 601 var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah -602 var in/eax: (addr gap-buffer) <- lookup *in-ah +602 var in/eax: (addr gap-buffer) <- lookup *in-ah 603 var read-result-h: (handle cell) 604 var read-result-ah/esi: (addr handle cell) <- address read-result-h 605 read-cell in, read-result-ah, trace @@ -668,291 +669,295 @@ if ('onhashchange' in window) { 609 break-if-= 610 return 611 } -612 var nil-storage: (handle cell) -613 var nil-ah/eax: (addr handle cell) <- address nil-storage -614 allocate-pair nil-ah -615 var eval-result-storage: (handle cell) -616 var eval-result/edi: (addr handle cell) <- address eval-result-storage -617 debug-print "^", 4/fg, 0xc5/bg=blue-bg -618 evaluate read-result-ah, eval-result, *nil-ah, globals, trace, screen-cell, keyboard-cell, 1/call-number -619 debug-print "$", 4/fg, 0xc5/bg=blue-bg -620 var error?/eax: boolean <- has-errors? trace -621 { -622 compare error?, 0/false -623 break-if-= -624 return -625 } -626 # if there was no error and the read-result starts with "set" or "def", save -627 # the gap buffer in the modified global, then create a new one for the next -628 # command. -629 maybe-stash-gap-buffer-to-global globals, read-result-ah, _in-ah -630 clear-stream out -631 print-cell eval-result, out, trace -632 mark-lines-dirty trace -633 } -634 -635 fn read-evaluate-and-move-to-globals _in-ah: (addr handle gap-buffer), globals: (addr global-table) { -636 var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah -637 var in/eax: (addr gap-buffer) <- lookup *in-ah -638 var read-result-h: (handle cell) -639 var read-result-ah/esi: (addr handle cell) <- address read-result-h -640 read-cell in, read-result-ah, 0/no-trace -641 var nil-storage: (handle cell) -642 var nil-ah/eax: (addr handle cell) <- address nil-storage -643 allocate-pair nil-ah -644 var eval-result-storage: (handle cell) -645 var eval-result/edi: (addr handle cell) <- address eval-result-storage -646 debug-print "^", 4/fg, 0xc5/bg=blue-bg -647 evaluate read-result-ah, eval-result, *nil-ah, globals, 0/no-trace, 0/no-screen-cell, 0/no-keyboard-cell, 1/call-number -648 debug-print "$", 4/fg, 0xc5/bg=blue-bg -649 move-gap-buffer-to-global globals, read-result-ah, _in-ah -650 } -651 -652 fn test-run-integer { -653 var sandbox-storage: sandbox -654 var sandbox/esi: (addr sandbox) <- address sandbox-storage -655 initialize-sandbox-with sandbox, "1" -656 # eval -657 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -658 # setup: screen -659 var screen-on-stack: screen -660 var screen/edi: (addr screen) <- address screen-on-stack -661 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -662 # -663 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -664 # skip one line of padding -665 check-screen-row screen, 1/y, " 1 ", "F - test-run-integer/0" -666 check-screen-row screen, 2/y, " ... ", "F - test-run-integer/1" -667 check-screen-row screen, 3/y, " => 1 ", "F - test-run-integer/2" -668 } -669 -670 fn test-run-error-invalid-integer { -671 var sandbox-storage: sandbox -672 var sandbox/esi: (addr sandbox) <- address sandbox-storage -673 initialize-sandbox-with sandbox, "1a" -674 # eval -675 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -676 # setup: screen -677 var screen-on-stack: screen -678 var screen/edi: (addr screen) <- address screen-on-stack -679 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -680 # -681 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -682 # skip one line of padding -683 check-screen-row screen, 1/y, " 1a ", "F - test-run-error-invalid-integer/0" -684 check-screen-row screen, 2/y, " ... ", "F - test-run-error-invalid-integer/0" -685 check-screen-row screen, 3/y, " invalid number ", "F - test-run-error-invalid-integer/2" -686 } -687 -688 fn test-run-with-spaces { -689 var sandbox-storage: sandbox -690 var sandbox/esi: (addr sandbox) <- address sandbox-storage -691 initialize-sandbox-with sandbox, " 1 \n" -692 # eval -693 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -694 # setup: screen -695 var screen-on-stack: screen -696 var screen/edi: (addr screen) <- address screen-on-stack -697 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -698 # -699 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -700 # skip one line of padding -701 check-screen-row screen, 1/y, " 1 ", "F - test-run-with-spaces/0" -702 check-screen-row screen, 2/y, " ", "F - test-run-with-spaces/1" -703 check-screen-row screen, 3/y, " ... ", "F - test-run-with-spaces/2" -704 check-screen-row screen, 4/y, " => 1 ", "F - test-run-with-spaces/3" -705 } -706 -707 fn test-run-quote { -708 var sandbox-storage: sandbox -709 var sandbox/esi: (addr sandbox) <- address sandbox-storage -710 initialize-sandbox-with sandbox, "'a" -711 # eval -712 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -713 # setup: screen -714 var screen-on-stack: screen -715 var screen/edi: (addr screen) <- address screen-on-stack -716 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -717 # -718 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -719 # skip one line of padding -720 check-screen-row screen, 1/y, " 'a ", "F - test-run-quote/0" -721 check-screen-row screen, 2/y, " ... ", "F - test-run-quote/1" -722 check-screen-row screen, 3/y, " => a ", "F - test-run-quote/2" -723 } -724 -725 fn test-run-dotted-list { -726 var sandbox-storage: sandbox -727 var sandbox/esi: (addr sandbox) <- address sandbox-storage -728 initialize-sandbox-with sandbox, "'(a . b)" -729 # eval -730 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -731 # setup: screen -732 var screen-on-stack: screen -733 var screen/edi: (addr screen) <- address screen-on-stack -734 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -735 # -736 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -737 # skip one line of padding -738 check-screen-row screen, 1/y, " '(a . b) ", "F - test-run-dotted-list/0" -739 check-screen-row screen, 2/y, " ... ", "F - test-run-dotted-list/1" -740 check-screen-row screen, 3/y, " => (a . b) ", "F - test-run-dotted-list/2" -741 } -742 -743 fn test-run-dot-and-list { -744 var sandbox-storage: sandbox -745 var sandbox/esi: (addr sandbox) <- address sandbox-storage -746 initialize-sandbox-with sandbox, "'(a . (b))" -747 # eval -748 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -749 # setup: screen -750 var screen-on-stack: screen -751 var screen/edi: (addr screen) <- address screen-on-stack -752 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -753 # -754 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -755 # skip one line of padding -756 check-screen-row screen, 1/y, " '(a . (b)) ", "F - test-run-dot-and-list/0" -757 check-screen-row screen, 2/y, " ... ", "F - test-run-dot-and-list/1" -758 check-screen-row screen, 3/y, " => (a b) ", "F - test-run-dot-and-list/2" -759 } -760 -761 fn test-run-final-dot { -762 var sandbox-storage: sandbox -763 var sandbox/esi: (addr sandbox) <- address sandbox-storage -764 initialize-sandbox-with sandbox, "'(a .)" -765 # eval -766 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -767 # setup: screen -768 var screen-on-stack: screen -769 var screen/edi: (addr screen) <- address screen-on-stack -770 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -771 # -772 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -773 # skip one line of padding -774 check-screen-row screen, 1/y, " '(a .) ", "F - test-run-final-dot/0" -775 check-screen-row screen, 2/y, " ... ", "F - test-run-final-dot/1" -776 check-screen-row screen, 3/y, " '. )' makes no sense ", "F - test-run-final-dot/2" -777 # further errors may occur -778 } -779 -780 fn test-run-double-dot { -781 var sandbox-storage: sandbox -782 var sandbox/esi: (addr sandbox) <- address sandbox-storage -783 initialize-sandbox-with sandbox, "'(a . .)" -784 # eval -785 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -786 # setup: screen -787 var screen-on-stack: screen -788 var screen/edi: (addr screen) <- address screen-on-stack -789 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -790 # -791 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -792 # skip one line of padding -793 check-screen-row screen, 1/y, " '(a . .) ", "F - test-run-double-dot/0" -794 check-screen-row screen, 2/y, " ... ", "F - test-run-double-dot/1" -795 check-screen-row screen, 3/y, " '. .' makes no sense ", "F - test-run-double-dot/2" -796 # further errors may occur -797 } -798 -799 fn test-run-multiple-expressions-after-dot { -800 var sandbox-storage: sandbox -801 var sandbox/esi: (addr sandbox) <- address sandbox-storage -802 initialize-sandbox-with sandbox, "'(a . b c)" -803 # eval -804 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -805 # setup: screen -806 var screen-on-stack: screen -807 var screen/edi: (addr screen) <- address screen-on-stack -808 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -809 # -810 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -811 # skip one line of padding -812 check-screen-row screen, 1/y, " '(a . b c) ", "F - test-run-multiple-expressions-after-dot/0" -813 check-screen-row screen, 2/y, " ... ", "F - test-run-multiple-expressions-after-dot/1" -814 check-screen-row screen, 3/y, " cannot have multiple expressions between '.' and ')' ", "F - test-run-multiple-expressions-after-dot/2" -815 # further errors may occur -816 } -817 -818 fn test-run-stream { -819 var sandbox-storage: sandbox -820 var sandbox/esi: (addr sandbox) <- address sandbox-storage -821 initialize-sandbox-with sandbox, "[a b]" -822 # eval -823 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -824 # setup: screen -825 var screen-on-stack: screen -826 var screen/edi: (addr screen) <- address screen-on-stack -827 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -828 # -829 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -830 # skip one line of padding -831 check-screen-row screen, 1/y, " [a b] ", "F - test-run-stream/0" -832 check-screen-row screen, 2/y, " ... ", "F - test-run-stream/1" -833 check-screen-row screen, 3/y, " => [a b] ", "F - test-run-stream/2" -834 } -835 -836 fn test-run-move-cursor-into-trace { -837 var sandbox-storage: sandbox -838 var sandbox/esi: (addr sandbox) <- address sandbox-storage -839 initialize-sandbox-with sandbox, "12" -840 # eval -841 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -842 # setup: screen -843 var screen-on-stack: screen -844 var screen/edi: (addr screen) <- address screen-on-stack -845 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics -846 # -847 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -848 # skip one line of padding -849 check-screen-row screen, 1/y, " 12 ", "F - test-run-move-cursor-into-trace/pre-0" -850 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " | ", "F - test-run-move-cursor-into-trace/pre-0/cursor" -851 check-screen-row screen, 2/y, " ... ", "F - test-run-move-cursor-into-trace/pre-1" -852 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/pre-1/cursor" -853 check-screen-row screen, 3/y, " => 12 ", "F - test-run-move-cursor-into-trace/pre-2" -854 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-run-move-cursor-into-trace/pre-2/cursor" -855 # move cursor into trace -856 edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -857 # -858 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -859 # skip one line of padding -860 check-screen-row screen, 1/y, " 12 ", "F - test-run-move-cursor-into-trace/trace-0" -861 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-run-move-cursor-into-trace/trace-0/cursor" -862 check-screen-row screen, 2/y, " ... ", "F - test-run-move-cursor-into-trace/trace-1" -863 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ||| ", "F - test-run-move-cursor-into-trace/trace-1/cursor" -864 check-screen-row screen, 3/y, " => 12 ", "F - test-run-move-cursor-into-trace/trace-2" -865 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-run-move-cursor-into-trace/trace-2/cursor" -866 # move cursor into input -867 edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen -868 # -869 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height -870 # skip one line of padding -871 check-screen-row screen, 1/y, " 12 ", "F - test-run-move-cursor-into-trace/input-0" -872 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " | ", "F - test-run-move-cursor-into-trace/input-0/cursor" -873 check-screen-row screen, 2/y, " ... ", "F - test-run-move-cursor-into-trace/input-1" -874 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/input-1/cursor" -875 check-screen-row screen, 3/y, " => 12 ", "F - test-run-move-cursor-into-trace/input-2" -876 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-run-move-cursor-into-trace/input-2/cursor" -877 } -878 -879 fn has-trace? _self: (addr sandbox) -> _/eax: boolean { -880 var self/esi: (addr sandbox) <- copy _self -881 var trace-ah/eax: (addr handle trace) <- get self, trace -882 var _trace/eax: (addr trace) <- lookup *trace-ah -883 var trace/edx: (addr trace) <- copy _trace -884 compare trace, 0 -885 { -886 break-if-!= -887 return 0/false -888 } -889 var first-free/ebx: (addr int) <- get trace, first-free -890 compare *first-free, 0 -891 { -892 break-if-> -893 return 0/false -894 } -895 return 1/true -896 } +612 macroexpand read-result-ah, globals, trace +613 var nil-h: (handle cell) +614 var nil-ah/eax: (addr handle cell) <- address nil-h +615 allocate-pair nil-ah +616 var eval-result-h: (handle cell) +617 var eval-result-ah/edi: (addr handle cell) <- address eval-result-h +618 #? set-cursor-position 0/screen, 0 0 +619 #? turn-on-debug-print +620 debug-print "^", 4/fg, 0/bg +621 evaluate read-result-ah, eval-result-ah, *nil-ah, globals, trace, screen-cell, keyboard-cell, 1/call-number +622 debug-print "$", 4/fg, 0/bg +623 var error?/eax: boolean <- has-errors? trace +624 { +625 compare error?, 0/false +626 break-if-= +627 return +628 } +629 # if there was no error and the read-result starts with "set" or "def", save +630 # the gap buffer in the modified global, then create a new one for the next +631 # command. +632 maybe-stash-gap-buffer-to-global globals, read-result-ah, _in-ah +633 clear-stream out +634 print-cell eval-result-ah, out, trace +635 mark-lines-dirty trace +636 } +637 +638 fn read-evaluate-and-move-to-globals _in-ah: (addr handle gap-buffer), globals: (addr global-table) { +639 var in-ah/eax: (addr handle gap-buffer) <- copy _in-ah +640 var in/eax: (addr gap-buffer) <- lookup *in-ah +641 var read-result-h: (handle cell) +642 var read-result-ah/esi: (addr handle cell) <- address read-result-h +643 read-cell in, read-result-ah, 0/no-trace +644 macroexpand read-result-ah, globals, 0/no-trace +645 var nil-storage: (handle cell) +646 var nil-ah/eax: (addr handle cell) <- address nil-storage +647 allocate-pair nil-ah +648 var eval-result-storage: (handle cell) +649 var eval-result/edi: (addr handle cell) <- address eval-result-storage +650 debug-print "^", 4/fg, 0/bg +651 evaluate read-result-ah, eval-result, *nil-ah, globals, 0/no-trace, 0/no-screen-cell, 0/no-keyboard-cell, 1/call-number +652 debug-print "$", 4/fg, 0/bg +653 move-gap-buffer-to-global globals, read-result-ah, _in-ah +654 } +655 +656 fn test-run-integer { +657 var sandbox-storage: sandbox +658 var sandbox/esi: (addr sandbox) <- address sandbox-storage +659 initialize-sandbox-with sandbox, "1" +660 # eval +661 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +662 # setup: screen +663 var screen-on-stack: screen +664 var screen/edi: (addr screen) <- address screen-on-stack +665 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +666 # +667 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +668 # skip one line of padding +669 check-screen-row screen, 1/y, " 1 ", "F - test-run-integer/0" +670 check-screen-row screen, 2/y, " ... ", "F - test-run-integer/1" +671 check-screen-row screen, 3/y, " => 1 ", "F - test-run-integer/2" +672 } +673 +674 fn test-run-error-invalid-integer { +675 var sandbox-storage: sandbox +676 var sandbox/esi: (addr sandbox) <- address sandbox-storage +677 initialize-sandbox-with sandbox, "1a" +678 # eval +679 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +680 # setup: screen +681 var screen-on-stack: screen +682 var screen/edi: (addr screen) <- address screen-on-stack +683 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +684 # +685 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +686 # skip one line of padding +687 check-screen-row screen, 1/y, " 1a ", "F - test-run-error-invalid-integer/0" +688 check-screen-row screen, 2/y, " ... ", "F - test-run-error-invalid-integer/0" +689 check-screen-row screen, 3/y, " invalid number ", "F - test-run-error-invalid-integer/2" +690 } +691 +692 fn test-run-with-spaces { +693 var sandbox-storage: sandbox +694 var sandbox/esi: (addr sandbox) <- address sandbox-storage +695 initialize-sandbox-with sandbox, " 1 \n" +696 # eval +697 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +698 # setup: screen +699 var screen-on-stack: screen +700 var screen/edi: (addr screen) <- address screen-on-stack +701 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +702 # +703 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +704 # skip one line of padding +705 check-screen-row screen, 1/y, " 1 ", "F - test-run-with-spaces/0" +706 check-screen-row screen, 2/y, " ", "F - test-run-with-spaces/1" +707 check-screen-row screen, 3/y, " ... ", "F - test-run-with-spaces/2" +708 check-screen-row screen, 4/y, " => 1 ", "F - test-run-with-spaces/3" +709 } +710 +711 fn test-run-quote { +712 var sandbox-storage: sandbox +713 var sandbox/esi: (addr sandbox) <- address sandbox-storage +714 initialize-sandbox-with sandbox, "'a" +715 # eval +716 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +717 # setup: screen +718 var screen-on-stack: screen +719 var screen/edi: (addr screen) <- address screen-on-stack +720 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +721 # +722 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +723 # skip one line of padding +724 check-screen-row screen, 1/y, " 'a ", "F - test-run-quote/0" +725 check-screen-row screen, 2/y, " ... ", "F - test-run-quote/1" +726 check-screen-row screen, 3/y, " => a ", "F - test-run-quote/2" +727 } +728 +729 fn test-run-dotted-list { +730 var sandbox-storage: sandbox +731 var sandbox/esi: (addr sandbox) <- address sandbox-storage +732 initialize-sandbox-with sandbox, "'(a . b)" +733 # eval +734 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +735 # setup: screen +736 var screen-on-stack: screen +737 var screen/edi: (addr screen) <- address screen-on-stack +738 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +739 # +740 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +741 # skip one line of padding +742 check-screen-row screen, 1/y, " '(a . b) ", "F - test-run-dotted-list/0" +743 check-screen-row screen, 2/y, " ... ", "F - test-run-dotted-list/1" +744 check-screen-row screen, 3/y, " => (a . b) ", "F - test-run-dotted-list/2" +745 } +746 +747 fn test-run-dot-and-list { +748 var sandbox-storage: sandbox +749 var sandbox/esi: (addr sandbox) <- address sandbox-storage +750 initialize-sandbox-with sandbox, "'(a . (b))" +751 # eval +752 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +753 # setup: screen +754 var screen-on-stack: screen +755 var screen/edi: (addr screen) <- address screen-on-stack +756 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +757 # +758 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +759 # skip one line of padding +760 check-screen-row screen, 1/y, " '(a . (b)) ", "F - test-run-dot-and-list/0" +761 check-screen-row screen, 2/y, " ... ", "F - test-run-dot-and-list/1" +762 check-screen-row screen, 3/y, " => (a b) ", "F - test-run-dot-and-list/2" +763 } +764 +765 fn test-run-final-dot { +766 var sandbox-storage: sandbox +767 var sandbox/esi: (addr sandbox) <- address sandbox-storage +768 initialize-sandbox-with sandbox, "'(a .)" +769 # eval +770 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +771 # setup: screen +772 var screen-on-stack: screen +773 var screen/edi: (addr screen) <- address screen-on-stack +774 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +775 # +776 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +777 # skip one line of padding +778 check-screen-row screen, 1/y, " '(a .) ", "F - test-run-final-dot/0" +779 check-screen-row screen, 2/y, " ... ", "F - test-run-final-dot/1" +780 check-screen-row screen, 3/y, " '. )' makes no sense ", "F - test-run-final-dot/2" +781 # further errors may occur +782 } +783 +784 fn test-run-double-dot { +785 var sandbox-storage: sandbox +786 var sandbox/esi: (addr sandbox) <- address sandbox-storage +787 initialize-sandbox-with sandbox, "'(a . .)" +788 # eval +789 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +790 # setup: screen +791 var screen-on-stack: screen +792 var screen/edi: (addr screen) <- address screen-on-stack +793 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +794 # +795 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +796 # skip one line of padding +797 check-screen-row screen, 1/y, " '(a . .) ", "F - test-run-double-dot/0" +798 check-screen-row screen, 2/y, " ... ", "F - test-run-double-dot/1" +799 check-screen-row screen, 3/y, " '. .' makes no sense ", "F - test-run-double-dot/2" +800 # further errors may occur +801 } +802 +803 fn test-run-multiple-expressions-after-dot { +804 var sandbox-storage: sandbox +805 var sandbox/esi: (addr sandbox) <- address sandbox-storage +806 initialize-sandbox-with sandbox, "'(a . b c)" +807 # eval +808 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +809 # setup: screen +810 var screen-on-stack: screen +811 var screen/edi: (addr screen) <- address screen-on-stack +812 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +813 # +814 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +815 # skip one line of padding +816 check-screen-row screen, 1/y, " '(a . b c) ", "F - test-run-multiple-expressions-after-dot/0" +817 check-screen-row screen, 2/y, " ... ", "F - test-run-multiple-expressions-after-dot/1" +818 check-screen-row screen, 3/y, " cannot have multiple expressions between '.' and ')' ", "F - test-run-multiple-expressions-after-dot/2" +819 # further errors may occur +820 } +821 +822 fn test-run-stream { +823 var sandbox-storage: sandbox +824 var sandbox/esi: (addr sandbox) <- address sandbox-storage +825 initialize-sandbox-with sandbox, "[a b]" +826 # eval +827 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +828 # setup: screen +829 var screen-on-stack: screen +830 var screen/edi: (addr screen) <- address screen-on-stack +831 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +832 # +833 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +834 # skip one line of padding +835 check-screen-row screen, 1/y, " [a b] ", "F - test-run-stream/0" +836 check-screen-row screen, 2/y, " ... ", "F - test-run-stream/1" +837 check-screen-row screen, 3/y, " => [a b] ", "F - test-run-stream/2" +838 } +839 +840 fn test-run-move-cursor-into-trace { +841 var sandbox-storage: sandbox +842 var sandbox/esi: (addr sandbox) <- address sandbox-storage +843 initialize-sandbox-with sandbox, "12" +844 # eval +845 edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +846 # setup: screen +847 var screen-on-stack: screen +848 var screen/edi: (addr screen) <- address screen-on-stack +849 initialize-screen screen, 0x80/width, 0x10/height, 0/no-pixel-graphics +850 # +851 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +852 # skip one line of padding +853 check-screen-row screen, 1/y, " 12 ", "F - test-run-move-cursor-into-trace/pre-0" +854 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " | ", "F - test-run-move-cursor-into-trace/pre-0/cursor" +855 check-screen-row screen, 2/y, " ... ", "F - test-run-move-cursor-into-trace/pre-1" +856 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/pre-1/cursor" +857 check-screen-row screen, 3/y, " => 12 ", "F - test-run-move-cursor-into-trace/pre-2" +858 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-run-move-cursor-into-trace/pre-2/cursor" +859 # move cursor into trace +860 edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +861 # +862 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +863 # skip one line of padding +864 check-screen-row screen, 1/y, " 12 ", "F - test-run-move-cursor-into-trace/trace-0" +865 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-run-move-cursor-into-trace/trace-0/cursor" +866 check-screen-row screen, 2/y, " ... ", "F - test-run-move-cursor-into-trace/trace-1" +867 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ||| ", "F - test-run-move-cursor-into-trace/trace-1/cursor" +868 check-screen-row screen, 3/y, " => 12 ", "F - test-run-move-cursor-into-trace/trace-2" +869 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-run-move-cursor-into-trace/trace-2/cursor" +870 # move cursor into input +871 edit-sandbox sandbox, 0xd/ctrl-m, 0/no-globals, 0/no-disk, 0/no-screen, 0/no-tweak-screen +872 # +873 render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height +874 # skip one line of padding +875 check-screen-row screen, 1/y, " 12 ", "F - test-run-move-cursor-into-trace/input-0" +876 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " | ", "F - test-run-move-cursor-into-trace/input-0/cursor" +877 check-screen-row screen, 2/y, " ... ", "F - test-run-move-cursor-into-trace/input-1" +878 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-run-move-cursor-into-trace/input-1/cursor" +879 check-screen-row screen, 3/y, " => 12 ", "F - test-run-move-cursor-into-trace/input-2" +880 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-run-move-cursor-into-trace/input-2/cursor" +881 } +882 +883 fn has-trace? _self: (addr sandbox) -> _/eax: boolean { +884 var self/esi: (addr sandbox) <- copy _self +885 var trace-ah/eax: (addr handle trace) <- get self, trace +886 var _trace/eax: (addr trace) <- lookup *trace-ah +887 var trace/edx: (addr trace) <- copy _trace +888 compare trace, 0 +889 { +890 break-if-!= +891 return 0/false +892 } +893 var first-free/ebx: (addr int) <- get trace, first-free +894 compare *first-free, 0 +895 { +896 break-if-> +897 return 0/false +898 } +899 return 1/true +900 } diff --git a/html/shell/tokenize.mu.html b/html/shell/tokenize.mu.html index d71e4d49..2b14ee40 100644 --- a/html/shell/tokenize.mu.html +++ b/html/shell/tokenize.mu.html @@ -18,6 +18,7 @@ a { color:inherit; } .Special { color: #ff6060; } .LineNr { } .Constant { color: #008787; } +.CommentedCode { color: #8a8a8a; } .Delimiter { color: #c000c0; } .muFunction { color: #af5f00; text-decoration: underline; } .muTest { color: #5f8700; } @@ -62,7 +63,7 @@ if ('onhashchange' in window) { 3 # they always have text-data. 4 5 fn tokenize in: (addr gap-buffer), out: (addr stream cell), trace: (addr trace) { - 6 trace-text trace, "read", "tokenize" + 6 trace-text trace, "tokenize", "tokenize" 7 trace-lower trace 8 rewind-gap-buffer in 9 var token-storage: cell @@ -74,53 +75,53 @@ if ('onhashchange' in window) { 15 break-if-!= 16 # initialize token data each iteration to avoid aliasing 17 var dest-ah/eax: (addr handle stream byte) <- get token, text-data - 18 populate-stream dest-ah, 0x100/max-definition-size - 19 # - 20 next-token in, token, trace - 21 var skip?/eax: boolean <- comment-token? token - 22 compare skip?, 0/false - 23 loop-if-!= - 24 var error?/eax: boolean <- has-errors? trace - 25 compare error?, 0/false - 26 { - 27 break-if-= - 28 return - 29 } - 30 write-to-stream out, token # shallow-copy text-data - 31 loop - 32 } - 33 trace-higher trace - 34 } - 35 - 36 fn test-tokenize-dotted-list { - 37 var in-storage: gap-buffer - 38 var in/esi: (addr gap-buffer) <- address in-storage - 39 initialize-gap-buffer-with in, "(a . b)" - 40 # - 41 var stream-storage: (stream cell 0x10) - 42 var stream/edi: (addr stream cell) <- address stream-storage - 43 # - 44 tokenize in, stream, 0/no-trace - 45 # - 46 var curr-token-storage: cell - 47 var curr-token/ebx: (addr cell) <- address curr-token-storage - 48 read-from-stream stream, curr-token - 49 var open-paren?/eax: boolean <- open-paren-token? curr-token - 50 check open-paren?, "F - test-tokenize-dotted-list: open paren" - 51 read-from-stream stream, curr-token # skip a - 52 read-from-stream stream, curr-token - 53 var dot?/eax: boolean <- dot-token? curr-token - 54 check dot?, "F - test-tokenize-dotted-list: dot" - 55 read-from-stream stream, curr-token # skip b - 56 read-from-stream stream, curr-token - 57 var close-paren?/eax: boolean <- close-paren-token? curr-token - 58 check close-paren?, "F - test-tokenize-dotted-list: close paren" + 18 # I'm allocating 1KB for every. single. token. Just because a whole definition needs to fit in a string sometimes. Absolutely bonkers. + 19 populate-stream dest-ah, 0x400/max-definition-size + 20 # + 21 next-token in, token, trace + 22 var skip?/eax: boolean <- comment-token? token + 23 compare skip?, 0/false + 24 loop-if-!= + 25 var error?/eax: boolean <- has-errors? trace + 26 compare error?, 0/false + 27 { + 28 break-if-= + 29 return + 30 } + 31 write-to-stream out, token # shallow-copy text-data + 32 loop + 33 } + 34 trace-higher trace + 35 } + 36 + 37 fn test-tokenize-quote { + 38 var in-storage: gap-buffer + 39 var in/esi: (addr gap-buffer) <- address in-storage + 40 initialize-gap-buffer-with in, "'(a)" + 41 # + 42 var stream-storage: (stream cell 0x10) + 43 var stream/edi: (addr stream cell) <- address stream-storage + 44 # + 45 tokenize in, stream, 0/no-trace + 46 # + 47 var curr-token-storage: cell + 48 var curr-token/ebx: (addr cell) <- address curr-token-storage + 49 read-from-stream stream, curr-token + 50 var quote?/eax: boolean <- quote-token? curr-token + 51 check quote?, "F - test-tokenize-quote: quote" + 52 read-from-stream stream, curr-token + 53 var open-paren?/eax: boolean <- open-paren-token? curr-token + 54 check open-paren?, "F - test-tokenize-quote: open paren" + 55 read-from-stream stream, curr-token # skip a + 56 read-from-stream stream, curr-token + 57 var close-paren?/eax: boolean <- close-paren-token? curr-token + 58 check close-paren?, "F - test-tokenize-quote: close paren" 59 } 60 - 61 fn test-tokenize-stream-literal { + 61 fn test-tokenize-backquote { 62 var in-storage: gap-buffer 63 var in/esi: (addr gap-buffer) <- address in-storage - 64 initialize-gap-buffer-with in, "[abc def]" + 64 initialize-gap-buffer-with in, "`(a)" 65 # 66 var stream-storage: (stream cell 0x10) 67 var stream/edi: (addr stream cell) <- address stream-storage @@ -129,733 +130,890 @@ if ('onhashchange' in window) { 70 # 71 var curr-token-storage: cell 72 var curr-token/ebx: (addr cell) <- address curr-token-storage - 73 read-from-stream stream, curr-token - 74 var stream?/eax: boolean <- stream-token? curr-token - 75 check stream?, "F - test-tokenize-stream-literal: type" - 76 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data - 77 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah - 78 var data-equal?/eax: boolean <- stream-data-equal? curr-token-data, "abc def" - 79 check data-equal?, "F - test-tokenize-stream-literal" - 80 var empty?/eax: boolean <- stream-empty? stream - 81 check empty?, "F - test-tokenize-stream-literal: empty?" - 82 } - 83 - 84 fn test-tokenize-stream-literal-in-tree { - 85 var in-storage: gap-buffer - 86 var in/esi: (addr gap-buffer) <- address in-storage - 87 initialize-gap-buffer-with in, "([abc def])" - 88 # - 89 var stream-storage: (stream cell 0x10) - 90 var stream/edi: (addr stream cell) <- address stream-storage - 91 # - 92 tokenize in, stream, 0/no-trace - 93 # - 94 var curr-token-storage: cell - 95 var curr-token/ebx: (addr cell) <- address curr-token-storage - 96 read-from-stream stream, curr-token - 97 var bracket?/eax: boolean <- bracket-token? curr-token - 98 check bracket?, "F - test-tokenize-stream-literal-in-tree: open paren" - 99 read-from-stream stream, curr-token -100 var stream?/eax: boolean <- stream-token? curr-token -101 check stream?, "F - test-tokenize-stream-literal-in-tree: type" -102 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data -103 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah -104 var data-equal?/eax: boolean <- stream-data-equal? curr-token-data, "abc def" -105 check data-equal?, "F - test-tokenize-stream-literal-in-tree" -106 read-from-stream stream, curr-token -107 var bracket?/eax: boolean <- bracket-token? curr-token -108 check bracket?, "F - test-tokenize-stream-literal-in-tree: close paren" -109 var empty?/eax: boolean <- stream-empty? stream -110 check empty?, "F - test-tokenize-stream-literal-in-tree: empty?" -111 } -112 -113 fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace) { -114 trace-text trace, "read", "next-token" -115 trace-lower trace -116 var out-cell/eax: (addr cell) <- copy _out-cell -117 { -118 var out-cell-type/eax: (addr int) <- get out-cell, type -119 copy-to *out-cell-type, 0/uninitialized -120 } -121 var out-ah/eax: (addr handle stream byte) <- get out-cell, text-data -122 var _out/eax: (addr stream byte) <- lookup *out-ah -123 var out/edi: (addr stream byte) <- copy _out -124 $next-token:body: { -125 clear-stream out -126 var g/eax: grapheme <- peek-from-gap-buffer in -127 { -128 var stream-storage: (stream byte 0x40) -129 var stream/esi: (addr stream byte) <- address stream-storage -130 write stream, "next: " -131 var gval/eax: int <- copy g -132 write-int32-hex stream, gval -133 trace trace, "read", stream -134 } -135 # comment -136 { -137 compare g, 0x23/comment -138 break-if-!= -139 rest-of-line in, out, trace -140 break $next-token:body -141 } -142 # digit -143 { -144 var digit?/eax: boolean <- decimal-digit? g -145 compare digit?, 0/false -146 break-if-= -147 next-number-token in, out, trace -148 break $next-token:body -149 } -150 # other symbol char -151 { -152 var symbol?/eax: boolean <- symbol-grapheme? g -153 compare symbol?, 0/false -154 break-if-= -155 next-symbol-token in, out, trace -156 break $next-token:body -157 } -158 # open square brackets begin streams -159 { -160 compare g, 0x5b/open-square-bracket -161 break-if-!= -162 g <- read-from-gap-buffer in # skip open bracket -163 next-stream-token in, out, trace -164 var out-cell/eax: (addr cell) <- copy _out-cell -165 var out-cell-type/eax: (addr int) <- get out-cell, type -166 copy-to *out-cell-type, 3/stream -167 break $next-token:body -168 } -169 # unbalanced close square brackets are errors -170 { -171 compare g, 0x5d/close-square-bracket -172 break-if-!= -173 error trace, "unbalanced ']'" -174 return -175 } -176 # other brackets are always single-char tokens -177 { -178 var bracket?/eax: boolean <- bracket-grapheme? g -179 compare bracket?, 0/false -180 break-if-= -181 var g/eax: grapheme <- read-from-gap-buffer in -182 next-bracket-token g, out, trace -183 break $next-token:body -184 } -185 # non-symbol operators -186 { -187 var operator?/eax: boolean <- operator-grapheme? g -188 compare operator?, 0/false -189 break-if-= -190 next-operator-token in, out, trace -191 break $next-token:body -192 } -193 } -194 trace-higher trace -195 var stream-storage: (stream byte 0x40) -196 var stream/eax: (addr stream byte) <- address stream-storage -197 write stream, "=> " -198 rewind-stream out -199 write-stream stream, out -200 trace trace, "read", stream + 73 read-from-stream stream, curr-token + 74 var backquote?/eax: boolean <- backquote-token? curr-token + 75 check backquote?, "F - test-tokenize-backquote: backquote" + 76 read-from-stream stream, curr-token + 77 var open-paren?/eax: boolean <- open-paren-token? curr-token + 78 check open-paren?, "F - test-tokenize-backquote: open paren" + 79 read-from-stream stream, curr-token # skip a + 80 read-from-stream stream, curr-token + 81 var close-paren?/eax: boolean <- close-paren-token? curr-token + 82 check close-paren?, "F - test-tokenize-backquote: close paren" + 83 } + 84 + 85 fn test-tokenize-unquote { + 86 var in-storage: gap-buffer + 87 var in/esi: (addr gap-buffer) <- address in-storage + 88 initialize-gap-buffer-with in, ",(a)" + 89 # + 90 var stream-storage: (stream cell 0x10) + 91 var stream/edi: (addr stream cell) <- address stream-storage + 92 # + 93 tokenize in, stream, 0/no-trace + 94 # + 95 var curr-token-storage: cell + 96 var curr-token/ebx: (addr cell) <- address curr-token-storage + 97 read-from-stream stream, curr-token + 98 var unquote?/eax: boolean <- unquote-token? curr-token + 99 check unquote?, "F - test-tokenize-unquote: unquote" +100 read-from-stream stream, curr-token +101 var open-paren?/eax: boolean <- open-paren-token? curr-token +102 check open-paren?, "F - test-tokenize-unquote: open paren" +103 read-from-stream stream, curr-token # skip a +104 read-from-stream stream, curr-token +105 var close-paren?/eax: boolean <- close-paren-token? curr-token +106 check close-paren?, "F - test-tokenize-unquote: close paren" +107 } +108 +109 fn test-tokenize-unquote-splice { +110 var in-storage: gap-buffer +111 var in/esi: (addr gap-buffer) <- address in-storage +112 initialize-gap-buffer-with in, ",@a" +113 # +114 var stream-storage: (stream cell 0x10) +115 var stream/edi: (addr stream cell) <- address stream-storage +116 # +117 tokenize in, stream, 0/no-trace +118 # +119 var curr-token-storage: cell +120 var curr-token/ebx: (addr cell) <- address curr-token-storage +121 read-from-stream stream, curr-token +122 var unquote-splice?/eax: boolean <- unquote-splice-token? curr-token +123 check unquote-splice?, "F - test-tokenize-unquote-splice: unquote-splice" +124 } +125 +126 fn test-tokenize-dotted-list { +127 var in-storage: gap-buffer +128 var in/esi: (addr gap-buffer) <- address in-storage +129 initialize-gap-buffer-with in, "(a . b)" +130 # +131 var stream-storage: (stream cell 0x10) +132 var stream/edi: (addr stream cell) <- address stream-storage +133 # +134 tokenize in, stream, 0/no-trace +135 # +136 var curr-token-storage: cell +137 var curr-token/ebx: (addr cell) <- address curr-token-storage +138 read-from-stream stream, curr-token +139 var open-paren?/eax: boolean <- open-paren-token? curr-token +140 check open-paren?, "F - test-tokenize-dotted-list: open paren" +141 read-from-stream stream, curr-token # skip a +142 read-from-stream stream, curr-token +143 var dot?/eax: boolean <- dot-token? curr-token +144 check dot?, "F - test-tokenize-dotted-list: dot" +145 read-from-stream stream, curr-token # skip b +146 read-from-stream stream, curr-token +147 var close-paren?/eax: boolean <- close-paren-token? curr-token +148 check close-paren?, "F - test-tokenize-dotted-list: close paren" +149 } +150 +151 fn test-tokenize-stream-literal { +152 var in-storage: gap-buffer +153 var in/esi: (addr gap-buffer) <- address in-storage +154 initialize-gap-buffer-with in, "[abc def]" +155 # +156 var stream-storage: (stream cell 0x10) +157 var stream/edi: (addr stream cell) <- address stream-storage +158 # +159 tokenize in, stream, 0/no-trace +160 # +161 var curr-token-storage: cell +162 var curr-token/ebx: (addr cell) <- address curr-token-storage +163 read-from-stream stream, curr-token +164 var stream?/eax: boolean <- stream-token? curr-token +165 check stream?, "F - test-tokenize-stream-literal: type" +166 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data +167 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah +168 var data-equal?/eax: boolean <- stream-data-equal? curr-token-data, "abc def" +169 check data-equal?, "F - test-tokenize-stream-literal" +170 var empty?/eax: boolean <- stream-empty? stream +171 check empty?, "F - test-tokenize-stream-literal: empty?" +172 } +173 +174 fn test-tokenize-stream-literal-in-tree { +175 var in-storage: gap-buffer +176 var in/esi: (addr gap-buffer) <- address in-storage +177 initialize-gap-buffer-with in, "([abc def])" +178 # +179 var stream-storage: (stream cell 0x10) +180 var stream/edi: (addr stream cell) <- address stream-storage +181 # +182 tokenize in, stream, 0/no-trace +183 # +184 var curr-token-storage: cell +185 var curr-token/ebx: (addr cell) <- address curr-token-storage +186 read-from-stream stream, curr-token +187 var bracket?/eax: boolean <- bracket-token? curr-token +188 check bracket?, "F - test-tokenize-stream-literal-in-tree: open paren" +189 read-from-stream stream, curr-token +190 var stream?/eax: boolean <- stream-token? curr-token +191 check stream?, "F - test-tokenize-stream-literal-in-tree: type" +192 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data +193 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah +194 var data-equal?/eax: boolean <- stream-data-equal? curr-token-data, "abc def" +195 check data-equal?, "F - test-tokenize-stream-literal-in-tree" +196 read-from-stream stream, curr-token +197 var bracket?/eax: boolean <- bracket-token? curr-token +198 check bracket?, "F - test-tokenize-stream-literal-in-tree: close paren" +199 var empty?/eax: boolean <- stream-empty? stream +200 check empty?, "F - test-tokenize-stream-literal-in-tree: empty?" 201 } 202 -203 fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -204 trace-text trace, "read", "looking for a symbol" +203 fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace) { +204 trace-text trace, "tokenize", "next-token" 205 trace-lower trace -206 $next-symbol-token:loop: { -207 var done?/eax: boolean <- gap-buffer-scan-done? in -208 compare done?, 0/false -209 break-if-!= -210 var g/eax: grapheme <- peek-from-gap-buffer in -211 { -212 var stream-storage: (stream byte 0x40) -213 var stream/esi: (addr stream byte) <- address stream-storage -214 write stream, "next: " -215 var gval/eax: int <- copy g -216 write-int32-hex stream, gval -217 trace trace, "read", stream -218 } -219 # if non-symbol, return -220 { -221 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g -222 compare symbol-grapheme?, 0/false -223 break-if-!= -224 trace-text trace, "read", "stop" -225 break $next-symbol-token:loop +206 var out-cell/eax: (addr cell) <- copy _out-cell +207 { +208 var out-cell-type/eax: (addr int) <- get out-cell, type +209 copy-to *out-cell-type, 0/uninitialized +210 } +211 var out-ah/eax: (addr handle stream byte) <- get out-cell, text-data +212 var _out/eax: (addr stream byte) <- lookup *out-ah +213 var out/edi: (addr stream byte) <- copy _out +214 $next-token:body: { +215 clear-stream out +216 var g/eax: grapheme <- peek-from-gap-buffer in +217 #? draw-grapheme-at-cursor 0/screen, g, 7/fg, 0/bg +218 #? move-cursor-rightward-and-downward 0/screen, 0, 0x80 +219 { +220 var stream-storage: (stream byte 0x40) +221 var stream/esi: (addr stream byte) <- address stream-storage +222 write stream, "next: " +223 var gval/eax: int <- copy g +224 write-int32-hex stream, gval +225 trace trace, "tokenize", stream 226 } -227 var g/eax: grapheme <- read-from-gap-buffer in -228 write-grapheme out, g -229 loop -230 } -231 trace-higher trace -232 var stream-storage: (stream byte 0x40) -233 var stream/esi: (addr stream byte) <- address stream-storage -234 write stream, "=> " -235 rewind-stream out -236 write-stream stream, out -237 trace trace, "read", stream -238 } -239 -240 fn next-operator-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -241 trace-text trace, "read", "looking for a operator" -242 trace-lower trace -243 $next-operator-token:loop: { -244 var done?/eax: boolean <- gap-buffer-scan-done? in -245 compare done?, 0/false -246 break-if-!= -247 var g/eax: grapheme <- peek-from-gap-buffer in -248 { -249 var stream-storage: (stream byte 0x40) -250 var stream/esi: (addr stream byte) <- address stream-storage -251 write stream, "next: " -252 var gval/eax: int <- copy g -253 write-int32-hex stream, gval -254 trace trace, "read", stream -255 } -256 # if non-operator, return -257 { -258 var operator-grapheme?/eax: boolean <- operator-grapheme? g -259 compare operator-grapheme?, 0/false -260 break-if-!= -261 trace-text trace, "read", "stop" -262 break $next-operator-token:loop -263 } -264 var g/eax: grapheme <- read-from-gap-buffer in -265 write-grapheme out, g -266 loop -267 } -268 trace-higher trace -269 var stream-storage: (stream byte 0x40) -270 var stream/esi: (addr stream byte) <- address stream-storage -271 write stream, "=> " -272 rewind-stream out -273 write-stream stream, out -274 trace trace, "read", stream -275 } -276 -277 fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -278 trace-text trace, "read", "looking for a number" -279 trace-lower trace -280 $next-number-token:loop: { -281 var done?/eax: boolean <- gap-buffer-scan-done? in -282 compare done?, 0/false -283 break-if-!= -284 var g/eax: grapheme <- peek-from-gap-buffer in -285 { -286 var stream-storage: (stream byte 0x40) -287 var stream/esi: (addr stream byte) <- address stream-storage -288 write stream, "next: " -289 var gval/eax: int <- copy g -290 write-int32-hex stream, gval -291 trace trace, "read", stream +227 # comment +228 { +229 compare g, 0x23/comment +230 break-if-!= +231 rest-of-line in, out, trace +232 break $next-token:body +233 } +234 # digit +235 { +236 var digit?/eax: boolean <- decimal-digit? g +237 compare digit?, 0/false +238 break-if-= +239 next-number-token in, out, trace +240 break $next-token:body +241 } +242 # other symbol char +243 { +244 var symbol?/eax: boolean <- symbol-grapheme? g +245 compare symbol?, 0/false +246 break-if-= +247 next-symbol-token in, out, trace +248 break $next-token:body +249 } +250 # open square brackets begin streams +251 { +252 compare g, 0x5b/open-square-bracket +253 break-if-!= +254 g <- read-from-gap-buffer in # skip open bracket +255 next-stream-token in, out, trace +256 var out-cell/eax: (addr cell) <- copy _out-cell +257 var out-cell-type/eax: (addr int) <- get out-cell, type +258 copy-to *out-cell-type, 3/stream +259 break $next-token:body +260 } +261 # unbalanced close square brackets are errors +262 { +263 compare g, 0x5d/close-square-bracket +264 break-if-!= +265 error trace, "unbalanced ']'" +266 return +267 } +268 # other brackets are always single-char tokens +269 { +270 var bracket?/eax: boolean <- bracket-grapheme? g +271 compare bracket?, 0/false +272 break-if-= +273 var g/eax: grapheme <- read-from-gap-buffer in +274 next-bracket-token g, out, trace +275 break $next-token:body +276 } +277 # non-symbol operators +278 { +279 var operator?/eax: boolean <- operator-grapheme? g +280 compare operator?, 0/false +281 break-if-= +282 next-operator-token in, out, trace +283 break $next-token:body +284 } +285 # quote +286 { +287 compare g, 0x27/single-quote +288 break-if-!= +289 g <- read-from-gap-buffer in # consume +290 write-grapheme out, g +291 break $next-token:body 292 } -293 # if not symbol grapheme, return +293 # backquote 294 { -295 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g -296 compare symbol-grapheme?, 0/false -297 break-if-!= -298 trace-text trace, "read", "stop" -299 break $next-number-token:loop +295 compare g, 0x60/single-quote +296 break-if-!= +297 g <- read-from-gap-buffer in # consume +298 write-grapheme out, g +299 break $next-token:body 300 } -301 # if not digit grapheme, abort +301 # unquote 302 { -303 var digit?/eax: boolean <- decimal-digit? g -304 compare digit?, 0/false -305 break-if-!= -306 error trace, "invalid number" -307 return -308 } -309 trace-text trace, "read", "append" -310 var g/eax: grapheme <- read-from-gap-buffer in -311 write-grapheme out, g -312 loop -313 } -314 trace-higher trace -315 } -316 -317 fn next-stream-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -318 trace-text trace, "read", "stream" -319 { -320 var empty?/eax: boolean <- gap-buffer-scan-done? in -321 compare empty?, 0/false -322 { -323 break-if-= -324 error trace, "unbalanced '['" -325 return -326 } -327 var g/eax: grapheme <- read-from-gap-buffer in -328 compare g, 0x5d/close-square-bracket -329 break-if-= -330 write-grapheme out, g -331 loop -332 } -333 var stream-storage: (stream byte 0x40) -334 var stream/esi: (addr stream byte) <- address stream-storage -335 write stream, "=> " -336 rewind-stream out -337 write-stream stream, out -338 trace trace, "read", stream -339 } -340 -341 fn next-bracket-token g: grapheme, out: (addr stream byte), trace: (addr trace) { -342 trace-text trace, "read", "bracket" -343 write-grapheme out, g -344 var stream-storage: (stream byte 0x40) -345 var stream/esi: (addr stream byte) <- address stream-storage -346 write stream, "=> " -347 rewind-stream out -348 write-stream stream, out -349 trace trace, "read", stream -350 } -351 -352 fn rest-of-line in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { -353 trace-text trace, "read", "comment" -354 { -355 var empty?/eax: boolean <- gap-buffer-scan-done? in -356 compare empty?, 0/false -357 { -358 break-if-= -359 return -360 } -361 var g/eax: grapheme <- read-from-gap-buffer in -362 compare g, 0xa/newline -363 break-if-= -364 write-grapheme out, g -365 loop -366 } -367 var stream-storage: (stream byte 0x80) -368 var stream/esi: (addr stream byte) <- address stream-storage -369 write stream, "=> " -370 rewind-stream out -371 write-stream stream, out -372 trace trace, "read", stream -373 } -374 -375 fn symbol-grapheme? g: grapheme -> _/eax: boolean { -376 ## whitespace -377 compare g, 9/tab -378 { -379 break-if-!= -380 return 0/false -381 } -382 compare g, 0xa/newline -383 { -384 break-if-!= -385 return 0/false -386 } -387 compare g, 0x20/space -388 { -389 break-if-!= -390 return 0/false -391 } -392 ## quotes -393 compare g, 0x22/double-quote -394 { -395 break-if-!= -396 return 0/false -397 } -398 compare g, 0x60/backquote -399 { -400 break-if-!= -401 return 0/false -402 } -403 ## brackets -404 compare g, 0x28/open-paren -405 { -406 break-if-!= -407 return 0/false -408 } -409 compare g, 0x29/close-paren -410 { -411 break-if-!= -412 return 0/false -413 } -414 compare g, 0x5b/open-square-bracket -415 { -416 break-if-!= -417 return 0/false -418 } -419 compare g, 0x5d/close-square-bracket -420 { -421 break-if-!= -422 return 0/false -423 } -424 compare g, 0x7b/open-curly-bracket -425 { -426 break-if-!= -427 return 0/false -428 } -429 compare g, 0x7d/close-curly-bracket -430 { -431 break-if-!= -432 return 0/false -433 } -434 # - other punctuation -435 # '!' is a symbol char -436 compare g, 0x23/hash -437 { -438 break-if-!= -439 return 0/false -440 } -441 # '$' is a symbol char -442 compare g, 0x25/percent -443 { -444 break-if-!= -445 return 0/false -446 } -447 compare g, 0x26/ampersand -448 { -449 break-if-!= -450 return 0/false -451 } -452 compare g, 0x27/single-quote -453 { -454 break-if-!= -455 return 0/false -456 } -457 compare g, 0x2a/asterisk -458 { -459 break-if-!= -460 return 0/false -461 } -462 compare g, 0x2b/plus -463 { -464 break-if-!= -465 return 0/false -466 } -467 compare g, 0x2c/comma -468 { -469 break-if-!= -470 return 0/false -471 } -472 compare g, 0x2d/dash # '-' not allowed in symbols -473 { -474 break-if-!= -475 return 0/false -476 } -477 compare g, 0x2e/period -478 { -479 break-if-!= -480 return 0/false -481 } -482 compare g, 0x2f/slash -483 { -484 break-if-!= -485 return 0/false -486 } -487 compare g, 0x3a/colon -488 { -489 break-if-!= -490 return 0/false +303 compare g, 0x2c/comma +304 break-if-!= +305 g <- read-from-gap-buffer in # consume +306 write-grapheme out, g +307 # check for unquote-splice +308 { +309 var g2/eax: grapheme <- peek-from-gap-buffer in +310 compare g2, 0x40/at-sign +311 break-if-!= +312 g2 <- read-from-gap-buffer in +313 write-grapheme out, g2 +314 } +315 break $next-token:body +316 } +317 abort "unknown token type" +318 } +319 trace-higher trace +320 var stream-storage: (stream byte 0x400) # maximum possible token size (next-stream-token) +321 var stream/eax: (addr stream byte) <- address stream-storage +322 write stream, "=> " +323 rewind-stream out +324 write-stream stream, out +325 trace trace, "tokenize", stream +326 } +327 +328 fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +329 trace-text trace, "tokenize", "looking for a symbol" +330 trace-lower trace +331 $next-symbol-token:loop: { +332 var done?/eax: boolean <- gap-buffer-scan-done? in +333 compare done?, 0/false +334 break-if-!= +335 var g/eax: grapheme <- peek-from-gap-buffer in +336 { +337 var stream-storage: (stream byte 0x40) +338 var stream/esi: (addr stream byte) <- address stream-storage +339 write stream, "next: " +340 var gval/eax: int <- copy g +341 write-int32-hex stream, gval +342 trace trace, "tokenize", stream +343 } +344 # if non-symbol, return +345 { +346 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g +347 compare symbol-grapheme?, 0/false +348 break-if-!= +349 trace-text trace, "tokenize", "stop" +350 break $next-symbol-token:loop +351 } +352 var g/eax: grapheme <- read-from-gap-buffer in +353 write-grapheme out, g +354 loop +355 } +356 trace-higher trace +357 var stream-storage: (stream byte 0x40) +358 var stream/esi: (addr stream byte) <- address stream-storage +359 write stream, "=> " +360 rewind-stream out +361 write-stream stream, out +362 trace trace, "tokenize", stream +363 } +364 +365 fn next-operator-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +366 trace-text trace, "tokenize", "looking for a operator" +367 trace-lower trace +368 $next-operator-token:loop: { +369 var done?/eax: boolean <- gap-buffer-scan-done? in +370 compare done?, 0/false +371 break-if-!= +372 var g/eax: grapheme <- peek-from-gap-buffer in +373 { +374 var stream-storage: (stream byte 0x40) +375 var stream/esi: (addr stream byte) <- address stream-storage +376 write stream, "next: " +377 var gval/eax: int <- copy g +378 write-int32-hex stream, gval +379 trace trace, "tokenize", stream +380 } +381 # if non-operator, return +382 { +383 var operator-grapheme?/eax: boolean <- operator-grapheme? g +384 compare operator-grapheme?, 0/false +385 break-if-!= +386 trace-text trace, "tokenize", "stop" +387 break $next-operator-token:loop +388 } +389 var g/eax: grapheme <- read-from-gap-buffer in +390 write-grapheme out, g +391 loop +392 } +393 trace-higher trace +394 var stream-storage: (stream byte 0x40) +395 var stream/esi: (addr stream byte) <- address stream-storage +396 write stream, "=> " +397 rewind-stream out +398 write-stream stream, out +399 trace trace, "tokenize", stream +400 } +401 +402 fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +403 trace-text trace, "tokenize", "looking for a number" +404 trace-lower trace +405 $next-number-token:loop: { +406 var done?/eax: boolean <- gap-buffer-scan-done? in +407 compare done?, 0/false +408 break-if-!= +409 var g/eax: grapheme <- peek-from-gap-buffer in +410 { +411 var stream-storage: (stream byte 0x40) +412 var stream/esi: (addr stream byte) <- address stream-storage +413 write stream, "next: " +414 var gval/eax: int <- copy g +415 write-int32-hex stream, gval +416 trace trace, "tokenize", stream +417 } +418 # if not symbol grapheme, return +419 { +420 var symbol-grapheme?/eax: boolean <- symbol-grapheme? g +421 compare symbol-grapheme?, 0/false +422 break-if-!= +423 trace-text trace, "tokenize", "stop" +424 break $next-number-token:loop +425 } +426 # if not digit grapheme, abort +427 { +428 var digit?/eax: boolean <- decimal-digit? g +429 compare digit?, 0/false +430 break-if-!= +431 error trace, "invalid number" +432 return +433 } +434 trace-text trace, "tokenize", "append" +435 var g/eax: grapheme <- read-from-gap-buffer in +436 write-grapheme out, g +437 loop +438 } +439 trace-higher trace +440 } +441 +442 fn next-stream-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +443 trace-text trace, "tokenize", "stream" +444 { +445 var empty?/eax: boolean <- gap-buffer-scan-done? in +446 compare empty?, 0/false +447 { +448 break-if-= +449 error trace, "unbalanced '['" +450 return +451 } +452 var g/eax: grapheme <- read-from-gap-buffer in +453 compare g, 0x5d/close-square-bracket +454 break-if-= +455 write-grapheme out, g +456 loop +457 } +458 var stream-storage: (stream byte 0x400) # max-definition-size +459 var stream/esi: (addr stream byte) <- address stream-storage +460 write stream, "=> " +461 rewind-stream out +462 write-stream stream, out +463 trace trace, "tokenize", stream +464 } +465 +466 fn next-bracket-token g: grapheme, out: (addr stream byte), trace: (addr trace) { +467 trace-text trace, "tokenize", "bracket" +468 write-grapheme out, g +469 var stream-storage: (stream byte 0x40) +470 var stream/esi: (addr stream byte) <- address stream-storage +471 write stream, "=> " +472 rewind-stream out +473 write-stream stream, out +474 trace trace, "tokenize", stream +475 } +476 +477 fn rest-of-line in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) { +478 trace-text trace, "tokenize", "comment" +479 { +480 var empty?/eax: boolean <- gap-buffer-scan-done? in +481 compare empty?, 0/false +482 { +483 break-if-= +484 return +485 } +486 var g/eax: grapheme <- read-from-gap-buffer in +487 compare g, 0xa/newline +488 break-if-= +489 write-grapheme out, g +490 loop 491 } -492 compare g, 0x3b/semi-colon -493 { -494 break-if-!= -495 return 0/false -496 } -497 compare g, 0x3c/less-than -498 { -499 break-if-!= -500 return 0/false -501 } -502 compare g, 0x3d/equal +492 var stream-storage: (stream byte 0x80) +493 var stream/esi: (addr stream byte) <- address stream-storage +494 write stream, "=> " +495 rewind-stream out +496 write-stream stream, out +497 trace trace, "tokenize", stream +498 } +499 +500 fn symbol-grapheme? g: grapheme -> _/eax: boolean { +501 ## whitespace +502 compare g, 9/tab 503 { 504 break-if-!= 505 return 0/false 506 } -507 compare g, 0x3e/greater-than +507 compare g, 0xa/newline 508 { 509 break-if-!= 510 return 0/false 511 } -512 # '?' is a symbol char -513 compare g, 0x40/at-sign -514 { -515 break-if-!= -516 return 0/false -517 } -518 compare g, 0x5c/backslash +512 compare g, 0x20/space +513 { +514 break-if-!= +515 return 0/false +516 } +517 ## quotes +518 compare g, 0x22/double-quote 519 { 520 break-if-!= 521 return 0/false 522 } -523 compare g, 0x5e/caret +523 compare g, 0x60/backquote 524 { 525 break-if-!= 526 return 0/false 527 } -528 # '_' is a symbol char -529 compare g, 0x7c/vertical-line +528 ## brackets +529 compare g, 0x28/open-paren 530 { 531 break-if-!= 532 return 0/false 533 } -534 compare g, 0x7e/tilde +534 compare g, 0x29/close-paren 535 { 536 break-if-!= 537 return 0/false 538 } -539 return 1/true -540 } -541 -542 fn bracket-grapheme? g: grapheme -> _/eax: boolean { -543 compare g, 0x28/open-paren -544 { -545 break-if-!= -546 return 1/true -547 } -548 compare g, 0x29/close-paren -549 { -550 break-if-!= -551 return 1/true -552 } -553 compare g, 0x5b/open-square-bracket -554 { -555 break-if-!= -556 return 1/true -557 } -558 compare g, 0x5d/close-square-bracket -559 { -560 break-if-!= -561 return 1/true -562 } -563 compare g, 0x7b/open-curly-bracket -564 { -565 break-if-!= -566 return 1/true -567 } -568 compare g, 0x7d/close-curly-bracket -569 { -570 break-if-!= -571 return 1/true -572 } -573 return 0/false -574 } -575 -576 fn operator-grapheme? g: grapheme -> _/eax: boolean { -577 # '$' is a symbol char -578 compare g, 0x25/percent -579 { -580 break-if-!= -581 return 1/false -582 } -583 compare g, 0x26/ampersand -584 { -585 break-if-!= -586 return 1/true -587 } -588 compare g, 0x27/single-quote -589 { -590 break-if-!= -591 return 1/true -592 } -593 compare g, 0x2a/asterisk -594 { -595 break-if-!= -596 return 1/true -597 } -598 compare g, 0x2b/plus -599 { -600 break-if-!= -601 return 1/true -602 } -603 compare g, 0x2c/comma -604 { -605 break-if-!= -606 return 1/true -607 } -608 compare g, 0x2d/dash # '-' not allowed in symbols -609 { -610 break-if-!= -611 return 1/true -612 } -613 compare g, 0x2e/period -614 { -615 break-if-!= -616 return 1/true -617 } -618 compare g, 0x2f/slash -619 { -620 break-if-!= -621 return 1/true -622 } -623 compare g, 0x3a/colon -624 { -625 break-if-!= -626 return 1/true -627 } -628 compare g, 0x3b/semi-colon -629 { -630 break-if-!= -631 return 1/true -632 } -633 compare g, 0x3c/less-than -634 { -635 break-if-!= -636 return 1/true -637 } -638 compare g, 0x3d/equal -639 { -640 break-if-!= -641 return 1/true -642 } -643 compare g, 0x3e/greater-than -644 { -645 break-if-!= -646 return 1/true -647 } -648 # '?' is a symbol char -649 compare g, 0x40/at-sign -650 { -651 break-if-!= -652 return 1/true -653 } -654 compare g, 0x5c/backslash -655 { -656 break-if-!= -657 return 1/true -658 } -659 compare g, 0x5e/caret +539 compare g, 0x5b/open-square-bracket +540 { +541 break-if-!= +542 return 0/false +543 } +544 compare g, 0x5d/close-square-bracket +545 { +546 break-if-!= +547 return 0/false +548 } +549 compare g, 0x7b/open-curly-bracket +550 { +551 break-if-!= +552 return 0/false +553 } +554 compare g, 0x7d/close-curly-bracket +555 { +556 break-if-!= +557 return 0/false +558 } +559 # - other punctuation +560 # '!' is a symbol char +561 compare g, 0x23/hash +562 { +563 break-if-!= +564 return 0/false +565 } +566 # '$' is a symbol char +567 compare g, 0x25/percent +568 { +569 break-if-!= +570 return 0/false +571 } +572 compare g, 0x26/ampersand +573 { +574 break-if-!= +575 return 0/false +576 } +577 compare g, 0x27/single-quote +578 { +579 break-if-!= +580 return 0/false +581 } +582 compare g, 0x60/backquote +583 { +584 break-if-!= +585 return 0/false +586 } +587 compare g, 0x2c/comma +588 { +589 break-if-!= +590 return 0/false +591 } +592 compare g, 0x40/at-sign +593 { +594 break-if-!= +595 return 0/false +596 } +597 compare g, 0x2a/asterisk +598 { +599 break-if-!= +600 return 0/false +601 } +602 compare g, 0x2b/plus +603 { +604 break-if-!= +605 return 0/false +606 } +607 compare g, 0x2d/dash # '-' not allowed in symbols +608 { +609 break-if-!= +610 return 0/false +611 } +612 compare g, 0x2e/period +613 { +614 break-if-!= +615 return 0/false +616 } +617 compare g, 0x2f/slash +618 { +619 break-if-!= +620 return 0/false +621 } +622 compare g, 0x3a/colon +623 { +624 break-if-!= +625 return 0/false +626 } +627 compare g, 0x3b/semi-colon +628 { +629 break-if-!= +630 return 0/false +631 } +632 compare g, 0x3c/less-than +633 { +634 break-if-!= +635 return 0/false +636 } +637 compare g, 0x3d/equal +638 { +639 break-if-!= +640 return 0/false +641 } +642 compare g, 0x3e/greater-than +643 { +644 break-if-!= +645 return 0/false +646 } +647 # '?' is a symbol char +648 compare g, 0x5c/backslash +649 { +650 break-if-!= +651 return 0/false +652 } +653 compare g, 0x5e/caret +654 { +655 break-if-!= +656 return 0/false +657 } +658 # '_' is a symbol char +659 compare g, 0x7c/vertical-line 660 { 661 break-if-!= -662 return 1/true +662 return 0/false 663 } -664 # '_' is a symbol char -665 compare g, 0x7c/vertical-line -666 { -667 break-if-!= -668 return 1/true -669 } -670 compare g, 0x7e/tilde -671 { -672 break-if-!= -673 return 1/true -674 } -675 return 0/false -676 } -677 -678 fn number-token? _in: (addr cell) -> _/eax: boolean { -679 var in/eax: (addr cell) <- copy _in -680 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -681 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -682 rewind-stream in-data -683 var g/eax: grapheme <- read-grapheme in-data -684 var result/eax: boolean <- decimal-digit? g -685 return result -686 } -687 -688 fn bracket-token? _in: (addr cell) -> _/eax: boolean { -689 var in/eax: (addr cell) <- copy _in -690 { -691 var in-type/eax: (addr int) <- get in, type -692 compare *in-type, 3/stream -693 break-if-!= -694 # streams are never paren tokens -695 return 0/false -696 } -697 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -698 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -699 rewind-stream in-data -700 var g/eax: grapheme <- read-grapheme in-data -701 var result/eax: boolean <- bracket-grapheme? g -702 return result -703 } -704 -705 fn quote-token? _in: (addr cell) -> _/eax: boolean { -706 var in/eax: (addr cell) <- copy _in -707 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -708 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -709 rewind-stream in-data -710 var g/eax: grapheme <- read-grapheme in-data -711 compare g, 0x27/single-quote -712 { -713 break-if-!= -714 return 1/true -715 } -716 return 0/false -717 } -718 -719 fn open-paren-token? _in: (addr cell) -> _/eax: boolean { -720 var in/eax: (addr cell) <- copy _in -721 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -722 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah -723 var in-data/ecx: (addr stream byte) <- copy _in-data -724 rewind-stream in-data -725 var g/eax: grapheme <- read-grapheme in-data -726 compare g, 0x28/open-paren -727 { -728 break-if-!= -729 var result/eax: boolean <- stream-empty? in-data -730 return result -731 } -732 return 0/false -733 } -734 -735 fn close-paren-token? _in: (addr cell) -> _/eax: boolean { -736 var in/eax: (addr cell) <- copy _in -737 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -738 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah -739 var in-data/ecx: (addr stream byte) <- copy _in-data -740 rewind-stream in-data -741 var g/eax: grapheme <- read-grapheme in-data -742 compare g, 0x29/close-paren -743 { -744 break-if-!= -745 var result/eax: boolean <- stream-empty? in-data -746 return result +664 compare g, 0x7e/tilde +665 { +666 break-if-!= +667 return 0/false +668 } +669 return 1/true +670 } +671 +672 fn bracket-grapheme? g: grapheme -> _/eax: boolean { +673 compare g, 0x28/open-paren +674 { +675 break-if-!= +676 return 1/true +677 } +678 compare g, 0x29/close-paren +679 { +680 break-if-!= +681 return 1/true +682 } +683 compare g, 0x5b/open-square-bracket +684 { +685 break-if-!= +686 return 1/true +687 } +688 compare g, 0x5d/close-square-bracket +689 { +690 break-if-!= +691 return 1/true +692 } +693 compare g, 0x7b/open-curly-bracket +694 { +695 break-if-!= +696 return 1/true +697 } +698 compare g, 0x7d/close-curly-bracket +699 { +700 break-if-!= +701 return 1/true +702 } +703 return 0/false +704 } +705 +706 fn operator-grapheme? g: grapheme -> _/eax: boolean { +707 # '$' is a symbol char +708 compare g, 0x25/percent +709 { +710 break-if-!= +711 return 1/false +712 } +713 compare g, 0x26/ampersand +714 { +715 break-if-!= +716 return 1/true +717 } +718 compare g, 0x27/single-quote +719 { +720 break-if-!= +721 return 0/true +722 } +723 compare g, 0x60/backquote +724 { +725 break-if-!= +726 return 0/false +727 } +728 compare g, 0x2c/comma +729 { +730 break-if-!= +731 return 0/false +732 } +733 compare g, 0x40/at-sign +734 { +735 break-if-!= +736 return 0/false +737 } +738 compare g, 0x2a/asterisk +739 { +740 break-if-!= +741 return 1/true +742 } +743 compare g, 0x2b/plus +744 { +745 break-if-!= +746 return 1/true 747 } -748 return 0/false -749 } -750 -751 fn dot-token? _in: (addr cell) -> _/eax: boolean { -752 var in/eax: (addr cell) <- copy _in -753 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -754 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah -755 var in-data/ecx: (addr stream byte) <- copy _in-data -756 rewind-stream in-data -757 var g/eax: grapheme <- read-grapheme in-data -758 compare g, 0x2e/dot +748 compare g, 0x2d/dash # '-' not allowed in symbols +749 { +750 break-if-!= +751 return 1/true +752 } +753 compare g, 0x2e/period +754 { +755 break-if-!= +756 return 1/true +757 } +758 compare g, 0x2f/slash 759 { 760 break-if-!= -761 var result/eax: boolean <- stream-empty? in-data -762 return result -763 } -764 return 0/false -765 } -766 -767 fn test-dot-token { -768 var tmp-storage: (handle cell) -769 var tmp-ah/eax: (addr handle cell) <- address tmp-storage -770 new-symbol tmp-ah, "." -771 var tmp/eax: (addr cell) <- lookup *tmp-ah -772 var result/eax: boolean <- dot-token? tmp -773 check result, "F - test-dot-token" -774 } -775 -776 fn stream-token? _in: (addr cell) -> _/eax: boolean { -777 var in/eax: (addr cell) <- copy _in -778 var in-type/eax: (addr int) <- get in, type -779 compare *in-type, 3/stream -780 { -781 break-if-= -782 return 0/false -783 } -784 return 1/true -785 } -786 -787 fn comment-token? _in: (addr cell) -> _/eax: boolean { -788 var in/eax: (addr cell) <- copy _in -789 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data -790 var in-data/eax: (addr stream byte) <- lookup *in-data-ah -791 rewind-stream in-data -792 var g/eax: grapheme <- read-grapheme in-data -793 compare g, 0x23/hash -794 { -795 break-if-= -796 return 0/false -797 } -798 return 1/true -799 } +761 return 1/true +762 } +763 compare g, 0x3a/colon +764 { +765 break-if-!= +766 return 1/true +767 } +768 compare g, 0x3b/semi-colon +769 { +770 break-if-!= +771 return 1/true +772 } +773 compare g, 0x3c/less-than +774 { +775 break-if-!= +776 return 1/true +777 } +778 compare g, 0x3d/equal +779 { +780 break-if-!= +781 return 1/true +782 } +783 compare g, 0x3e/greater-than +784 { +785 break-if-!= +786 return 1/true +787 } +788 # '?' is a symbol char +789 compare g, 0x5c/backslash +790 { +791 break-if-!= +792 return 1/true +793 } +794 compare g, 0x5e/caret +795 { +796 break-if-!= +797 return 1/true +798 } +799 # '_' is a symbol char +800 compare g, 0x7c/vertical-line +801 { +802 break-if-!= +803 return 1/true +804 } +805 compare g, 0x7e/tilde +806 { +807 break-if-!= +808 return 1/true +809 } +810 return 0/false +811 } +812 +813 fn number-token? _in: (addr cell) -> _/eax: boolean { +814 var in/eax: (addr cell) <- copy _in +815 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +816 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +817 rewind-stream in-data +818 var g/eax: grapheme <- read-grapheme in-data +819 var result/eax: boolean <- decimal-digit? g +820 return result +821 } +822 +823 fn bracket-token? _in: (addr cell) -> _/eax: boolean { +824 var in/eax: (addr cell) <- copy _in +825 { +826 var in-type/eax: (addr int) <- get in, type +827 compare *in-type, 3/stream +828 break-if-!= +829 # streams are never paren tokens +830 return 0/false +831 } +832 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +833 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +834 rewind-stream in-data +835 var g/eax: grapheme <- read-grapheme in-data +836 var result/eax: boolean <- bracket-grapheme? g +837 return result +838 } +839 +840 fn quote-token? _in: (addr cell) -> _/eax: boolean { +841 var in/eax: (addr cell) <- copy _in +842 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +843 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +844 rewind-stream in-data +845 var result/eax: boolean <- stream-data-equal? in-data, "'" +846 return result +847 } +848 +849 fn backquote-token? _in: (addr cell) -> _/eax: boolean { +850 var in/eax: (addr cell) <- copy _in +851 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +852 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +853 rewind-stream in-data +854 var result/eax: boolean <- stream-data-equal? in-data, "`" +855 return result +856 } +857 +858 fn unquote-token? _in: (addr cell) -> _/eax: boolean { +859 var in/eax: (addr cell) <- copy _in +860 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +861 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +862 rewind-stream in-data +863 var result/eax: boolean <- stream-data-equal? in-data, "," +864 return result +865 } +866 +867 fn unquote-splice-token? _in: (addr cell) -> _/eax: boolean { +868 var in/eax: (addr cell) <- copy _in +869 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +870 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +871 rewind-stream in-data +872 var result/eax: boolean <- stream-data-equal? in-data, ",@" +873 return result +874 } +875 +876 fn open-paren-token? _in: (addr cell) -> _/eax: boolean { +877 var in/eax: (addr cell) <- copy _in +878 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +879 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah +880 var in-data/ecx: (addr stream byte) <- copy _in-data +881 rewind-stream in-data +882 var g/eax: grapheme <- read-grapheme in-data +883 compare g, 0x28/open-paren +884 { +885 break-if-!= +886 var result/eax: boolean <- stream-empty? in-data +887 return result +888 } +889 return 0/false +890 } +891 +892 fn close-paren-token? _in: (addr cell) -> _/eax: boolean { +893 var in/eax: (addr cell) <- copy _in +894 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +895 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah +896 var in-data/ecx: (addr stream byte) <- copy _in-data +897 rewind-stream in-data +898 var g/eax: grapheme <- read-grapheme in-data +899 compare g, 0x29/close-paren +900 { +901 break-if-!= +902 var result/eax: boolean <- stream-empty? in-data +903 return result +904 } +905 return 0/false +906 } +907 +908 fn dot-token? _in: (addr cell) -> _/eax: boolean { +909 var in/eax: (addr cell) <- copy _in +910 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +911 var _in-data/eax: (addr stream byte) <- lookup *in-data-ah +912 var in-data/ecx: (addr stream byte) <- copy _in-data +913 rewind-stream in-data +914 var g/eax: grapheme <- read-grapheme in-data +915 compare g, 0x2e/dot +916 { +917 break-if-!= +918 var result/eax: boolean <- stream-empty? in-data +919 return result +920 } +921 return 0/false +922 } +923 +924 fn test-dot-token { +925 var tmp-storage: (handle cell) +926 var tmp-ah/eax: (addr handle cell) <- address tmp-storage +927 new-symbol tmp-ah, "." +928 var tmp/eax: (addr cell) <- lookup *tmp-ah +929 var result/eax: boolean <- dot-token? tmp +930 check result, "F - test-dot-token" +931 } +932 +933 fn stream-token? _in: (addr cell) -> _/eax: boolean { +934 var in/eax: (addr cell) <- copy _in +935 var in-type/eax: (addr int) <- get in, type +936 compare *in-type, 3/stream +937 { +938 break-if-= +939 return 0/false +940 } +941 return 1/true +942 } +943 +944 fn comment-token? _in: (addr cell) -> _/eax: boolean { +945 var in/eax: (addr cell) <- copy _in +946 var in-data-ah/eax: (addr handle stream byte) <- get in, text-data +947 var in-data/eax: (addr stream byte) <- lookup *in-data-ah +948 rewind-stream in-data +949 var g/eax: grapheme <- read-grapheme in-data +950 compare g, 0x23/hash +951 { +952 break-if-= +953 return 0/false +954 } +955 return 1/true +956 } diff --git a/html/shell/trace.mu.html b/html/shell/trace.mu.html index 8a74c7a4..ebab0591 100644 --- a/html/shell/trace.mu.html +++ b/html/shell/trace.mu.html @@ -119,7 +119,7 @@ if ('onhashchange' in window) { 60 } 61 var max/edx: (addr int) <- get self, first-free 62 var trace-ah/eax: (addr handle array trace-line) <- get self, data - 63 var _trace/eax: (addr array trace-line) <- lookup *trace-ah + 63 var _trace/eax: (addr array trace-line) <- lookup *trace-ah 64 var trace/esi: (addr array trace-line) <- copy _trace 65 var i/ecx: int <- copy 0 66 { @@ -128,7 +128,7 @@ if ('onhashchange' in window) { 69 var offset/eax: (offset trace-line) <- compute-offset trace, i 70 var curr/eax: (addr trace-line) <- index trace, offset 71 var curr-label-ah/eax: (addr handle array byte) <- get curr, label - 72 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah + 72 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah 73 var error?/eax: boolean <- string-equal? curr-label, "error" 74 compare error?, 0/false 75 { @@ -146,7 +146,7 @@ if ('onhashchange' in window) { 87 compare self, 0 88 break-if-= 89 var data-ah/eax: (addr handle array trace-line) <- get self, data - 90 var data/eax: (addr array trace-line) <- lookup *data-ah + 90 var data/eax: (addr array trace-line) <- lookup *data-ah 91 var index-addr/edi: (addr int) <- get self, first-free 92 { 93 compare *index-addr, 0x8000/lines @@ -274,7 +274,7 @@ if ('onhashchange' in window) { 215 fn trace-contains? _self: (addr trace), label: (addr array byte), data: (addr array byte), start: int -> _/eax: boolean { 216 var self/esi: (addr trace) <- copy _self 217 var candidates-ah/eax: (addr handle array trace-line) <- get self, data - 218 var candidates/eax: (addr array trace-line) <- lookup *candidates-ah + 218 var candidates/eax: (addr array trace-line) <- lookup *candidates-ah 219 var i/ecx: int <- copy start 220 var max/edx: (addr int) <- get self, first-free 221 { @@ -289,13 +289,13 @@ if ('onhashchange' in window) { 230 var curr/ecx: (addr trace-line) <- index candidates, curr-offset 231 # if curr->label does not match, return false 232 var curr-label-ah/eax: (addr handle array byte) <- get curr, label - 233 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah + 233 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah 234 var match?/eax: boolean <- string-equal? curr-label, label 235 compare match?, 0/false 236 break-if-= 237 # if curr->data does not match, return false 238 var curr-data-ah/eax: (addr handle array byte) <- get curr, data - 239 var curr-data/eax: (addr array byte) <- lookup *curr-data-ah + 239 var curr-data/eax: (addr array byte) <- lookup *curr-data-ah 240 var match?/eax: boolean <- string-equal? curr-data, data 241 compare match?, 0/false 242 break-if-= @@ -319,10 +319,10 @@ if ('onhashchange' in window) { 260 return 0/false 261 } 262 var a-label-ah/eax: (addr handle array byte) <- get a, label - 263 var _a-label/eax: (addr array byte) <- lookup *a-label-ah + 263 var _a-label/eax: (addr array byte) <- lookup *a-label-ah 264 var a-label/ecx: (addr array byte) <- copy _a-label 265 var b-label-ah/ebx: (addr handle array byte) <- get b, label - 266 var b-label/eax: (addr array byte) <- lookup *b-label-ah + 266 var b-label/eax: (addr array byte) <- lookup *b-label-ah 267 var label-match?/eax: boolean <- string-equal? a-label, b-label 268 { 269 compare label-match?, 0/false @@ -330,10 +330,10 @@ if ('onhashchange' in window) { 271 return 0/false 272 } 273 var a-data-ah/eax: (addr handle array byte) <- get a, data - 274 var _a-data/eax: (addr array byte) <- lookup *a-data-ah + 274 var _a-data/eax: (addr array byte) <- lookup *a-data-ah 275 var a-data/ecx: (addr array byte) <- copy _a-data 276 var b-data-ah/ebx: (addr handle array byte) <- get b, data - 277 var b-data/eax: (addr array byte) <- lookup *b-data-ah + 277 var b-data/eax: (addr array byte) <- lookup *b-data-ah 278 var data-match?/eax: boolean <- string-equal? a-data, b-data 279 return data-match? 280 } @@ -348,7 +348,7 @@ if ('onhashchange' in window) { 289 return 290 } 291 var trace-ah/eax: (addr handle array trace-line) <- get self, data - 292 var _trace/eax: (addr array trace-line) <- lookup *trace-ah + 292 var _trace/eax: (addr array trace-line) <- lookup *trace-ah 293 var trace/edi: (addr array trace-line) <- copy _trace 294 var i/edx: int <- copy 0 295 var max-addr/ebx: (addr int) <- get self, first-free @@ -359,1317 +359,1348 @@ if ('onhashchange' in window) { 300 $dump-trace:iter: { 301 var offset/ebx: (offset trace-line) <- compute-offset trace, i 302 var curr/ebx: (addr trace-line) <- index trace, offset - 303 var curr-label-ah/eax: (addr handle array byte) <- get curr, label - 304 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah - 305 y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0xc5/bg=blue-bg - 306 } - 307 i <- increment - 308 loop - 309 } - 310 } - 311 - 312 ## UI stuff - 313 - 314 fn mark-lines-dirty _self: (addr trace) { - 315 var self/eax: (addr trace) <- copy _self - 316 var dest/edx: (addr boolean) <- get self, recompute-visible? - 317 copy-to *dest, 1/true - 318 } - 319 - 320 fn mark-lines-clean _self: (addr trace) { - 321 var self/eax: (addr trace) <- copy _self - 322 var dest/edx: (addr boolean) <- get self, recompute-visible? - 323 copy-to *dest, 0/false - 324 } - 325 - 326 fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int, xmax: int, ymax: int, show-cursor?: boolean -> _/ecx: int { - 327 var already-hiding-lines?: boolean - 328 var y/ecx: int <- copy ymin - 329 var self/esi: (addr trace) <- copy _self - 330 compare self, 0 - 331 { - 332 break-if-!= - 333 return ymin - 334 } - 335 clamp-cursor-to-top self, y - 336 var trace-ah/eax: (addr handle array trace-line) <- get self, data - 337 var _trace/eax: (addr array trace-line) <- lookup *trace-ah - 338 var trace/edi: (addr array trace-line) <- copy _trace - 339 var i/edx: int <- copy 0 - 340 var max-addr/ebx: (addr int) <- get self, first-free - 341 var max/ebx: int <- copy *max-addr - 342 $render-trace:loop: { - 343 compare i, max - 344 break-if->= - 345 $render-trace:iter: { - 346 var offset/ebx: (offset trace-line) <- compute-offset trace, i - 347 var curr/ebx: (addr trace-line) <- index trace, offset - 348 var curr-label-ah/eax: (addr handle array byte) <- get curr, label - 349 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah - 350 var bg/edi: int <- copy 0xc5/bg=blue-bg - 351 compare show-cursor?, 0/false - 352 { - 353 break-if-= - 354 var cursor-y/eax: (addr int) <- get self, cursor-y - 355 compare *cursor-y, y - 356 break-if-!= - 357 bg <- copy 7/cursor-line-bg - 358 var cursor-line-index/eax: (addr int) <- get self, cursor-line-index - 359 copy-to *cursor-line-index, i - 360 } - 361 # always display errors - 362 var error?/eax: boolean <- string-equal? curr-label, "error" - 363 { - 364 compare error?, 0/false - 365 break-if-= - 366 y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0xc/fg=trace-error, bg - 367 copy-to already-hiding-lines?, 0/false - 368 break $render-trace:iter - 369 } - 370 # display expanded lines - 371 var display?/eax: boolean <- should-render? self, curr - 372 { - 373 compare display?, 0/false - 374 break-if-= - 375 y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0x38/fg=trace, bg - 376 copy-to already-hiding-lines?, 0/false - 377 break $render-trace:iter - 378 } - 379 # ignore the rest - 380 compare already-hiding-lines?, 0/false - 381 { - 382 break-if-!= - 383 var x/eax: int <- copy xmin - 384 x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, x, y, 9/fg=trace, bg - 385 y <- increment - 386 copy-to already-hiding-lines?, 1/true - 387 } - 388 } - 389 i <- increment - 390 loop - 391 } - 392 # prevent cursor from going too far down - 393 clamp-cursor-to-bottom self, y, screen, xmin, ymin, xmax, ymax - 394 mark-lines-clean self - 395 return y - 396 } - 397 - 398 fn render-trace-line screen: (addr screen), _self: (addr trace-line), xmin: int, ymin: int, xmax: int, ymax: int, fg: int, bg: int -> _/ecx: int { - 399 var self/esi: (addr trace-line) <- copy _self - 400 var xsave/edx: int <- copy xmin - 401 var y/ecx: int <- copy ymin - 402 var label-ah/eax: (addr handle array byte) <- get self, label - 403 var _label/eax: (addr array byte) <- lookup *label-ah - 404 var label/ebx: (addr array byte) <- copy _label - 405 var error?/eax: boolean <- string-equal? label, "error" - 406 compare error?, 0/false - 407 { - 408 break-if-!= - 409 var x/eax: int <- copy xsave - 410 { - 411 var depth/edx: (addr int) <- get self, depth - 412 x, y <- draw-int32-decimal-wrapping-right-then-down screen, *depth, xmin, ymin, xmax, ymax, x, y, fg, bg - 413 x, y <- draw-text-wrapping-right-then-down screen, " ", xmin, ymin, xmax, ymax, x, y, fg, bg - 414 # don't show label in UI; it's just for tests - 415 } - 416 xsave <- copy x - 417 } - 418 var data-ah/eax: (addr handle array byte) <- get self, data - 419 var _data/eax: (addr array byte) <- lookup *data-ah - 420 var data/ebx: (addr array byte) <- copy _data - 421 var x/eax: int <- copy xsave - 422 x, y <- draw-text-wrapping-right-then-down screen, data, xmin, ymin, xmax, ymax, x, y, fg, bg - 423 y <- increment - 424 return y - 425 } - 426 - 427 # this is super-inefficient, string comparing every trace line - 428 # against every visible line on every render - 429 fn should-render? _self: (addr trace), _line: (addr trace-line) -> _/eax: boolean { - 430 var self/esi: (addr trace) <- copy _self - 431 # if visible? is already cached, just return it - 432 var dest/edx: (addr boolean) <- get self, recompute-visible? - 433 compare *dest, 0/false - 434 { - 435 break-if-!= - 436 var line/eax: (addr trace-line) <- copy _line - 437 var result/eax: (addr boolean) <- get line, visible? - 438 return *result - 439 } - 440 # recompute - 441 var candidates-ah/eax: (addr handle array trace-line) <- get self, visible - 442 var candidates/eax: (addr array trace-line) <- lookup *candidates-ah - 443 var i/ecx: int <- copy 0 - 444 var len/edx: int <- length candidates - 445 { - 446 compare i, len - 447 break-if->= - 448 { - 449 var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i - 450 var curr/ecx: (addr trace-line) <- index candidates, curr-offset - 451 var match?/eax: boolean <- trace-lines-equal? curr, _line - 452 compare match?, 0/false - 453 break-if-= - 454 var line/eax: (addr trace-line) <- copy _line - 455 var dest/eax: (addr boolean) <- get line, visible? - 456 copy-to *dest, 1/true - 457 return 1/true - 458 } - 459 i <- increment - 460 loop - 461 } - 462 var line/eax: (addr trace-line) <- copy _line - 463 var dest/eax: (addr boolean) <- get line, visible? - 464 copy-to *dest, 0/false - 465 return 0/false - 466 } - 467 - 468 fn clamp-cursor-to-top _self: (addr trace), _y: int { - 469 var y/ecx: int <- copy _y - 470 var self/esi: (addr trace) <- copy _self - 471 var cursor-y/eax: (addr int) <- get self, cursor-y - 472 compare *cursor-y, y - 473 break-if->= - 474 copy-to *cursor-y, y - 475 } - 476 - 477 # extremely hacky; consider deleting test-render-trace-empty-3 when you clean this up - 478 fn clamp-cursor-to-bottom _self: (addr trace), _y: int, screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int { - 479 var y/ebx: int <- copy _y - 480 compare y, ymin - 481 { - 482 break-if-> - 483 return - 484 } - 485 y <- decrement - 486 var self/esi: (addr trace) <- copy _self - 487 var cursor-y/eax: (addr int) <- get self, cursor-y - 488 compare *cursor-y, y - 489 break-if-<= - 490 copy-to *cursor-y, y - 491 # redraw cursor-line - 492 # TODO: ugly duplication - 493 var trace-ah/eax: (addr handle array trace-line) <- get self, data - 494 var trace/eax: (addr array trace-line) <- lookup *trace-ah - 495 var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index - 496 var cursor-line-index/ecx: int <- copy *cursor-line-index-addr - 497 var first-free/edx: (addr int) <- get self, first-free - 498 compare cursor-line-index, *first-free - 499 { - 500 break-if-< - 501 return - 502 } - 503 var cursor-offset/ecx: (offset trace-line) <- compute-offset trace, cursor-line-index - 504 var cursor-line/ecx: (addr trace-line) <- index trace, cursor-offset - 505 var display?/eax: boolean <- should-render? self, cursor-line - 506 { - 507 compare display?, 0/false - 508 break-if-= - 509 var dummy/ecx: int <- render-trace-line screen, cursor-line, xmin, y, xmax, ymax, 0x38/fg=trace, 7/cursor-line-bg - 510 return - 511 } - 512 var dummy1/eax: int <- copy 0 - 513 var dummy2/ecx: int <- copy 0 - 514 dummy1, dummy2 <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, xmin, y, 9/fg=trace, 7/cursor-line-bg - 515 } - 516 - 517 fn test-render-trace-empty { - 518 var t-storage: trace - 519 var t/esi: (addr trace) <- address t-storage - 520 initialize-trace t, 0x10, 0x10 - 521 # setup: screen - 522 var screen-on-stack: screen - 523 var screen/edi: (addr screen) <- address screen-on-stack - 524 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics - 525 # - 526 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor - 527 # - 528 check-ints-equal y, 0, "F - test-render-trace-empty/cursor" - 529 check-screen-row screen, 0/y, " ", "F - test-render-trace-empty" - 530 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-trace-empty/bg" - 531 } - 532 - 533 fn test-render-trace-empty-2 { - 534 var t-storage: trace - 535 var t/esi: (addr trace) <- address t-storage - 536 initialize-trace t, 0x10, 0x10 - 537 # setup: screen - 538 var screen-on-stack: screen - 539 var screen/edi: (addr screen) <- address screen-on-stack - 540 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics - 541 # - 542 var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 0/no-cursor # cursor below top row - 543 # - 544 check-ints-equal y, 2, "F - test-render-trace-empty-2/cursor" - 545 check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-2" - 546 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-2/bg" - 547 } - 548 - 549 fn test-render-trace-empty-3 { - 550 var t-storage: trace - 551 var t/esi: (addr trace) <- address t-storage - 552 initialize-trace t, 0x10, 0x10 - 553 # setup: screen - 554 var screen-on-stack: screen - 555 var screen/edi: (addr screen) <- address screen-on-stack - 556 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics - 557 # - 558 var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 1/show-cursor # try show cursor - 559 # still no cursor to show - 560 check-ints-equal y, 2, "F - test-render-trace-empty-3/cursor" - 561 check-screen-row screen, 1/y, " ", "F - test-render-trace-empty-3/line-above-cursor" - 562 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-empty-3/bg-for-line-above-cursor" - 563 check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-3" - 564 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-3/bg" - 565 } - 566 - 567 fn test-render-trace-collapsed-by-default { - 568 var t-storage: trace - 569 var t/esi: (addr trace) <- address t-storage - 570 initialize-trace t, 0x10, 0x10 - 571 trace-text t, "l", "data" - 572 # setup: screen - 573 var screen-on-stack: screen - 574 var screen/edi: (addr screen) <- address screen-on-stack - 575 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics - 576 # - 577 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor - 578 # - 579 check-ints-equal y, 1, "F - test-render-trace-collapsed-by-default/cursor" - 580 check-screen-row screen, 0/y, "... ", "F - test-render-trace-collapsed-by-default" - 581 } - 582 - 583 fn test-render-trace-error { - 584 var t-storage: trace - 585 var t/esi: (addr trace) <- address t-storage - 586 initialize-trace t, 0x10, 0x10 - 587 error t, "error" - 588 # setup: screen - 589 var screen-on-stack: screen - 590 var screen/edi: (addr screen) <- address screen-on-stack - 591 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics - 592 # - 593 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor - 594 # - 595 check-ints-equal y, 1, "F - test-render-trace-error/cursor" - 596 check-screen-row screen, 0/y, "error", "F - test-render-trace-error" - 597 } - 598 - 599 fn test-render-trace-error-at-start { - 600 var t-storage: trace - 601 var t/esi: (addr trace) <- address t-storage - 602 initialize-trace t, 0x10, 0x10 - 603 # - 604 error t, "error" - 605 trace-text t, "l", "data" - 606 # setup: screen - 607 var screen-on-stack: screen - 608 var screen/edi: (addr screen) <- address screen-on-stack - 609 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics - 610 # - 611 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor - 612 # - 613 check-ints-equal y, 2, "F - test-render-trace-error-at-start/cursor" - 614 check-screen-row screen, 0/y, "error", "F - test-render-trace-error-at-start/0" - 615 check-screen-row screen, 1/y, "... ", "F - test-render-trace-error-at-start/1" - 616 } - 617 - 618 fn test-render-trace-error-at-end { - 619 var t-storage: trace - 620 var t/esi: (addr trace) <- address t-storage - 621 initialize-trace t, 0x10, 0x10 - 622 # - 623 trace-text t, "l", "data" - 624 error t, "error" - 625 # setup: screen - 626 var screen-on-stack: screen - 627 var screen/edi: (addr screen) <- address screen-on-stack - 628 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics - 629 # - 630 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor - 631 # - 632 check-ints-equal y, 2, "F - test-render-trace-error-at-end/cursor" - 633 check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-at-end/0" - 634 check-screen-row screen, 1/y, "error", "F - test-render-trace-error-at-end/1" - 635 } - 636 - 637 fn test-render-trace-error-in-the-middle { - 638 var t-storage: trace - 639 var t/esi: (addr trace) <- address t-storage - 640 initialize-trace t, 0x10, 0x10 + 303 y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg + 304 } + 305 i <- increment + 306 loop + 307 } + 308 } + 309 + 310 fn dump-trace-with-label _self: (addr trace), label: (addr array byte) { + 311 var already-hiding-lines?: boolean + 312 var y/ecx: int <- copy 0 + 313 var self/esi: (addr trace) <- copy _self + 314 compare self, 0 + 315 { + 316 break-if-!= + 317 return + 318 } + 319 var trace-ah/eax: (addr handle array trace-line) <- get self, data + 320 var _trace/eax: (addr array trace-line) <- lookup *trace-ah + 321 var trace/edi: (addr array trace-line) <- copy _trace + 322 var i/edx: int <- copy 0 + 323 var max-addr/ebx: (addr int) <- get self, first-free + 324 var max/ebx: int <- copy *max-addr + 325 $dump-trace:loop: { + 326 compare i, max + 327 break-if->= + 328 $dump-trace:iter: { + 329 var offset/ebx: (offset trace-line) <- compute-offset trace, i + 330 var curr/ebx: (addr trace-line) <- index trace, offset + 331 var curr-label-ah/eax: (addr handle array byte) <- get curr, label + 332 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah + 333 var show?/eax: boolean <- string-equal? curr-label, label + 334 compare show?, 0/false + 335 break-if-= + 336 y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg + 337 } + 338 i <- increment + 339 loop + 340 } + 341 } + 342 + 343 ## UI stuff + 344 + 345 fn mark-lines-dirty _self: (addr trace) { + 346 var self/eax: (addr trace) <- copy _self + 347 var dest/edx: (addr boolean) <- get self, recompute-visible? + 348 copy-to *dest, 1/true + 349 } + 350 + 351 fn mark-lines-clean _self: (addr trace) { + 352 var self/eax: (addr trace) <- copy _self + 353 var dest/edx: (addr boolean) <- get self, recompute-visible? + 354 copy-to *dest, 0/false + 355 } + 356 + 357 fn render-trace screen: (addr screen), _self: (addr trace), xmin: int, ymin: int, xmax: int, ymax: int, show-cursor?: boolean -> _/ecx: int { + 358 var already-hiding-lines?: boolean + 359 var y/ecx: int <- copy ymin + 360 var self/esi: (addr trace) <- copy _self + 361 compare self, 0 + 362 { + 363 break-if-!= + 364 return ymin + 365 } + 366 clamp-cursor-to-top self, y + 367 var trace-ah/eax: (addr handle array trace-line) <- get self, data + 368 var _trace/eax: (addr array trace-line) <- lookup *trace-ah + 369 var trace/edi: (addr array trace-line) <- copy _trace + 370 var i/edx: int <- copy 0 + 371 var max-addr/ebx: (addr int) <- get self, first-free + 372 var max/ebx: int <- copy *max-addr + 373 $render-trace:loop: { + 374 compare i, max + 375 break-if->= + 376 $render-trace:iter: { + 377 var offset/ebx: (offset trace-line) <- compute-offset trace, i + 378 var curr/ebx: (addr trace-line) <- index trace, offset + 379 var curr-label-ah/eax: (addr handle array byte) <- get curr, label + 380 var curr-label/eax: (addr array byte) <- lookup *curr-label-ah + 381 var bg/edi: int <- copy 0xc5/bg=blue-bg + 382 compare show-cursor?, 0/false + 383 { + 384 break-if-= + 385 var cursor-y/eax: (addr int) <- get self, cursor-y + 386 compare *cursor-y, y + 387 break-if-!= + 388 bg <- copy 7/cursor-line-bg + 389 var cursor-line-index/eax: (addr int) <- get self, cursor-line-index + 390 copy-to *cursor-line-index, i + 391 } + 392 # always display errors + 393 var error?/eax: boolean <- string-equal? curr-label, "error" + 394 { + 395 compare error?, 0/false + 396 break-if-= + 397 y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0xc/fg=trace-error, bg + 398 copy-to already-hiding-lines?, 0/false + 399 break $render-trace:iter + 400 } + 401 # display expanded lines + 402 var display?/eax: boolean <- should-render? self, curr + 403 { + 404 compare display?, 0/false + 405 break-if-= + 406 y <- render-trace-line screen, curr, xmin, y, xmax, ymax, 0x38/fg=trace, bg + 407 copy-to already-hiding-lines?, 0/false + 408 break $render-trace:iter + 409 } + 410 # ignore the rest + 411 compare already-hiding-lines?, 0/false + 412 { + 413 break-if-!= + 414 var x/eax: int <- copy xmin + 415 x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, x, y, 9/fg=trace, bg + 416 y <- increment + 417 copy-to already-hiding-lines?, 1/true + 418 } + 419 } + 420 i <- increment + 421 loop + 422 } + 423 # prevent cursor from going too far down + 424 clamp-cursor-to-bottom self, y, screen, xmin, ymin, xmax, ymax + 425 mark-lines-clean self + 426 return y + 427 } + 428 + 429 fn render-trace-line screen: (addr screen), _self: (addr trace-line), xmin: int, ymin: int, xmax: int, ymax: int, fg: int, bg: int -> _/ecx: int { + 430 var self/esi: (addr trace-line) <- copy _self + 431 var xsave/edx: int <- copy xmin + 432 var y/ecx: int <- copy ymin + 433 var label-ah/eax: (addr handle array byte) <- get self, label + 434 var _label/eax: (addr array byte) <- lookup *label-ah + 435 var label/ebx: (addr array byte) <- copy _label + 436 var error?/eax: boolean <- string-equal? label, "error" + 437 compare error?, 0/false + 438 { + 439 break-if-!= + 440 var x/eax: int <- copy xsave + 441 { + 442 var depth/edx: (addr int) <- get self, depth + 443 x, y <- draw-int32-decimal-wrapping-right-then-down screen, *depth, xmin, ymin, xmax, ymax, x, y, fg, bg + 444 x, y <- draw-text-wrapping-right-then-down screen, " ", xmin, ymin, xmax, ymax, x, y, fg, bg + 445 # don't show label in UI; it's just for tests + 446 } + 447 xsave <- copy x + 448 } + 449 var data-ah/eax: (addr handle array byte) <- get self, data + 450 var _data/eax: (addr array byte) <- lookup *data-ah + 451 var data/ebx: (addr array byte) <- copy _data + 452 var x/eax: int <- copy xsave + 453 x, y <- draw-text-wrapping-right-then-down screen, data, xmin, ymin, xmax, ymax, x, y, fg, bg + 454 y <- increment + 455 return y + 456 } + 457 + 458 # this is super-inefficient, string comparing every trace line + 459 # against every visible line on every render + 460 fn should-render? _self: (addr trace), _line: (addr trace-line) -> _/eax: boolean { + 461 var self/esi: (addr trace) <- copy _self + 462 # if visible? is already cached, just return it + 463 var dest/edx: (addr boolean) <- get self, recompute-visible? + 464 compare *dest, 0/false + 465 { + 466 break-if-!= + 467 var line/eax: (addr trace-line) <- copy _line + 468 var result/eax: (addr boolean) <- get line, visible? + 469 return *result + 470 } + 471 # recompute + 472 var candidates-ah/eax: (addr handle array trace-line) <- get self, visible + 473 var candidates/eax: (addr array trace-line) <- lookup *candidates-ah + 474 var i/ecx: int <- copy 0 + 475 var len/edx: int <- length candidates + 476 { + 477 compare i, len + 478 break-if->= + 479 { + 480 var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i + 481 var curr/ecx: (addr trace-line) <- index candidates, curr-offset + 482 var match?/eax: boolean <- trace-lines-equal? curr, _line + 483 compare match?, 0/false + 484 break-if-= + 485 var line/eax: (addr trace-line) <- copy _line + 486 var dest/eax: (addr boolean) <- get line, visible? + 487 copy-to *dest, 1/true + 488 return 1/true + 489 } + 490 i <- increment + 491 loop + 492 } + 493 var line/eax: (addr trace-line) <- copy _line + 494 var dest/eax: (addr boolean) <- get line, visible? + 495 copy-to *dest, 0/false + 496 return 0/false + 497 } + 498 + 499 fn clamp-cursor-to-top _self: (addr trace), _y: int { + 500 var y/ecx: int <- copy _y + 501 var self/esi: (addr trace) <- copy _self + 502 var cursor-y/eax: (addr int) <- get self, cursor-y + 503 compare *cursor-y, y + 504 break-if->= + 505 copy-to *cursor-y, y + 506 } + 507 + 508 # extremely hacky; consider deleting test-render-trace-empty-3 when you clean this up + 509 fn clamp-cursor-to-bottom _self: (addr trace), _y: int, screen: (addr screen), xmin: int, ymin: int, xmax: int, ymax: int { + 510 var y/ebx: int <- copy _y + 511 compare y, ymin + 512 { + 513 break-if-> + 514 return + 515 } + 516 y <- decrement + 517 var self/esi: (addr trace) <- copy _self + 518 var cursor-y/eax: (addr int) <- get self, cursor-y + 519 compare *cursor-y, y + 520 break-if-<= + 521 copy-to *cursor-y, y + 522 # redraw cursor-line + 523 # TODO: ugly duplication + 524 var trace-ah/eax: (addr handle array trace-line) <- get self, data + 525 var trace/eax: (addr array trace-line) <- lookup *trace-ah + 526 var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index + 527 var cursor-line-index/ecx: int <- copy *cursor-line-index-addr + 528 var first-free/edx: (addr int) <- get self, first-free + 529 compare cursor-line-index, *first-free + 530 { + 531 break-if-< + 532 return + 533 } + 534 var cursor-offset/ecx: (offset trace-line) <- compute-offset trace, cursor-line-index + 535 var cursor-line/ecx: (addr trace-line) <- index trace, cursor-offset + 536 var display?/eax: boolean <- should-render? self, cursor-line + 537 { + 538 compare display?, 0/false + 539 break-if-= + 540 var dummy/ecx: int <- render-trace-line screen, cursor-line, xmin, y, xmax, ymax, 0x38/fg=trace, 7/cursor-line-bg + 541 return + 542 } + 543 var dummy1/eax: int <- copy 0 + 544 var dummy2/ecx: int <- copy 0 + 545 dummy1, dummy2 <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, xmin, y, 9/fg=trace, 7/cursor-line-bg + 546 } + 547 + 548 fn test-render-trace-empty { + 549 var t-storage: trace + 550 var t/esi: (addr trace) <- address t-storage + 551 initialize-trace t, 0x10, 0x10 + 552 # setup: screen + 553 var screen-on-stack: screen + 554 var screen/edi: (addr screen) <- address screen-on-stack + 555 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics + 556 # + 557 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor + 558 # + 559 check-ints-equal y, 0, "F - test-render-trace-empty/cursor" + 560 check-screen-row screen, 0/y, " ", "F - test-render-trace-empty" + 561 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-render-trace-empty/bg" + 562 } + 563 + 564 fn test-render-trace-empty-2 { + 565 var t-storage: trace + 566 var t/esi: (addr trace) <- address t-storage + 567 initialize-trace t, 0x10, 0x10 + 568 # setup: screen + 569 var screen-on-stack: screen + 570 var screen/edi: (addr screen) <- address screen-on-stack + 571 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics + 572 # + 573 var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 0/no-cursor # cursor below top row + 574 # + 575 check-ints-equal y, 2, "F - test-render-trace-empty-2/cursor" + 576 check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-2" + 577 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-2/bg" + 578 } + 579 + 580 fn test-render-trace-empty-3 { + 581 var t-storage: trace + 582 var t/esi: (addr trace) <- address t-storage + 583 initialize-trace t, 0x10, 0x10 + 584 # setup: screen + 585 var screen-on-stack: screen + 586 var screen/edi: (addr screen) <- address screen-on-stack + 587 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics + 588 # + 589 var y/ecx: int <- render-trace screen, t, 0/xmin, 2/ymin, 5/xmax, 4/ymax, 1/show-cursor # try show cursor + 590 # still no cursor to show + 591 check-ints-equal y, 2, "F - test-render-trace-empty-3/cursor" + 592 check-screen-row screen, 1/y, " ", "F - test-render-trace-empty-3/line-above-cursor" + 593 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-empty-3/bg-for-line-above-cursor" + 594 check-screen-row screen, 2/y, " ", "F - test-render-trace-empty-3" + 595 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-empty-3/bg" + 596 } + 597 + 598 fn test-render-trace-collapsed-by-default { + 599 var t-storage: trace + 600 var t/esi: (addr trace) <- address t-storage + 601 initialize-trace t, 0x10, 0x10 + 602 trace-text t, "l", "data" + 603 # setup: screen + 604 var screen-on-stack: screen + 605 var screen/edi: (addr screen) <- address screen-on-stack + 606 initialize-screen screen, 5/width, 4/height, 0/no-pixel-graphics + 607 # + 608 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 5/xmax, 4/ymax, 0/no-cursor + 609 # + 610 check-ints-equal y, 1, "F - test-render-trace-collapsed-by-default/cursor" + 611 check-screen-row screen, 0/y, "... ", "F - test-render-trace-collapsed-by-default" + 612 } + 613 + 614 fn test-render-trace-error { + 615 var t-storage: trace + 616 var t/esi: (addr trace) <- address t-storage + 617 initialize-trace t, 0x10, 0x10 + 618 error t, "error" + 619 # setup: screen + 620 var screen-on-stack: screen + 621 var screen/edi: (addr screen) <- address screen-on-stack + 622 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 623 # + 624 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor + 625 # + 626 check-ints-equal y, 1, "F - test-render-trace-error/cursor" + 627 check-screen-row screen, 0/y, "error", "F - test-render-trace-error" + 628 } + 629 + 630 fn test-render-trace-error-at-start { + 631 var t-storage: trace + 632 var t/esi: (addr trace) <- address t-storage + 633 initialize-trace t, 0x10, 0x10 + 634 # + 635 error t, "error" + 636 trace-text t, "l", "data" + 637 # setup: screen + 638 var screen-on-stack: screen + 639 var screen/edi: (addr screen) <- address screen-on-stack + 640 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics 641 # - 642 trace-text t, "l", "line 1" - 643 error t, "error" - 644 trace-text t, "l", "line 3" - 645 # setup: screen - 646 var screen-on-stack: screen - 647 var screen/edi: (addr screen) <- address screen-on-stack - 648 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics - 649 # - 650 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor - 651 # - 652 check-ints-equal y, 3, "F - test-render-trace-error-in-the-middle/cursor" - 653 check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-in-the-middle/0" - 654 check-screen-row screen, 1/y, "error", "F - test-render-trace-error-in-the-middle/1" - 655 check-screen-row screen, 2/y, "... ", "F - test-render-trace-error-in-the-middle/2" - 656 } - 657 - 658 fn test-render-trace-cursor-in-single-line { - 659 var t-storage: trace - 660 var t/esi: (addr trace) <- address t-storage - 661 initialize-trace t, 0x10, 0x10 + 642 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor + 643 # + 644 check-ints-equal y, 2, "F - test-render-trace-error-at-start/cursor" + 645 check-screen-row screen, 0/y, "error", "F - test-render-trace-error-at-start/0" + 646 check-screen-row screen, 1/y, "... ", "F - test-render-trace-error-at-start/1" + 647 } + 648 + 649 fn test-render-trace-error-at-end { + 650 var t-storage: trace + 651 var t/esi: (addr trace) <- address t-storage + 652 initialize-trace t, 0x10, 0x10 + 653 # + 654 trace-text t, "l", "data" + 655 error t, "error" + 656 # setup: screen + 657 var screen-on-stack: screen + 658 var screen/edi: (addr screen) <- address screen-on-stack + 659 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 660 # + 661 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor 662 # - 663 trace-text t, "l", "line 1" - 664 error t, "error" - 665 trace-text t, "l", "line 3" - 666 # setup: screen - 667 var screen-on-stack: screen - 668 var screen/edi: (addr screen) <- address screen-on-stack - 669 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics - 670 # - 671 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor + 663 check-ints-equal y, 2, "F - test-render-trace-error-at-end/cursor" + 664 check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-at-end/0" + 665 check-screen-row screen, 1/y, "error", "F - test-render-trace-error-at-end/1" + 666 } + 667 + 668 fn test-render-trace-error-in-the-middle { + 669 var t-storage: trace + 670 var t/esi: (addr trace) <- address t-storage + 671 initialize-trace t, 0x10, 0x10 672 # - 673 check-screen-row screen, 0/y, "... ", "F - test-render-trace-cursor-in-single-line/0" - 674 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-render-trace-cursor-in-single-line/0/cursor" - 675 check-screen-row screen, 1/y, "error ", "F - test-render-trace-cursor-in-single-line/1" - 676 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-cursor-in-single-line/1/cursor" - 677 check-screen-row screen, 2/y, "... ", "F - test-render-trace-cursor-in-single-line/2" - 678 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-cursor-in-single-line/2/cursor" - 679 } - 680 - 681 fn render-trace-menu screen: (addr screen) { - 682 var width/eax: int <- copy 0 - 683 var height/ecx: int <- copy 0 - 684 width, height <- screen-size screen - 685 var y/ecx: int <- copy height - 686 y <- decrement - 687 set-cursor-position screen, 0/x, y - 688 draw-text-rightward-from-cursor screen, " ctrl-r ", width, 0/fg, 0x5c/bg=black - 689 draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0xc5/bg=blue-bg - 690 draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 0x5c/bg=black - 691 draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0xc5/bg=blue-bg - 692 draw-text-rightward-from-cursor screen, " ctrl-m ", width, 0/fg, 3/bg=keyboard - 693 draw-text-rightward-from-cursor screen, " to keyboard ", width, 7/fg, 0xc5/bg=blue-bg - 694 draw-text-rightward-from-cursor screen, " j ", width, 0/fg, 0x5c/bg=black - 695 draw-text-rightward-from-cursor screen, " down ", width, 7/fg, 0xc5/bg=blue-bg - 696 draw-text-rightward-from-cursor screen, " k ", width, 0/fg, 0x5c/bg=black - 697 draw-text-rightward-from-cursor screen, " up ", width, 7/fg, 0xc5/bg=blue-bg - 698 draw-text-rightward-from-cursor screen, " enter ", width, 0/fg, 0x5c/bg=black - 699 draw-text-rightward-from-cursor screen, " expand ", width, 7/fg, 0xc5/bg=blue-bg - 700 draw-text-rightward-from-cursor screen, " backspace ", width, 0/fg, 0x5c/bg=black - 701 draw-text-rightward-from-cursor screen, " collapse ", width, 7/fg, 0xc5/bg=blue-bg - 702 } - 703 - 704 fn edit-trace _self: (addr trace), key: grapheme { - 705 var self/esi: (addr trace) <- copy _self - 706 # cursor down - 707 { - 708 compare key, 0x6a/j - 709 break-if-!= - 710 var cursor-y/eax: (addr int) <- get self, cursor-y - 711 increment *cursor-y - 712 return - 713 } - 714 { - 715 compare key, 0x81/down-arrow - 716 break-if-!= - 717 var cursor-y/eax: (addr int) <- get self, cursor-y - 718 increment *cursor-y - 719 return - 720 } - 721 # cursor up - 722 { - 723 compare key, 0x6b/k - 724 break-if-!= - 725 var cursor-y/eax: (addr int) <- get self, cursor-y - 726 decrement *cursor-y - 727 return - 728 } - 729 { - 730 compare key, 0x82/up-arrow - 731 break-if-!= - 732 var cursor-y/eax: (addr int) <- get self, cursor-y - 733 decrement *cursor-y - 734 return - 735 } - 736 # enter = expand - 737 { - 738 compare key, 0xa/newline - 739 break-if-!= - 740 expand self - 741 return - 742 } - 743 # backspace = collapse - 744 { - 745 compare key, 8/backspace - 746 break-if-!= - 747 collapse self - 748 return - 749 } - 750 } - 751 - 752 fn expand _self: (addr trace) { - 753 var self/esi: (addr trace) <- copy _self - 754 var trace-ah/eax: (addr handle array trace-line) <- get self, data - 755 var _trace/eax: (addr array trace-line) <- lookup *trace-ah - 756 var trace/edi: (addr array trace-line) <- copy _trace - 757 var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index - 758 var cursor-line-index/ecx: int <- copy *cursor-line-index-addr - 759 var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index - 760 var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset - 761 var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible? - 762 var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth - 763 var target-depth/ebx: int <- copy *cursor-line-depth - 764 # if cursor-line is already visible, increment target-depth - 765 compare *cursor-line-visible?, 0/false - 766 { - 767 break-if-= - 768 target-depth <- increment - 769 } - 770 # reveal the run of lines starting at cursor-line-index with depth target-depth - 771 var i/ecx: int <- copy cursor-line-index - 772 var max/edx: (addr int) <- get self, first-free - 773 { - 774 compare i, *max - 775 break-if->= - 776 var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i - 777 var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset - 778 var curr-line-depth/eax: (addr int) <- get curr-line, depth - 779 compare *curr-line-depth, target-depth - 780 break-if-< - 781 { - 782 break-if-!= - 783 var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible? - 784 copy-to *curr-line-visible?, 1/true - 785 reveal-trace-line self, curr-line - 786 } - 787 i <- increment - 788 loop - 789 } - 790 } - 791 - 792 fn collapse _self: (addr trace) { - 793 var self/esi: (addr trace) <- copy _self - 794 var trace-ah/eax: (addr handle array trace-line) <- get self, data - 795 var _trace/eax: (addr array trace-line) <- lookup *trace-ah - 796 var trace/edi: (addr array trace-line) <- copy _trace - 797 var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index - 798 var cursor-line-index/ecx: int <- copy *cursor-line-index-addr - 799 var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index - 800 var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset - 801 var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible? - 802 # if cursor-line is not visible, do nothing - 803 compare *cursor-line-visible?, 0/false + 673 trace-text t, "l", "line 1" + 674 error t, "error" + 675 trace-text t, "l", "line 3" + 676 # setup: screen + 677 var screen-on-stack: screen + 678 var screen/edi: (addr screen) <- address screen-on-stack + 679 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 680 # + 681 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 0/no-cursor + 682 # + 683 check-ints-equal y, 3, "F - test-render-trace-error-in-the-middle/cursor" + 684 check-screen-row screen, 0/y, "... ", "F - test-render-trace-error-in-the-middle/0" + 685 check-screen-row screen, 1/y, "error", "F - test-render-trace-error-in-the-middle/1" + 686 check-screen-row screen, 2/y, "... ", "F - test-render-trace-error-in-the-middle/2" + 687 } + 688 + 689 fn test-render-trace-cursor-in-single-line { + 690 var t-storage: trace + 691 var t/esi: (addr trace) <- address t-storage + 692 initialize-trace t, 0x10, 0x10 + 693 # + 694 trace-text t, "l", "line 1" + 695 error t, "error" + 696 trace-text t, "l", "line 3" + 697 # setup: screen + 698 var screen-on-stack: screen + 699 var screen/edi: (addr screen) <- address screen-on-stack + 700 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 701 # + 702 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor + 703 # + 704 check-screen-row screen, 0/y, "... ", "F - test-render-trace-cursor-in-single-line/0" + 705 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-render-trace-cursor-in-single-line/0/cursor" + 706 check-screen-row screen, 1/y, "error ", "F - test-render-trace-cursor-in-single-line/1" + 707 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-render-trace-cursor-in-single-line/1/cursor" + 708 check-screen-row screen, 2/y, "... ", "F - test-render-trace-cursor-in-single-line/2" + 709 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-render-trace-cursor-in-single-line/2/cursor" + 710 } + 711 + 712 fn render-trace-menu screen: (addr screen) { + 713 var width/eax: int <- copy 0 + 714 var height/ecx: int <- copy 0 + 715 width, height <- screen-size screen + 716 var y/ecx: int <- copy height + 717 y <- decrement + 718 set-cursor-position screen, 0/x, y + 719 draw-text-rightward-from-cursor screen, " ctrl-r ", width, 0/fg, 0x5c/bg=black + 720 draw-text-rightward-from-cursor screen, " run main ", width, 7/fg, 0xc5/bg=blue-bg + 721 draw-text-rightward-from-cursor screen, " ctrl-s ", width, 0/fg, 0x5c/bg=black + 722 draw-text-rightward-from-cursor screen, " run sandbox ", width, 7/fg, 0xc5/bg=blue-bg + 723 draw-text-rightward-from-cursor screen, " ctrl-m ", width, 0/fg, 3/bg=keyboard + 724 draw-text-rightward-from-cursor screen, " to keyboard ", width, 7/fg, 0xc5/bg=blue-bg + 725 draw-text-rightward-from-cursor screen, " j ", width, 0/fg, 0x5c/bg=black + 726 draw-text-rightward-from-cursor screen, " down ", width, 7/fg, 0xc5/bg=blue-bg + 727 draw-text-rightward-from-cursor screen, " k ", width, 0/fg, 0x5c/bg=black + 728 draw-text-rightward-from-cursor screen, " up ", width, 7/fg, 0xc5/bg=blue-bg + 729 draw-text-rightward-from-cursor screen, " enter ", width, 0/fg, 0x5c/bg=black + 730 draw-text-rightward-from-cursor screen, " expand ", width, 7/fg, 0xc5/bg=blue-bg + 731 draw-text-rightward-from-cursor screen, " backspace ", width, 0/fg, 0x5c/bg=black + 732 draw-text-rightward-from-cursor screen, " collapse ", width, 7/fg, 0xc5/bg=blue-bg + 733 } + 734 + 735 fn edit-trace _self: (addr trace), key: grapheme { + 736 var self/esi: (addr trace) <- copy _self + 737 # cursor down + 738 { + 739 compare key, 0x6a/j + 740 break-if-!= + 741 var cursor-y/eax: (addr int) <- get self, cursor-y + 742 increment *cursor-y + 743 return + 744 } + 745 { + 746 compare key, 0x81/down-arrow + 747 break-if-!= + 748 var cursor-y/eax: (addr int) <- get self, cursor-y + 749 increment *cursor-y + 750 return + 751 } + 752 # cursor up + 753 { + 754 compare key, 0x6b/k + 755 break-if-!= + 756 var cursor-y/eax: (addr int) <- get self, cursor-y + 757 decrement *cursor-y + 758 return + 759 } + 760 { + 761 compare key, 0x82/up-arrow + 762 break-if-!= + 763 var cursor-y/eax: (addr int) <- get self, cursor-y + 764 decrement *cursor-y + 765 return + 766 } + 767 # enter = expand + 768 { + 769 compare key, 0xa/newline + 770 break-if-!= + 771 expand self + 772 return + 773 } + 774 # backspace = collapse + 775 { + 776 compare key, 8/backspace + 777 break-if-!= + 778 collapse self + 779 return + 780 } + 781 } + 782 + 783 fn expand _self: (addr trace) { + 784 var self/esi: (addr trace) <- copy _self + 785 var trace-ah/eax: (addr handle array trace-line) <- get self, data + 786 var _trace/eax: (addr array trace-line) <- lookup *trace-ah + 787 var trace/edi: (addr array trace-line) <- copy _trace + 788 var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index + 789 var cursor-line-index/ecx: int <- copy *cursor-line-index-addr + 790 var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index + 791 var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset + 792 var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible? + 793 var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth + 794 var target-depth/ebx: int <- copy *cursor-line-depth + 795 # if cursor-line is already visible, increment target-depth + 796 compare *cursor-line-visible?, 0/false + 797 { + 798 break-if-= + 799 target-depth <- increment + 800 } + 801 # reveal the run of lines starting at cursor-line-index with depth target-depth + 802 var i/ecx: int <- copy cursor-line-index + 803 var max/edx: (addr int) <- get self, first-free 804 { - 805 break-if-!= - 806 return - 807 } - 808 # hide all lines between previous and next line with a lower depth - 809 var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth - 810 var cursor-y/edx: (addr int) <- get self, cursor-y - 811 var target-depth/ebx: int <- copy *cursor-line-depth - 812 var i/ecx: int <- copy cursor-line-index - 813 $collapse:loop1: { - 814 compare i, 0 - 815 break-if-< - 816 var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i - 817 var curr-line/eax: (addr trace-line) <- index trace, curr-line-offset - 818 { - 819 var curr-line-depth/eax: (addr int) <- get curr-line, depth - 820 compare *curr-line-depth, target-depth - 821 break-if-< $collapse:loop1 - 822 } - 823 # if cursor-line is visible, decrement cursor-y - 824 { - 825 var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible? - 826 compare *curr-line-visible?, 0/false - 827 break-if-= - 828 decrement *cursor-y - 829 } - 830 i <- decrement - 831 loop - 832 } - 833 i <- increment - 834 var max/edx: (addr int) <- get self, first-free - 835 $collapse:loop2: { - 836 compare i, *max - 837 break-if->= - 838 var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i - 839 var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset - 840 var curr-line-depth/eax: (addr int) <- get curr-line, depth - 841 compare *curr-line-depth, target-depth - 842 break-if-< - 843 { - 844 hide-trace-line self, curr-line - 845 var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible? - 846 copy-to *curr-line-visible?, 0/false - 847 } - 848 i <- increment - 849 loop - 850 } - 851 } - 852 - 853 # the 'visible' array is not required to be in order - 854 # elements can also be deleted out of order - 855 # so it can have holes - 856 # however, lines in it always have visible? set - 857 # we'll use visible? being unset as a sign of emptiness - 858 fn reveal-trace-line _self: (addr trace), line: (addr trace-line) { - 859 var self/esi: (addr trace) <- copy _self - 860 var visible-ah/eax: (addr handle array trace-line) <- get self, visible - 861 var visible/eax: (addr array trace-line) <- lookup *visible-ah - 862 var i/ecx: int <- copy 0 - 863 var len/edx: int <- length visible - 864 { - 865 compare i, len - 866 break-if->= - 867 var curr-offset/edx: (offset trace-line) <- compute-offset visible, i - 868 var curr/edx: (addr trace-line) <- index visible, curr-offset - 869 var curr-visible?/eax: (addr boolean) <- get curr, visible? - 870 compare *curr-visible?, 0/false - 871 { - 872 break-if-!= - 873 # empty slot found - 874 copy-object line, curr - 875 return - 876 } - 877 i <- increment - 878 loop - 879 } - 880 abort "too many visible lines; increase size of array trace.visible" - 881 } - 882 - 883 fn hide-trace-line _self: (addr trace), line: (addr trace-line) { - 884 var self/esi: (addr trace) <- copy _self - 885 var visible-ah/eax: (addr handle array trace-line) <- get self, visible - 886 var visible/eax: (addr array trace-line) <- lookup *visible-ah - 887 var i/ecx: int <- copy 0 - 888 var len/edx: int <- length visible - 889 { - 890 compare i, len - 891 break-if->= - 892 var curr-offset/edx: (offset trace-line) <- compute-offset visible, i - 893 var curr/edx: (addr trace-line) <- index visible, curr-offset - 894 var found?/eax: boolean <- trace-lines-equal? curr, line - 895 compare found?, 0/false - 896 { - 897 break-if-= - 898 clear-object curr - 899 } - 900 i <- increment - 901 loop - 902 } - 903 } - 904 - 905 fn test-cursor-down-and-up-within-trace { - 906 var t-storage: trace - 907 var t/esi: (addr trace) <- address t-storage - 908 initialize-trace t, 0x10, 0x10 - 909 # - 910 trace-text t, "l", "line 1" - 911 error t, "error" - 912 trace-text t, "l", "line 3" - 913 # setup: screen - 914 var screen-on-stack: screen - 915 var screen/edi: (addr screen) <- address screen-on-stack - 916 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics - 917 # - 918 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor - 919 # - 920 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-0" - 921 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/pre-0/cursor" - 922 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/pre-1" - 923 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/pre-1/cursor" - 924 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-2" - 925 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/pre-2/cursor" - 926 # cursor down - 927 edit-trace t, 0x6a/j - 928 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor - 929 # - 930 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/down-0" - 931 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-and-up-within-trace/down-0/cursor" - 932 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/down-1" - 933 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||||| ", "F - test-cursor-down-and-up-within-trace/down-1/cursor" - 934 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/down-2" - 935 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/down-2/cursor" - 936 # cursor up - 937 edit-trace t, 0x6b/k - 938 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor - 939 # - 940 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/up-0" - 941 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/up-0/cursor" - 942 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/up-1" - 943 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/up-1/cursor" - 944 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/up-2" - 945 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/up-2/cursor" - 946 } - 947 - 948 fn test-cursor-down-past-bottom-of-trace { - 949 var t-storage: trace - 950 var t/esi: (addr trace) <- address t-storage - 951 initialize-trace t, 0x10, 0x10 - 952 # - 953 trace-text t, "l", "line 1" - 954 error t, "error" - 955 trace-text t, "l", "line 3" - 956 # setup: screen - 957 var screen-on-stack: screen - 958 var screen/edi: (addr screen) <- address screen-on-stack - 959 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 805 compare i, *max + 806 break-if->= + 807 var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i + 808 var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset + 809 var curr-line-depth/eax: (addr int) <- get curr-line, depth + 810 compare *curr-line-depth, target-depth + 811 break-if-< + 812 { + 813 break-if-!= + 814 var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible? + 815 copy-to *curr-line-visible?, 1/true + 816 reveal-trace-line self, curr-line + 817 } + 818 i <- increment + 819 loop + 820 } + 821 } + 822 + 823 fn collapse _self: (addr trace) { + 824 var self/esi: (addr trace) <- copy _self + 825 var trace-ah/eax: (addr handle array trace-line) <- get self, data + 826 var _trace/eax: (addr array trace-line) <- lookup *trace-ah + 827 var trace/edi: (addr array trace-line) <- copy _trace + 828 var cursor-line-index-addr/ecx: (addr int) <- get self, cursor-line-index + 829 var cursor-line-index/ecx: int <- copy *cursor-line-index-addr + 830 var cursor-line-offset/eax: (offset trace-line) <- compute-offset trace, cursor-line-index + 831 var cursor-line/edx: (addr trace-line) <- index trace, cursor-line-offset + 832 var cursor-line-visible?/eax: (addr boolean) <- get cursor-line, visible? + 833 # if cursor-line is not visible, do nothing + 834 compare *cursor-line-visible?, 0/false + 835 { + 836 break-if-!= + 837 return + 838 } + 839 # hide all lines between previous and next line with a lower depth + 840 var cursor-line-depth/ebx: (addr int) <- get cursor-line, depth + 841 var cursor-y/edx: (addr int) <- get self, cursor-y + 842 var target-depth/ebx: int <- copy *cursor-line-depth + 843 var i/ecx: int <- copy cursor-line-index + 844 $collapse:loop1: { + 845 compare i, 0 + 846 break-if-< + 847 var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i + 848 var curr-line/eax: (addr trace-line) <- index trace, curr-line-offset + 849 { + 850 var curr-line-depth/eax: (addr int) <- get curr-line, depth + 851 compare *curr-line-depth, target-depth + 852 break-if-< $collapse:loop1 + 853 } + 854 # if cursor-line is visible, decrement cursor-y + 855 { + 856 var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible? + 857 compare *curr-line-visible?, 0/false + 858 break-if-= + 859 decrement *cursor-y + 860 } + 861 i <- decrement + 862 loop + 863 } + 864 i <- increment + 865 var max/edx: (addr int) <- get self, first-free + 866 $collapse:loop2: { + 867 compare i, *max + 868 break-if->= + 869 var curr-line-offset/eax: (offset trace-line) <- compute-offset trace, i + 870 var curr-line/edx: (addr trace-line) <- index trace, curr-line-offset + 871 var curr-line-depth/eax: (addr int) <- get curr-line, depth + 872 compare *curr-line-depth, target-depth + 873 break-if-< + 874 { + 875 hide-trace-line self, curr-line + 876 var curr-line-visible?/eax: (addr boolean) <- get curr-line, visible? + 877 copy-to *curr-line-visible?, 0/false + 878 } + 879 i <- increment + 880 loop + 881 } + 882 } + 883 + 884 # the 'visible' array is not required to be in order + 885 # elements can also be deleted out of order + 886 # so it can have holes + 887 # however, lines in it always have visible? set + 888 # we'll use visible? being unset as a sign of emptiness + 889 fn reveal-trace-line _self: (addr trace), line: (addr trace-line) { + 890 var self/esi: (addr trace) <- copy _self + 891 var visible-ah/eax: (addr handle array trace-line) <- get self, visible + 892 var visible/eax: (addr array trace-line) <- lookup *visible-ah + 893 var i/ecx: int <- copy 0 + 894 var len/edx: int <- length visible + 895 { + 896 compare i, len + 897 break-if->= + 898 var curr-offset/edx: (offset trace-line) <- compute-offset visible, i + 899 var curr/edx: (addr trace-line) <- index visible, curr-offset + 900 var curr-visible?/eax: (addr boolean) <- get curr, visible? + 901 compare *curr-visible?, 0/false + 902 { + 903 break-if-!= + 904 # empty slot found + 905 copy-object line, curr + 906 return + 907 } + 908 i <- increment + 909 loop + 910 } + 911 abort "too many visible lines; increase size of array trace.visible" + 912 } + 913 + 914 fn hide-trace-line _self: (addr trace), line: (addr trace-line) { + 915 var self/esi: (addr trace) <- copy _self + 916 var visible-ah/eax: (addr handle array trace-line) <- get self, visible + 917 var visible/eax: (addr array trace-line) <- lookup *visible-ah + 918 var i/ecx: int <- copy 0 + 919 var len/edx: int <- length visible + 920 { + 921 compare i, len + 922 break-if->= + 923 var curr-offset/edx: (offset trace-line) <- compute-offset visible, i + 924 var curr/edx: (addr trace-line) <- index visible, curr-offset + 925 var found?/eax: boolean <- trace-lines-equal? curr, line + 926 compare found?, 0/false + 927 { + 928 break-if-= + 929 clear-object curr + 930 } + 931 i <- increment + 932 loop + 933 } + 934 } + 935 + 936 fn test-cursor-down-and-up-within-trace { + 937 var t-storage: trace + 938 var t/esi: (addr trace) <- address t-storage + 939 initialize-trace t, 0x10, 0x10 + 940 # + 941 trace-text t, "l", "line 1" + 942 error t, "error" + 943 trace-text t, "l", "line 3" + 944 # setup: screen + 945 var screen-on-stack: screen + 946 var screen/edi: (addr screen) <- address screen-on-stack + 947 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 948 # + 949 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor + 950 # + 951 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-0" + 952 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/pre-0/cursor" + 953 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/pre-1" + 954 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/pre-1/cursor" + 955 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/pre-2" + 956 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/pre-2/cursor" + 957 # cursor down + 958 edit-trace t, 0x6a/j + 959 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor 960 # - 961 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor - 962 # - 963 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-0" - 964 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/pre-0/cursor" - 965 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/pre-1" - 966 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-1/cursor" - 967 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-2" - 968 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-2/cursor" - 969 # cursor down several times - 970 edit-trace t, 0x6a/j - 971 edit-trace t, 0x6a/j - 972 edit-trace t, 0x6a/j - 973 edit-trace t, 0x6a/j - 974 edit-trace t, 0x6a/j - 975 # hack: we do need to render to make this test pass; we're mixing state management with rendering - 976 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor - 977 # cursor clamps at bottom - 978 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-0" - 979 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-0/cursor" - 980 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/down-1" - 981 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-1/cursor" - 982 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-2" - 983 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/down-2/cursor" - 984 } - 985 - 986 fn test-expand-within-trace { - 987 var t-storage: trace - 988 var t/esi: (addr trace) <- address t-storage - 989 initialize-trace t, 0x10, 0x10 - 990 # - 991 trace-text t, "l", "line 1" - 992 trace-text t, "l", "line 2" - 993 # setup: screen - 994 var screen-on-stack: screen - 995 var screen/edi: (addr screen) <- address screen-on-stack - 996 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics - 997 # - 998 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor - 999 # -1000 check-screen-row screen, 0/y, "... ", "F - test-expand-within-trace/pre-0" -1001 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-expand-within-trace/pre-0/cursor" -1002 check-screen-row screen, 1/y, " ", "F - test-expand-within-trace/pre-1" -1003 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/pre-1/cursor" -1004 # expand -1005 edit-trace t, 0xa/enter -1006 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1007 # -1008 check-screen-row screen, 0/y, "0 line 1 ", "F - test-expand-within-trace/expand-0" -1009 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-expand-within-trace/expand-0/cursor" -1010 check-screen-row screen, 1/y, "0 line 2 ", "F - test-expand-within-trace/expand-1" -1011 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/expand-1/cursor" -1012 check-screen-row screen, 2/y, " ", "F - test-expand-within-trace/expand-2" -1013 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-expand-within-trace/expand-2/cursor" -1014 } -1015 -1016 fn test-trace-expand-skips-lower-depth { -1017 var t-storage: trace -1018 var t/esi: (addr trace) <- address t-storage -1019 initialize-trace t, 0x10, 0x10 -1020 # -1021 trace-text t, "l", "line 1" -1022 trace-lower t + 961 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/down-0" + 962 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-and-up-within-trace/down-0/cursor" + 963 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/down-1" + 964 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||||| ", "F - test-cursor-down-and-up-within-trace/down-1/cursor" + 965 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/down-2" + 966 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/down-2/cursor" + 967 # cursor up + 968 edit-trace t, 0x6b/k + 969 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor + 970 # + 971 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-and-up-within-trace/up-0" + 972 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-and-up-within-trace/up-0/cursor" + 973 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-and-up-within-trace/up-1" + 974 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-and-up-within-trace/up-1/cursor" + 975 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-and-up-within-trace/up-2" + 976 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-and-up-within-trace/up-2/cursor" + 977 } + 978 + 979 fn test-cursor-down-past-bottom-of-trace { + 980 var t-storage: trace + 981 var t/esi: (addr trace) <- address t-storage + 982 initialize-trace t, 0x10, 0x10 + 983 # + 984 trace-text t, "l", "line 1" + 985 error t, "error" + 986 trace-text t, "l", "line 3" + 987 # setup: screen + 988 var screen-on-stack: screen + 989 var screen/edi: (addr screen) <- address screen-on-stack + 990 initialize-screen screen, 0xa/width, 4/height, 0/no-pixel-graphics + 991 # + 992 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor + 993 # + 994 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-0" + 995 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/pre-0/cursor" + 996 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/pre-1" + 997 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-1/cursor" + 998 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/pre-2" + 999 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-cursor-down-past-bottom-of-trace/pre-2/cursor" +1000 # cursor down several times +1001 edit-trace t, 0x6a/j +1002 edit-trace t, 0x6a/j +1003 edit-trace t, 0x6a/j +1004 edit-trace t, 0x6a/j +1005 edit-trace t, 0x6a/j +1006 # hack: we do need to render to make this test pass; we're mixing state management with rendering +1007 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0xa/xmax, 4/ymax, 1/show-cursor +1008 # cursor clamps at bottom +1009 check-screen-row screen, 0/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-0" +1010 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-0/cursor" +1011 check-screen-row screen, 1/y, "error ", "F - test-cursor-down-past-bottom-of-trace/down-1" +1012 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-cursor-down-past-bottom-of-trace/down-1/cursor" +1013 check-screen-row screen, 2/y, "... ", "F - test-cursor-down-past-bottom-of-trace/down-2" +1014 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "||| ", "F - test-cursor-down-past-bottom-of-trace/down-2/cursor" +1015 } +1016 +1017 fn test-expand-within-trace { +1018 var t-storage: trace +1019 var t/esi: (addr trace) <- address t-storage +1020 initialize-trace t, 0x10, 0x10 +1021 # +1022 trace-text t, "l", "line 1" 1023 trace-text t, "l", "line 2" 1024 # setup: screen 1025 var screen-on-stack: screen 1026 var screen/edi: (addr screen) <- address screen-on-stack 1027 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics 1028 # -1029 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1029 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor 1030 # -1031 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-skips-lower-depth/pre-0" -1032 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-skips-lower-depth/pre-0/cursor" -1033 check-screen-row screen, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1" -1034 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1/cursor" +1031 check-screen-row screen, 0/y, "... ", "F - test-expand-within-trace/pre-0" +1032 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-expand-within-trace/pre-0/cursor" +1033 check-screen-row screen, 1/y, " ", "F - test-expand-within-trace/pre-1" +1034 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/pre-1/cursor" 1035 # expand -1036 edit-trace t, 0xa/enter -1037 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1036 edit-trace t, 0xa/enter +1037 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor 1038 # -1039 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-skips-lower-depth/expand-0" -1040 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-skips-lower-depth/expand-0/cursor" -1041 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-skips-lower-depth/expand-1" -1042 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/expand-1/cursor" -1043 check-screen-row screen, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2" -1044 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2/cursor" +1039 check-screen-row screen, 0/y, "0 line 1 ", "F - test-expand-within-trace/expand-0" +1040 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-expand-within-trace/expand-0/cursor" +1041 check-screen-row screen, 1/y, "0 line 2 ", "F - test-expand-within-trace/expand-1" +1042 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-expand-within-trace/expand-1/cursor" +1043 check-screen-row screen, 2/y, " ", "F - test-expand-within-trace/expand-2" +1044 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-expand-within-trace/expand-2/cursor" 1045 } 1046 -1047 fn test-trace-expand-continues-past-lower-depth { +1047 fn test-trace-expand-skips-lower-depth { 1048 var t-storage: trace 1049 var t/esi: (addr trace) <- address t-storage 1050 initialize-trace t, 0x10, 0x10 1051 # 1052 trace-text t, "l", "line 1" 1053 trace-lower t -1054 trace-text t, "l", "line 1.1" -1055 trace-higher t -1056 trace-text t, "l", "line 2" -1057 # setup: screen -1058 var screen-on-stack: screen -1059 var screen/edi: (addr screen) <- address screen-on-stack -1060 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1054 trace-text t, "l", "line 2" +1055 # setup: screen +1056 var screen-on-stack: screen +1057 var screen/edi: (addr screen) <- address screen-on-stack +1058 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1059 # +1060 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor 1061 # -1062 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1063 # -1064 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-continues-past-lower-depth/pre-0" -1065 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-continues-past-lower-depth/pre-0/cursor" -1066 check-screen-row screen, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1" -1067 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1/cursor" -1068 # expand -1069 edit-trace t, 0xa/enter -1070 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1071 # -1072 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-continues-past-lower-depth/expand-0" -1073 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-continues-past-lower-depth/expand-0/cursor" -1074 # TODO: might be too wasteful to show every place where lines are hidden -1075 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-continues-past-lower-depth/expand-1" -1076 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-1/cursor" -1077 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-continues-past-lower-depth/expand-2" -1078 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-2/cursor" -1079 } -1080 -1081 fn test-trace-expand-stops-at-higher-depth { -1082 var t-storage: trace -1083 var t/esi: (addr trace) <- address t-storage -1084 initialize-trace t, 0x10, 0x10 -1085 # -1086 trace-text t, "l", "line 1.1" -1087 trace-lower t -1088 trace-text t, "l", "line 1.1.1" -1089 trace-higher t -1090 trace-text t, "l", "line 1.2" -1091 trace-higher t -1092 trace-text t, "l", "line 2" -1093 trace-lower t -1094 trace-text t, "l", "line 2.1" -1095 # setup: screen -1096 var screen-on-stack: screen -1097 var screen/edi: (addr screen) <- address screen-on-stack -1098 initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics -1099 # -1100 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1101 # -1102 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-stops-at-higher-depth/pre-0" -1103 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-stops-at-higher-depth/pre-0/cursor" -1104 check-screen-row screen, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1" -1105 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1/cursor" -1106 # expand -1107 edit-trace t, 0xa/enter -1108 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1109 # -1110 check-screen-row screen, 0/y, "0 line 1.1 ", "F - test-trace-expand-stops-at-higher-depth/expand-0" -1111 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||||| ", "F - test-trace-expand-stops-at-higher-depth/expand-0/cursor" -1112 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-1" -1113 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-1/cursor" -1114 check-screen-row screen, 2/y, "0 line 1.2 ", "F - test-trace-expand-stops-at-higher-depth/expand-2" -1115 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-2/cursor" -1116 check-screen-row screen, 3/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-3" -1117 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-3/cursor" -1118 check-screen-row screen, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4" -1119 check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4/cursor" -1120 } -1121 -1122 fn test-trace-expand-twice { -1123 var t-storage: trace -1124 var t/esi: (addr trace) <- address t-storage -1125 initialize-trace t, 0x10, 0x10 -1126 # -1127 trace-text t, "l", "line 1" -1128 trace-lower t -1129 trace-text t, "l", "line 1.1" -1130 trace-higher t -1131 trace-text t, "l", "line 2" -1132 # setup: screen -1133 var screen-on-stack: screen -1134 var screen/edi: (addr screen) <- address screen-on-stack -1135 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics -1136 # -1137 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1138 # -1139 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-twice/pre-0" -1140 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-twice/pre-0/cursor" -1141 check-screen-row screen, 1/y, " ", "F - test-trace-expand-twice/pre-1" -1142 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/pre-1/cursor" -1143 # expand -1144 edit-trace t, 0xa/enter -1145 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1146 # -1147 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/expand-0" -1148 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-twice/expand-0/cursor" -1149 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/expand-1" -1150 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/expand-1/cursor" -1151 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/expand-2" -1152 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand-2/cursor" -1153 # cursor down -1154 edit-trace t, 0x6a/j -1155 # hack: we need to render here to make this test pass; we're mixing state management with rendering -1156 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1062 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-skips-lower-depth/pre-0" +1063 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-skips-lower-depth/pre-0/cursor" +1064 check-screen-row screen, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1" +1065 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/pre-1/cursor" +1066 # expand +1067 edit-trace t, 0xa/enter +1068 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1069 # +1070 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-skips-lower-depth/expand-0" +1071 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-skips-lower-depth/expand-0/cursor" +1072 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-skips-lower-depth/expand-1" +1073 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-skips-lower-depth/expand-1/cursor" +1074 check-screen-row screen, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2" +1075 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-skips-lower-depth/expand-2/cursor" +1076 } +1077 +1078 fn test-trace-expand-continues-past-lower-depth { +1079 var t-storage: trace +1080 var t/esi: (addr trace) <- address t-storage +1081 initialize-trace t, 0x10, 0x10 +1082 # +1083 trace-text t, "l", "line 1" +1084 trace-lower t +1085 trace-text t, "l", "line 1.1" +1086 trace-higher t +1087 trace-text t, "l", "line 2" +1088 # setup: screen +1089 var screen-on-stack: screen +1090 var screen/edi: (addr screen) <- address screen-on-stack +1091 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1092 # +1093 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1094 # +1095 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-continues-past-lower-depth/pre-0" +1096 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-continues-past-lower-depth/pre-0/cursor" +1097 check-screen-row screen, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1" +1098 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/pre-1/cursor" +1099 # expand +1100 edit-trace t, 0xa/enter +1101 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1102 # +1103 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-continues-past-lower-depth/expand-0" +1104 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-continues-past-lower-depth/expand-0/cursor" +1105 # TODO: might be too wasteful to show every place where lines are hidden +1106 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-continues-past-lower-depth/expand-1" +1107 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-1/cursor" +1108 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-continues-past-lower-depth/expand-2" +1109 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-continues-past-lower-depth/expand-2/cursor" +1110 } +1111 +1112 fn test-trace-expand-stops-at-higher-depth { +1113 var t-storage: trace +1114 var t/esi: (addr trace) <- address t-storage +1115 initialize-trace t, 0x10, 0x10 +1116 # +1117 trace-text t, "l", "line 1.1" +1118 trace-lower t +1119 trace-text t, "l", "line 1.1.1" +1120 trace-higher t +1121 trace-text t, "l", "line 1.2" +1122 trace-higher t +1123 trace-text t, "l", "line 2" +1124 trace-lower t +1125 trace-text t, "l", "line 2.1" +1126 # setup: screen +1127 var screen-on-stack: screen +1128 var screen/edi: (addr screen) <- address screen-on-stack +1129 initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics +1130 # +1131 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1132 # +1133 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-stops-at-higher-depth/pre-0" +1134 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-stops-at-higher-depth/pre-0/cursor" +1135 check-screen-row screen, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1" +1136 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/pre-1/cursor" +1137 # expand +1138 edit-trace t, 0xa/enter +1139 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1140 # +1141 check-screen-row screen, 0/y, "0 line 1.1 ", "F - test-trace-expand-stops-at-higher-depth/expand-0" +1142 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||||| ", "F - test-trace-expand-stops-at-higher-depth/expand-0/cursor" +1143 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-1" +1144 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-1/cursor" +1145 check-screen-row screen, 2/y, "0 line 1.2 ", "F - test-trace-expand-stops-at-higher-depth/expand-2" +1146 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-2/cursor" +1147 check-screen-row screen, 3/y, "... ", "F - test-trace-expand-stops-at-higher-depth/expand-3" +1148 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-3/cursor" +1149 check-screen-row screen, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4" +1150 check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-expand-stops-at-higher-depth/expand-4/cursor" +1151 } +1152 +1153 fn test-trace-expand-twice { +1154 var t-storage: trace +1155 var t/esi: (addr trace) <- address t-storage +1156 initialize-trace t, 0x10, 0x10 1157 # -1158 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/down-0" -1159 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/down-0/cursor" -1160 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/down-1" -1161 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||| ", "F - test-trace-expand-twice/down-1/cursor" -1162 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/down-2" -1163 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/down-2/cursor" -1164 # expand again -1165 edit-trace t, 0xa/enter -1166 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1158 trace-text t, "l", "line 1" +1159 trace-lower t +1160 trace-text t, "l", "line 1.1" +1161 trace-higher t +1162 trace-text t, "l", "line 2" +1163 # setup: screen +1164 var screen-on-stack: screen +1165 var screen/edi: (addr screen) <- address screen-on-stack +1166 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics 1167 # -1168 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/expand2-0" -1169 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/expand2-0/cursor" -1170 check-screen-row screen, 1/y, "1 line 1.1 ", "F - test-trace-expand-twice/expand2-1" -1171 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-expand-twice/expand2-1/cursor" -1172 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/expand2-2" -1173 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand2-2/cursor" -1174 } -1175 -1176 fn test-trace-refresh-cursor { -1177 var t-storage: trace -1178 var t/esi: (addr trace) <- address t-storage -1179 initialize-trace t, 0x10, 0x10 -1180 # -1181 trace-text t, "l", "line 1" -1182 trace-text t, "l", "line 2" -1183 trace-text t, "l", "line 3" -1184 # setup: screen -1185 var screen-on-stack: screen -1186 var screen/edi: (addr screen) <- address screen-on-stack -1187 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1168 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1169 # +1170 check-screen-row screen, 0/y, "... ", "F - test-trace-expand-twice/pre-0" +1171 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-expand-twice/pre-0/cursor" +1172 check-screen-row screen, 1/y, " ", "F - test-trace-expand-twice/pre-1" +1173 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/pre-1/cursor" +1174 # expand +1175 edit-trace t, 0xa/enter +1176 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1177 # +1178 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/expand-0" +1179 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-expand-twice/expand-0/cursor" +1180 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/expand-1" +1181 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-expand-twice/expand-1/cursor" +1182 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/expand-2" +1183 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand-2/cursor" +1184 # cursor down +1185 edit-trace t, 0x6a/j +1186 # hack: we need to render here to make this test pass; we're mixing state management with rendering +1187 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor 1188 # -1189 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1190 # -1191 check-screen-row screen, 0/y, "... ", "F - test-trace-refresh-cursor/pre-0" -1192 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-refresh-cursor/pre-0/cursor" -1193 check-screen-row screen, 1/y, " ", "F - test-trace-refresh-cursor/pre-1" -1194 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/pre-1/cursor" -1195 # expand -1196 edit-trace t, 0xa/enter -1197 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1189 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/down-0" +1190 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/down-0/cursor" +1191 check-screen-row screen, 1/y, "... ", "F - test-trace-expand-twice/down-1" +1192 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "||| ", "F - test-trace-expand-twice/down-1/cursor" +1193 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/down-2" +1194 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/down-2/cursor" +1195 # expand again +1196 edit-trace t, 0xa/enter +1197 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor 1198 # -1199 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/expand-0" -1200 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-refresh-cursor/expand-0/cursor" -1201 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/expand-1" -1202 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/expand-1/cursor" -1203 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/expand-2" -1204 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-refresh-cursor/expand-2/cursor" -1205 # cursor down -1206 edit-trace t, 0x6a/j -1207 edit-trace t, 0x6a/j -1208 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1209 # -1210 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/down-0" -1211 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/down-0/cursor" -1212 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/down-1" -1213 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/down-1/cursor" -1214 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/down-2" -1215 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/down-2/cursor" -1216 # recreate trace -1217 clear-trace t -1218 trace-text t, "l", "line 1" -1219 trace-text t, "l", "line 2" -1220 trace-text t, "l", "line 3" -1221 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1222 # cursor remains unchanged -1223 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/refresh-0" -1224 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/refresh-0/cursor" -1225 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/refresh-1" -1226 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/refresh-1/cursor" -1227 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/refresh-2" -1228 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/refresh-2/cursor" -1229 } -1230 -1231 fn test-trace-preserve-cursor-on-refresh { -1232 var t-storage: trace -1233 var t/esi: (addr trace) <- address t-storage -1234 initialize-trace t, 0x10, 0x10 -1235 # -1236 trace-text t, "l", "line 1" -1237 trace-text t, "l", "line 2" -1238 trace-text t, "l", "line 3" -1239 # setup: screen -1240 var screen-on-stack: screen -1241 var screen/edi: (addr screen) <- address screen-on-stack -1242 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics -1243 # -1244 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1245 # -1246 check-screen-row screen, 0/y, "... ", "F - test-trace-preserve-cursor-on-refresh/pre-0" -1247 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-preserve-cursor-on-refresh/pre-0/cursor" -1248 check-screen-row screen, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1" -1249 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1/cursor" -1250 # expand -1251 edit-trace t, 0xa/enter -1252 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1253 # -1254 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-preserve-cursor-on-refresh/expand-0" -1255 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/expand-0/cursor" -1256 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-preserve-cursor-on-refresh/expand-1" -1257 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-1/cursor" -1258 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/expand-2" -1259 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-2/cursor" -1260 # cursor down -1261 edit-trace t, 0x6a/j -1262 edit-trace t, 0x6a/j -1263 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1264 # -1265 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-preserve-cursor-on-refresh/down-0" -1266 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-0/cursor" -1267 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-preserve-cursor-on-refresh/down-1" -1268 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-1/cursor" -1269 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/down-2" -1270 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/down-2/cursor" -1271 # recreate trace with slightly different lines -1272 clear-trace t -1273 trace-text t, "l", "line 4" -1274 trace-text t, "l", "line 5" -1275 trace-text t, "l", "line 3" # cursor line is unchanged -1276 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1277 # cursor remains unchanged -1278 check-screen-row screen, 0/y, "0 line 4 ", "F - test-trace-preserve-cursor-on-refresh/refresh-0" -1279 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-0/cursor" -1280 check-screen-row screen, 1/y, "0 line 5 ", "F - test-trace-preserve-cursor-on-refresh/refresh-1" -1281 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-1/cursor" -1282 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/refresh-2" -1283 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/refresh-2/cursor" -1284 } -1285 -1286 fn test-trace-keep-cursor-visible-on-refresh { -1287 var t-storage: trace -1288 var t/esi: (addr trace) <- address t-storage -1289 initialize-trace t, 0x10, 0x10 -1290 # -1291 trace-text t, "l", "line 1" -1292 trace-text t, "l", "line 2" -1293 trace-text t, "l", "line 3" -1294 # setup: screen -1295 var screen-on-stack: screen -1296 var screen/edi: (addr screen) <- address screen-on-stack -1297 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics -1298 # -1299 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1300 # -1301 check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0" -1302 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0/cursor" -1303 check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1" -1304 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1/cursor" -1305 # expand -1306 edit-trace t, 0xa/enter -1307 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1308 # -1309 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0" -1310 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0/cursor" -1311 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1" -1312 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1/cursor" -1313 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2" -1314 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2/cursor" -1315 # cursor down -1316 edit-trace t, 0x6a/j -1317 edit-trace t, 0x6a/j -1318 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1319 # -1320 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/down-0" -1321 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-0/cursor" -1322 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/down-1" -1323 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-1/cursor" -1324 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/down-2" -1325 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/down-2/cursor" -1326 # recreate trace with entirely different lines -1327 clear-trace t -1328 trace-text t, "l", "line 4" -1329 trace-text t, "l", "line 5" -1330 trace-text t, "l", "line 6" -1331 mark-lines-dirty t -1332 clear-screen screen -1333 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1334 # trace collapses, and cursor bumps up -1335 check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0" -1336 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0/cursor" -1337 check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1" -1338 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1/cursor" -1339 check-screen-row screen, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2" -1340 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2/cursor" -1341 } -1342 -1343 fn test-trace-collapse-at-top { -1344 var t-storage: trace -1345 var t/esi: (addr trace) <- address t-storage -1346 initialize-trace t, 0x10, 0x10 -1347 # -1348 trace-text t, "l", "line 1" -1349 trace-lower t -1350 trace-text t, "l", "line 1.1" -1351 trace-higher t -1352 trace-text t, "l", "line 2" -1353 # setup: screen -1354 var screen-on-stack: screen -1355 var screen/edi: (addr screen) <- address screen-on-stack -1356 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics -1357 # -1358 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1359 # -1360 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/pre-0" -1361 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/pre-0/cursor" -1362 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/pre-1" -1363 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/pre-1/cursor" -1364 # expand -1365 edit-trace t, 0xa/enter -1366 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1367 # -1368 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-at-top/expand-0" -1369 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-at-top/expand-0/cursor" -1370 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-at-top/expand-1" -1371 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/expand-1/cursor" -1372 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-at-top/expand-2" -1373 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-at-top/expand-2/cursor" -1374 # collapse -1375 edit-trace t, 8/backspace -1376 # hack: we need to render here to make this test pass; we're mixing state management with rendering -1377 clear-screen screen -1378 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1379 # -1380 check-ints-equal y, 1, "F - test-trace-collapse-at-top/post-0/y" -1381 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/post-0" -1382 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/post-0/cursor" -1383 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/post-1" -1384 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/post-1/cursor" -1385 } -1386 -1387 fn test-trace-collapse { -1388 var t-storage: trace -1389 var t/esi: (addr trace) <- address t-storage -1390 initialize-trace t, 0x10, 0x10 -1391 # -1392 trace-text t, "l", "line 1" -1393 trace-text t, "l", "line 2" -1394 # setup: screen -1395 var screen-on-stack: screen -1396 var screen/edi: (addr screen) <- address screen-on-stack -1397 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1199 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-expand-twice/expand2-0" +1200 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-expand-twice/expand2-0/cursor" +1201 check-screen-row screen, 1/y, "1 line 1.1 ", "F - test-trace-expand-twice/expand2-1" +1202 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-expand-twice/expand2-1/cursor" +1203 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-expand-twice/expand2-2" +1204 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-expand-twice/expand2-2/cursor" +1205 } +1206 +1207 fn test-trace-refresh-cursor { +1208 var t-storage: trace +1209 var t/esi: (addr trace) <- address t-storage +1210 initialize-trace t, 0x10, 0x10 +1211 # +1212 trace-text t, "l", "line 1" +1213 trace-text t, "l", "line 2" +1214 trace-text t, "l", "line 3" +1215 # setup: screen +1216 var screen-on-stack: screen +1217 var screen/edi: (addr screen) <- address screen-on-stack +1218 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1219 # +1220 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1221 # +1222 check-screen-row screen, 0/y, "... ", "F - test-trace-refresh-cursor/pre-0" +1223 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-refresh-cursor/pre-0/cursor" +1224 check-screen-row screen, 1/y, " ", "F - test-trace-refresh-cursor/pre-1" +1225 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/pre-1/cursor" +1226 # expand +1227 edit-trace t, 0xa/enter +1228 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1229 # +1230 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/expand-0" +1231 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-refresh-cursor/expand-0/cursor" +1232 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/expand-1" +1233 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/expand-1/cursor" +1234 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/expand-2" +1235 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-refresh-cursor/expand-2/cursor" +1236 # cursor down +1237 edit-trace t, 0x6a/j +1238 edit-trace t, 0x6a/j +1239 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1240 # +1241 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/down-0" +1242 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/down-0/cursor" +1243 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/down-1" +1244 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/down-1/cursor" +1245 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/down-2" +1246 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/down-2/cursor" +1247 # recreate trace +1248 clear-trace t +1249 trace-text t, "l", "line 1" +1250 trace-text t, "l", "line 2" +1251 trace-text t, "l", "line 3" +1252 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1253 # cursor remains unchanged +1254 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-refresh-cursor/refresh-0" +1255 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-refresh-cursor/refresh-0/cursor" +1256 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-refresh-cursor/refresh-1" +1257 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-refresh-cursor/refresh-1/cursor" +1258 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-refresh-cursor/refresh-2" +1259 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-refresh-cursor/refresh-2/cursor" +1260 } +1261 +1262 fn test-trace-preserve-cursor-on-refresh { +1263 var t-storage: trace +1264 var t/esi: (addr trace) <- address t-storage +1265 initialize-trace t, 0x10, 0x10 +1266 # +1267 trace-text t, "l", "line 1" +1268 trace-text t, "l", "line 2" +1269 trace-text t, "l", "line 3" +1270 # setup: screen +1271 var screen-on-stack: screen +1272 var screen/edi: (addr screen) <- address screen-on-stack +1273 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1274 # +1275 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1276 # +1277 check-screen-row screen, 0/y, "... ", "F - test-trace-preserve-cursor-on-refresh/pre-0" +1278 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-preserve-cursor-on-refresh/pre-0/cursor" +1279 check-screen-row screen, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1" +1280 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/pre-1/cursor" +1281 # expand +1282 edit-trace t, 0xa/enter +1283 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1284 # +1285 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-preserve-cursor-on-refresh/expand-0" +1286 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/expand-0/cursor" +1287 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-preserve-cursor-on-refresh/expand-1" +1288 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-1/cursor" +1289 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/expand-2" +1290 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-preserve-cursor-on-refresh/expand-2/cursor" +1291 # cursor down +1292 edit-trace t, 0x6a/j +1293 edit-trace t, 0x6a/j +1294 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1295 # +1296 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-preserve-cursor-on-refresh/down-0" +1297 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-0/cursor" +1298 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-preserve-cursor-on-refresh/down-1" +1299 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/down-1/cursor" +1300 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/down-2" +1301 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/down-2/cursor" +1302 # recreate trace with slightly different lines +1303 clear-trace t +1304 trace-text t, "l", "line 4" +1305 trace-text t, "l", "line 5" +1306 trace-text t, "l", "line 3" # cursor line is unchanged +1307 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1308 # cursor remains unchanged +1309 check-screen-row screen, 0/y, "0 line 4 ", "F - test-trace-preserve-cursor-on-refresh/refresh-0" +1310 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-0/cursor" +1311 check-screen-row screen, 1/y, "0 line 5 ", "F - test-trace-preserve-cursor-on-refresh/refresh-1" +1312 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-preserve-cursor-on-refresh/refresh-1/cursor" +1313 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-preserve-cursor-on-refresh/refresh-2" +1314 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-preserve-cursor-on-refresh/refresh-2/cursor" +1315 } +1316 +1317 fn test-trace-keep-cursor-visible-on-refresh { +1318 var t-storage: trace +1319 var t/esi: (addr trace) <- address t-storage +1320 initialize-trace t, 0x10, 0x10 +1321 # +1322 trace-text t, "l", "line 1" +1323 trace-text t, "l", "line 2" +1324 trace-text t, "l", "line 3" +1325 # setup: screen +1326 var screen-on-stack: screen +1327 var screen/edi: (addr screen) <- address screen-on-stack +1328 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1329 # +1330 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1331 # +1332 check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0" +1333 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/pre-0/cursor" +1334 check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1" +1335 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/pre-1/cursor" +1336 # expand +1337 edit-trace t, 0xa/enter +1338 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1339 # +1340 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0" +1341 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/expand-0/cursor" +1342 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1" +1343 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-1/cursor" +1344 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2" +1345 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/expand-2/cursor" +1346 # cursor down +1347 edit-trace t, 0x6a/j +1348 edit-trace t, 0x6a/j +1349 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1350 # +1351 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-keep-cursor-visible-on-refresh/down-0" +1352 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-0/cursor" +1353 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-keep-cursor-visible-on-refresh/down-1" +1354 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/down-1/cursor" +1355 check-screen-row screen, 2/y, "0 line 3 ", "F - test-trace-keep-cursor-visible-on-refresh/down-2" +1356 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-keep-cursor-visible-on-refresh/down-2/cursor" +1357 # recreate trace with entirely different lines +1358 clear-trace t +1359 trace-text t, "l", "line 4" +1360 trace-text t, "l", "line 5" +1361 trace-text t, "l", "line 6" +1362 mark-lines-dirty t +1363 clear-screen screen +1364 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1365 # trace collapses, and cursor bumps up +1366 check-screen-row screen, 0/y, "... ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0" +1367 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-0/cursor" +1368 check-screen-row screen, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1" +1369 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-1/cursor" +1370 check-screen-row screen, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2" +1371 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-keep-cursor-visible-on-refresh/refresh-2/cursor" +1372 } +1373 +1374 fn test-trace-collapse-at-top { +1375 var t-storage: trace +1376 var t/esi: (addr trace) <- address t-storage +1377 initialize-trace t, 0x10, 0x10 +1378 # +1379 trace-text t, "l", "line 1" +1380 trace-lower t +1381 trace-text t, "l", "line 1.1" +1382 trace-higher t +1383 trace-text t, "l", "line 2" +1384 # setup: screen +1385 var screen-on-stack: screen +1386 var screen/edi: (addr screen) <- address screen-on-stack +1387 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1388 # +1389 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1390 # +1391 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/pre-0" +1392 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/pre-0/cursor" +1393 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/pre-1" +1394 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/pre-1/cursor" +1395 # expand +1396 edit-trace t, 0xa/enter +1397 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor 1398 # -1399 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1400 # -1401 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/pre-0" -1402 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/pre-0/cursor" -1403 check-screen-row screen, 1/y, " ", "F - test-trace-collapse/pre-1" -1404 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/pre-1/cursor" -1405 # expand -1406 edit-trace t, 0xa/enter -1407 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1408 # -1409 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse/expand-0" -1410 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse/expand-0/cursor" -1411 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-collapse/expand-1" -1412 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/expand-1/cursor" -1413 # cursor down -1414 edit-trace t, 0x6a/j -1415 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1416 # collapse -1417 edit-trace t, 8/backspace -1418 clear-screen screen -1419 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1420 # -1421 check-ints-equal y, 1, "F - test-trace-collapse/post-0/y" -1422 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/post-0" -1423 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/post-0/cursor" -1424 check-screen-row screen, 1/y, " ", "F - test-trace-collapse/post-1" -1425 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/post-1/cursor" -1426 } -1427 -1428 fn test-trace-collapse-skips-invisible-lines { -1429 var t-storage: trace -1430 var t/esi: (addr trace) <- address t-storage -1431 initialize-trace t, 0x10, 0x10 -1432 # -1433 trace-text t, "l", "line 1" -1434 trace-lower t -1435 trace-text t, "l", "line 1.1" -1436 trace-higher t -1437 trace-text t, "l", "line 2" -1438 # setup: screen -1439 var screen-on-stack: screen -1440 var screen/edi: (addr screen) <- address screen-on-stack -1441 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics -1442 # -1443 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1444 # -1445 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/pre-0" -1446 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/pre-0/cursor" -1447 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1" -1448 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1/cursor" -1449 # expand -1450 edit-trace t, 0xa/enter -1451 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1452 # two visible lines with an invisible line in between -1453 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-skips-invisible-lines/expand-0" -1454 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-skips-invisible-lines/expand-0/cursor" -1455 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-skips-invisible-lines/expand-1" -1456 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-1/cursor" -1457 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-skips-invisible-lines/expand-2" -1458 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-2/cursor" -1459 # cursor down to second visible line -1460 edit-trace t, 0x6a/j -1461 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1462 edit-trace t, 0x6a/j -1463 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1464 # collapse -1465 edit-trace t, 8/backspace -1466 clear-screen screen -1467 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1468 # -1469 check-ints-equal y, 1, "F - test-trace-collapse-skips-invisible-lines/post-0/y" -1470 var cursor-y/eax: (addr int) <- get t, cursor-y -1471 check-ints-equal *cursor-y, 0, "F - test-trace-collapse-skips-invisible-lines/post-0/cursor-y" -1472 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/post-0" -1473 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/post-0/cursor" -1474 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1" -1475 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1/cursor" -1476 } -1477 -1478 fn test-trace-collapse-two-levels { -1479 var t-storage: trace -1480 var t/esi: (addr trace) <- address t-storage -1481 initialize-trace t, 0x10, 0x10 -1482 # -1483 trace-text t, "l", "line 1" -1484 trace-lower t -1485 trace-text t, "l", "line 1.1" -1486 trace-higher t -1487 trace-text t, "l", "line 2" -1488 # setup: screen -1489 var screen-on-stack: screen -1490 var screen/edi: (addr screen) <- address screen-on-stack -1491 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics -1492 # -1493 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1494 # -1495 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/pre-0" -1496 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/pre-0/cursor" -1497 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1" -1498 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1/cursor" -1499 # expand -1500 edit-trace t, 0xa/enter -1501 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1502 # two visible lines with an invisible line in between -1503 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-two-levels/expand-0" -1504 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-two-levels/expand-0/cursor" -1505 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-two-levels/expand-1" -1506 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/expand-1/cursor" -1507 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-two-levels/expand-2" -1508 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand-2/cursor" -1509 # cursor down to ellipses -1510 edit-trace t, 0x6a/j -1511 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1512 # expand -1513 edit-trace t, 0xa/enter -1514 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1515 # two visible lines with an invisible line in between -1516 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-two-levels/expand2-0" -1517 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-two-levels/expand2-0/cursor" -1518 check-screen-row screen, 1/y, "1 line 1.1 ", "F - test-trace-collapse-two-levels/expand2-1" -1519 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-collapse-two-levels/expand2-1/cursor" -1520 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-two-levels/expand2-2" -1521 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand2-2/cursor" -1522 # cursor down to second visible line -1523 edit-trace t, 0x6a/j -1524 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1525 # collapse -1526 edit-trace t, 8/backspace -1527 clear-screen screen -1528 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor -1529 # -1530 check-ints-equal y, 1, "F - test-trace-collapse-two-levels/post-0/y" -1531 var cursor-y/eax: (addr int) <- get t, cursor-y -1532 check-ints-equal *cursor-y, 0, "F - test-trace-collapse-two-levels/post-0/cursor-y" -1533 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/post-0" -1534 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/post-0/cursor" -1535 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/post-1" -1536 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/post-1/cursor" -1537 } -1538 -1539 fn test-trace-collapse-nested-level { -1540 var t-storage: trace -1541 var t/esi: (addr trace) <- address t-storage -1542 initialize-trace t, 0x10, 0x10 -1543 # -1544 trace-text t, "l", "line 1" -1545 trace-lower t -1546 trace-text t, "l", "line 1.1" -1547 trace-higher t -1548 trace-text t, "l", "line 2" -1549 trace-lower t -1550 trace-text t, "l", "line 2.1" -1551 trace-text t, "l", "line 2.2" -1552 trace-higher t -1553 # setup: screen -1554 var screen-on-stack: screen -1555 var screen/edi: (addr screen) <- address screen-on-stack -1556 initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics -1557 # -1558 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1559 # -1560 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-nested-level/pre-0" -1561 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-nested-level/pre-0/cursor" -1562 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1" -1563 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1/cursor" -1564 # expand -1565 edit-trace t, 0xa/enter -1566 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1567 # two visible lines with an invisible line in between -1568 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/expand-0" -1569 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-nested-level/expand-0/cursor" -1570 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand-1" -1571 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand-1/cursor" -1572 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/expand-2" -1573 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand-2/cursor" -1574 check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/expand-3" -1575 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/expand-3/cursor" -1576 # cursor down to bottom -1577 edit-trace t, 0x6a/j -1578 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1579 edit-trace t, 0x6a/j -1580 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1581 edit-trace t, 0x6a/j -1582 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1583 # expand -1584 edit-trace t, 0xa/enter -1585 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1586 # two visible lines with an invisible line in between -1587 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/expand2-0" -1588 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/expand2-0/cursor" -1589 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand2-1" -1590 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand2-1/cursor" -1591 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/expand2-2" -1592 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand2-2/cursor" -1593 check-screen-row screen, 3/y, "1 line 2.1 ", "F - test-trace-collapse-nested-level/expand2-3" -1594 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "|||||||||| ", "F - test-trace-collapse-nested-level/expand2-3/cursor" -1595 check-screen-row screen, 4/y, "1 line 2.2 ", "F - test-trace-collapse-nested-level/expand2-4" -1596 check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-collapse-nested-level/expand2-4/cursor" -1597 # collapse -1598 edit-trace t, 8/backspace -1599 clear-screen screen -1600 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor -1601 # -1602 check-ints-equal y, 4, "F - test-trace-collapse-nested-level/post-0/y" -1603 var cursor-y/eax: (addr int) <- get t, cursor-y -1604 check-ints-equal *cursor-y, 2, "F - test-trace-collapse-nested-level/post-0/cursor-y" -1605 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/post-0" -1606 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/post-0/cursor" -1607 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/post-1" -1608 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/post-1/cursor" -1609 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/post-2" -1610 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-collapse-nested-level/post-2/cursor" -1611 check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/post-3" -1612 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/post-3/cursor" -1613 } +1399 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-at-top/expand-0" +1400 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-at-top/expand-0/cursor" +1401 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-at-top/expand-1" +1402 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/expand-1/cursor" +1403 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-at-top/expand-2" +1404 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-at-top/expand-2/cursor" +1405 # collapse +1406 edit-trace t, 8/backspace +1407 # hack: we need to render here to make this test pass; we're mixing state management with rendering +1408 clear-screen screen +1409 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1410 # +1411 check-ints-equal y, 1, "F - test-trace-collapse-at-top/post-0/y" +1412 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-at-top/post-0" +1413 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-at-top/post-0/cursor" +1414 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-at-top/post-1" +1415 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-at-top/post-1/cursor" +1416 } +1417 +1418 fn test-trace-collapse { +1419 var t-storage: trace +1420 var t/esi: (addr trace) <- address t-storage +1421 initialize-trace t, 0x10, 0x10 +1422 # +1423 trace-text t, "l", "line 1" +1424 trace-text t, "l", "line 2" +1425 # setup: screen +1426 var screen-on-stack: screen +1427 var screen/edi: (addr screen) <- address screen-on-stack +1428 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1429 # +1430 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1431 # +1432 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/pre-0" +1433 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/pre-0/cursor" +1434 check-screen-row screen, 1/y, " ", "F - test-trace-collapse/pre-1" +1435 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/pre-1/cursor" +1436 # expand +1437 edit-trace t, 0xa/enter +1438 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1439 # +1440 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse/expand-0" +1441 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse/expand-0/cursor" +1442 check-screen-row screen, 1/y, "0 line 2 ", "F - test-trace-collapse/expand-1" +1443 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/expand-1/cursor" +1444 # cursor down +1445 edit-trace t, 0x6a/j +1446 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1447 # collapse +1448 edit-trace t, 8/backspace +1449 clear-screen screen +1450 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1451 # +1452 check-ints-equal y, 1, "F - test-trace-collapse/post-0/y" +1453 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse/post-0" +1454 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse/post-0/cursor" +1455 check-screen-row screen, 1/y, " ", "F - test-trace-collapse/post-1" +1456 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse/post-1/cursor" +1457 } +1458 +1459 fn test-trace-collapse-skips-invisible-lines { +1460 var t-storage: trace +1461 var t/esi: (addr trace) <- address t-storage +1462 initialize-trace t, 0x10, 0x10 +1463 # +1464 trace-text t, "l", "line 1" +1465 trace-lower t +1466 trace-text t, "l", "line 1.1" +1467 trace-higher t +1468 trace-text t, "l", "line 2" +1469 # setup: screen +1470 var screen-on-stack: screen +1471 var screen/edi: (addr screen) <- address screen-on-stack +1472 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1473 # +1474 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1475 # +1476 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/pre-0" +1477 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/pre-0/cursor" +1478 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1" +1479 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/pre-1/cursor" +1480 # expand +1481 edit-trace t, 0xa/enter +1482 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1483 # two visible lines with an invisible line in between +1484 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-skips-invisible-lines/expand-0" +1485 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-skips-invisible-lines/expand-0/cursor" +1486 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-skips-invisible-lines/expand-1" +1487 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-1/cursor" +1488 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-skips-invisible-lines/expand-2" +1489 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-skips-invisible-lines/expand-2/cursor" +1490 # cursor down to second visible line +1491 edit-trace t, 0x6a/j +1492 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1493 edit-trace t, 0x6a/j +1494 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1495 # collapse +1496 edit-trace t, 8/backspace +1497 clear-screen screen +1498 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1499 # +1500 check-ints-equal y, 1, "F - test-trace-collapse-skips-invisible-lines/post-0/y" +1501 var cursor-y/eax: (addr int) <- get t, cursor-y +1502 check-ints-equal *cursor-y, 0, "F - test-trace-collapse-skips-invisible-lines/post-0/cursor-y" +1503 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-skips-invisible-lines/post-0" +1504 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-skips-invisible-lines/post-0/cursor" +1505 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1" +1506 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-skips-invisible-lines/post-1/cursor" +1507 } +1508 +1509 fn test-trace-collapse-two-levels { +1510 var t-storage: trace +1511 var t/esi: (addr trace) <- address t-storage +1512 initialize-trace t, 0x10, 0x10 +1513 # +1514 trace-text t, "l", "line 1" +1515 trace-lower t +1516 trace-text t, "l", "line 1.1" +1517 trace-higher t +1518 trace-text t, "l", "line 2" +1519 # setup: screen +1520 var screen-on-stack: screen +1521 var screen/edi: (addr screen) <- address screen-on-stack +1522 initialize-screen screen, 0x10/width, 4/height, 0/no-pixel-graphics +1523 # +1524 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1525 # +1526 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/pre-0" +1527 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/pre-0/cursor" +1528 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1" +1529 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/pre-1/cursor" +1530 # expand +1531 edit-trace t, 0xa/enter +1532 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1533 # two visible lines with an invisible line in between +1534 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-two-levels/expand-0" +1535 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-two-levels/expand-0/cursor" +1536 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-two-levels/expand-1" +1537 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/expand-1/cursor" +1538 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-two-levels/expand-2" +1539 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand-2/cursor" +1540 # cursor down to ellipses +1541 edit-trace t, 0x6a/j +1542 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1543 # expand +1544 edit-trace t, 0xa/enter +1545 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1546 # two visible lines with an invisible line in between +1547 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-two-levels/expand2-0" +1548 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-two-levels/expand2-0/cursor" +1549 check-screen-row screen, 1/y, "1 line 1.1 ", "F - test-trace-collapse-two-levels/expand2-1" +1550 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, "|||||||||| ", "F - test-trace-collapse-two-levels/expand2-1/cursor" +1551 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-two-levels/expand2-2" +1552 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-two-levels/expand2-2/cursor" +1553 # cursor down to second visible line +1554 edit-trace t, 0x6a/j +1555 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1556 # collapse +1557 edit-trace t, 8/backspace +1558 clear-screen screen +1559 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 4/ymax, 1/show-cursor +1560 # +1561 check-ints-equal y, 1, "F - test-trace-collapse-two-levels/post-0/y" +1562 var cursor-y/eax: (addr int) <- get t, cursor-y +1563 check-ints-equal *cursor-y, 0, "F - test-trace-collapse-two-levels/post-0/cursor-y" +1564 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-two-levels/post-0" +1565 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-two-levels/post-0/cursor" +1566 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-two-levels/post-1" +1567 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-two-levels/post-1/cursor" +1568 } +1569 +1570 fn test-trace-collapse-nested-level { +1571 var t-storage: trace +1572 var t/esi: (addr trace) <- address t-storage +1573 initialize-trace t, 0x10, 0x10 +1574 # +1575 trace-text t, "l", "line 1" +1576 trace-lower t +1577 trace-text t, "l", "line 1.1" +1578 trace-higher t +1579 trace-text t, "l", "line 2" +1580 trace-lower t +1581 trace-text t, "l", "line 2.1" +1582 trace-text t, "l", "line 2.2" +1583 trace-higher t +1584 # setup: screen +1585 var screen-on-stack: screen +1586 var screen/edi: (addr screen) <- address screen-on-stack +1587 initialize-screen screen, 0x10/width, 8/height, 0/no-pixel-graphics +1588 # +1589 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1590 # +1591 check-screen-row screen, 0/y, "... ", "F - test-trace-collapse-nested-level/pre-0" +1592 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "||| ", "F - test-trace-collapse-nested-level/pre-0/cursor" +1593 check-screen-row screen, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1" +1594 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/pre-1/cursor" +1595 # expand +1596 edit-trace t, 0xa/enter +1597 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1598 # two visible lines with an invisible line in between +1599 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/expand-0" +1600 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, "|||||||| ", "F - test-trace-collapse-nested-level/expand-0/cursor" +1601 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand-1" +1602 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand-1/cursor" +1603 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/expand-2" +1604 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand-2/cursor" +1605 check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/expand-3" +1606 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/expand-3/cursor" +1607 # cursor down to bottom +1608 edit-trace t, 0x6a/j +1609 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1610 edit-trace t, 0x6a/j +1611 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1612 edit-trace t, 0x6a/j +1613 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1614 # expand +1615 edit-trace t, 0xa/enter +1616 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1617 # two visible lines with an invisible line in between +1618 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/expand2-0" +1619 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/expand2-0/cursor" +1620 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/expand2-1" +1621 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/expand2-1/cursor" +1622 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/expand2-2" +1623 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, " ", "F - test-trace-collapse-nested-level/expand2-2/cursor" +1624 check-screen-row screen, 3/y, "1 line 2.1 ", "F - test-trace-collapse-nested-level/expand2-3" +1625 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, "|||||||||| ", "F - test-trace-collapse-nested-level/expand2-3/cursor" +1626 check-screen-row screen, 4/y, "1 line 2.2 ", "F - test-trace-collapse-nested-level/expand2-4" +1627 check-background-color-in-screen-row screen, 7/bg=cursor, 4/y, " ", "F - test-trace-collapse-nested-level/expand2-4/cursor" +1628 # collapse +1629 edit-trace t, 8/backspace +1630 clear-screen screen +1631 var y/ecx: int <- render-trace screen, t, 0/xmin, 0/ymin, 0x10/xmax, 8/ymax, 1/show-cursor +1632 # +1633 check-ints-equal y, 4, "F - test-trace-collapse-nested-level/post-0/y" +1634 var cursor-y/eax: (addr int) <- get t, cursor-y +1635 check-ints-equal *cursor-y, 2, "F - test-trace-collapse-nested-level/post-0/cursor-y" +1636 check-screen-row screen, 0/y, "0 line 1 ", "F - test-trace-collapse-nested-level/post-0" +1637 check-background-color-in-screen-row screen, 7/bg=cursor, 0/y, " ", "F - test-trace-collapse-nested-level/post-0/cursor" +1638 check-screen-row screen, 1/y, "... ", "F - test-trace-collapse-nested-level/post-1" +1639 check-background-color-in-screen-row screen, 7/bg=cursor, 1/y, " ", "F - test-trace-collapse-nested-level/post-1/cursor" +1640 check-screen-row screen, 2/y, "0 line 2 ", "F - test-trace-collapse-nested-level/post-2" +1641 check-background-color-in-screen-row screen, 7/bg=cursor, 2/y, "|||||||| ", "F - test-trace-collapse-nested-level/post-2/cursor" +1642 check-screen-row screen, 3/y, "... ", "F - test-trace-collapse-nested-level/post-3" +1643 check-background-color-in-screen-row screen, 7/bg=cursor, 3/y, " ", "F - test-trace-collapse-nested-level/post-3/cursor" +1644 }