diff options
-rwxr-xr-x | apps/mu | bin | 147461 -> 147638 bytes | |||
-rw-r--r-- | apps/mu.subx | 120 |
2 files changed, 89 insertions, 31 deletions
diff --git a/apps/mu b/apps/mu index 97a85f1b..3adcc79b 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index 6f63b8f7..12c77243 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -293,9 +293,9 @@ Block-var: # (handle var) Stmt1-operation: # (handle array byte) 4/imm32 -Stmt1-inouts: # (handle list var) +Stmt1-inouts: # (handle stmt-var) 8/imm32 -Stmt1-outputs: # (handle list var) +Stmt1-outputs: # (handle stmt-var) 0xc/imm32 Vardef-var: # (handle var) @@ -303,9 +303,9 @@ Vardef-var: # (handle var) Regvardef-operation: # (handle array byte) 4/imm32 -Regvardef-inouts: # (handle list var) +Regvardef-inouts: # (handle stmt-var) 8/imm32 -Regvardef-outputs: # (handle list var) # will have exactly one element +Regvardef-outputs: # (handle stmt-var) # will have exactly one element 0xc/imm32 Stmt-size: # (addr int) @@ -337,6 +337,16 @@ List-next: List-size: # (addr int) 8/imm32 +# A stmt-var is like a list of vars with call-site specific metadata +Stmt-var-value: # (handle var) + 0/imm32 +Stmt-var-next: # (handle stmt-var) + 4/imm32 +Stmt-var-is-deref: # boolean + 8/imm32 +Stmt-var-size: # (addr int) + 0xc/imm32 + # Types are expressed as trees (s-expressions) of type-ids (ints). # However, there's no need for singletons, so we can assume (int) == int # - if x->right == nil, x is an atom @@ -3739,7 +3749,7 @@ test-parse-mu-reg-var-def: (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next - 8b/-> *eax 0/r32/eax # List-value + 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 @@ -3773,11 +3783,14 @@ parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx + 52/push-edx 57/push-edi # var name/ecx: slice 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp + # var is-deref?: boolean = false + ba/copy-to-edx 0/imm32/false # result/edi: (handle stmt) (allocate Heap *Stmt-size) # => eax (zero-out %eax *Stmt-size) @@ -3793,20 +3806,32 @@ $parse-mu-stmt:read-outputs: # name = next-mu-token(line) (next-mu-token *(ebp+8) %ecx) # if slice-empty?(word-slice) break - (slice-empty? %ecx) + (slice-empty? %ecx) # => eax 3d/compare-eax-and 0/imm32/false 0f 85/jump-if-!= break/disp32 # if (name == "<-") break - (slice-equal? %ecx "<-") + (slice-equal? %ecx "<-") # => eax 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= break/disp8 + 0f 85/jump-if-!= break/disp32 + # is-deref? = false + ba/copy-to-edx 0/imm32/false + # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? + 8b/-> *ecx 0/r32/eax # Slice-start + 8a/copy-byte *eax 0/r32/AL + 81 4/subop/and %eax 0xff/imm32 + 3d/compare-eax-and 0x2a/imm32/asterisk + { + 75/jump-if-!= break/disp8 + ff 0/subop/increment *ecx + ba/copy-to-edx 1/imm32/true + } # assert(is-identifier?(name)) - (is-identifier? %ecx) + (is-identifier? %ecx) # => eax 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 - # + # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax - (append-list Heap %eax *(edi+0xc)) # Stmt1-outputs => eax + (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs e9/jump loop/disp32 } @@ -3819,6 +3844,7 @@ $parse-mu-stmt:end: 81 0/subop/add %esp 8/imm32 # . restore registers 5f/pop-to-edi + 5a/pop-to-edx 59/pop-to-ecx # . epilogue 89/<- %esp 5/r32/ebp @@ -4199,7 +4225,7 @@ test-parse-mu-stmt: # edx: (handle list var) = result->inouts 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts # ebx: (handle var) = result->inouts->value - 8b/-> *edx 3/r32/ebx # List-value + 8b/-> *edx 3/r32/ebx # Stmt-var-value (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name # . epilogue 89/<- %esp 5/r32/ebp @@ -4235,7 +4261,7 @@ test-parse-mu-stmt-with-comma: # edx: (handle list var) = result->inouts 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts # ebx: (handle var) = result->inouts->value - 8b/-> *edx 3/r32/ebx # List-value + 8b/-> *edx 3/r32/ebx # Stmt-var-value (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name # . epilogue 89/<- %esp 5/r32/ebp @@ -4464,7 +4490,7 @@ $new-regvardef:end: 5d/pop-to-ebp c3/return -new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list _type) -> result/eax: (handle list _type) +append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -4472,11 +4498,28 @@ new-list: # ad: (addr allocation-descriptor), value: _type, next: (handle list 51/push-ecx # (allocate *(ebp+8) *List-size) # => eax + (zero-out %eax *List-size) 8b/-> *(ebp+0xc) 1/r32/ecx 89/<- *eax 1/r32/ecx # List-value + # if (list == null) return result + 81 7/subop/compare *(ebp+0x10) 0/imm32 + 74/jump-if-= $append-list:end/disp8 + # otherwise append + # var curr/ecx = list 8b/-> *(ebp+0x10) 1/r32/ecx - 89/<- *(eax+4) 1/r32/ecx # List-next -$new-list:end: + # while (curr->next != null) curr = curr->next + { + 81 7/subop/compare *(ecx+4) 0/imm32 # List-next + 74/jump-if-= break/disp8 + # curr = curr->next + 8b/-> *(ecx+4) 1/r32/ecx + eb/jump loop/disp8 + } + # curr->next = result + 89/<- *(ecx+4) 0/r32/eax + # return list + 8b/-> *(ebp+0x10) 0/r32/eax +$append-list:end: # . restore registers 59/pop-to-ecx # . epilogue @@ -4484,21 +4527,24 @@ $new-list:end: 5d/pop-to-ebp c3/return -append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) +append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx # - (allocate *(ebp+8) *List-size) # => eax + (allocate *(ebp+8) *Stmt-var-size) # => eax + (zero-out %eax *Stmt-var-size) 8b/-> *(ebp+0xc) 1/r32/ecx - 89/<- *eax 1/r32/ecx # List-value + 89/<- *eax 1/r32/ecx # Stmt-var-value + 8b/-> *(ebp+0x14) 1/r32/ecx + 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref # if (list == null) return result 81 7/subop/compare *(ebp+0x10) 0/imm32 - 74/jump-if-= $new-list:end/disp8 + 74/jump-if-= $append-stmt-var:end/disp8 # otherwise append - # var curr/ecx = list + # var curr/ecx: (handle stmt-var) = vars 8b/-> *(ebp+0x10) 1/r32/ecx # while (curr->next != null) curr = curr->next { @@ -4510,9 +4556,9 @@ append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle li } # curr->next = result 89/<- *(ecx+4) 0/r32/eax - # return list + # return vars 8b/-> *(ebp+0x10) 0/r32/eax -$append-list:end: +$append-stmt-var:end: # . restore registers 59/pop-to-ecx # . epilogue @@ -4934,7 +4980,7 @@ emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file 8b/-> *(ebp+0xc) 1/r32/ecx # var target/edx: (addr array byte) = curr-stmt->inouts->value->name 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts - 8b/-> *edx 2/r32/edx # List-value + 8b/-> *edx 2/r32/edx # Stmt-var-value 8b/-> *edx 2/r32/edx # Var-name # clean up until target block (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) @@ -5347,13 +5393,13 @@ $emit-subx-stmt-list:array-length: (write-buffered *(ebp+8) "8b/copy-from *") # inouts[0]->register 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts - 8b/-> *eax 0/r32/eax # List-value + 8b/-> *eax 0/r32/eax # Stmt-var-value (write-buffered *(ebp+8) *(eax+0x10)) # Var-register => eax # (write-buffered *(ebp+8) " ") # outputs[0] "/r32" 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs - 8b/-> *eax 0/r32/eax # List-value + 8b/-> *eax 0/r32/eax # Stmt-var-value (get Registers *(eax+0x10) 8 "Registers") # Var-register => eax (print-int32-buffered *(ebp+8) *eax) (write-buffered *(ebp+8) "/r32\n") @@ -7341,7 +7387,7 @@ $mu-stmt-matches-primitive?:prim-inout-is-null: } # if (curr != curr2) return false { - (operand-matches-primitive? *esi *edi) # => eax + (operand-matches-primitive? %esi *edi) # List-value => eax 3d/compare-eax-and 0/imm32/false 75/jump-if-!= break/disp8 b8/copy-to-eax 0/imm32/false @@ -7383,7 +7429,7 @@ $mu-stmt-matches-primitive?:check-output: } # if (curr != curr2) return false { - (operand-matches-primitive? *esi *edi) # List-value List-value => eax + (operand-matches-primitive? %esi *edi) # List-value => eax 3d/compare-eax-and 0/imm32/false 75/jump-if-!= break/disp8 b8/copy-to-eax 0/imm32 @@ -7409,15 +7455,18 @@ $mu-stmt-matches-primitive?:end: 5d/pop-to-ebp c3/return -operand-matches-primitive?: # var: (handle var), prim-var: (handle var) -> result/eax: boolean +operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers + 51/push-ecx 56/push-esi 57/push-edi - # esi = var - 8b/-> *(ebp+8) 6/r32/esi + # ecx = s + 8b/-> *(ebp+8) 1/r32/ecx + # var var/esi : (handle var) = s->value + 8b/-> *ecx 6/r32/esi # Stmt-var-value # edi = prim-var 8b/-> *(ebp+0xc) 7/r32/edi # if (var->type != prim-var->type) return false @@ -7425,6 +7474,14 @@ operand-matches-primitive?: # var: (handle var), prim-var: (handle var) -> resu 3d/compare-eax-and 0/imm32/false b8/copy-to-eax 0/imm32/false 74/jump-if-= $operand-matches-primitive?:end/disp8 + # if prim-var is in memory and var is in register but dereference, match + { + 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register + 75/jump-if-!= break/disp8 + 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register + 74/jump-if-= break/disp8 + # TODO + } # return false if var->register doesn't match prim-var->register { # if register addresses are equal, it's a match @@ -7452,6 +7509,7 @@ $operand-matches-primitive?:end: # . restore registers 5f/pop-to-edi 5e/pop-to-esi + 59/pop-to-ecx # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp |