diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-02-02 18:41:15 -0800 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-02-02 18:41:15 -0800 |
commit | 6b6b6851cc89994c8546e9b7eff3be4b43641686 (patch) | |
tree | 92992d97c0d3bf833da4b25a4832307ebf2c2f05 | |
parent | 0566c88ff4f8589fa526153fb933242229cc3b8f (diff) | |
download | mu-6b6b6851cc89994c8546e9b7eff3be4b43641686.tar.gz |
5981 - decompose block cleanup into two traversals
Momentarily less efficient, but we will soon need the ability to emit cleanup code without losing all our state.
-rwxr-xr-x | apps/mu | bin | 110559 -> 110722 bytes | |||
-rw-r--r-- | apps/mu.subx | 148 |
2 files changed, 113 insertions, 35 deletions
diff --git a/apps/mu b/apps/mu index b54a5b8d..b254e2e4 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index e598433c..f2326284 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -4251,7 +4251,7 @@ $emit-subx-stmt-list:break: (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "}\n") # return $emit-subx-stmt-list - e9/jump $emit-subx-stmt-list:reclaim-loop/disp32 + e9/jump $emit-subx-stmt-list:cleanup/disp32 } { $emit-subx-stmt-list:check-for-loop: @@ -4304,47 +4304,93 @@ $emit-subx-stmt-list:named-block: 8b/-> *(esi+4) 6/r32/esi # List-next e9/jump loop/disp32 } - # reclaim locals +$emit-subx-stmt-list:cleanup: + (emit-cleanup-code *(ebp+8) *(ebp+0x10) *Curr-block-depth) + (clean-up-blocks *(ebp+0x10) *Curr-block-depth) +$emit-subx-stmt-list:end: + # . restore registers + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/<- %esp 5/r32/ebp + 5d/pop-to-ebp + c3/return + +$emit-subx-stmt-list:abort-regvardef-without-register: + # error("var '" var->name "' initialized from an instruction must live in a register\n") + (write-buffered Stderr "var '") + (write-buffered Stderr *eax) # Var-name + (write-buffered Stderr "' initialized from an instruction must live in a register\n") + (flush Stderr) + # . syscall(exit, 1) + bb/copy-to-ebx 1/imm32 + b8/copy-to-eax 1/imm32/exit + cd/syscall 0x80/imm8 + # never gets here + +# emit clean-up code for 'vars' until some block depth +# doesn't actually modify 'vars' so we need traverse manually inside the stack +emit-cleanup-code: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 53/push-ebx + # ecx = vars + 8b/-> *(ebp+0xc) 1/r32/ecx + # var eax: int = vars->top + 8b/-> *ecx 0/r32/eax + # var min/ecx: (address (handle var)) = vars->data + 81 0/subop/add %ecx 8/imm32 + # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] + 81 5/subop/subtract %eax 4/imm32 + 8d/copy-address *(ecx+eax) 0/r32/eax + # edx = until-block-depth + 8b/-> *(ebp+0x10) 2/r32/edx { -$emit-subx-stmt-list:reclaim-loop: - 8b/-> *(ebp+0x10) 0/r32/eax - 81 7/subop/compare *eax 0/imm32 # Stack-top - 0f 84/jump-if-= break/disp32 - # var v/ecx : (handle var) = top(vars) - (top %eax) # => eax - 89/<- %ecx 0/r32/eax - # if v->block-depth == *Curr-block-depth - 8b/-> *Curr-block-depth 0/r32/eax - 39/compare *(ecx+8) 0/r32/eax # Var-block-depth - 0f 85/jump-if-!= break/disp32 +$emit-cleanup-code:loop: + # if (curr < min) break + 39/compare %eax 1/r32/ecx + 0f 82/jump-if-addr< break/disp32 + # var v/ebx: (handle var) = *curr + 8b/-> *eax 3/r32/ebx + # if (v->block-depth < until-block-depth) break + 39/compare *(ebx+8) 2/r32/edx # Var-block-depth + 0f 8c/jump-if-< break/disp32 # if v is in a register - 81 7/subop/compare *(ecx+0x10) 0/imm32 # Var-register + 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register { 74/jump-if-= break/disp8 -$emit-subx-stmt-list:reclaim-var-in-register: +$emit-cleanup-code:reclaim-var-in-register: (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "8f 0/subop/pop %") - (write-buffered *(ebp+8) *(ecx+0x10)) + (write-buffered *(ebp+8) *(ebx+0x10)) (write-buffered *(ebp+8) Newline) } - # if v is on the stack + # otherwise v is on the stack { 75/jump-if-!= break/disp8 -$emit-subx-stmt-list:reclaim-var-on-stack: - (size-of %ecx) # => eax - 01/add *Next-local-stack-offset 0/r32/eax +$emit-cleanup-code:reclaim-var-on-stack: + 50/push-eax + (size-of %ebx) # => eax (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "81 0/subop/add %esp ") (print-int32-buffered *(ebp+8) %eax) (write-buffered *(ebp+8) "/imm32\n") + 58/pop-to-eax } - # - (pop *(ebp+0x10)) + # curr -= 4 + 2d/subtract-from-eax 4/imm32 e9/jump loop/disp32 } -$emit-subx-stmt-list:end: +$emit-cleanup-code:end: # . restore registers - 5e/pop-to-esi + 5b/pop-to-ebx 5a/pop-to-edx 59/pop-to-ecx 58/pop-to-eax @@ -4353,17 +4399,49 @@ $emit-subx-stmt-list:end: 5d/pop-to-ebp c3/return -$emit-subx-stmt-list:abort-regvardef-without-register: - # error("var '" var->name "' initialized from an instruction must live in a register\n") - (write-buffered Stderr "var '") - (write-buffered Stderr *eax) # Var-name - (write-buffered Stderr "' initialized from an instruction must live in a register\n") - (flush Stderr) - # . syscall(exit, 1) - bb/copy-to-ebx 1/imm32 - b8/copy-to-eax 1/imm32/exit - cd/syscall 0x80/imm8 - # never gets here +# clean up global state for 'vars' until (but excluding) some block depth +clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int + # . prologue + 55/push-ebp + 89/<- %ebp 4/r32/esp + # . save registers + 50/push-eax + 51/push-ecx + 56/push-esi + # esi = vars + 8b/-> *(ebp+8) 6/r32/esi + # ecx = until-block-depth + 8b/-> *(ebp+0xc) 1/r32/ecx + { +$clean-up-blocks:reclaim-loop: + # if (vars->top <= 0) break + 81 7/subop/compare *esi 0/imm32 # Stack-top + 7e/jump-if-<= break/disp8 + # var v/eax : (handle var) = top(vars) + (top %esi) # => eax + # if (v->block-depth < until-block-depth) break + 39/compare *(eax+8) 1/r32/ecx # Var-block-depth + 7c/jump-if-< break/disp8 + # if v is on the stack, update Next-local-stack-offset + 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register + { + 75/jump-if-!= break/disp8 +$clean-up-blocks:reclaim-var-on-stack: + (size-of %eax) # => eax + 01/add *Next-local-stack-offset 0/r32/eax + } + (pop %esi) + e9/jump loop/disp32 + } +$clean-up-blocks: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 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) # . prologue |