7145 - roll back to 7143
This commit is contained in:
parent
264acd9ec9
commit
8c44afcccc
263
apps/mu.subx
263
apps/mu.subx
|
@ -2606,7 +2606,58 @@ test-always-shadow-outermost-reg-vars-in-function:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-shadow-local:
|
||||
_pending-test-clobber-dead-local:
|
||||
# . 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 foo {\n")
|
||||
(write _test-input-stream " var x/ecx: int <- copy 3\n")
|
||||
(write _test-input-stream " {\n")
|
||||
(write _test-input-stream " var y/ecx: int <- copy 4\n")
|
||||
(write _test-input-stream " }\n")
|
||||
(write _test-input-stream "}\n")
|
||||
# convert
|
||||
(convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
|
||||
(flush _test-output-buffered-file)
|
||||
#? # dump _test-output-stream {{{
|
||||
#? (write 2 "^")
|
||||
#? (write-stream 2 _test-output-stream)
|
||||
#? (write 2 "$\n")
|
||||
#? (rewind-stream _test-output-stream)
|
||||
#? # }}}
|
||||
# check output
|
||||
(check-next-stream-line-equal _test-output-stream "foo:" "F - test-clobber-dead-local/0")
|
||||
(check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-clobber-dead-local/1")
|
||||
(check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-clobber-dead-local/2")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-clobber-dead-local/3")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-clobber-dead-local/4")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-clobber-dead-local/5")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-clobber-dead-local/6")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-clobber-dead-local/7")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-clobber-dead-local/8")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-clobber-dead-local/9")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-clobber-dead-local/10") # no push/pop here
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-clobber-dead-local/11")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-clobber-dead-local/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-clobber-dead-local/13")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-clobber-dead-local/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-clobber-dead-local/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-clobber-dead-local/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-clobber-dead-local/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-clobber-dead-local/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-clobber-dead-local/19")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-shadow-live-local:
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -2633,29 +2684,29 @@ test-shadow-local:
|
|||
#? (rewind-stream _test-output-stream)
|
||||
#? # }}}
|
||||
# check output
|
||||
(check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-local/0")
|
||||
(check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-local/1")
|
||||
(check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-local/2")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-local/3")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-local/4")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-local/5")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-local/6")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-local/7")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-local/8")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-local/9")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-local/10")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-local/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-local/12")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-local/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-local/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-local/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-local/16")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-local/17")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-local/18")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-local/19")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-local/20")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-local/21")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-local/22")
|
||||
(check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-live-local/0")
|
||||
(check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-live-local/1")
|
||||
(check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-live-local/2")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-live-local/3")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-local/4")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-live-local/5")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-local/6")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-live-local/7")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-local/8")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-live-local/9")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-local/10")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-live-local/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-local/12")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-local/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-live-local/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-live-local/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-local/16")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-local/17")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-live-local/18")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-live-local/19")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-live-local/20")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-live-local/21")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-live-local/22")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -2871,7 +2922,7 @@ test-spill-different-register-in-block:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-shadow-output:
|
||||
test-shadow-live-output:
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -2898,27 +2949,27 @@ test-shadow-output:
|
|||
#? (rewind-stream _test-output-stream)
|
||||
#? # }}}
|
||||
# check output
|
||||
(check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-output/0")
|
||||
(check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-output/1")
|
||||
(check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-output/2")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-output/3")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-output/4")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-output/5")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-output/7") # no push because it's an output reg
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-output/8")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-output/9")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-output/10")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-output/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-output/12")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-output/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-output/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-output/15")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-output/17")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-output/18")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-output/19")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-output/20")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-output/21")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-output/21")
|
||||
(check-next-stream-line-equal _test-output-stream "foo:" "F - test-shadow-live-output/0")
|
||||
(check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-shadow-live-output/1")
|
||||
(check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-shadow-live-output/2")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-shadow-live-output/3")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-output/4")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-shadow-live-output/5")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-shadow-live-output/7") # no push because it's an output reg
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-shadow-live-output/8")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-shadow-live-output/9")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-shadow-live-output/10")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-shadow-live-output/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-shadow-live-output/12")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-output/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-shadow-live-output/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-shadow-live-output/15")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-shadow-live-output/17")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-shadow-live-output/18")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-shadow-live-output/19")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-shadow-live-output/20")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-shadow-live-output/21")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-shadow-live-output/21")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -2997,16 +3048,14 @@ test-local-clobbered-by-fn-output:
|
|||
(check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-local-clobbered-by-fn-output/3")
|
||||
(check-next-stream-line-equal _test-output-stream " {" "F - test-local-clobbered-by-fn-output/4")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-local-clobbered-by-fn-output/5")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-local-clobbered-by-fn-output/6")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-local-clobbered-by-fn-output/7")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ecx 0x00000001/r32" "F - test-local-clobbered-by-fn-output/8")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-local-clobbered-by-fn-output/9") # not a pop because there's already a function output in the reg
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-local-clobbered-by-fn-output/10")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-local-clobbered-by-fn-output/11")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-local-clobbered-by-fn-output/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-local-clobbered-by-fn-output/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-local-clobbered-by-fn-output/14")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-local-clobbered-by-fn-output/15")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 4/imm32" "F - test-local-clobbered-by-fn-output/6") # no push because it's an output reg
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %ecx 0x00000001/r32" "F - test-local-clobbered-by-fn-output/7")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-local-clobbered-by-fn-output/8")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-local-clobbered-by-fn-output/9")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-local-clobbered-by-fn-output/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-local-clobbered-by-fn-output/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-local-clobbered-by-fn-output/12")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-local-clobbered-by-fn-output/13")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -18536,7 +18585,7 @@ $emit-subx-stmt-list:zero-arg-unconditional-loop:
|
|||
# unconditional loops with a target
|
||||
{
|
||||
0f 84/jump-if-= break/disp32
|
||||
(emit-subx-cleanup-and-unconditional-nonlocal-branch *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14))
|
||||
(emit-subx-cleanup-and-unconditional-nonlocal-branch *(ebp+8) %ecx *(ebp+0x10))
|
||||
e9/jump $emit-subx-stmt-list:clean-up/disp32
|
||||
}
|
||||
}
|
||||
|
@ -18553,7 +18602,7 @@ $emit-subx-stmt-list:unconditional-break:
|
|||
# simple unconditional breaks without a target
|
||||
0f 84/jump-if-= $emit-subx-stmt-list:emit-cleanup/disp32 # easy: just skip remaining statements
|
||||
# unconditional breaks with a target
|
||||
(emit-subx-cleanup-and-unconditional-nonlocal-branch *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14))
|
||||
(emit-subx-cleanup-and-unconditional-nonlocal-branch *(ebp+8) %ecx *(ebp+0x10))
|
||||
e9/jump $emit-subx-stmt-list:clean-up/disp32
|
||||
}
|
||||
# }}}
|
||||
|
@ -18605,7 +18654,7 @@ $emit-subx-stmt-list:conditional-branch-with-target:
|
|||
ff 0/subop/increment *Curr-block-depth
|
||||
#
|
||||
(emit-reverse-break *(ebp+8) %ecx)
|
||||
(emit-subx-cleanup-and-unconditional-nonlocal-branch *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14))
|
||||
(emit-subx-cleanup-and-unconditional-nonlocal-branch *(ebp+8) %ecx *(ebp+0x10))
|
||||
# cleanup epilogue
|
||||
ff 1/subop/decrement *Curr-block-depth
|
||||
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||
|
@ -18637,7 +18686,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
|
||||
(push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x18) *(ebp+0x1c))
|
||||
(push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
|
||||
# emit the instruction as usual
|
||||
(emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x18) *(ebp+0x1c))
|
||||
#
|
||||
|
@ -18650,7 +18699,7 @@ $emit-subx-stmt-list:continue:
|
|||
e9/jump loop/disp32
|
||||
}
|
||||
$emit-subx-stmt-list:emit-cleanup:
|
||||
(emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
|
||||
(emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
|
||||
$emit-subx-stmt-list:clean-up:
|
||||
(clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
|
||||
(clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
|
||||
|
@ -18666,7 +18715,7 @@ $emit-subx-stmt-list:end:
|
|||
c3/return
|
||||
|
||||
# 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
|
||||
push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
|
||||
push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -18695,11 +18744,16 @@ push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-
|
|||
# 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
|
||||
# var emit-spill?/edx: boolean = not-yet-spilled-this-block?(v, vars)
|
||||
# var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
|
||||
(not-yet-spilled-this-block? %ecx *(ebp+0x10)) # => eax
|
||||
89/<- %edx 0/r32/eax
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
|
||||
(will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18)) # => eax
|
||||
89/<- %edx 0/r32/eax
|
||||
# check emit-spill?
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
|
||||
# TODO: assert(size-of(output) == 4)
|
||||
# *Curr-local-stack-offset -= 4
|
||||
81 5/subop/subtract *Curr-local-stack-offset 4/imm32
|
||||
|
@ -18725,14 +18779,14 @@ $push-output-and-maybe-emit-spill:end:
|
|||
|
||||
$push-output-and-maybe-emit-spill:abort:
|
||||
# error("var '" var->name "' initialized from an instruction must live in a register\n")
|
||||
(write-buffered *(ebp+0x18) "var '")
|
||||
(write-buffered *(ebp+0x18) *eax) # Var-name
|
||||
(write-buffered *(ebp+0x18) "' initialized from an instruction must live in a register\n")
|
||||
(flush *(ebp+0x18))
|
||||
(stop *(ebp+0x1c) 1)
|
||||
(write-buffered *(ebp+0x1c) "var '")
|
||||
(write-buffered *(ebp+0x1c) *eax) # Var-name
|
||||
(write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
|
||||
(flush *(ebp+0x1c))
|
||||
(stop *(ebp+0x20) 1)
|
||||
# never gets here
|
||||
|
||||
emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var), fn: (addr function)
|
||||
emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -18746,7 +18800,7 @@ emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file
|
|||
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
||||
(lookup *eax *(eax+4)) # Var-name Var-name => eax
|
||||
# clean up until target block
|
||||
(emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax *(ebp+0x14))
|
||||
(emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
|
||||
# emit jump to target block
|
||||
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||
(write-buffered *(ebp+8) "e9/jump ")
|
||||
|
@ -18930,7 +18984,7 @@ $emit-unconditional-jump-to-depth:end:
|
|||
|
||||
# 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-until-depth: # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
|
||||
emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -18978,7 +19032,8 @@ $emit-cleanup-code-until-depth:check-for-previous-spill:
|
|||
3d/compare-eax-and 0/imm32/false
|
||||
74/jump-if-= break/disp8
|
||||
$emit-cleanup-code-until-depth:reclaim-var-in-register:
|
||||
(emit-pop-register *(ebp+8) %ebx *(ebp+0xc) *(ebp+0x14))
|
||||
(lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax
|
||||
(emit-pop-register *(ebp+8) %eax)
|
||||
}
|
||||
eb/jump $emit-cleanup-code-until-depth:continue/disp8
|
||||
}
|
||||
|
@ -19050,21 +19105,16 @@ $emit-push-register:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
emit-pop-register: # out: (addr buffered-file), regvar: (addr var), vars: (addr stack live-var), fn: (addr function)
|
||||
emit-pop-register: # out: (addr buffered-file), reg: (addr array byte)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
50/push-eax
|
||||
51/push-ecx
|
||||
56/push-esi
|
||||
# esi = regvar
|
||||
8b/-> *(ebp+0xc) 6/r32/esi
|
||||
# var reg/ecx: (addr array byte) = lookup(regvar->register)
|
||||
(lookup *(esi+0x18) *(esi+0x1c)) # Var-register Var-register => eax
|
||||
89/<- %ecx 0/r32/eax
|
||||
# eax = reg
|
||||
8b/-> *(ebp+0xc) 0/r32/eax
|
||||
# var prefix/eax: byte = reg->data[0]
|
||||
8a/copy-byte *(ecx+4) 0/r32/AL
|
||||
8a/copy-byte *(eax+4) 0/r32/AL
|
||||
81 4/subop/and %eax 0xff/imm32
|
||||
# if (prefix == 'x') pop to xmm register
|
||||
{
|
||||
|
@ -19074,7 +19124,8 @@ emit-pop-register: # out: (addr buffered-file), regvar: (addr var), vars: (addr
|
|||
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||
(write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
|
||||
# var prefix/eax: byte = reg->data[3]
|
||||
8a/copy-byte *(ecx+7) 0/r32/AL
|
||||
8b/-> *(ebp+0xc) 0/r32/eax
|
||||
8a/copy-byte *(eax+7) 0/r32/AL
|
||||
81 4/subop/and %eax 0xff/imm32
|
||||
(write-byte-buffered *(ebp+8) %eax)
|
||||
(write-buffered *(ebp+8) "/x32\n")
|
||||
|
@ -19085,12 +19136,10 @@ emit-pop-register: # out: (addr buffered-file), regvar: (addr var), vars: (addr
|
|||
# otherwise pop to gp register
|
||||
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||
(write-buffered *(ebp+8) "8f 0/subop/pop %")
|
||||
(write-buffered *(ebp+8) %ecx)
|
||||
(write-buffered *(ebp+8) *(ebp+0xc))
|
||||
(write-buffered *(ebp+8) Newline)
|
||||
$emit-pop-register:end:
|
||||
# . restore registers
|
||||
5e/pop-to-esi
|
||||
59/pop-to-ecx
|
||||
58/pop-to-eax
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
|
@ -19099,7 +19148,7 @@ $emit-pop-register:end:
|
|||
|
||||
# emit clean-up code for 'vars' until a given label is encountered
|
||||
# doesn't actually modify 'vars' so we need traverse manually inside the stack
|
||||
emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte), fn: (addr function)
|
||||
emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -19139,7 +19188,8 @@ $emit-cleanup-code-until-target:check-for-previous-spill:
|
|||
3d/compare-eax-and 0/imm32/false
|
||||
74/jump-if-= break/disp8
|
||||
$emit-cleanup-code-until-target:reclaim-var-in-register:
|
||||
(emit-pop-register *(ebp+8) %ebx *(ebp+0xc) *(ebp+0x14))
|
||||
(lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax
|
||||
(emit-pop-register *(ebp+8) %eax)
|
||||
}
|
||||
eb/jump $emit-cleanup-code-until-target:continue/disp8
|
||||
}
|
||||
|
@ -19319,6 +19369,35 @@ $not-yet-spilled-this-block?:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# could the register of 'v' ever be written to by one of the vars in fn-outputs?
|
||||
will-not-write-some-register?: # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# eax = v
|
||||
8b/-> *(ebp+8) 0/r32/eax
|
||||
# var reg/eax: (addr array byte) = lookup(v->register)
|
||||
(lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax
|
||||
# var target/eax: (addr var) = find-register(fn-outputs, reg)
|
||||
(find-register *(ebp+0x10) %eax) # => eax
|
||||
# if (target == 0) return true
|
||||
{
|
||||
3d/compare-eax-and 0/imm32
|
||||
75/jump-if-!= break/disp8
|
||||
b8/copy-to-eax 1/imm32/true
|
||||
eb/jump $will-not-write-some-register?:end/disp8
|
||||
}
|
||||
# return !assigns-in-stmts?(stmts, target)
|
||||
(assigns-in-stmts? *(ebp+0xc) %eax) # => eax
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
# assume: true = 1, so no need to mask with 0x000000ff
|
||||
0f 94/set-if-= %al
|
||||
$will-not-write-some-register?:end:
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# return fn output with matching register
|
||||
# always returns false if 'reg' is null
|
||||
find-register: # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
|
||||
|
@ -19538,8 +19617,14 @@ $same-register-spilled-before?:end:
|
|||
# This would be a simple series of pops, if it wasn't for fn outputs, which
|
||||
# can occur anywhere in the stack.
|
||||
# So we have to _compact_ the entire array underlying the stack.
|
||||
# If a register already contains a function output, we drop the var to avoid
|
||||
# clobbering it.
|
||||
#
|
||||
# We want to allow a fn output register to be written to by locals before the
|
||||
# output is set.
|
||||
# So fn outputs can't just be pushed at the start of the function.
|
||||
#
|
||||
# We want to allow other locals to shadow a fn output register after the
|
||||
# output is set.
|
||||
# So the output can't just always override anything in the stack. Sequence matters.
|
||||
clean-up-blocks: # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
|
||||
# pseudocode:
|
||||
# to = vars->top (which points outside the stack)
|
||||
|
|
Loading…
Reference in New Issue