5948 - branching to named blocks

This commit is contained in:
Kartik Agaram 2020-01-29 17:34:07 -08:00
parent c913d04dfa
commit d20fbf71c3
16 changed files with 476 additions and 32 deletions

View File

@ -16,10 +16,52 @@ Entry: # run all tests
string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> eax: boolean
# pseudocode:
# if (s->length != benchmark->length) return false
# return string-starts-with?(s, benchmark)
#
# . prologue
55/push-ebp
89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
# . save registers
51/push-ecx
56/push-esi
57/push-edi
# esi = s
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# edi = benchmark
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
# ecx = s->length
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
$string-equal?:lengths:
# if (ecx != benchmark->length) return false
39/compare 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # compare *edi and ecx
b8/copy-to-eax 0/imm32/false
75/jump-if-!= $string-equal?:end/disp8
$string-equal?:contents:
# string-starts-with?(s, benchmark)
# . . push args
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+0xc)
ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
# . . call
e8/call string-starts-with?/disp32
# . . discard args
81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
$string-equal?:end:
# . restore registers
5f/pop-to-edi
5e/pop-to-esi
59/pop-to-ecx
# . epilogue
89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
5d/pop-to-ebp
c3/return
string-starts-with?: # s: (addr array byte), benchmark: (addr array byte) -> eax: boolean
# pseudocode:
# if (s->length < benchmark->length) return false
# currs = s->data
# currb = benchmark->data
# maxs = &s->data[s->length]
# while currs < maxs
# maxb = &benchmark->data[benchmark->length]
# while currb < maxb
# c1 = *currs
# c2 = *currb
# if (c1 != c2) return false
@ -45,44 +87,44 @@ string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> eax: boo
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
# edi = benchmark
8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
# ecx = s->length
8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
$string-equal?:lengths:
# if (ecx != benchmark->length) return false
39/compare 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # compare *edi and ecx
75/jump-if-!= $string-equal?:false/disp8
# var blen/ecx: int = benchmark->length
8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
$string-starts-with?:lengths:
# if (s->length < blen) return false
39/compare 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # compare *esi with ecx
7c/jump-if-< $string-starts-with?:false/disp8
# var currs/esi: (addr byte) = s->data
81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 4/imm32 # add to esi
# var maxs/ecx: (addr byte) = &s->data[s->length]
01/add 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # add esi to ecx
# var currb/edi: (addr byte) = benchmark->data
81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi
# var maxb/ecx: (addr byte) = &benchmark->data[benchmark->length]
01/add 3/mod/direct 1/rm32/ecx . . . 7/r32/edi . . # add edi to ecx
# var c1/eax: byte = 0
31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
# var c2/edx: byte = 0
31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx
$string-equal?:loop:
$string-starts-with?:loop:
# if (currs >= maxs) return true
39/compare 3/mod/direct 6/rm32/esi . . . 1/r32/ecx . . # compare esi with ecx
73/jump-if-addr>= $string-equal?:true/disp8
39/compare 3/mod/direct 7/rm32/edi . . . 1/r32/ecx . . # compare edi with ecx
73/jump-if-addr>= $string-starts-with?:true/disp8
# c1 = *currs
8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL
# c2 = *currb
8a/copy-byte 0/mod/indirect 7/rm32/edi . . . 2/r32/DL . . # copy byte at *edi to DL
# if (c1 != c2) return false
39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax and edx
75/jump-if-!= $string-equal?:false/disp8
75/jump-if-!= $string-starts-with?:false/disp8
# ++currs
46/increment-esi
# ++currb
47/increment-edi
eb/jump $string-equal?:loop/disp8
$string-equal?:true:
eb/jump $string-starts-with?:loop/disp8
$string-starts-with?:true:
b8/copy-to-eax 1/imm32
eb/jump $string-equal?:end/disp8
$string-equal?:false:
eb/jump $string-starts-with?:end/disp8
$string-starts-with?:false:
b8/copy-to-eax 0/imm32
$string-equal?:end:
$string-starts-with?:end:
# . restore registers
5f/pop-to-edi
5e/pop-to-esi

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
apps/hex

Binary file not shown.

BIN
apps/mu

Binary file not shown.

View File

