diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-11-15 13:11:43 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-11-15 13:18:38 -0800 |
commit | 0e0a60013d392b5b3920781ec04c3b6a1a061bbb (patch) | |
tree | 84020a10143fcc5cae440ac891603ea58e7d02c9 | |
parent | e996502f013f7b7060156b54feae5d9850aaf048 (diff) | |
download | mu-0e0a60013d392b5b3920781ec04c3b6a1a061bbb.tar.gz |
7238 - mu.subx: final restrictions on 'addr'
I had to tweak one app that wasn't following the rules.
-rw-r--r-- | 115write-byte.subx | 12 | ||||
-rwxr-xr-x | apps/assort | bin | 46549 -> 46677 bytes | |||
-rwxr-xr-x | apps/braces | bin | 48604 -> 48732 bytes | |||
-rw-r--r-- | apps/browse/main.mu | 17 | ||||
-rwxr-xr-x | apps/calls | bin | 53599 -> 53727 bytes | |||
-rwxr-xr-x | apps/crenshaw2-1 | bin | 45890 -> 46018 bytes | |||
-rwxr-xr-x | apps/crenshaw2-1b | bin | 46437 -> 46565 bytes | |||
-rwxr-xr-x | apps/dquotes | bin | 50171 -> 50299 bytes | |||
-rwxr-xr-x | apps/factorial | bin | 45000 -> 45128 bytes | |||
-rwxr-xr-x | apps/hex | bin | 48729 -> 48857 bytes | |||
-rwxr-xr-x | apps/mu | bin | 554858 -> 559546 bytes | |||
-rw-r--r-- | apps/mu.subx | 339 | ||||
-rwxr-xr-x | apps/pack | bin | 59239 -> 59367 bytes | |||
-rwxr-xr-x | apps/sigils | bin | 60973 -> 61101 bytes | |||
-rwxr-xr-x | apps/survey | bin | 56481 -> 56609 bytes | |||
-rwxr-xr-x | apps/tests | bin | 45340 -> 45468 bytes |
16 files changed, 354 insertions, 14 deletions
diff --git a/115write-byte.subx b/115write-byte.subx index 4fe793a8..0a4e3c7d 100644 --- a/115write-byte.subx +++ b/115write-byte.subx @@ -439,8 +439,16 @@ _test-error-stream: # (stream byte) # current read index 0/imm32 # line - 0x80/imm32 # 128 bytes - # data (8 lines x 16 bytes/line) + 0x100/imm32 # 256 bytes + # data (16 lines x 16 bytes/line) + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/apps/assort b/apps/assort index 3fa27b27..ee69e7e4 100755 --- a/apps/assort +++ b/apps/assort Binary files differdiff --git a/apps/braces b/apps/braces index ae630053..cd098220 100755 --- a/apps/braces +++ b/apps/braces Binary files differdiff --git a/apps/browse/main.mu b/apps/browse/main.mu index d2510071..91eb46e0 100644 --- a/apps/browse/main.mu +++ b/apps/browse/main.mu @@ -19,20 +19,13 @@ fn main args-on-stack: (addr array addr array byte) -> _/ebx: int { return 0 # TODO: get at Num-test-failures somehow } # otherwise interactive mode - var result/ebx: int <- interactive args-on-stack - return result -} - -fn interactive _args: (addr array addr array byte) -> _/ebx: int { - # initialize fs from args[1] - var args/eax: (addr array addr array byte) <- copy _args + var args/eax: (addr array addr array byte) <- copy args-on-stack var arg/eax: (addr addr array byte) <- index args, 1 var filename/eax: (addr array byte) <- copy *arg var file-storage: (handle buffered-file) var file-storage-addr/esi: (addr handle buffered-file) <- address file-storage open filename, 0, file-storage-addr - var _fs/eax: (addr buffered-file) <- lookup file-storage - var fs/esi: (addr buffered-file) <- copy _fs + var fs/eax: (addr buffered-file) <- lookup file-storage # if no file, exit { compare fs, 0 @@ -41,6 +34,11 @@ fn interactive _args: (addr array addr array byte) -> _/ebx: int { return 1 } # + interactive fs + return 0 +} + +fn interactive fs: (addr buffered-file) { enable-screen-grid-mode enable-keyboard-immediate-mode # initialize screen state @@ -57,7 +55,6 @@ fn interactive _args: (addr array addr array byte) -> _/ebx: int { } enable-keyboard-type-mode enable-screen-type-mode - return 0 } fn render screen: (addr paginated-screen), fs: (addr buffered-file) { diff --git a/apps/calls b/apps/calls index 1ddfd3a3..440185ca 100755 --- a/apps/calls +++ b/apps/calls Binary files differdiff --git a/apps/crenshaw2-1 b/apps/crenshaw2-1 index 40497b3e..5a88adb7 100755 --- a/apps/crenshaw2-1 +++ b/apps/crenshaw2-1 Binary files differdiff --git a/apps/crenshaw2-1b b/apps/crenshaw2-1b index 91686feb..95447807 100755 --- a/apps/crenshaw2-1b +++ b/apps/crenshaw2-1b Binary files differdiff --git a/apps/dquotes b/apps/dquotes index a8fb2e13..69183207 100755 --- a/apps/dquotes +++ b/apps/dquotes Binary files differdiff --git a/apps/factorial b/apps/factorial index 7b3d9a28..7040ea3e 100755 --- a/apps/factorial +++ b/apps/factorial Binary files differdiff --git a/apps/hex b/apps/hex index c5b05406..22db822a 100755 --- a/apps/hex +++ b/apps/hex Binary files differdiff --git a/apps/mu b/apps/mu index 12d13375..89e061ff 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index 69d85941..4301a5fc 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -845,6 +845,243 @@ test-function-with-inout-in-register: 5d/pop-to-ebp c3/return +test-function-with-addr-output: + # . 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 -> _/eax: (addr int) {\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-function-with-addr-output: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function" "F - test-function-with-addr-output: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-function-with-addr-inout: + # . 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 a: (addr addr int) {\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-function-with-addr-inout: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function" "F - test-function-with-addr-inout: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-function-with-addr-inout-2: + # . 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 a: (addr array addr int) {\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-function-with-addr-inout-2: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function" "F - test-function-with-addr-inout-2: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-function-with-addr-inout-3: + # . 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 a: (addr array (addr int) 3) {\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-function-with-addr-inout-3: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function" "F - test-function-with-addr-inout-3: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +test-function-with-addr-inout-4: + # . 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 a: (array (addr int) 3) {\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-function-with-addr-inout-4: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function" "F - test-function-with-addr-inout-4: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status") + # don't restore from ebp + 81 0/subop/add %esp 8/imm32 + # . epilogue + 5d/pop-to-ebp + c3/return + +# 'main' is an exception +test-function-main-with-addr-inout: + # . 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 main a: (addr addr int) {\n") + (write _test-input-stream "}\n") + # convert + (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0) + (flush _test-output-buffered-file) + # no errors + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + test-convert-function-with-arg-and-body: # . prologue 55/push-ebp @@ -14178,11 +14415,23 @@ $populate-mu-function-header:check-for-inout: 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 # v = parse-var-with-type(word-slice, first-line) (parse-var-with-type %ecx *(ebp+8) %ebx *(ebp+0x14) *(ebp+0x18)) - # assert(v->register == null) + # if (v->register != null) abort # . eax: (addr var) = lookup(v) (lookup *ebx *(ebx+4)) # => eax 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 + # if function name is "main" + # and v->type contains an 'addr' anywhere except the start, abort + { + (lookup *edi *(edi+4)) # Function-name Function-name => eax + (string-equal? %eax "main") # => eax + 3d/compare-eax-and 0/imm32/false + 75/jump-if-!= break/disp8 + (lookup *ebx *(ebx+4)) # => eax + (addr-payload-contains-addr? %eax) # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32 + } # v->block-depth is implicitly 0 # # out->inouts = append(v, out->inouts) @@ -14222,11 +14471,17 @@ $populate-mu-function-header:check-for-out: (lookup *ebx *(ebx+4)) # => eax 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 - # assert(var->name == "_") + # if (var->name != "_") abort (lookup *eax *(eax+4)) # Var-name Var-name => eax (string-equal? %eax "_") # => eax 3d/compare-eax-and 0/imm32/false 0f 84/jump-if-= $populate-mu-function-header:error4/disp32 + # if v->type is an addr, abort + (lookup *ebx *(ebx+4)) # => eax + (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax + (is-mu-addr-type? %eax) # => eax + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32 # out->outputs = append(v, out->outputs) 8d/copy-address *(edi+0x10) 0/r32/eax # Function-outputs (append-list Heap *ebx *(ebx+4) *(edi+0x10) *(edi+0x14) %eax) # Function-outputs, Function-outputs @@ -14330,6 +14585,32 @@ $populate-mu-function-header:error-loop: (stop *(ebp+0x18) 1) # never gets here +$populate-mu-function-header:error-addr-output: + # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function") + (write-buffered *(ebp+0x14) "fn ") + 50/push-eax + (lookup *edi *(edi+4)) # Function-name Function-name => eax + (write-buffered *(ebp+0x14) %eax) + 58/pop-to-eax + (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + +$populate-mu-function-header:error-nested-addr-inout: + # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function") + (write-buffered *(ebp+0x14) "fn ") + (lookup *edi *(edi+4)) # Function-name Function-name => eax + (write-buffered *(ebp+0x14) %eax) + (write-buffered *(ebp+0x14) ": inout '") + (lookup *ebx *(ebx+4)) # => eax + (lookup *eax *(eax+4)) # Var-name Var-name => eax + (write-buffered *(ebp+0x14) %eax) + (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n") + (flush *(ebp+0x14)) + (stop *(ebp+0x18) 1) + # never gets here + # scenarios considered: # ✓ fn foo # ✗ fn foo { @@ -14558,6 +14839,60 @@ $populate-mu-function-signature:error-loop: (stop *(ebp+0x18) 1) # never gets here +addr-payload-contains-addr?: # v: (addr var) -> result/eax: boolean + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # var t/eax: (addr type-tree) = v->type + 8b/-> *(ebp+8) 0/r32/eax + (lookup *(eax+8) *(eax+0xc)) # Var-type Var-type => eax + # if t->right contains addr, return true + (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax + (type-tree-contains? %eax 2) # addr => eax + # we don't have to look at t->left as long as it's guaranteed to be an atom +$addr-payload-contains-addr?:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +type-tree-contains?: # t: (addr type-tree), n: type-id -> result/eax: boolean + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 51/push-ecx + # if t is null, return false + 8b/-> *(ebp+8) 0/r32/eax + 3d/compare-eax-and 0/imm32 + 0f 84/jump-if-= $type-tree-contains?:end/disp32 # eax changes type + # if t is an atom, return (t->value == n) + 81 7/subop/compare *eax 0/imm32/false + { + 74/jump-if-= break/disp8 + 8b/-> *(ebp+0xc) 1/r32/ecx + 39/compare *(eax+4) 1/r32/ecx # Type-tree-value + 0f 94/set-if-= %al + 81 4/subop/and %eax 0xff/imm32 + eb/jump $type-tree-contains?:end/disp8 + } + # if t->left contains n, return true + (lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax + (type-tree-contains? %eax *(ebp+0xc)) # => eax + 3d/compare-eax-and 0/imm32/false + 75/jump-if-!= $type-tree-contains?:end/disp8 + # otherwise return whether t->right contains n + 8b/-> *(ebp+8) 0/r32/eax + (lookup *(eax+0xc) *(eax+0x10)) # Type-tree-right Type-tree-right => eax + (type-tree-contains? %eax *(ebp+0xc)) # => eax +$type-tree-contains?:end: + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + function-exists?: # s: (addr slice) -> result/eax: boolean # . prologue 55/push-ebp diff --git a/apps/pack b/apps/pack index 07884e8b..29e59e58 100755 --- a/apps/pack +++ b/apps/pack Binary files differdiff --git a/apps/sigils b/apps/sigils index 640c4317..3300a975 100755 --- a/apps/sigils +++ b/apps/sigils Binary files differdiff --git a/apps/survey b/apps/survey index 27bde944..1adeef7c 100755 --- a/apps/survey +++ b/apps/survey Binary files differdiff --git a/apps/tests b/apps/tests index 7d8e0c27..b606df1d 100755 --- a/apps/tests +++ b/apps/tests Binary files differ |