diff options
author | Kartik Agaram <vc@akkartik.com> | 2020-05-06 22:55:18 -0700 |
---|---|---|
committer | Kartik Agaram <vc@akkartik.com> | 2020-05-18 00:44:48 -0700 |
commit | b101712767a4db8c7c27358d3fae0b290df17f89 (patch) | |
tree | 970fc4f4e68eb4f8e8459903d24644fdf56c8bff | |
parent | ac01980addebc8d76471a4213b4113ad3493f513 (diff) | |
download | mu-b101712767a4db8c7c27358d3fae0b290df17f89.tar.gz |
mu.subx: spilling register for reg vars
-rw-r--r-- | 092stack.subx | 3 | ||||
-rw-r--r-- | apps/mu.subx | 39 |
2 files changed, 22 insertions, 20 deletions
diff --git a/092stack.subx b/092stack.subx index 5b015ea9..b49b00fb 100644 --- a/092stack.subx +++ b/092stack.subx @@ -1,6 +1,9 @@ # A stack looks like this: # top: int # data: (array byte) # prefixed by size as usual +# +# TODO: is it confusing that the push opcodes grow memory downward, but the +# push function grows stacks upward? == code # instruction effective address register displacement immediate diff --git a/apps/mu.subx b/apps/mu.subx index e8f78aba..2e60edf5 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -7426,9 +7426,7 @@ $emit-subx-stmt-list:check-for-reg-var-def: 0f 85/jump-if-!= break/disp32 $emit-subx-stmt-list:reg-var-def: # TODO: ensure that there's exactly one output - (compute-reg-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10)) - # register variable definition - (push *(ebp+0x10) %eax) + (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10)) # emit the instruction as usual (emit-subx-stmt *(ebp+8) %ecx Primitives) # var-seen? = true @@ -7456,8 +7454,7 @@ $emit-subx-stmt-list:end: 5d/pop-to-ebp c3/return -# TODO -compute-reg-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), out: (addr handle var) +push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -7465,32 +7462,34 @@ compute-reg-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg- 51/push-ecx # ecx = stmt 8b/-> *(ebp+0xc) 1/r32/ecx - # var output/ecx: (handle var) = curr-stmt->outputs->value - 8b/-> *(ecx+0xc) 1/r32/ecx # Regvardef-inouts - 8b/-> *ecx 1/r32/ecx # List-value + # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs) + (lookup *(ecx+0x14) *(ecx+0x18)) # Regvardef-outputs Regvardef-outputs => eax + # push(vars, sv->value) + (push *(ebp+0x10) *eax) # Stmt-var-value + (push *(ebp+0x10) *(eax+4)) # Stmt-var-value + # var v/ecx: (addr var) = lookup(sv->value) + (lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax + 89/<- %ecx 0/r32/eax # v->block-depth = *Curr-block-depth 8b/-> *Curr-block-depth 0/r32/eax - 89/<- *(ecx+8) 0/r32/eax # Var-block-depth - # var reg/eax: (handle array byte) = output->register - 8b/-> *(ecx+0x10) 0/r32/eax # Var-register - # ensure that output is in a register - 3d/compare-eax-and 0/imm32 - 0f 84/jump-if-= $compute-reg-and-maybe-emit-spill:abort/disp32 + 89/<- *(ecx+0x10) 0/r32/eax # Var-block-depth + # ensure that v is in a register + 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register + 0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32 # if already-spilled-this-block?(reg, vars) return (already-spilled-this-block? %ecx *(ebp+0x10)) # => eax 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= $compute-reg-and-maybe-emit-spill:end/disp8 + 75/jump-if-!= $push-output-and-maybe-emit-spill:end/disp8 # TODO: assert(size-of(output) == 4) # *Curr-local-stack-offset -= 4 81 5/subop/subtract *Curr-local-stack-offset 4/imm32 # emit spill (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "ff 6/subop/push %") - (write-buffered *(ebp+8) *(ecx+0x10)) # Var-register + (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax + (write-buffered *(ebp+8) %eax) (write-buffered *(ebp+8) Newline) -$compute-reg-and-maybe-emit-spill:end: - # return output - 89/<- %eax 1/r32/ecx +$push-output-and-maybe-emit-spill:end: # . restore registers 59/pop-to-ecx # . epilogue @@ -7498,7 +7497,7 @@ $compute-reg-and-maybe-emit-spill:end: 5d/pop-to-ebp c3/return -$compute-reg-and-maybe-emit-spill:abort: +$push-output-and-maybe-emit-spill:abort: # error("var '" var->name "' initialized from an instruction must live in a register\n") (write-buffered Stderr "var '") (write-buffered Stderr *eax) # Var-name |