@ -132,7 +132,7 @@
#
# A named block contains:
# tag: 4
# name: (handle array byte)
# name: (handle array byte) -- starting with '$'
# statements: (handle list statement)
# == Translation: managing the stack
@ -1157,7 +1157,7 @@ test-convert-function-with-local-var-in-block:
test-convert-function-with-local-var-in-named-block:
# empty function decl => function prologue and epilogue
# fn foo {
# bar: {
# $bar: {
# var x: int
# increment x
# }
@ -1169,12 +1169,12 @@ test-convert-function-with-local-var-in-named-block:
# 89/<- %ebp 4/r32/esp
# {
# {
# bar:loop:
# $bar:loop:
# 68/push 0/imm32
# ff 0/subop/increment *(ebp-4)
# 81 0/subop/add %esp 4/imm32
# }
# bar:break:
# $bar:break:
# }
# # . epilogue
# 89/<- %esp 5/r32/ebp
@ -1190,7 +1190,7 @@ test-convert-function-with-local-var-in-named-block:
(clear-stream $_test-output-buffered-file->buffer)
#
(write _test-input-stream "fn foo {\n")
(write _test-input-stream " bar: {\n")
(write _test-input-stream " $bar: {\n")
(write _test-input-stream " var x: int\n")
(write _test-input-stream " increment x\n")
(write _test-input-stream " }\n")
@ -1211,12 +1211,12 @@ test-convert-function-with-local-var-in-named-block:
(check-next-stream-line-equal _test-output-stream "89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3")
(check-next-stream-line-equal _test-output-stream "{" "F - test-convert-function-with-local-var-in-named-block/4")
(check-next-stream-line-equal _test-output-stream "{" "F - test-convert-function-with-local-var-in-named-block/5")
(check-next-stream-line-equal _test-output-stream "bar:loop:" "F - test-convert-function-with-local-var-in-named-block/6")
(check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/6")
(check-next-stream-line-equal _test-output-stream "68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/7")
(check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/8")
(check-next-stream-line-equal _test-output-stream "81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-named-block/9")
(check-next-stream-line-equal _test-output-stream "}" "F - test-convert-function-with-local-var-in-named-block/10")
(check-next-stream-line-equal _test-output-stream "bar:break:" "F - test-convert-function-with-local-var-in-named-block/11")
(check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/11")
(check-next-stream-line-equal _test-output-stream "}" "F - test-convert-function-with-local-var-in-named-block/12")
(check-next-stream-line-equal _test-output-stream "# . epilogue" "F - test-convert-function-with-local-var-in-named-block/13")
(check-next-stream-line-equal _test-output-stream "89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/14")
@ -1302,6 +1302,85 @@ test-convert-function-with-branches-in-block:
5d/pop-to-ebp
c3/return
test-convert-function-with-branches-in-named-block:
# empty function decl => function prologue and epilogue
# fn foo x: int {
# $bar: {
# break-if->= $bar
# loop-if-addr< $bar
# increment x
# loop
# }
# }
# =>
# foo:
# # . prologue
# 55/push-ebp
# 89/<- %ebp 4/r32/esp
# {
# {
# $bar:loop:
# 0f 8d/jump-if->= $bar:break/disp32
# 0f 82/jump-if-addr< $bar:loop/disp32
# ff 0/subop/increment *(ebp+8)
# e9/jump loop/disp32
# }
# $bar:break:
# }
# # . epilogue
# 89/<- %esp 5/r32/ebp
# 5d/pop-to-ebp
# c3/return
# . 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 x: int {\n")
(write _test-input-stream " $bar: {\n")
(write _test-input-stream " break-if->= $bar\n")
(write _test-input-stream " loop-if-addr< $bar\n")
(write _test-input-stream " increment x\n")
(write _test-input-stream " loop\n")
(write _test-input-stream " }\n")
(write _test-input-stream "}\n")
# convert
(convert-mu _test-input-buffered-file _test-output-buffered-file)
(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-convert-function-with-branches-in-named-block/0")
(check-next-stream-line-equal _test-output-stream "# . prologue" "F - test-convert-function-with-branches-in-named-block/1")
(check-next-stream-line-equal _test-output-stream "55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2")
(check-next-stream-line-equal _test-output-stream "89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3")
(check-next-stream-line-equal _test-output-stream "{" "F - test-convert-function-with-branches-in-named-block/4")
(check-next-stream-line-equal _test-output-stream "{" "F - test-convert-function-with-branches-in-named-block/5")
(check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/6")
(check-next-stream-line-equal _test-output-stream "0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/7")
(check-next-stream-line-equal _test-output-stream "0f 82/jump-if-addr< $bar:loop/disp32" "F - test-convert-function-with-branches-in-named-block/8")
(check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/9")
(check-next-stream-line-equal _test-output-stream "e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/10")
(check-next-stream-line-equal _test-output-stream "}" "F - test-convert-function-with-branches-in-named-block/11")
(check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/12")
(check-next-stream-line-equal _test-output-stream "}" "F - test-convert-function-with-branches-in-named-block/13")
(check-next-stream-line-equal _test-output-stream "# . epilogue" "F - test-convert-function-with-branches-in-named-block/14")
(check-next-stream-line-equal _test-output-stream "89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/15")
(check-next-stream-line-equal _test-output-stream "5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/16")
(check-next-stream-line-equal _test-output-stream "c3/return" "F - test-convert-function-with-branches-in-named-block/17")
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
#######################################################
# Parsing
#######################################################
@ -3401,7 +3480,25 @@ $add-operation-and-inputs-to-stmt:read-inouts:
(slice-equal? %ecx "<-")
3d/compare-eax-and 0/imm32
0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
#
# if (name starts with "$") treat it as a literal
{
# var eax: byte = name[0]
8b/-> *ecx 0/r32/eax
8a/copy-byte *eax 0/r32/AL
81 4/subop/and %eax 0xff/imm32
# if (eax != '$') goto next condition
3d/compare-eax-and 0x24/imm32/dollar
75/jump-if-!= break/disp8
# var eax: (handle var)
(new-label Heap %ecx) # => eax
# stmt->inouts = append(eax, stmt->inouts)
(append-list Heap %eax *(edi+8)) # Stmt1-inouts => eax
89/<- *(edi+8) 0/r32/eax # Stmt1-inouts
# continue
e9/jump $add-operation-and-inputs-to-stmt:read-inouts/disp32
}
$add-operation-and-inputs-to-stmt:regular-inout:
# otherwise
(lookup-var-or-literal %ecx *(ebp+0x10)) # => eax
(append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax
89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts
@ -3860,6 +3957,33 @@ $new-literal-integer:abort:
cd/syscall 0x80/imm8
# never gets here
new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
51/push-ecx
# var s/ecx: (addr array byte)
(slice-to-string Heap *(ebp+0xc)) # => eax
89/<- %ecx 0/r32/eax
#
(allocate *(ebp+8) *Var-size) # => eax
89/<- *eax 1/r32/ecx # Var-name
89/<- %ecx 0/r32/eax
(allocate *(ebp+8) *Tree-size) # => eax
89/<- *(ecx+4) 0/r32/eax # Var-type
89/<- %eax 1/r32/ecx
c7 0/subop/copy *(eax+8) 0/imm32 # Var-block
c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset
c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register
$new-label:end:
# . restore registers
59/pop-to-ecx
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement)
# . prologue
55/push-ebp
@ -4227,7 +4351,7 @@ $emit-subx-stmt-list:regvardef:
8b/-> *eax 0/r32/eax
# ensure that output is in a register
81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register
0f 84/jump-if-equal $emit-subx-stmt-list:abort-regvardef-without-register/disp32
0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32
# emit spill
(write-buffered *(ebp+8) "ff 6/subop/push %")
(write-buffered *(ebp+8) *(eax+0x10))
@ -4341,19 +4465,21 @@ emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), pri
51/push-ecx
# if stmt matches a primitive, emit it
{
$emit-subx-statement:primitive:
$emit-subx-statement:check-for-primitive:
(find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax
3d/compare-eax-and 0/imm32
74/jump-if-= break/disp8
$emit-subx-statement:primitive:
(emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr
e9/jump $emit-subx-statement:end/disp32
}
# else if stmt matches a function, emit a call to it
{
$emit-subx-statement:call:
$emit-subx-statement:check-for-call:
(find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax
3d/compare-eax-and 0/imm32
74/jump-if-= break/disp8
$emit-subx-statement:call:
(emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr
e9/jump $emit-subx-statement:end/disp32
}
@ -4370,8 +4496,9 @@ $emit-subx-statement:end:
$emit-subx-statement:abort:
# error("couldn't translate '" stmt "'\n")
(write-buffered Stderr "couldn't translate '")
#? (emit-string Stderr *(ebp+0xc)) # TODO
(write-buffered Stderr "couldn't translate an instruction with operation '")
8b/-> *(ebp+0xc) 0/r32/eax
(write-buffered Stderr *(eax+4)) # Stmt1-operation
(write-buffered Stderr "'\n")
(flush Stderr)
# . syscall(exit, 1)
@ -5341,6 +5468,238 @@ _Primitive-loop:
0/imm32/no-imm32
0/imm32/no-disp32
0/imm32/no-output
_Primitive-break-if-addr<-named/imm32/next
# - branches to named blocks
_Primitive-break-if-addr<-named:
"break-if-addr<"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 82/jump-if-addr<"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-addr>=-named/imm32/next
_Primitive-break-if-addr>=-named:
"break-if-addr>="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 83/jump-if-addr>="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-=-named/imm32/next
_Primitive-break-if-=-named:
"break-if-="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 84/jump-if-="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-!=-named/imm32/next
_Primitive-break-if-!=-named:
"break-if-!="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 85/jump-if-!="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-addr<=-named/imm32/next
_Primitive-break-if-addr<=-named:
"break-if-addr<="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 86/jump-if-addr<="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-addr>-named/imm32/next
_Primitive-break-if-addr>-named:
"break-if-addr>"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 87/jump-if-addr>"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-<-named/imm32/next
_Primitive-break-if-<-named:
"break-if-<"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8c/jump-if-<"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if->=-named/imm32/next
_Primitive-break-if->=-named:
"break-if->="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8d/jump-if->="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if-<=-named/imm32/next
_Primitive-break-if-<=-named:
"break-if-<="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8e/jump-if-<="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-break-if->-named/imm32/next
_Primitive-break-if->-named:
"break-if->"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8f/jump-if->"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-addr<-named/imm32/next
_Primitive-loop-if-addr<-named:
"loop-if-addr<"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 82/jump-if-addr<"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-addr>=-named/imm32/next
_Primitive-loop-if-addr>=-named:
"loop-if-addr>="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 83/jump-if-addr>="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-=-named/imm32/next
_Primitive-loop-if-=-named:
"loop-if-="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 84/jump-if-="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-!=-named/imm32/next
_Primitive-loop-if-!=-named:
"loop-if-!="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 85/jump-if-!="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-addr<=-named/imm32/next
_Primitive-loop-if-addr<=-named:
"loop-if-addr<="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 86/jump-if-addr<="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-addr>-named/imm32/next
_Primitive-loop-if-addr>-named:
"loop-if-addr>"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 87/jump-if-addr>"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-<-named/imm32/next
_Primitive-loop-if-<-named:
"loop-if-<"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8c/jump-if-<"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if->=-named/imm32/next
_Primitive-loop-if->=-named:
"loop-if->="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8d/jump-if->="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if-<=-named/imm32/next
_Primitive-loop-if-<=-named:
"loop-if-<="/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8e/jump-if-<="/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-if->-named/imm32/next
_Primitive-loop-if->-named:
"loop-if->"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"0f 8f/jump-if->"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
_Primitive-loop-named/imm32/next # we probably don't need an unconditional break
_Primitive-loop-named:
"loop"/imm32/name
Single-lit-var/imm32/inouts
0/imm32/outputs
"e9/jump"/imm32/subx-name
0/imm32/no-rm32
0/imm32/no-r32
0/imm32/no-imm32
1/imm32/disp32-is-first-inout
0/imm32/no-output
0/imm32/next
Single-int-var-on-stack:
@ -5476,6 +5835,8 @@ emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), pri
(emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt
# emit imm32 if necessary
(emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt
# emit disp32 if necessary
(emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt
(write-buffered *(ebp+8) Newline)
$emit-subx-primitive:end:
# . restore registers
@ -5615,6 +5976,47 @@ $emit-subx-imm32:end:
5d/pop-to-ebp
c3/return
emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
# if (location == 0) return
81 7/subop/compare *(ebp+0xc) 0/imm32
0f 84/jump-if-= $emit-subx-disp32:end/disp32
#
(get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # stmt, l => var/eax
(write-buffered *(ebp+8) Space)
(write-buffered *(ebp+8) *eax) # Var-name
# hack: if instruction operation starts with "break", emit ":break"
# var name/ecx: (addr array byte) = stmt->operation
8b/-> *(ebp+0x10) 0/r32/eax
8b/-> *(eax+4) 1/r32/ecx
{
(string-starts-with? %ecx "break") # => eax
3d/compare-eax-and 0/imm32
74/jump-if-= break/disp8
(write-buffered *(ebp+8) ":break")
}
# hack: if instruction operation starts with "loop", emit ":loop"
{
(string-starts-with? %ecx "loop") # => eax
3d/compare-eax-and 0/imm32
74/jump-if-= break/disp8
(write-buffered *(ebp+8) ":loop")
}
(write-buffered *(ebp+8) "/disp32")
$emit-subx-disp32:end:
# . restore registers
59/pop-to-ecx
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function)
# . prologue
55/push-ebp

BIN
apps/pack

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.