about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-03-15 16:44:55 -0700
committerKartik Agaram <vc@akkartik.com>2020-03-15 16:44:55 -0700
commitf559236bdf9103c5f88d8dfc098f3afe3de64e4a (patch)
treed2a3d5df9ebe9b4ff9143a751a5bbca0b21d296a
parente2a0b4407305cdcd35ea8ff727c7080872050ff7 (diff)
downloadmu-f559236bdf9103c5f88d8dfc098f3afe3de64e4a.tar.gz
6152 - fix regression in factorial.mu
I had to amend commit 6148 three times yesterday as I kept finding bugs
by inspection. And yet I stubbornly thought I didn't need a test.
-rwxr-xr-xapps/mubin207490 -> 210747 bytes
-rw-r--r--apps/mu.subx102
2 files changed, 100 insertions, 2 deletions
diff --git a/apps/mu b/apps/mu
index d76a48d8..17916ee9 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index fa967d63..f78f6bbb 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -2865,6 +2865,68 @@ test-convert-function-call-with-arg-of-user-defined-type:
     5d/pop-to-ebp
     c3/return
 
+test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
+    # . 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 f {\n")
+    (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
+    (write _test-input-stream "  foo *a\n")
+    (write _test-input-stream "}\n")
+    (write _test-input-stream "fn foo x: t {\n")
+    (write _test-input-stream "}\n")
+    (write _test-input-stream "type t {\n")
+    (write _test-input-stream "  x: int\n")
+    (write _test-input-stream "  y: int\n")
+    (write _test-input-stream "}\n")
+    # convert
+    (convert-mu _test-input-buffered-file _test-output-buffered-file)
+    (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 "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
+    (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")
+    (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
+    (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
+    # var a
+    (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")
+    (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")
+    # foo a
+    (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")
+    #
+    (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")
+    (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
+    (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
+    (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")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
+    (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
+    (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
+    (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
+    (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")
+    (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
+    (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")
+    (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
+    (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 # we don't have special support for call-by-reference; just explicitly create
 # a new variable with the address of the arg
 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
@@ -6542,6 +6604,41 @@ $size-of:end:
     5d/pop-to-ebp
     c3/return
 
+size-of-deref:  # v: (handle var) -> result/eax: int
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    # var t/ecx: (handle tree type-id) = v->type
+    8b/-> *(ebp+8) 1/r32/ecx
+    8b/-> *(ecx+4) 1/r32/ecx  # Var-type
+    # TODO: assert(t is an addr)
+    8b/-> *(ecx+4) 1/r32/ecx  # Tree-right
+    # if is-mu-array?(t) return size-of-array(t)
+    {
+      (is-mu-array? %ecx)  # => eax
+      3d/compare-eax-and 0/imm32/false
+      74/jump-if-= break/disp8
+      (size-of-array %ecx)  # => eax
+      eb/jump $size-of:end/disp8
+    }
+    # if (t->left >= *Max-type-id) t = t->left
+    {
+      8b/-> *Max-type-id 0/r32/eax
+      39/compare *ecx 0/r32/eax  # Tree-left
+      72/jump-if-addr< break/disp8
+      8b/-> *ecx 1/r32/ecx  # Tree-left
+    }
+    (size-of-type-id *ecx)  # Atom-left => eax
+$size-of-deref:end:
+    # . restore registers
+    59/pop-to-ecx
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 is-mu-array?:  # t: (handle tree type-id) -> result/eax: boolean
     # . prologue
     55/push-ebp
@@ -10021,8 +10118,9 @@ emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (hand
     56/push-esi
     # esi = v
     8b/-> *(ebp+0xc) 6/r32/esi
-    # var size/ecx: int = size-of(v)
-    (size-of %esi)  # => eax
+    # var size/ecx: int = size-of-deref(v)
+    (size-of-deref %esi)  # => eax
+    89/<- %ecx 0/r32/eax
     # TODO: assert size is a multiple of 4
     # var i/eax: int = 0
     b8/copy-to-eax 0/imm32