From f58a6acc3f744de683037f81be857ec59162e01c Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 28 Jun 2020 00:55:31 -0700 Subject: 6579 --- apps/mu.subx | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 5 deletions(-) (limited to 'apps/mu.subx') diff --git a/apps/mu.subx b/apps/mu.subx index 8fa9c6de..b5ce6562 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -378,7 +378,7 @@ Tree-size: # (addr int) # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs. Type-id: # (stream (addr array byte)) - 0x20/imm32/write + 0/imm32/write # initialized later from Primitive-type-ids 0/imm32/read 0x100/imm32/size # data @@ -400,6 +400,9 @@ Type-id: # (stream (addr array byte)) 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +Primitive-type-ids: # (addr int) + 0x24 + # == Type definitions # Program->types contains some typeinfo for each type definition. # Types contain vars with types, but can't specify registers. @@ -473,9 +476,12 @@ convert-mu: # in: (addr buffered-file), out: (addr buffered-file), err: (addr b # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax # initialize global data structures c7 0/subop/copy *Next-block-index 1/imm32 - c7 0/subop/copy *Type-id 0x24/imm32 # stream-write + 8b/-> *Primitive-type-ids 0/r32/eax + 89/<- *Type-id 0/r32/eax # stream-write c7 0/subop/copy *_Program-functions 0/imm32 c7 0/subop/copy *_Program-functions->payload 0/imm32 c7 0/subop/copy *_Program-types 0/imm32 @@ -487,6 +493,8 @@ convert-mu: # in: (addr buffered-file), out: (addr buffered-file), err: (addr b (check-mu-types *(ebp+0x10) *(ebp+0x14)) (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) $convert-mu:end: + # . restore registers + 58/pop-to-eax # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp @@ -4816,7 +4824,101 @@ test-get-with-wrong-field: (check-stream-equal _test-output-stream "" "F - test-get-with-wrong-field: output should be empty") (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: type 't' has no member called 'y'" "F - test-get-with-wrong-field: error message") # check that stop(1) was called - (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status") + (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: 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-base-type: + # . 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 c/ecx: (addr int) <- get a, y\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-get-with-wrong-base-type: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: var 'a' must have a 'type' definition" "F - test-get-with-wrong-base-type: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: 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-offset-type: + # . 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: t\n") + (write _test-input-stream " var b: int\n") + (write _test-input-stream " var c/ecx: (addr int) <- get a, b\n") + (write _test-input-stream "}\n") + (write _test-input-stream "type t {\n") + (write _test-input-stream " x: 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-get-with-wrong-offset-type: output should be empty") + (check-next-stream-line-equal _test-error-stream "fn foo: stmt get: type 't' has no member called 'b'" "F - test-get-with-wrong-offset-type: error message") + # check that stop(1) was called + (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status") # don't restore from ebp 81 0/subop/add %esp 8/imm32 # . epilogue @@ -8732,6 +8834,22 @@ $container-type:end: 5d/pop-to-ebp c3/return +is-container?: # t: type-id -> result/eax: boolean + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # + 8b/-> *(ebp+8) 0/r32/eax + c1/shift 4/subop/left %eax 2/imm8 + 3b/compare 0/r32/eax *Primitive-type-ids + 0f 9d/set-if->= %al + 81 4/subop/and %eax 0xff/imm32 +$is-container?:end: + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + find-or-create-typeinfo: # t: type-id, out: (addr handle typeinfo) # . prologue 55/push-ebp @@ -9949,6 +10067,11 @@ check-mu-get-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffere # var base/ebx: (addr stmt-var) = stmt->inouts->value (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax 89/<- %ebx 0/r32/eax + # if base is a non-container, error + (container-type %ebx) # => eax + (is-container? %eax) # => eax + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $check-mu-get-stmt:error1/disp32 # TODO: check >1 inouts # var offset/ecx: (addr var) = stmt->inouts->next->value (lookup *(esi+0xc) *(esi+0x10)) # Stmt1-inouts Stmt1-inouts => eax @@ -9956,7 +10079,7 @@ check-mu-get-stmt: # stmt: (addr stmt), fn: (addr function), err: (addr buffere (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax 89/<- %ecx 0/r32/eax 81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized # Var-offset - 74/jump-if-= $check-mu-get-stmt:abort/disp8 + 0f 84/jump-if-= $check-mu-get-stmt:error2/disp32 # TODO: check >0 outputs # var output/edi: (addr var) = stmt->outputs->value (lookup *(esi+0x14) *(esi+0x18)) # Stmt1-outputs Stmt1-outputs => eax @@ -9975,7 +10098,22 @@ $check-mu-get-stmt:end: 5d/pop-to-ebp c3/return -$check-mu-get-stmt:abort: +$check-mu-get-stmt:error1: + # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n") + (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 get: var '") + (lookup *ebx *(ebx+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) "' must have a 'type' definition\n") + (flush *(ebp+0x10)) + (stop *(ebp+0x14) 1) + # never gets here + +$check-mu-get-stmt:error2: # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n") (write-buffered *(ebp+0x10) "fn ") 8b/-> *(ebp+0xc) 0/r32/eax -- cgit 1.4.1-2-gfad0