6390 - return `length` in elements
This commit is contained in:
parent
d89af9bdfa
commit
156763463d
110
apps/mu.subx
110
apps/mu.subx
|
@ -2436,14 +2436,15 @@ test-convert-length-of-array:
|
||||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5")
|
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5")
|
||||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6")
|
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6")
|
||||||
(check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7")
|
(check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7")
|
||||||
(check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array/9")
|
(check-next-stream-line-equal _test-output-stream " 8b/-> *eax 0x00000000/r32" "F - test-convert-length-of-array/8")
|
||||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11")
|
(check-next-stream-line-equal _test-output-stream " c1/shift 5/subop/>> %eax 0x00000002/imm32" "F - test-convert-length-of-array/9")
|
||||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12")
|
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10")
|
||||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13")
|
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/11")
|
||||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14")
|
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/12")
|
||||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15")
|
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/13")
|
||||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16")
|
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/14")
|
||||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17")
|
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/15")
|
||||||
|
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/16")
|
||||||
# . epilogue
|
# . epilogue
|
||||||
89/<- %esp 5/r32/ebp
|
89/<- %esp 5/r32/ebp
|
||||||
5d/pop-to-ebp
|
5d/pop-to-ebp
|
||||||
|
@ -2484,14 +2485,15 @@ test-convert-length-of-array-on-stack:
|
||||||
(check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-length-of-array-on-stack/7")
|
(check-next-stream-line-equal _test-output-stream " 68/push 0x0000000c/imm32" "F - test-convert-length-of-array-on-stack/7")
|
||||||
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-on-stack/8")
|
(check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array-on-stack/8")
|
||||||
(check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0xfffffff0) 0x00000000/r32" "F - test-convert-length-of-array-on-stack/9")
|
(check-next-stream-line-equal _test-output-stream " 8b/-> *(ebp+0xfffffff0) 0x00000000/r32" "F - test-convert-length-of-array-on-stack/9")
|
||||||
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-on-stack/10")
|
(check-next-stream-line-equal _test-output-stream " c1/shift 5/subop/>> %eax 0x00000002/imm32" "F - test-convert-length-of-array-on-stack/10")
|
||||||
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-length-of-array-on-stack/11")
|
(check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array-on-stack/11")
|
||||||
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-on-stack/12")
|
(check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000010/imm32" "F - test-convert-length-of-array-on-stack/12")
|
||||||
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-on-stack/13")
|
(check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array-on-stack/13")
|
||||||
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-on-stack/14")
|
(check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array-on-stack/14")
|
||||||
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-on-stack/15")
|
(check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array-on-stack/15")
|
||||||
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-on-stack/16")
|
(check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array-on-stack/16")
|
||||||
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-on-stack/17")
|
(check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array-on-stack/17")
|
||||||
|
(check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array-on-stack/18")
|
||||||
# . epilogue
|
# . epilogue
|
||||||
89/<- %esp 5/r32/ebp
|
89/<- %esp 5/r32/ebp
|
||||||
5d/pop-to-ebp
|
5d/pop-to-ebp
|
||||||
|
@ -8842,28 +8844,31 @@ translate-mu-length-stmt: # out: (addr buffered-file), stmt: (addr stmt)
|
||||||
# . save registers
|
# . save registers
|
||||||
50/push-eax
|
50/push-eax
|
||||||
51/push-ecx
|
51/push-ecx
|
||||||
|
52/push-edx
|
||||||
|
53/push-ebx
|
||||||
# ecx = stmt
|
# ecx = stmt
|
||||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||||
#
|
#
|
||||||
(emit-indent *(ebp+8) *Curr-block-depth)
|
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||||
(write-buffered *(ebp+8) "8b/-> *")
|
(write-buffered *(ebp+8) "8b/-> *")
|
||||||
# var base/eax: (handle var) = inouts[0]
|
# var base/ebx: (addr var) = inouts[0]
|
||||||
(lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax
|
(lookup *(ecx+0xc) *(ecx+0x10)) # Stmt1-inouts Stmt1-inouts => eax
|
||||||
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
||||||
|
89/<- %ebx 0/r32/eax
|
||||||
# if base is an (addr array ...) in a register
|
# if base is an (addr array ...) in a register
|
||||||
{
|
{
|
||||||
81 7/subop/compare *(eax+0x18)) 0/imm32 # Var-register
|
81 7/subop/compare *(ebx+0x18)) 0/imm32 # Var-register
|
||||||
74/jump-if-= break/disp8
|
74/jump-if-= break/disp8
|
||||||
(lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax
|
(lookup *(ebx+0x18) *(ebx+0x1c)) # Var-register Var-register => eax
|
||||||
(write-buffered *(ebp+8) %eax)
|
(write-buffered *(ebp+8) %eax)
|
||||||
eb/jump $translate-mu-length-stmt:emit-output/disp8
|
eb/jump $translate-mu-length-stmt:emit-output/disp8
|
||||||
}
|
}
|
||||||
# otherwise if base is an (array ...) on the stack
|
# otherwise if base is an (array ...) on the stack
|
||||||
{
|
{
|
||||||
81 7/subop/compare *(eax+0x14)) 0/imm32 # Var-offset
|
81 7/subop/compare *(ebx+0x14)) 0/imm32 # Var-offset
|
||||||
74/jump-if-= break/disp8
|
74/jump-if-= break/disp8
|
||||||
(write-buffered *(ebp+8) "(ebp+")
|
(write-buffered *(ebp+8) "(ebp+")
|
||||||
(print-int32-buffered *(ebp+8) *(eax+0x14)) # Var-offset
|
(print-int32-buffered *(ebp+8) *(ebx+0x14)) # Var-offset
|
||||||
(write-buffered *(ebp+8) ")")
|
(write-buffered *(ebp+8) ")")
|
||||||
}
|
}
|
||||||
$translate-mu-length-stmt:emit-output:
|
$translate-mu-length-stmt:emit-output:
|
||||||
|
@ -8871,12 +8876,40 @@ $translate-mu-length-stmt:emit-output:
|
||||||
# outputs[0] "/r32"
|
# outputs[0] "/r32"
|
||||||
(lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax
|
(lookup *(ecx+0x14) *(ecx+0x18)) # Stmt1-outputs Stmt1-outputs => eax
|
||||||
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
(lookup *eax *(eax+4)) # Stmt-var-value Stmt-var-value => eax
|
||||||
|
# edx = outputs[0]->register
|
||||||
(lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax
|
(lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax
|
||||||
(get Registers %eax 0xc "Registers") # => eax
|
89/<- %edx 0/r32/eax
|
||||||
|
#
|
||||||
|
(get Registers %edx 0xc "Registers") # => eax
|
||||||
(print-int32-buffered *(ebp+8) *eax)
|
(print-int32-buffered *(ebp+8) *eax)
|
||||||
(write-buffered *(ebp+8) "/r32\n")
|
(write-buffered *(ebp+8) "/r32\n")
|
||||||
|
$translate-mu-length-stmt:check-power-of-2:
|
||||||
|
# ecx = size-of(element-type(base))
|
||||||
|
(array-element-type-id %ebx) # => eax
|
||||||
|
(size-of-type-id %eax) # => eax
|
||||||
|
89/<- %ecx 0/r32/eax
|
||||||
|
#
|
||||||
|
(power-of-2? %ecx) # => eax
|
||||||
|
3d/compare-eax-and 0/imm32/false
|
||||||
|
{
|
||||||
|
0f 84/jump-if-= break/disp32
|
||||||
|
$translate-mu-length-stmt:is-power-of-2:
|
||||||
|
(emit-indent *(ebp+8) *Curr-block-depth)
|
||||||
|
(write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
|
||||||
|
(write-buffered *(ebp+8) %edx)
|
||||||
|
(write-buffered *(ebp+8) Space)
|
||||||
|
(num-shift-rights %ecx) # => eax
|
||||||
|
(print-int32-buffered *(ebp+8) %eax)
|
||||||
|
(write-buffered *(ebp+8) "/imm32\n")
|
||||||
|
eb/jump $translate-mu-length-stmt:end/disp8
|
||||||
|
}
|
||||||
|
{
|
||||||
|
75/jump-if-!= break/disp8
|
||||||
|
$translate-mu-length-stmt:not-power-of-2:
|
||||||
|
}
|
||||||
$translate-mu-length-stmt:end:
|
$translate-mu-length-stmt:end:
|
||||||
# . restore registers
|
# . restore registers
|
||||||
|
5b/pop-to-ebx
|
||||||
59/pop-to-ecx
|
59/pop-to-ecx
|
||||||
58/pop-to-eax
|
58/pop-to-eax
|
||||||
# . epilogue
|
# . epilogue
|
||||||
|
@ -9310,6 +9343,39 @@ $array-element-type-id:end:
|
||||||
5d/pop-to-ebp
|
5d/pop-to-ebp
|
||||||
c3/return
|
c3/return
|
||||||
|
|
||||||
|
power-of-2?: # n: int -> result/eax: boolean
|
||||||
|
# precondition: n is positive
|
||||||
|
# . prologue
|
||||||
|
55/push-ebp
|
||||||
|
89/<- %ebp 4/r32/esp
|
||||||
|
# eax = n
|
||||||
|
8b/-> *(ebp+8) 0/r32/eax
|
||||||
|
# if (n < 0) abort
|
||||||
|
3d/compare-eax-with 0/imm32
|
||||||
|
0f 8c/jump-if-< $power-of-2?:abort/disp32
|
||||||
|
# var tmp/eax: int = n-1
|
||||||
|
48/decrement-eax
|
||||||
|
# var tmp2/eax: int = n & tmp
|
||||||
|
23/and-> *(ebp+8) 0/r32/eax
|
||||||
|
# return (tmp2 == 0)
|
||||||
|
3d/compare-eax-and 0/imm32
|
||||||
|
0f 94/set-byte-if-= %al
|
||||||
|
81 4/subop/and %eax 0xff/imm32
|
||||||
|
$power-of-2?:end:
|
||||||
|
# . epilogue
|
||||||
|
89/<- %esp 5/r32/ebp
|
||||||
|
5d/pop-to-ebp
|
||||||
|
c3/return
|
||||||
|
|
||||||
|
$power-of-2?:abort:
|
||||||
|
(write-buffered Stderr "power-of-2?: negative number\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
|
||||||
|
|
||||||
num-shift-rights: # n: int -> result/eax: int
|
num-shift-rights: # n: int -> result/eax: int
|
||||||
# precondition: n is a positive power of 2
|
# precondition: n is a positive power of 2
|
||||||
# . prologue
|
# . prologue
|
||||||
|
|
|
@ -183,11 +183,35 @@ var/reg: (offset T) <- compute-offset arr: (addr array T), idx: int # arr
|
||||||
var/reg <- index arr/rega: (addr array T), o/rego: offset
|
var/reg <- index arr/rega: (addr array T), o/rego: offset
|
||||||
=> "8d/copy-address *(" rega "+" rego "+4) " reg "/r32"
|
=> "8d/copy-address *(" rega "+" rego "+4) " reg "/r32"
|
||||||
|
|
||||||
Computing the length of an array can get complex.
|
Computing the length of an array is complex.
|
||||||
|
|
||||||
var/reg <- length arr/reg2: (addr array T)
|
var/reg <- length arr/reg2: (addr array T)
|
||||||
| if T is byte (TODO)
|
| if T is byte (TODO)
|
||||||
=> "8b/-> *" reg2 " " reg "/r32"
|
=> "8b/-> *" reg2 " " reg "/r32"
|
||||||
|
| if size-of(T) is 4 or 8 or 16 or 32 or 64 or 128
|
||||||
|
=> "8b/-> *" reg2 " " reg "/r32"
|
||||||
|
"c1/shift 5/subop/logic-right %" reg " " log2(size-of(T)) "/imm8"
|
||||||
|
| otherwise (TODO)
|
||||||
|
x86 has no instruction to divide by a literal, so
|
||||||
|
we need up to 3 extra registers! eax/edx for division and say ecx
|
||||||
|
=> if reg is not eax
|
||||||
|
"50/push-eax"
|
||||||
|
if reg is not ecx
|
||||||
|
"51/push-ecx"
|
||||||
|
if reg is not edx
|
||||||
|
"52/push-edx"
|
||||||
|
"8b/-> *" reg2 " eax/r32"
|
||||||
|
"31/xor %edx 2/r32/edx" # sign-extend, but array size can't be negative
|
||||||
|
"b9/copy-to-ecx " size-of(T) "/imm32"
|
||||||
|
"f7 7/subop/idiv-eax-edx-by %ecx"
|
||||||
|
if reg is not eax
|
||||||
|
"89/<- %" reg " 0/r32/eax"
|
||||||
|
if reg is not edx
|
||||||
|
"5a/pop-to-edx"
|
||||||
|
if reg is not ecx
|
||||||
|
"59/pop-to-ecx"
|
||||||
|
if reg is not eax
|
||||||
|
"58/pop-to-eax"
|
||||||
|
|
||||||
# User-defined types
|
# User-defined types
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue