diff options
-rwxr-xr-x | apps/mu | bin | 577078 -> 579317 bytes | |||
-rw-r--r-- | apps/mu.subx | 200 |
2 files changed, 188 insertions, 12 deletions
diff --git a/apps/mu b/apps/mu index 70e8a1ca..8ebf2cb3 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index 0859e2d4..b47de2a6 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -7689,6 +7689,51 @@ test-copy-null-value-to-offset: 5d/pop-to-ebp c3/return +test-copy-non-literal-to-byte: + # . 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) + (clear-stream _test-error-stream) + (clear-stream $_test-error-buffered-file->buffer) + # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 68/push 0/imm32 + 68/push 0/imm32 + 89/<- %edx 4/r32/esp + (tailor-exit-descriptor %edx 0x10) + # + (write _test-input-stream "fn foo {\n") + (write _test-input-stream " var x/ecx: int <- copy 3\n") + (write _test-input-stream " var y/ecx: byte <- copy x\n") + (write _test-input-stream "}\n") + # convert + (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + # registers except esp clobbered at this point + # restore ed + 89/<- %edx 4/r32/esp + (flush _test-output-buffered-file) + (flush _test-error-buffered-file) +#? # dump _test-error-stream {{{ +#? (write 2 "^") +#? (write-stream 2 _test-error-stream) +#? (write 2 "$\n") +#? (rewind-stream _test-error-stream) +#? # }}} + # check output + (check-stream-equal _test-output-stream "" "F - test-copy-non-literal-to-byte: output should be empty") + (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") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + test-copy-deref-address: # . prologue 55/push-ebp @@ -8164,6 +8209,52 @@ test-copy-to-null-value-to-offset: 5d/pop-to-ebp c3/return +test-copy-to-non-literal-to-byte: + # . 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) + (clear-stream _test-error-stream) + (clear-stream $_test-error-buffered-file->buffer) + # var ed/edx: exit-descriptor = tailor-exit-descriptor(16) + 68/push 0/imm32 + 68/push 0/imm32 + 89/<- %edx 4/r32/esp + (tailor-exit-descriptor %edx 0x10) + # + (write _test-input-stream "fn foo {\n") + (write _test-input-stream " var x/ecx: int <- copy 3\n") + (write _test-input-stream " var y/eax: (addr byte) <- copy 0\n") + (write _test-input-stream " copy-to *y, x\n") + (write _test-input-stream "}\n") + # convert + (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx) + # registers except esp clobbered at this point + # restore ed + 89/<- %edx 4/r32/esp + (flush _test-output-buffered-file) + (flush _test-error-buffered-file) +#? # dump _test-error-stream {{{ +#? (write 2 "^") +#? (write-stream 2 _test-error-stream) +#? (write 2 "$\n") +#? (rewind-stream _test-error-stream) +#? # }}} + # check output + (check-stream-equal _test-output-stream "" "F - test-copy-to-non-literal-to-byte: output should be empty") + (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") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + test-copy-to-deref-address: # . prologue 55/push-ebp @@ -20545,6 +20636,22 @@ check-mu-primitive: # stmt: (addr stmt), fn: (addr function), err: (addr buffer (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) e9/jump $check-mu-primitive:end/disp32 } + # if (op == "copy-byte") check-mu-copy-byte-stmt + { + (string-equal? %ecx "copy-byte") # => eax + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= break/disp8 + (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) + e9/jump $check-mu-primitive:end/disp32 + } + # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt + { + (string-equal? %ecx "copy-byte-to") # => eax + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= break/disp8 + (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) + e9/jump $check-mu-primitive:end/disp32 + } # if (op == "compare") check-mu-compare-stmt { (string-equal? %ecx "compare") # => eax @@ -20893,11 +21000,6 @@ $is-mu-numberlike-output?:check-boolean: (is-simple-mu-type? %esi 5) # boolean => eax 3d/compare-eax-and 0/imm32/false 75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8 -$is-mu-numberlike-output?:check-byte: - # if t is a byte, return - (is-simple-mu-type? %esi 8) # byte => eax - 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= $is-mu-numberlike-output?:return-true/disp8 $is-mu-numberlike-output?:check-code-point: # if t is a code-point, return (is-simple-mu-type? %esi 0xd) # code-point => eax @@ -21026,6 +21128,20 @@ $check-mu-copy-stmt:types: (string-equal? %eax "0") # => eax 3d/compare-eax-and 0/imm32/false 74/jump-if-= break/disp8 + e9/jump $check-mu-copy-stmt:end/disp32 + } + # if output is a byte, abort if inout is not a literal. Otherwise return. + { + (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax + (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax + (is-simple-mu-type? %eax 8) # byte => eax + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= break/disp8 + (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax + (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax + (is-simple-mu-type? %eax 0) # literal => eax + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32 eb/jump $check-mu-copy-stmt:end/disp8 } # if output is not number-like, abort @@ -21112,6 +21228,20 @@ $check-mu-copy-stmt:error-inout-too-large: (stop *(ebp+0x14) 1) # never gets here +$check-mu-copy-stmt:error-non-literal-to-byte: + (write-buffered *(ebp+0x10) "fn ") + 8b/-> *(ebp+0xc) 0/r32/eax + (lookup *eax *(eax+4)) # Function-name Function-name => eax + (write-buffered *(ebp+0x10) %eax) + (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '") + (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax + (lookup *eax *(eax+4)) # Var-name Var-name => eax + (write-buffered *(ebp+0x10) %eax) + (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + check-mu-copy-to-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) # . prologue 55/push-ebp @@ -21183,15 +21313,18 @@ $check-mu-copy-to-stmt:types: (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax 89/<- %ebx 0/r32/eax # if (dest->is-deref?) dest-type = dest-type->payload +$check-mu-copy-to-stmt:check-dest-deref: 8b/-> *(edi+0x10) 0/r32/eax # Stmt-var-is-deref 3d/compare-eax-and 0/imm32/false { 74/jump-if-= break/disp8 (lookup *(ebx+0xc) *(ebx+0x10)) # Type-tree-right Type-tree-right => eax +$check-mu-copy-to-stmt:dest-is-deref: # if dest-type->right is null, dest-type = dest-type->left 81 7/subop/compare *(eax+0xc) 0/imm32 # Type-tree-right { 75/jump-if-!= break/disp8 +$check-mu-copy-to-stmt:dest-is-deref2: (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax } 89/<- %ebx 0/r32/eax @@ -21202,9 +21335,8 @@ $check-mu-copy-to-stmt:types: 0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32 # if dest is an addr and src is 0, return { - (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax - (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax - (is-mu-addr-type? %eax) # => eax +$check-mu-copy-to-stmt:final-check-addr: + (is-mu-addr-type? %ebx) # => eax 3d/compare-eax-and 0/imm32/false 74/jump-if-= break/disp8 (lookup *esi *(esi+4)) # Stmt-var-value Stmt-var-value => eax @@ -21216,11 +21348,10 @@ $check-mu-copy-to-stmt:types: } # if dest is an offset and src is 0, return { - (lookup *edi *(edi+4)) # Stmt-var-value Stmt-var-value => eax - (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax - 81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom +$check-mu-copy-to-stmt:final-check-offset: + 81 7/subop/compare *ebx 0/imm32/false # Type-tree-is-atom 75/jump-if-!= break/disp8 - (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax + (lookup *(ebx+4) *(ebx+8)) # Type-tree-left Type-tree-left => eax (is-simple-mu-type? %eax 7) # offset => eax 3d/compare-eax-and 0/imm32/false 74/jump-if-= break/disp8 @@ -21229,6 +21360,17 @@ $check-mu-copy-to-stmt:types: (string-equal? %eax "0") # => eax 3d/compare-eax-and 0/imm32/false 74/jump-if-= break/disp8 + e9/jump $check-mu-copy-to-stmt:end/disp32 + } + # if dest is a byte, abort if src is not a literal. Otherwise return. + { +$check-mu-copy-to-stmt:final-check-byte: + (is-simple-mu-type? %ebx 8) # byte => eax + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= break/disp8 + (is-simple-mu-type? %ecx 0) # literal => eax + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32 eb/jump $check-mu-copy-to-stmt:end/disp8 } # if dest is not number-like, abort @@ -21292,6 +21434,40 @@ $check-mu-copy-to-stmt:error-src-too-large: (stop *(ebp+0x14) 1) # never gets here +$check-mu-copy-to-stmt:error-non-literal-to-byte: + (write-buffered *(ebp+0x10) "fn ") + 8b/-> *(ebp+0xc) 0/r32/eax + (lookup *eax *(eax+4)) # Function-name Function-name => eax + (write-buffered *(ebp+0x10) %eax) + (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + +check-mu-copy-byte-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers +$check-mu-copy-byte-stmt:end: + # . restore registers + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +check-mu-copy-byte-to-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers +$check-mu-copy-byte-to-stmt:end: + # . restore registers + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + check-mu-compare-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) # . prologue 55/push-ebp |