about summary refs log tree commit diff stats
path: root/apps/mu.subx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mu.subx')
-rw-r--r--apps/mu.subx165
1 files changed, 146 insertions, 19 deletions
diff --git a/apps/mu.subx b/apps/mu.subx
index 02a4d9d1..70ad482d 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -3367,6 +3367,59 @@ test-convert-index-into-array-on-stack-with-literal:
     5d/pop-to-ebp
     c3/return
 
+test-convert-index-into-array-of-bytes-on-stack-with-literal:
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # setup
+    (clear-stream _test-input-stream)
+    (clear-stream $_test-input-buffered-file->buffer)
+    (clear-stream _test-output-stream)
+    (clear-stream $_test-output-buffered-file->buffer)
+    #
+    (write _test-input-stream "fn foo {\n")
+    (write _test-input-stream "  var arr: (array byte 3)\n")
+    (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
+    (flush _test-output-buffered-file)
+#?     # dump _test-output-stream {{{
+#?     (write 2 "^")
+#?     (write-stream 2 _test-output-stream)
+#?     (write 2 "$\n")
+#?     (rewind-stream _test-output-stream)
+#?     # }}}
+    # check output
+    (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
+    (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")
+    (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
+    # var arr
+    (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")
+    (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")
+    # var x
+    (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")
+    # x is at (ebp-7) + 4 + 2 = ebp-1
+    (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/9")
+    # reclaim x
+    (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/10")
+    # reclaim arr
+    (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/11")
+    #
+    (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
+    (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
+    (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/15")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 test-convert-index-into-array-using-offset:
     # . prologue
     55/push-ebp
@@ -10126,7 +10179,7 @@ emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (ad
       (string-equal? %ecx "length")  # => eax
       3d/compare-eax-and 0/imm32
       0f 84/jump-if-= break/disp32
-      (translate-mu-length-stmt *(ebp+8) *(ebp+0xc))
+      (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
       e9/jump $emit-subx-stmt:end/disp32
     }
     # index into array
@@ -10144,7 +10197,7 @@ emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (ad
       (string-equal? %ecx "compute-offset")  # => eax
       3d/compare-eax-and 0/imm32
       0f 84/jump-if-= break/disp32
-      (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc))
+      (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
       e9/jump $emit-subx-stmt:end/disp32
     }
     # get field from record
@@ -10197,7 +10250,7 @@ translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err:
     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
     89/<- %ebx 0/r32/eax
     # var elemsize/ecx: int = array-element-size(base)
-    (array-element-size %ebx)  # => eax
+    (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
     89/<- %ecx 0/r32/eax
     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
@@ -10301,14 +10354,12 @@ $translate-mu-length-stmt:end:
     5d/pop-to-ebp
     c3/return
 
-array-element-size:  # arr: (addr var) -> result/eax: int
+array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
-    # eax = arr
-    8b/-> *(ebp+8) 0/r32/eax
     #
-    (array-element-type-id %eax)  # => eax
+    (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
     (size-of-type-id-as-array-element %eax)  # => eax
 $array-element-size:end:
     # . epilogue
@@ -10498,7 +10549,7 @@ $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
         (write-buffered *(ebp+8) "<<")
         # . log2(array-element-size(base->type))
         # TODO: ensure size is a power of 2
-        (array-element-size %ebx)  # => eax
+        (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
         (num-shift-rights %eax)  # => eax
         (print-int32-buffered *(ebp+8) %eax)
         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
@@ -10534,7 +10585,7 @@ $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
       (parse-hex-int %eax)  # => eax
       89/<- %edx 0/r32/eax
       # offset = idx-value * array-element-size(base->type)
-      (array-element-size %ebx)  # => eax
+      (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
       f7 4/subop/multiply-into-eax %edx  # clobbers edx
       # offset += 4 for array size
       05/add-to-eax 4/imm32
@@ -10609,7 +10660,7 @@ $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
         (write-buffered *(ebp+8) "<<")
         # . log2(array-element-size(base))
         # TODO: ensure size is a power of 2
-        (array-element-size %ecx)  # => eax
+        (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
         (num-shift-rights %eax)  # => eax
         (print-int32-buffered *(ebp+8) %eax)
         #
@@ -10651,7 +10702,7 @@ $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
       (parse-hex-int %eax)  # Var-name => eax
       89/<- %edx 0/r32/eax
       # offset = idx-value * array-element-size(base)
-      (array-element-size %ecx)  # => eax
+      (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
       f7 4/subop/multiply-into-eax %edx  # clobbers edx
       # offset += base->offset
       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
@@ -10685,7 +10736,7 @@ $translate-mu-index-stmt-with-array-on-stack:end:
     5d/pop-to-ebp
     c3/return
 
-translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
+translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -10711,7 +10762,7 @@ $translate-mu-compute-index-stmt:emit-elem-size:
     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
     89/<- %ebx 0/r32/eax
     # print array-element-size(base)
-    (array-element-size %ebx)  # => eax
+    (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
     (print-int32-buffered *(ebp+8) %eax)
     (write-buffered *(ebp+8) "/imm32 ")
 $translate-mu-compute-index-stmt:emit-output:
@@ -10795,20 +10846,58 @@ $translate-mu-get-stmt:end:
     5d/pop-to-ebp
     c3/return
 
-array-element-type-id:  # v: (addr var) -> result/eax: type-id
+array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
     # precondition: n is positive
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
     #
     8b/-> *(ebp+8) 0/r32/eax
+    # var t/eax: (addr tree type-id)
     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
-    # TODO: ensure type->left is 'addr'
-    (lookup *(eax+0xc) *(eax+0x10))  # Tree-right Tree-right => eax
-    # TODO: ensure that type->right is non-null
-    # TODO: ensure that type->right->left is 'array'
+    # if t == 0 abort
+    3d/compare-eax-with 0/imm32
+    0f 84/jump-if-== $array-element-type-id:error0/disp32
+    # if t->is-atom? abort
+    81 7/subop/compare *eax 0/imm32/false  # Tree-is-atom
+    0f 85/jump-if-!= $array-element-type-id:error1/disp32
+    # if (t->left == addr) t = t->right
+    {
+      50/push-eax
+      (lookup *(eax+4) *(eax+8))  # Tree-left Tree-left => eax
+      (is-simple-mu-type? %eax 2)  # addr => eax
+      3d/compare-eax-with 0/imm32/false
+      58/pop-to-eax
+      74/jump-if-= break/disp8
+$array-element-type-id:skip-addr:
+      (lookup *(eax+0xc) *(eax+0x10))  # Tree-right Tree-right => eax
+    }
+    # if t == 0 abort
+    3d/compare-eax-with 0/imm32
+    0f 84/jump-if-= $array-element-type-id:error2/disp32
+    # if t->is-atom? abort
+    81 7/subop/compare *eax 0/imm32/false  # Tree-is-atom
+    0f 85/jump-if-!= $array-element-type-id:error2/disp32
+    # if t->left != array abort
+    {
+      50/push-eax
+      (lookup *(eax+4) *(eax+8))  # Tree-left Tree-left => eax
+      (is-simple-mu-type? %eax 3)  # array => eax
+      3d/compare-eax-with 0/imm32/false
+      58/pop-to-eax
+$array-element-type-id:no-array:
+      0f 84/jump-if-= $array-element-type-id:error2/disp32
+    }
+$array-element-type-id:skip-array:
+    # t = t->right
     (lookup *(eax+0xc) *(eax+0x10))  # Tree-right Tree-right => eax
-    # TODO: ensure that type->right->right is non-null
+    # if t == 0 abort
+    3d/compare-eax-with 0/imm32
+    0f 84/jump-if-= $array-element-type-id:error2/disp32
+    # if t->is-atom? abort
+    81 7/subop/compare *eax 0/imm32/false  # Tree-is-atom
+    0f 85/jump-if-!= $array-element-type-id:error2/disp32
+    # return t->left->value
     (lookup *(eax+4) *(eax+8))  # Tree-left Tree-left => eax
     8b/-> *(eax+4) 0/r32/eax  # Tree-value
 $array-element-type-id:end:
@@ -10817,6 +10906,44 @@ $array-element-type-id:end:
     5d/pop-to-ebp
     c3/return
 
+$array-element-type-id:error0:
+    (write-buffered *(ebp+0xc) "array-element-type-id: var '")
+    50/push-eax
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0xc) %eax)
+    58/pop-to-eax
+    (write-buffered *(ebp+0xc) "' has no type\n")
+    (flush *(ebp+0xc))
+    (stop *(ebp+0x10) 1)
+    # never gets here
+
+$array-element-type-id:error1:
+    (write-buffered *(ebp+0xc) "array-element-type-id: var '")
+    50/push-eax
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0xc) %eax)
+    58/pop-to-eax
+    (write-buffered *(ebp+0xc) "' has atomic type ")
+    (print-int32-buffered *(ebp+0xc) *(eax+4))  # Tree-value
+    (write-buffered *(ebp+0xc) Newline)
+    (flush *(ebp+0xc))
+    (stop *(ebp+0x10) 1)
+    # never gets here
+
+$array-element-type-id:error2:
+    (write-buffered *(ebp+0xc) "array-element-type-id: var '")
+    50/push-eax
+    8b/-> *(ebp+8) 0/r32/eax
+    (lookup *eax *(eax+4))  # Var-name Var-name => eax
+    (write-buffered *(ebp+0xc) %eax)
+    58/pop-to-eax
+    (write-buffered *(ebp+0xc) "' has non-array type\n")
+    (flush *(ebp+0xc))
+    (stop *(ebp+0x10) 1)
+    # never gets here
+
 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
     # precondition: n is positive
     # . prologue