5750
We can now compile primitive statements while selecting the right template to code-gen each one from. Even when multiple templates have the same name.
This commit is contained in:
parent
eafdbfc103
commit
3b40e3c331
436
apps/mu.subx
436
apps/mu.subx
|
@ -1086,19 +1086,6 @@ $emit-subx-imm32:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
#? # var args/ecx : (list var) = stmt->inouts
|
||||
#? 8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
#? 8b/-> *(ecx+4) 1/r32/ecx # Stmt-inouts
|
||||
#? {
|
||||
#? # if (curr == null) break
|
||||
#? 81 7/subop/compare %ecx 0/imm32
|
||||
#? 74/jump-if-equal break/disp8
|
||||
#? #
|
||||
#? (emit-subx-call-operand *(ebp+8) *ecx)
|
||||
#? # args = args->next
|
||||
#? 8b/-> *(ecx+4) 1/r32/ecx
|
||||
#? }
|
||||
|
||||
emit-subx-call: # out : (address buffered-file), stmt : (address statement), vars : (address variable), callee : (address function)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
|
@ -1213,6 +1200,7 @@ find-matching-primitive: # primitives : (address primitive), stmt : (address st
|
|||
# var curr/ecx : (address primitive) = primitives
|
||||
8b/-> *(ebp+8) 1/r32/ecx
|
||||
{
|
||||
$find-matching-primitive:loop:
|
||||
# if (curr == null) break
|
||||
81 7/subop/compare %ecx 0/imm32
|
||||
74/jump-if-equal break/disp8
|
||||
|
@ -1224,8 +1212,9 @@ find-matching-primitive: # primitives : (address primitive), stmt : (address st
|
|||
89/<- %eax 1/r32/ecx
|
||||
eb/jump $find-matching-function:end/disp8
|
||||
}
|
||||
$find-matching-primitive:next-primitive:
|
||||
# curr = curr->next
|
||||
8b/-> *(ecx+0x18) 1/r32/ecx # Primitive-next
|
||||
8b/-> *(ecx+0x1c) 1/r32/ecx # Primitive-next
|
||||
eb/jump loop/disp8
|
||||
}
|
||||
# return null
|
||||
|
@ -1257,23 +1246,219 @@ $mu-stmt-matches-function?:end:
|
|||
c3/return
|
||||
|
||||
mu-stmt-matches-primitive?: # stmt : (address statement), primitive : (address primitive) => result/eax : boolean
|
||||
# A mu stmt matches a primitive if the name matches, all the inout vars
|
||||
# match, and all the output vars match.
|
||||
# Vars match if types match and registers match.
|
||||
# In addition, a stmt output matches a primitive's output if types match
|
||||
# and the primitive has a wildcard register.
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
51/push-ecx
|
||||
# return primitive->name == stmt->operation
|
||||
52/push-edx
|
||||
53/push-ebx
|
||||
56/push-esi
|
||||
57/push-edi
|
||||
# ecx = stmt
|
||||
8b/-> *(ebp+8) 1/r32/ecx
|
||||
8b/-> *(ebp+0xc) 0/r32/eax
|
||||
(string-equal? *ecx *eax) # => eax
|
||||
# edx = primitive
|
||||
8b/-> *(ebp+0xc) 2/r32/edx
|
||||
{
|
||||
$mu-stmt-matches-primitive?:check-name:
|
||||
# if (primitive->name != stmt->operation) return false
|
||||
(string-equal? *ecx *edx) # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
$mu-stmt-matches-primitive?:check-inouts:
|
||||
# curr = stmt->inouts
|
||||
8b/-> *(ecx+4) 6/r32/esi # Stmt-inouts
|
||||
# curr2 = primitive->inouts
|
||||
8b/-> *(edx+4) 7/r32/edi # Primitive-inouts
|
||||
{
|
||||
# if (curr == 0) return (curr2 == 0)
|
||||
{
|
||||
81 7/subop/compare %esi 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
{
|
||||
81 7/subop/compare %edi 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
# return true
|
||||
b8/copy-to-eax 1/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# return false
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# if (curr2 == 0) return false
|
||||
{
|
||||
81 7/subop/compare %edi 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# if (curr != curr2) return false
|
||||
{
|
||||
(operand-matches-primitive? *esi *edi) # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# curr=curr->next
|
||||
8b/-> *(ecx+4) 1/r32/ecx # Operand-next
|
||||
# curr2=curr2->next
|
||||
8b/-> *(edx+4) 2/r32/edx # Operand-next
|
||||
}
|
||||
$mu-stmt-matches-primitive?:check-outputs:
|
||||
# ecx = stmt
|
||||
8b/-> *(ebp+8) 1/r32/ecx
|
||||
# edx = primitive
|
||||
8b/-> *(ebp+0xc) 2/r32/edx
|
||||
# curr = stmt->outputs
|
||||
8b/-> *(ecx+8) 6/r32/esi # Stmt-outputs
|
||||
# curr2 = primitive->outputs
|
||||
8b/-> *(edx+8) 7/r32/edi # Primitive-outputs
|
||||
{
|
||||
# if (curr == 0) return (curr2 == 0)
|
||||
{
|
||||
81 7/subop/compare %esi 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
{
|
||||
81 7/subop/compare %edi 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
# return true
|
||||
b8/copy-to-eax 1/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# return false
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# if (curr2 == 0) return false
|
||||
{
|
||||
81 7/subop/compare %edi 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# if (curr != curr2) return false
|
||||
{
|
||||
(output-operand-matches-primitive? *esi *edi) # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
b8/copy-to-eax 0/imm32
|
||||
e9/jump $mu-stmt-matches-primitive?:end/disp32
|
||||
}
|
||||
# curr=curr->next
|
||||
8b/-> *(ecx+4) 1/r32/ecx # Operand-next
|
||||
# curr2=curr2->next
|
||||
8b/-> *(edx+4) 2/r32/edx # Operand-next
|
||||
}
|
||||
$mu-stmt-matches-primitive?:return-true:
|
||||
b8/copy-to-eax 1/imm32
|
||||
$mu-stmt-matches-primitive?:end:
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5e/pop-to-esi
|
||||
5b/pop-to-ebx
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
operand-matches-primitive?: # var1 : (address var), var2 : (address var) => result/eax : boolean
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
56/push-esi
|
||||
57/push-edi
|
||||
# esi = var1
|
||||
8b/-> *(ebp+8) 6/r32/esi
|
||||
# edi = var2
|
||||
8b/-> *(ebp+0xc) 7/r32/edi
|
||||
# if (var1->type != var2->type) return false
|
||||
# if (var1->register != var1->register) return false
|
||||
{
|
||||
# if addresses are equal, don't return here
|
||||
8b/-> *(esi+0x10) 0/r32/eax
|
||||
39/compare *(edi+0x10) 0/r32/eax
|
||||
74/jump-if-equal break/disp8
|
||||
# if either address is 0, return false
|
||||
3d/compare-eax-and 0/imm32
|
||||
74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var1->register to result
|
||||
81 7/subop/compare *(edi+0x10) 0/imm32
|
||||
74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var1->register to result
|
||||
# if string contents don't match, return false
|
||||
(string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register
|
||||
3d/compare-eax-and 0/imm32
|
||||
b8/copy-to-eax 0/imm32/false
|
||||
74/jump-if-equal $operand-matches-primitive?:end/disp8
|
||||
}
|
||||
# return true
|
||||
b8/copy-to-eax 1/imm32/true
|
||||
$operand-matches-primitive?:end:
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5e/pop-to-esi
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# like operand-matches-primitive? but also handles "*" register in primitive
|
||||
output-operand-matches-primitive?: # var : (address var), primout-var : (address var) => result/eax : boolean
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
56/push-esi
|
||||
57/push-edi
|
||||
# esi = var
|
||||
8b/-> *(ebp+8) 6/r32/esi
|
||||
# edi = primout-var
|
||||
8b/-> *(ebp+0xc) 7/r32/edi
|
||||
# if (var->type != primout-var->type) return false
|
||||
# return false if var->register doesn't match primout-var->register
|
||||
{
|
||||
# if addresses are equal, don't return here
|
||||
8b/-> *(esi+0x10) 0/r32/eax
|
||||
39/compare *(edi+0x10) 0/r32/eax
|
||||
74/jump-if-equal break/disp8
|
||||
# if either address is 0, return false
|
||||
3d/compare-eax-and 0/imm32
|
||||
74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result
|
||||
81 7/subop/compare *(edi+0x10) 0/imm32
|
||||
74/jump-if-equal $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result
|
||||
# if primout-var->register is "*", return true
|
||||
(string-equal? *(edi+0x10) "*") # Var-register
|
||||
3d/compare-eax-and 0/imm32
|
||||
b8/copy-to-eax 1/imm32/true
|
||||
75/jump-if-not-equal $operand-matches-primitive?:end/disp8
|
||||
# if string contents don't match, return false
|
||||
(string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register
|
||||
3d/compare-eax-and 0/imm32
|
||||
b8/copy-to-eax 0/imm32/false
|
||||
74/jump-if-equal $operand-matches-primitive?:end/disp8
|
||||
}
|
||||
# return true
|
||||
b8/copy-to-eax 1/imm32/true
|
||||
$output-operand-matches-primitive?:end:
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5e/pop-to-esi
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-emit-subx-statement-primitive:
|
||||
# Primitive operation on a variable on the stack.
|
||||
# increment foo
|
||||
|
@ -1305,21 +1490,25 @@ test-emit-subx-statement-primitive:
|
|||
68/push 1/imm32/type-int
|
||||
68/push "foo"/imm32
|
||||
89/<- %ecx 4/r32/esp
|
||||
#? $aa-var-in-ecx:
|
||||
# vars/edx : (stack 1)
|
||||
51/push-ecx/var-foo
|
||||
68/push 1/imm32/data-length
|
||||
68/push 1/imm32/top
|
||||
89/<- %edx 4/r32/esp
|
||||
# operand/esi : (list var)
|
||||
#? $aa-vars-in-edx:
|
||||
# operand/ebx : (list var)
|
||||
68/push 0/imm32/next
|
||||
51/push-ecx/var-foo
|
||||
89/<- %esi 4/r32/esp
|
||||
89/<- %ebx 4/r32/esp
|
||||
#? $aa-stmt-operand-in-ebx:
|
||||
# stmt/esi : statement
|
||||
68/push 0/imm32/next
|
||||
68/push 0/imm32/outputs
|
||||
56/push-esi/operands
|
||||
53/push-ebx/operands
|
||||
68/push "increment"/imm32/operation
|
||||
89/<- %esi 4/r32/esp
|
||||
#? $aa-stmt-in-esi:
|
||||
# primitives/ebx : primitive
|
||||
68/push 0/imm32/next
|
||||
68/push 0/imm32/no-imm32
|
||||
|
@ -1327,9 +1516,10 @@ test-emit-subx-statement-primitive:
|
|||
68/push 1/imm32/rm32-is-first-inout
|
||||
68/push "ff 0/subop/increment"/imm32/subx-name
|
||||
68/push 0/imm32/outputs
|
||||
51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call
|
||||
53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call
|
||||
68/push "increment"/imm32/name
|
||||
89/<- %ebx 4/r32/esp
|
||||
$aa-primitive-in-ebx:
|
||||
# convert
|
||||
(emit-subx-statement _test-output-buffered-file %esi %edx %ebx 0)
|
||||
(flush _test-output-buffered-file)
|
||||
|
@ -1361,7 +1551,7 @@ test-emit-subx-statement-primitive-register:
|
|||
#
|
||||
# There's a primitive with this info:
|
||||
# name: 'increment'
|
||||
# inout: int/reg
|
||||
# out: int/reg
|
||||
# value: 'ff 0/subop/increment'
|
||||
#
|
||||
# There's nothing in functions.
|
||||
|
@ -1384,13 +1574,13 @@ test-emit-subx-statement-primitive-register:
|
|||
68/push 1/imm32/data-length
|
||||
68/push 1/imm32/top
|
||||
89/<- %edx 4/r32/esp
|
||||
# operand/esi : (list var)
|
||||
# operand/ebx : (list var)
|
||||
68/push 0/imm32/next
|
||||
51/push-ecx/var-foo
|
||||
89/<- %esi 4/r32/esp
|
||||
89/<- %ebx 4/r32/esp
|
||||
# stmt/esi : statement
|
||||
68/push 0/imm32/next
|
||||
56/push-esi/outputs
|
||||
53/push-ebx/outputs
|
||||
68/push 0/imm32/inouts
|
||||
68/push "increment"/imm32/operation
|
||||
89/<- %esi 4/r32/esp
|
||||
|
@ -1433,6 +1623,202 @@ test-emit-subx-statement-primitive-register:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-emit-subx-statement-select-primitive:
|
||||
# Select the right primitive between overloads.
|
||||
# foo <- increment
|
||||
# =>
|
||||
# ff 0/subop/increment %eax # sub-optimal, but should suffice
|
||||
#
|
||||
# There's a variable on the var stack as follows:
|
||||
# name: 'foo'
|
||||
# type: int
|
||||
# register: 'eax'
|
||||
#
|
||||
# There's two primitives, as follows:
|
||||
# - name: 'increment'
|
||||
# out: int/reg
|
||||
# value: 'ff 0/subop/increment'
|
||||
# - name: 'increment'
|
||||
# inout: int/mem
|
||||
# value: 'ff 0/subop/increment'
|
||||
#
|
||||
# There's nothing in functions.
|
||||
#
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# setup
|
||||
(clear-stream _test-output-stream)
|
||||
(clear-stream _test-output-buffered-file->buffer)
|
||||
# var-foo/ecx : var in eax
|
||||
68/push "eax"/imm32/register
|
||||
68/push 0/imm32/no-stack-offset
|
||||
68/push 1/imm32/block-depth
|
||||
68/push 1/imm32/type-int
|
||||
68/push "foo"/imm32
|
||||
89/<- %ecx 4/r32/esp
|
||||
# vars/edx : (stack 1)
|
||||
51/push-ecx/var-foo
|
||||
68/push 1/imm32/data-length
|
||||
68/push 1/imm32/top
|
||||
89/<- %edx 4/r32/esp
|
||||
# real-outputs/edi : (list var)
|
||||
68/push 0/imm32/next
|
||||
51/push-ecx/var-foo
|
||||
89/<- %edi 4/r32/esp
|
||||
# stmt/esi : statement
|
||||
68/push 0/imm32/next
|
||||
57/push-edi/outputs
|
||||
68/push 0/imm32/inouts
|
||||
68/push "increment"/imm32/operation
|
||||
89/<- %esi 4/r32/esp
|
||||
# formal-var/ebx : var in any register
|
||||
68/push Any-register/imm32
|
||||
68/push 0/imm32/no-stack-offset
|
||||
68/push 1/imm32/block-depth
|
||||
68/push 1/imm32/type-int
|
||||
68/push "dummy"/imm32
|
||||
89/<- %ebx 4/r32/esp
|
||||
# formal-outputs/ebx : (list var)
|
||||
68/push 0/imm32/next
|
||||
53/push-ebx/formal-var
|
||||
89/<- %ebx 4/r32/esp
|
||||
# primitive1/ebx : primitive
|
||||
68/push 0/imm32/next
|
||||
68/push 0/imm32/no-imm32
|
||||
68/push 0/imm32/no-r32
|
||||
68/push 3/imm32/rm32-in-first-output
|
||||
68/push "ff 0/subop/increment"/imm32/subx-name
|
||||
53/push-ebx/outputs/formal-outputs
|
||||
68/push 0/imm32/inouts
|
||||
68/push "increment"/imm32/name
|
||||
89/<- %ebx 4/r32/esp
|
||||
# primitives/ebx : primitive
|
||||
53/push-ebx/next
|
||||
68/push 0/imm32/no-imm32
|
||||
68/push 0/imm32/no-r32
|
||||
68/push 1/imm32/rm32-is-first-inout
|
||||
68/push "ff 0/subop/increment"/imm32/subx-name
|
||||
68/push 0/imm32/outputs
|
||||
57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call
|
||||
68/push "increment"/imm32/name
|
||||
89/<- %ebx 4/r32/esp
|
||||
# convert
|
||||
(emit-subx-statement _test-output-buffered-file %esi %edx %ebx 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 "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive/0")
|
||||
# . reclaim locals
|
||||
81 0/subop/add %esp 0x48/imm32
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-emit-subx-statement-select-primitive-2:
|
||||
# Select the right primitive between overloads.
|
||||
# foo <- increment
|
||||
# =>
|
||||
# ff 0/subop/increment %eax # sub-optimal, but should suffice
|
||||
#
|
||||
# There's a variable on the var stack as follows:
|
||||
# name: 'foo'
|
||||
# type: int
|
||||
# register: 'eax'
|
||||
#
|
||||
# There's two primitives, as follows:
|
||||
# - name: 'increment'
|
||||
# out: int/reg
|
||||
# value: 'ff 0/subop/increment'
|
||||
# - name: 'increment'
|
||||
# inout: int/mem
|
||||
# value: 'ff 0/subop/increment'
|
||||
#
|
||||
# There's nothing in functions.
|
||||
#
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# setup
|
||||
(clear-stream _test-output-stream)
|
||||
(clear-stream _test-output-buffered-file->buffer)
|
||||
# var-foo/ecx : var in eax
|
||||
68/push "eax"/imm32/register
|
||||
68/push 0/imm32/no-stack-offset
|
||||
68/push 1/imm32/block-depth
|
||||
68/push 1/imm32/type-int
|
||||
68/push "foo"/imm32
|
||||
89/<- %ecx 4/r32/esp
|
||||
# vars/edx : (stack 1)
|
||||
51/push-ecx/var-foo
|
||||
68/push 1/imm32/data-length
|
||||
68/push 1/imm32/top
|
||||
89/<- %edx 4/r32/esp
|
||||
# inouts/edi : (list var)
|
||||
68/push 0/imm32/next
|
||||
51/push-ecx/var-foo
|
||||
89/<- %edi 4/r32/esp
|
||||
# stmt/esi : statement
|
||||
68/push 0/imm32/next
|
||||
68/push 0/imm32/outputs
|
||||
57/push-edi/inouts
|
||||
68/push "increment"/imm32/operation
|
||||
89/<- %esi 4/r32/esp
|
||||
# formal-var/ebx : var in any register
|
||||
68/push Any-register/imm32
|
||||
68/push 0/imm32/no-stack-offset
|
||||
68/push 1/imm32/block-depth
|
||||
68/push 1/imm32/type-int
|
||||
68/push "dummy"/imm32
|
||||
89/<- %ebx 4/r32/esp
|
||||
# operand/ebx : (list var)
|
||||
68/push 0/imm32/next
|
||||
53/push-ebx/formal-var
|
||||
89/<- %ebx 4/r32/esp
|
||||
# primitive1/ebx : primitive
|
||||
68/push 0/imm32/next
|
||||
68/push 0/imm32/no-imm32
|
||||
68/push 0/imm32/no-r32
|
||||
68/push 3/imm32/rm32-in-first-output
|
||||
68/push "ff 0/subop/increment"/imm32/subx-name
|
||||
53/push-ebx/outputs/formal-outputs
|
||||
68/push 0/imm32/inouts
|
||||
68/push "increment"/imm32/name
|
||||
89/<- %ebx 4/r32/esp
|
||||
# primitives/ebx : primitive
|
||||
53/push-ebx/next
|
||||
68/push 0/imm32/no-imm32
|
||||
68/push 0/imm32/no-r32
|
||||
68/push 1/imm32/rm32-is-first-inout
|
||||
68/push "ff 0/subop/increment"/imm32/subx-name
|
||||
68/push 0/imm32/outputs
|
||||
57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call
|
||||
68/push "increment"/imm32/name
|
||||
89/<- %ebx 4/r32/esp
|
||||
# convert
|
||||
(emit-subx-statement _test-output-buffered-file %esi %edx %ebx 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 "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2/0")
|
||||
# . reclaim locals
|
||||
81 0/subop/add %esp 0x48/imm32
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-emit-subx-statement-function-call:
|
||||
# Call a function on a variable on the stack.
|
||||
# f foo
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue