about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xapps/mubin183373 -> 182906 bytes
-rw-r--r--apps/mu.subx157
2 files changed, 91 insertions, 66 deletions
diff --git a/apps/mu b/apps/mu
index 314f2383..8c30c331 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx
index 191c94b3..4a4bde35 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -327,9 +327,9 @@ Var-name:  # (handle array byte)
   0/imm32
 Var-type:  # (handle tree type-id)
   4/imm32
-Var-block-depth:  # int
+Var-block-depth:  # int -- not available until code-generation time
   8/imm32
-Var-offset:  # int
+Var-offset:  # int -- not available until code-generation time
   0xc/imm32
 Var-register:  # (handle array byte) -- name of a register
   0x10/imm32
@@ -2748,7 +2748,6 @@ populate-mu-function-header:  # first-line: (addr stream byte), out: (handle fun
     #   next-mu-token(first-line, name)
     #   assert(name not in '{' '}' '->')
     #   out->name = slice-to-string(name)
-    #   var next-offset: int = 8
     #   ## inouts
     #   while true
     #     ## name
@@ -2758,8 +2757,6 @@ populate-mu-function-header:  # first-line: (addr stream byte), out: (handle fun
     #     assert(name != '}')
     #     var v: (handle var) = parse-var-with-type(name, first-line)
     #     assert(v->register == null)
-    #     v->stack-offset = next-offset
-    #     next-offset += size-of(v)
     #     # v->block-depth is implicitly 0
     #     out->inouts = append(out->inouts, v)
     #     push(vars, v)
@@ -2788,8 +2785,6 @@ populate-mu-function-header:  # first-line: (addr stream byte), out: (handle fun
     68/push 0/imm32/end
     68/push 0/imm32/start
     89/<- %ecx 4/r32/esp
-    # var next-offset/edx = 8
-    ba/copy-to-edx 8/imm32
     # read function name
     (next-mu-token *(ebp+8) %ecx)
     # error checking
@@ -2833,11 +2828,6 @@ $populate-mu-function-header:check-for-inout:
       # assert(v->register == null)
       81 7/subop/compare *(ebx+0x10) 0/imm32  # Var-register
       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
-      # v->stack-offset = next-offset
-      89/<- *(ebx+0xc) 2/r32/edx  # Var-offset
-      # next-offset += size-of(v)
-      (size-of %ebx)  # => eax
-      01/add %edx 0/r32/eax
       # v->block-depth is implicitly 0
       #
       # out->inouts = append(out->inouts, v)
@@ -4056,9 +4046,6 @@ populate-mu-function-body:  # in: (addr buffered-file), out: (handle function),
     8b/-> *(ebp+8) 6/r32/esi
     # edi = out
     8b/-> *(ebp+0xc) 7/r32/edi
-    # initialize some global state
-    c7 0/subop/copy *Curr-block-depth 1/imm32
-    c7 0/subop/copy *Next-local-stack-offset -4/imm32
     # var eax: (handle block) = parse-mu-block(in, vars, fn)
     (parse-mu-block %esi *(ebp+0x10) %edi)  # => eax
     # out->body = eax
@@ -4073,26 +4060,11 @@ $populate-mu-function-body:end:
     5d/pop-to-ebp
     c3/return
 
-== data
-
-# Global state added to each var record when parsing a function
-
-Curr-block-depth:  # (addr int)
-    0/imm32
-Next-local-stack-offset:  # (addr int)
-    -4/imm32
-
-Next-block-index:  # (addr int)
-    1/imm32
-
-== code
-
 # parses a block, assuming that the leading '{' has already been read by the caller
 parse-mu-block:  # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block)
     # pseudocode:
     #   var line: (stream byte 512)
     #   var word-slice: slice
-    #   increment *Curr-block-depth
     #   result/eax = allocate(Heap, Stmt-size)
     #   result->tag = 0/block
     #   result->name = some unique name
@@ -4122,7 +4094,6 @@ parse-mu-block:  # in: (addr buffered-file), vars: (addr stack (handle var)), fn
     #     else
     #       stmt = parse-mu-stmt(line, vars, fn)
     #       append-to-block(result, stmt)
