diff options
-rwxr-xr-x | apps/mu | bin | 336039 -> 338359 bytes | |||
-rw-r--r-- | apps/mu.subx | 165 |
2 files changed, 165 insertions, 0 deletions
diff --git a/apps/mu b/apps/mu index 880fbdfd..2561389a 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index 5309a417..9ded880c 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -4783,6 +4783,98 @@ test-convert-get-on-function-argument-with-known-type: 5d/pop-to-ebp c3/return +test-add-with-too-many-inouts: + # . 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 a: int\n") + (write _test-input-stream " var b/ecx: int <- add a, 0\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-add-with-too-many-inouts: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: too many inouts; most primitives support at most two arguments, across inouts and outputs" "F - test-add-with-too-many-inouts: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-add-with-too-many-outputs: + # . 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 a/eax: int <- copy 0\n") + (write _test-input-stream " var b/ebx: int <- copy 0\n") + (write _test-input-stream " var c/ecx: int <- copy 0\n") + (write _test-input-stream " c, b <- add a\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-add-with-too-many-outputs: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: stmt add: too many outputs; most primitives support at most one output" "F - test-add-with-too-many-outputs: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + test-get-with-wrong-field: # . prologue 55/push-ebp @@ -10555,13 +10647,86 @@ check-mu-numberlike-primitive: # stmt: (addr stmt), fn: (addr function), err: ( 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers + 50/push-eax + 51/push-ecx + 56/push-esi + # esi = stmt + 8b/-> *(ebp+8) 6/r32/esi + # var gas/ecx: int = 2 + b9/copy-to-ecx 2/imm32 + # - check at most 1 output + # var output/edi: (addr var) = stmt->outputs->value + (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax + { + 3d/compare-eax-and 0/imm32 + 0f 84/jump-if-= break/disp32 + 89/<- %edi 0/r32/eax + (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax + 3d/compare-eax-and 0/imm32 + 0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32 + # check output is in a register + # --gas + 49/decrement-ecx + } + # - check first inout + (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax + { + 3d/compare-eax-and 0/imm32 + 0f 84/jump-if-= break/disp32 + 81 7/subop/compare %ecx 0/imm32 + 0f 84/jump-if-= break/disp32 + # --gas + 49/decrement-ecx + } + # - check second inout + (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax + { + 3d/compare-eax-and 0/imm32 + 0f 84/jump-if-= break/disp32 + (lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax + 3d/compare-eax-and 0/imm32 + 0f 84/jump-if-= break/disp32 + # is a second inout allowed? + 81 7/subop/compare %ecx 0/imm32 + 0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32 + } + # check types are one of literal, int, boolean $check-mu-numberlike-primitive:end: # . restore registers + 5e/pop-to-esi + 59/pop-to-ecx + 58/pop-to-eax # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return +$check-mu-numberlike-primitive:error-too-many-inouts: + (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 ") + (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax + (write-buffered *(ebp+0x10) %eax) + (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + +$check-mu-numberlike-primitive:error-too-many-outputs: + (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 ") + (lookup *(esi+4) *(esi+8)) # Stmt1-operation Stmt1-operation => eax + (write-buffered *(ebp+0x10) %eax) + (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + check-mu-copy-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor) # . prologue 55/push-ebp |