7261 - mu.subx: array bounds-checking done
This commit is contained in:
parent
83221b4e21
commit
1696ed831a
|
@ -0,0 +1,84 @@
|
|||
# Helper to check an array's bounds, and to abort if they're violated.
|
||||
# Really only intended to be called from code generated by mu.subx.
|
||||
|
||||
== code
|
||||
|
||||
__check-mu-array-bounds: # index: int, elem-size: int, arr-size: int, function-name: (addr array byte), array-name: (addr array byte)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
50/push-eax
|
||||
51/push-ecx
|
||||
52/push-edx
|
||||
# . not bothering saving ebx; it's only clobbered if we're going to abort
|
||||
# ecx = arr-size
|
||||
8b/-> *(ebp+0x10) 1/r32/ecx
|
||||
# var overflow/edx: int = 0
|
||||
ba/copy-to-edx 0/imm32
|
||||
# var offset/eax: int = index * elem-size
|
||||
8b/-> *(ebp+8) 0/r32/eax
|
||||
f7 4/subop/multiply-eax-with *(ebp+0xc)
|
||||
# check for overflow
|
||||
81 7/subop/compare %edx 0/imm32
|
||||
0f 85/jump-if-!= __check-mu-array-bounds:overflow/disp32
|
||||
# check bounds
|
||||
39/compare %eax 1/r32/ecx
|
||||
0f 82/jump-if-unsigned< $__check-mu-array-bounds:end/disp32 # negative index should always abort
|
||||
# abort if necessary
|
||||
(write-buffered Stderr "fn ")
|
||||
(write-buffered Stderr *(ebp+0x14))
|
||||
(write-buffered Stderr ": offset ")
|
||||
(write-int32-hex-buffered Stderr %eax)
|
||||
(write-buffered Stderr " is too large for array '")
|
||||
(write-buffered Stderr *(ebp+0x18))
|
||||
(write-buffered Stderr "'\n")
|
||||
(flush Stderr)
|
||||
# exit(1)
|
||||
bb/copy-to-ebx 1/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
$__check-mu-array-bounds:end:
|
||||
# . restore registers
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
58/pop-to-eax
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
__check-mu-array-bounds:overflow:
|
||||
# "fn " function-name ": offset to array '" array-name "' overflowed 32 bits\n"
|
||||
(write-buffered Stderr "fn ")
|
||||
(write-buffered Stderr *(ebp+0x14))
|
||||
(write-buffered Stderr ": offset to array '")
|
||||
(write-buffered Stderr *(ebp+0x18))
|
||||
(write-buffered Stderr "' overflowed 32 bits\n")
|
||||
(flush Stderr)
|
||||
# exit(1)
|
||||
bb/copy-to-ebx 1/imm32
|
||||
e8/call syscall_exit/disp32
|
||||
|
||||
# potential alternative
|
||||
|
||||
#? __bounds-check: # msg: (addr array byte)
|
||||
#? (write-buffered Stderr "abort: array bounds exceeded in fn ")
|
||||
#? 8b/-> *(esp+4) 0/r32/eax # we're going to abort, so just clobber away
|
||||
#? (write-buffered Stderr %eax)
|
||||
#? (write-buffered Stderr Newline)
|
||||
#? # exit(1)
|
||||
#? bb/copy-to-ebx 1/imm32
|
||||
#? e8/call syscall_exit/disp32
|
||||
|
||||
# to be called as follows:
|
||||
# var/reg <- index arr/rega: (addr array T), idx/regi: int
|
||||
# | if size-of(T) is 1, 2, 4 or 8
|
||||
# => # temporarily save array size to reg to check bounds
|
||||
# "8b/-> *" rega " " reg "/r32"
|
||||
# "c1/shift 5/subop/right %" reg " " log2(size-of(T)) "/imm32"
|
||||
# "3b/compare " reg "/r32 *" rega
|
||||
# "68/push \"" function "\"/imm32" # pass function name to error message
|
||||
# "0f 8d/jump-if->= __bounds_check/disp32"
|
||||
# "81 0/subop/add %esp 4/imm32" # drop function name
|
||||
# # actually save the index addr in reg
|
||||
# "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"
|
334
apps/mu.subx
334
apps/mu.subx
|
@ -5997,15 +5997,16 @@ test-convert-index-into-array:
|
|||
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array/7")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array/8")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/12")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/14")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/17")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/18")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32" "F - test-convert-index-into-array/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array/13")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array/19")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6046,15 +6047,16 @@ test-convert-index-into-array-of-bytes:
|
|||
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes/7")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes/8")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-of-bytes/9")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes/14")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes/15")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes/16")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes/19")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes/20")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes/13")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes/19")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6092,15 +6094,16 @@ test-convert-index-into-array-with-literal:
|
|||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-with-literal/5")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-with-literal/6")
|
||||
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-with-literal/7")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-with-literal/8")
|
||||
# 2 * 4 bytes/elem + 4 bytes for size = offset 12
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/8")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/9")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/10")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/11")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/14")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x0000000c) 0x00000000/r32" "F - test-convert-index-into-array-with-literal/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-with-literal/10")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-with-literal/11")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-with-literal/12")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-with-literal/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-with-literal/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-with-literal/15")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-with-literal/16")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6138,6 +6141,7 @@ test-convert-index-into-array-of-bytes-with-literal:
|
|||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-index-into-array-of-bytes-with-literal/5")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-with-literal/6")
|
||||
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-index-into-array-of-bytes-with-literal/7")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-with-literal/8")
|
||||
# 2 * 1 byte/elem + 4 bytes for size = offset 6
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + 0x00000006) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-with-literal/8")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-with-literal/9")
|
||||
|
@ -6189,19 +6193,20 @@ test-convert-index-into-array-on-stack:
|
|||
# var idx
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack/8")
|
||||
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 2/imm32" "F - test-convert-index-into-array-on-stack/9")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")" "F - test-convert-index-into-array-on-stack/10")
|
||||
# var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32" "F - test-convert-index-into-array-on-stack/11")
|
||||
# reclaim idx
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack/12")
|
||||
# reclaim arr
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack/13")
|
||||
#
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/14")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/17")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/18")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack/19")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6242,19 +6247,20 @@ test-convert-index-into-array-on-stack-with-literal:
|
|||
(check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-index-into-array-on-stack-with-literal/7")
|
||||
# var x
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-on-stack-with-literal/8")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")" "F - test-convert-index-into-array-on-stack-with-literal/9")
|
||||
# x is at (ebp-0x10) + 4 + 2*4 = ebp-4
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32" "F - test-convert-index-into-array-on-stack-with-literal/10")
|
||||
# reclaim x
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-on-stack-with-literal/11")
|
||||
# reclaim arr
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-index-into-array-on-stack-with-literal/12")
|
||||
#
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/12")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/13")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/16")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/17")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-on-stack-with-literal/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-on-stack-with-literal/14")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-on-stack-with-literal/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-on-stack-with-literal/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-on-stack-with-literal/17")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-on-stack-with-literal/18")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6295,19 +6301,20 @@ test-convert-index-into-array-of-bytes-on-stack-with-literal:
|
|||
(check-next-stream-line-equal _test-output-stream " 68/push 0x00000003/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/7")
|
||||
# var x
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/8")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
|
||||
# x is at (ebp-7) + 4 + 2 = ebp-1
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
|
||||
# reclaim x
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
|
||||
# reclaim arr
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000007/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000007/imm32" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
|
||||
#
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6350,15 +6357,16 @@ test-convert-index-into-array-using-offset:
|
|||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset/8")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-using-offset/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/13")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/19")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-using-offset/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset/14")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset/15")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset/16")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset/19")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset/20")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6401,15 +6409,16 @@ test-convert-index-into-array-of-bytes-using-offset:
|
|||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/8")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-index-into-array-of-bytes-using-offset/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 69/multiply %ecx 0x00000001/imm32 0x00000001/r32" "F - test-convert-index-into-array-of-bytes-using-offset/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset/13")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset/19")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-using-offset/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset/14")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset/15")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset/16")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset/19")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset/20")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6452,16 +6461,17 @@ test-convert-index-into-array-using-offset-on-stack:
|
|||
(check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-using-offset-on-stack/8")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-using-offset-on-stack/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32" "F - test-convert-index-into-array-using-offset-on-stack/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/14")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/15")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/16")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/19")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/20")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-using-offset-on-stack/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-using-offset-on-stack/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-using-offset-on-stack/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-using-offset-on-stack/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-using-offset-on-stack/15")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-using-offset-on-stack/16")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-using-offset-on-stack/17")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-using-offset-on-stack/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-using-offset-on-stack/19")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-using-offset-on-stack/20")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-using-offset-on-stack/21")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -6504,16 +6514,17 @@ test-convert-index-into-array-of-bytes-using-offset-on-stack:
|
|||
(check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/8")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9")
|
||||
(check-next-stream-line-equal _test-output-stream " 69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx + 4) 0x00000000/r32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -9534,15 +9545,16 @@ test-convert-array-of-user-defined-types:
|
|||
(check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-array-of-user-defined-types/7")
|
||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-array-of-user-defined-types/8")
|
||||
(check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-array-of-user-defined-types/9")
|
||||
(check-next-stream-line-equal _test-output-stream " (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")" "F - test-convert-array-of-user-defined-types/10")
|
||||
(check-next-stream-line-equal _test-output-stream " 8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32" "F - test-convert-array-of-user-defined-types/11")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/13")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/14")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/15")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/16")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/18")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/19")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/20")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-array-of-user-defined-types/12")
|
||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-array-of-user-defined-types/13")
|
||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-array-of-user-defined-types/14")
|
||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-array-of-user-defined-types/15")
|
||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-array-of-user-defined-types/16")
|
||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-array-of-user-defined-types/17")
|
||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-array-of-user-defined-types/18")
|
||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-array-of-user-defined-types/19")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -24774,6 +24786,11 @@ Curr-local-stack-offset: # (addr int)
|
|||
|
||||
== code
|
||||
|
||||
# We may not need to pass err/ed everywhere here. I think they're relics of Mu
|
||||
# getting type checks later in life.
|
||||
# But we do need them for runtime checks, particularly array index bounds checks.
|
||||
# So perhaps it's not worth taking them out. They're a safety net.
|
||||
|
||||
emit-subx: # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
|
@ -26844,6 +26861,8 @@ translate-mu-index-stmt: # out: (addr buffered-file), stmt: (addr stmt), fn: (a
|
|||
(lookup *(ebx+0xc) *(ebx+0x10)) # Stmt1-inouts Stmt1-inouts => eax
|
||||
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
||||
89/<- %ebx 0/r32/eax
|
||||
# emit bounds-check
|
||||
(emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
|
||||
# if (var->register) do one thing
|
||||
{
|
||||
81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register
|
||||
|
@ -26880,6 +26899,125 @@ $translate-mu-index-stmt:error2:
|
|||
(stop *(ebp+0x18) 1)
|
||||
# never gets here
|
||||
|
||||
emit-mu-index-bounds-check: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
50/push-eax
|
||||
51/push-ecx
|
||||
52/push-edx
|
||||
53/push-ebx
|
||||
# ecx = stmt
|
||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
#
|
||||
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||
(write-buffered *(ebp+8) "(__check-mu-array-bounds ")
|
||||
$emit-mu-index-bounds-check:compute-base:
|
||||
# var base/ebx: (addr var) = inouts[0]
|
||||
(lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax
|
||||
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
||||
89/<- %ebx 0/r32/eax
|
||||
$emit-mu-index-bounds-check:emit-index:
|
||||
# var index/edx: (addr var) = inouts[1]
|
||||
(lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax
|
||||
(lookup *(eax+8) *(eax+0xc)) # Stmt-var-next Stmt-var-next => eax
|
||||
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
||||
89/<- %edx 0/r32/eax
|
||||
# if index->register, print its code
|
||||
81 7/subop/compare *(edx+0x18) 0/imm32 # Var-register
|
||||
{
|
||||
0f 84/jump-if-= break/disp32
|
||||
$emit-mu-index-bounds-check:emit-register-index:
|
||||
(write-buffered *(ebp+8) "%")
|
||||
(lookup *(edx+0x18) *(edx+0x1c)) # Var-register Var-register => eax
|
||||
(write-buffered *(ebp+8) %eax)
|
||||
eb/jump $emit-mu-index-bounds-check:index-done/disp8
|
||||
}
|
||||
# otherwise if index is a literal, print it
|
||||
$emit-mu-index-bounds-check:emit-literal-index:
|
||||
(lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax
|
||||
(is-simple-mu-type? %eax 0) # => eax
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
{
|
||||
0f 84/jump-if-= break/disp32
|
||||
(lookup *edx *(edx+4)) # Var-name Var-name => eax
|
||||
(write-buffered *(ebp+8) %eax)
|
||||
}
|
||||
$emit-mu-index-bounds-check:index-done:
|
||||
(write-buffered *(ebp+8) " ")
|
||||
$emit-mu-index-bounds-check:emit-element-size:
|
||||
# if index is a literal or int, print size of array element
|
||||
{
|
||||
{
|
||||
(lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax
|
||||
(is-simple-mu-type? %eax 0) # literal => eax
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
75/jump-if-!= break/disp8
|
||||
(lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax
|
||||
(is-simple-mu-type? %eax 1) # int => eax
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
75/jump-if-!= break/disp8
|
||||
eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
|
||||
}
|
||||
$emit-mu-index-bounds-check:emit-int-register-index:
|
||||
(array-element-size %ebx *(ebp+0x14) *(ebp+0x18)) # => eax
|
||||
(write-int32-hex-buffered *(ebp+8) %eax)
|
||||
e9/jump $emit-mu-index-bounds-check:emit-base/disp32
|
||||
}
|
||||
$emit-mu-index-bounds-check:emit-element-size-offset:
|
||||
# if index has type (offset ...), print "1"
|
||||
(lookup *(edx+8) *(edx+0xc)) # Var-type Var-type => eax
|
||||
81 7/subop/compare *eax 0/imm32/false # Type-tree-is-atom
|
||||
{
|
||||
75/jump-if-!= break/disp8
|
||||
(lookup *(eax+4) *(eax+8)) # Type-tree-left Type-tree-left => eax
|
||||
(is-simple-mu-type? %eax 7) # => eax
|
||||
3d/compare-eax-and 0/imm32/false
|
||||
{
|
||||
0f 84/jump-if-= break/disp32
|
||||
$emit-mu-index-bounds-check:emit-offset-register-index:
|
||||
(write-buffered *(ebp+8) "1")
|
||||
}
|
||||
}
|
||||
$emit-mu-index-bounds-check:emit-base:
|
||||
# if base is in a register, print " *" base->register
|
||||
81 7/subop/compare *(ebx+0x18) 0/imm32 # Var-register
|
||||
{
|
||||
74/jump-if-= break/disp8
|
||||
(write-buffered *(ebp+8) " *")
|
||||
(lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax
|
||||
(write-buffered *(ebp+8) %eax)
|
||||
e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
|
||||
}
|
||||
# otherwise print " *(ebp+" base->offset ")"
|
||||
(write-buffered *(ebp+8) " *(ebp+")
|
||||
(write-int32-hex-buffered *(ebp+8) *(ebx+0x14)) # Var-offset
|
||||
(write-buffered *(ebp+8) ")")
|
||||
$emit-mu-index-bounds-check:emit-function-name:
|
||||
# " \"" function-name "\""
|
||||
(write-buffered *(ebp+8) " \"")
|
||||
8b/-> *(ebp+0x10) 1/r32/ecx
|
||||
(lookup *ecx *(ecx+4)) # Function-name Function-name => eax
|
||||
(write-buffered *(ebp+8) %eax)
|
||||
(write-buffered *(ebp+8) "\"")
|
||||
$emit-mu-index-bounds-check:emit-array-name:
|
||||
# " \"" base->name "\""
|
||||
(write-buffered *(ebp+8) " \"")
|
||||
(lookup *ebx *(ebx+4)) # Var-name Var-name => eax
|
||||
(write-buffered *(ebp+8) %eax)
|
||||
(write-buffered *(ebp+8) "\")\n")
|
||||
$emit-mu-index-bounds-check:end:
|
||||
# . restore registers
|
||||
5b/pop-to-ebx
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
58/pop-to-eax
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
translate-mu-index-stmt-with-array-in-register: # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
|
|
2
mu.md
2
mu.md
|
@ -681,7 +681,7 @@ populate x, 3 # array of 3 T's
|
|||
I said at the start that most instructions map 1:1 to x86 machine code. To
|
||||
enforce type- and memory-safety, I was forced to carve out a few exceptions:
|
||||
|
||||
* the `index` instruction on arrays, for bounds-checking (not yet implemented)
|
||||
* the `index` instruction on arrays, for bounds-checking
|
||||
* the `length` instruction on arrays, for translating the array size in bytes
|
||||
into the number of elements.
|
||||
* the `lookup` instruction on handles, for validating fat-pointer metadata
|
||||
|
|
|
@ -312,24 +312,28 @@ var/reg: (addr T) <- address var2: T
|
|||
=> "8d/copy-address *(ebp+" var2.stack-offset ") " reg "/r32"
|
||||
|
||||
# Array operations
|
||||
(TODO: bounds-checking)
|
||||
|
||||
var/reg <- index arr/rega: (addr array T), idx/regi: int
|
||||
| if size-of(T) is 4 or 8
|
||||
=> "8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"
|
||||
| if size-of(T) is 1, 2, 4 or 8
|
||||
=> "(__check-mu-array-bounds *" rega " %" regi " " size-of(T) ")"
|
||||
"8d/copy-address *(" rega "+" regi "<<" log2(size-of(T)) "+4) " reg "/r32"
|
||||
var/reg <- index arr: (array T len), idx/regi: int
|
||||
=> "8d/copy-address *(ebp+" regi "<<" log2(size-of(T)) "+" (arr.stack-offset + 4) ") " reg "/r32"
|
||||
=> "(__check-mu-array-bounds *(ebp+" arr.stack-offset ") %" regi " " size-of(T) ")"
|
||||
"8d/copy-address *(ebp+" regi "<<" log2(size-of(T)) "+" (arr.stack-offset + 4) ") " reg "/r32"
|
||||
var/reg <- index arr/rega: (addr array T), n
|
||||
=> "8d/copy-address *(" rega "+" (n*size-of(T)+4) ") " reg "/r32"
|
||||
=> "(__check-mu-array-bounds *" rega " " n " " size-of(T) ")"
|
||||
"8d/copy-address *(" rega "+" (n*size-of(T)+4) ") " reg "/r32"
|
||||
var/reg <- index arr: (array T len), n
|
||||
=> "8d/copy-address *(ebp+" (arr.stack-offset+4+n*size-of(T)) ") " reg "/r32"
|
||||
=> "(__check-mu-array-bounds *(ebp+" arr.stack-offset ") " n " " size-of(T) ")"
|
||||
"8d/copy-address *(ebp+" (arr.stack-offset+4+n*size-of(T)) ") " reg "/r32"
|
||||
|
||||
var/reg: (offset T) <- compute-offset arr: (addr array T), idx/regi: int # arr can be in reg or mem
|
||||
=> "69/multiply %" regi " " size-of(T) "/imm32 " reg "/r32"
|
||||
var/reg: (offset T) <- compute-offset arr: (addr array T), idx: int # arr can be in reg or mem
|
||||
=> "69/multiply *(ebp+" idx.stack-offset ") " size-of(T) "/imm32 " reg "/r32"
|
||||
var/reg <- index arr/rega: (addr array T), o/rego: offset
|
||||
=> "8d/copy-address *(" rega "+" rego "+4) " reg "/r32"
|
||||
var/reg <- index arr/rega: (addr array T), o/rego: (offset T)
|
||||
=> "(__check-mu-array-bounds %" rega " %" rego " 1 \"" function-name "\")"
|
||||
"8d/copy-address *(" rega "+" rego "+4) " reg "/r32"
|
||||
|
||||
Computing the length of an array is complex.
|
||||
|
||||
|
|
Loading…
Reference in New Issue