-    #   decrement *Curr-block-depth
     #   return result
     #
     # . prologue
@@ -4154,8 +4125,6 @@ parse-mu-block:  # in: (addr buffered-file), vars: (addr stack (handle var)), fn
     89/<- *(edi+8) 0/r32/eax  # Block-var
     # push result->var to vars
     (push *(ebp+0xc) %eax)
-    # increment *Curr-block-depth
-    ff 0/subop/increment *Curr-block-depth
     {
 $parse-mu-block:line-loop:
       # line = read-line-buffered(in)
@@ -4240,8 +4209,6 @@ $parse-mu-block:regular-stmt:
       (append-to-block Heap %edi %eax)
       e9/jump loop/disp32
     } # end line loop
-    # decrement *Curr-block-depth
-    ff 1/subop/decrement *Curr-block-depth
     #
     (pop *(ebp+0xc))  # => eax
     # return result
@@ -4327,6 +4294,14 @@ $new-block-name:end:
     5d/pop-to-ebp
     c3/return
 
+== data
+
+# Global state added to each var record when parsing a function
+Next-block-index:  # (addr int)
+    1/imm32
+
+== code
+
 check-no-tokens-left:  # line: (addr stream byte)
     # . prologue
     55/push-ebp
@@ -4377,7 +4352,6 @@ $check-no-tokens-left:end:
 parse-mu-named-block:  # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt)
     # pseudocode:
     #   var v: (handle var) = new-literal(name)
-    #   v->block-depth = *Curr-block-depth  # containing block depth
     #   push(vars, v)
     #   result = parse-mu-block(in, vars, fn)
     #   pop(vars)
@@ -4427,9 +4401,6 @@ parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack (handle var)) -
     (next-mu-token *(ebp+8) %ecx)
     (parse-var-with-type %ecx *(ebp+8))  # => eax
     89/<- %edx 0/r32/eax
-    # v->block-depth = *Curr-block-depth
-    8b/-> *Curr-block-depth 0/r32/eax
-    89/<- *(edx+8) 0/r32/eax
     #
     (push *(ebp+0xc) %edx)
     # either v has no register and there's no more to this line
@@ -4437,9 +4408,6 @@ parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack (handle var)) -
     3d/compare-eax-and 0/imm32
     {
       75/jump-if-!= break/disp8
-      # v->stack-offset = *Next-local-stack-offset
-      8b/-> *Next-local-stack-offset 0/r32/eax
-      89/<- *(edx+0xc) 0/r32/eax  # Var-offset
       # TODO: ensure that there's nothing else on this line
       (new-var-def Heap %edx)  # => eax
       eb/jump $parse-mu-var-def:end/disp8
@@ -4457,11 +4425,6 @@ parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack (handle var)) -
       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc))
     }
 $parse-mu-var-def:end:
-    # *Next-local-stack-offset -= size-of(v)
-    50/push-eax
-    (size-of %edx)  # => eax
-    29/subtract-from *Next-local-stack-offset 0/r32/eax
-    58/pop-to-eax
     # . reclaim locals
     81 0/subop/add %esp 8/imm32
     # . restore registers
@@ -4494,8 +4457,6 @@ test-parse-mu-var-def:
     # setup
     (clear-stream _test-input-stream)
     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
-    c7 0/subop/copy *Curr-block-depth 1/imm32
-    c7 0/subop/copy *Next-local-stack-offset -4/imm32
     # var vars/ecx: (stack (addr var) 4)
     81 5/subop/subtract %esp 0x10/imm32
     68/push 0x10/imm32/length
@@ -4509,14 +4470,10 @@ test-parse-mu-var-def:
     8b/-> *(eax+4) 0/r32/eax  # Vardef-var
     (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name")  # Var-name
     (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
-    (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
-    (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset")  # Var-offset
     # ensure type is int
     8b/-> *(eax+4) 0/r32/eax  # Var-type
     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Tree-left
     (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0")  # Tree-right
-    # globals
-    (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -4530,8 +4487,6 @@ test-parse-mu-reg-var-def:
     # setup
     (clear-stream _test-input-stream)
     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
-    c7 0/subop/copy *Curr-block-depth 1/imm32
-    c7 0/subop/copy *Next-local-stack-offset -4/imm32
     # var vars/ecx: (stack (addr var) 4)
     81 5/subop/subtract %esp 0x10/imm32
     68/push 0x10/imm32/length
@@ -4547,14 +4502,10 @@ test-parse-mu-reg-var-def:
     8b/-> *eax 0/r32/eax  # Stmt-var-value
     (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
     (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register")  # Var-register
-    (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
-    (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset")  # Var-offset
     # ensure type is int
     8b/-> *(eax+4) 0/r32/eax  # Var-type
     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Tree-left
     (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0")  # Tree-right
-    # globals
-    (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset")
     # . epilogue
     89/<- %esp 5/r32/ebp
     5d/pop-to-ebp
@@ -5201,9 +5152,6 @@ new-literal:  # ad: (addr allocation-descriptor), name: (addr slice) -> result/e
     (new-var *(ebp+8) %ecx)  # => eax
     # result->type = type
     89/<- *(eax+4) 2/r32/edx  # Var-type
-    # result->block-depth = *Curr-block-depth
-    8b/-> *Curr-block-depth 1/r32/ecx
-    89/<- *(eax+8) 1/r32/ecx  # Var-block-depth
 $new-literal:end:
     # . restore registers
     5a/pop-to-edx
@@ -6138,6 +6086,15 @@ $type-equal?:end:
 # Code-generation
 #######################################################
 
+== data
+
+Curr-block-depth:  # (addr int)
+    0/imm32
+Next-local-stack-offset:  # (addr int)
+    -4/imm32
+
+== code
+
 emit-subx:  # out: (addr buffered-file)
     # . prologue
     55/push-ebp
@@ -6173,6 +6130,8 @@ emit-subx-function:  # out: (addr buffered-file), f: (handle function)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
+    # some preprocessing
+    (populate-mu-type-offsets-in-inouts *(ebp+0xc))
     # . save registers
     50/push-eax
     51/push-ecx
@@ -6190,12 +6149,15 @@ emit-subx-function:  # out: (addr buffered-file), f: (handle function)
     #
     (write-buffered %edi *ecx)
     (write-buffered %edi ":\n")
-    # Important: each block's depth during code-generation should be identical
-    # to what it was during parsing.
+    # initialize some global state
     c7 0/subop/copy *Curr-block-depth 1/imm32
+    c7 0/subop/copy *Next-local-stack-offset -4/imm32
+    #
     (emit-subx-prologue %edi)
     (emit-subx-block %edi *(ecx+0x10) %edx)  # Function-body
     (emit-subx-epilogue %edi)
+    # TODO: validate that *Curr-block-depth and *Next-local-stack-offset have
+    # been cleaned up
 $emit-subx-function:end:
     # . reclaim locals
     81 0/subop/add %esp 408/imm32
@@ -6209,6 +6171,48 @@ $emit-subx-function:end:
     5d/pop-to-ebp
     c3/return
 
+populate-mu-type-offsets-in-inouts:  # f: (handle function)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    51/push-ecx
+    52/push-edx
+    53/push-ebx
+    57/push-edi
+    # var next-offset/edx: int = 8
+    ba/copy-to-edx 8/imm32
+    # var curr/ecx: (handle list var) = f->inouts
+    8b/-> *(ebp+8) 1/r32/ecx
+    8b/-> *(ecx+8) 1/r32/ecx  # Function-inouts
+    {
+$populate-mu-type-offsets-in-inouts:loop:
+      81 7/subop/compare %ecx 0/imm32
+      74/jump-if-= break/disp8
+      # var v/ebx: (handle var) = curr->value
+      8b/-> *ecx 3/r32/ebx  # List-value
+      # v->offset = next-offset
+      89/<- *(ebx+0xc) 2/r32/edx  # Var-offset
+      # next-offset += size-of(v)
+      (size-of %ebx)  # => eax
+      01/add %edx 0/r32/eax
+      # curr = curr->next
+      8b/-> *(ecx+4) 1/r32/ecx  # List-next
+      eb/jump loop/disp8
+    }
+$populate-mu-type-offsets-in-inouts:end:
+    # . restore registers
+    5f/pop-to-edi
+    5b/pop-to-ebx
+    5a/pop-to-edx
+    59/pop-to-ecx
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 emit-subx-stmt-list:  # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var))
     # . prologue
     55/push-ebp
@@ -6408,6 +6412,9 @@ compute-reg-and-maybe-emit-spill:  # out: (addr buffered-file), stmt: (handle re
     # var output/ecx: (handle var) = curr-stmt->outputs->value
     8b/-> *(ecx+0xc) 1/r32/ecx  # Regvardef-inouts
     8b/-> *ecx 1/r32/ecx  # List-value
+    # v->block-depth = *Curr-block-depth
+    8b/-> *Curr-block-depth 0/r32/eax
+    89/<- *(ecx+8) 0/r32/eax  # Var-block-depth
     # var reg/eax: (handle array byte) = output->register
     8b/-> *(ecx+0x10) 0/r32/eax  # Var-register
     # ensure that output is in a register
@@ -6417,6 +6424,9 @@ compute-reg-and-maybe-emit-spill:  # out: (addr buffered-file), stmt: (handle re
     (already-spilled-this-block? %ecx *(ebp+0x10))  # => eax
     3d/compare-eax-and 0/imm32/false
     75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8
+    # TODO: assert(sizeof(output) == 4)
+    # *Next-local-stack-offset -= 4
+    81 5/subop/subtract *Next-local-stack-offset 4/imm32
     # emit spill
     (emit-indent *(ebp+8) *Curr-block-depth)
     (write-buffered *(ebp+8) "ff 6/subop/push %")
@@ -6981,8 +6991,18 @@ emit-subx-var-def:  # out: (addr buffered-file), stmt: (handle stmt)
     51/push-ecx
     # eax = stmt
     8b/-> *(ebp+0xc) 0/r32/eax
+    # var v/ecx: (handle var)
+    8b/-> *(eax+4) 1/r32/ecx
+    # v->offset = *Next-local-stack-offset
+    8b/-> *Next-local-stack-offset 0/r32/eax
+    89/<- *(ecx+0xc) 0/r32/eax  # Var-offset
+    # v->block-depth = *Curr-block-depth
+    8b/-> *Curr-block-depth 0/r32/eax
+    89/<- *(ecx+8) 0/r32/eax  # Var-block-depth
     # var n/eax: int = size-of(stmt->var)
-    (size-of *(eax+4))  # Vardef-var => eax
+    (size-of %ecx)  # Vardef-var => eax
+    # *Next-local-stack-offset -= n
+    29/subtract-from *Next-local-stack-offset 0/r32/eax
     # while n > 0
     {
       3d/compare-eax-with 0/imm32
@@ -7421,6 +7441,10 @@ emit-subx-block:  # out: (addr buffered-file), block: (handle block), vars: (add
     56/push-esi
     # esi = block
     8b/-> *(ebp+0xc) 6/r32/esi
+    # block->var->block-depth = *Curr-block-depth
+    8b/-> *(esi+8) 0/r32/eax  # Block-var
+    8b/-> *Curr-block-depth 1/r32/ecx
+    89/<- *(eax+8) 1/r32/ecx  # Var-block-depth
     # var stmts/eax: (handle list stmt) = block->statements
     8b/-> *(esi+4) 0/r32/eax  # Block-stmts
     #
@@ -7430,8 +7454,9 @@ $emit-subx-block:check-empty:
       0f 84/jump-if-= break/disp32
       (emit-indent *(ebp+8) *Curr-block-depth)
       (write-buffered *(ebp+8) "{\n")
-      # var v/ecx: (addr array byte) = block->var->name
+      # var v/ecx: (handle var)
       8b/-> *(esi+8) 1/r32/ecx  # Block-var
+      #
       (write-buffered *(ebp+8) *ecx)  # Var-name
       (write-buffered *(ebp+8) ":loop:\n")
       ff 0/subop/increment *Curr-block-depth