5820
One test failing. It took enough debugging just to get to the expected failure that it seems worth saving this snapshot. Saw some signs that I have to remember to zero-out allocated memory. We need a scalable solution for this. I think parse-var-with-type needs to be rewritten. Just added a test and a hacky fix for now.
This commit is contained in:
parent
c69f33143c
commit
40dbfe20d1
215
apps/mu.subx
215
apps/mu.subx
|
@ -640,9 +640,11 @@ parse-mu: # in : (address buffered-file)
|
|||
# else if slice-starts-with?(word-slice, "#") # comment
|
||||
# continue # end of line
|
||||
# else if slice-equal(word-slice, "fn")
|
||||
# var new-function : (handle function) = new function
|
||||
# populate-mu-function-header(in, new-function)
|
||||
# populate-mu-function-body(in, new-function)
|
||||
# var new-function : (handle function) = allocate(function)
|
||||
# var vars : (ref stack (address var) 256)
|
||||
# populate-mu-function-header(in, new-function, vars)
|
||||
# populate-mu-function-body(in, new-function, vars)
|
||||
# assert(vars->top == 0)
|
||||
# *curr-function = new-function
|
||||
# curr-function = &new-function->next
|
||||
# else
|
||||
|
@ -655,6 +657,7 @@ parse-mu: # in : (address buffered-file)
|
|||
50/push-eax
|
||||
51/push-ecx
|
||||
52/push-edx
|
||||
53/push-ebx
|
||||
57/push-edi
|
||||
# var line/ecx : (ref stream byte 512)
|
||||
81 5/subop/subtract %esp 0x200/imm32
|
||||
|
@ -668,6 +671,11 @@ parse-mu: # in : (address buffered-file)
|
|||
89/<- %edx 4/r32/esp
|
||||
# var curr-function/edi : (handle function) = Program
|
||||
bf/copy-to-edi Program/imm32
|
||||
# var vars/ebx : (ref stack (address var) 256)
|
||||
81 5/subop/subtract %esp 0x400/imm32
|
||||
68/push 0x400/imm32/length
|
||||
68/push 0/imm32/top
|
||||
89/<- %ebx 4/r32/esp
|
||||
{
|
||||
$parse-mu:line-loop:
|
||||
(clear-stream %ecx)
|
||||
|
@ -700,10 +708,14 @@ $parse-mu:fn:
|
|||
(slice-equal? %edx "fn")
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 84/jump-if-equal break/disp32
|
||||
# var new-function/eax : (handle function) = populate-mu-function()
|
||||
# var new-function/eax : (handle function) = populate-mu-function(in, new-function, vars)
|
||||
(allocate Heap *Function-size) # => eax
|
||||
(populate-mu-function-header %ecx %eax)
|
||||
(populate-mu-function-body *(ebp+8) %eax)
|
||||
(zero-out %eax *Function-size)
|
||||
(populate-mu-function-header %ecx %eax %ebx)
|
||||
(populate-mu-function-body *(ebp+8) %eax %ebx)
|
||||
# assert(vars->top == 0)
|
||||
81 7/subop/compare *ebx 0/imm32
|
||||
75/jump-if-not-equal $parse-mu:error2/disp8
|
||||
# *curr-function = new-function
|
||||
89/<- *edi 0/r32/eax
|
||||
# curr-function = &new-function->next
|
||||
|
@ -711,13 +723,14 @@ $parse-mu:fn:
|
|||
e9/jump $parse-mu:line-loop/disp32
|
||||
}
|
||||
# otherwise abort
|
||||
e9/jump $parse-mu:abort/disp32
|
||||
e9/jump $parse-mu:error1/disp32
|
||||
} # end line loop
|
||||
$parse-mu:end:
|
||||
# . reclaim locals
|
||||
81 0/subop/add %esp 0x214/imm32
|
||||
81 0/subop/add %esp 0x630/imm32
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5b/pop-to-ebx
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
58/pop-to-eax
|
||||
|
@ -726,7 +739,7 @@ $parse-mu:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
$parse-mu:abort:
|
||||
$parse-mu:error1:
|
||||
# error("unexpected top-level command: " word-slice "\n")
|
||||
(write-buffered Stderr "unexpected top-level command: ")
|
||||
(write-slice-buffered Stderr %edx)
|
||||
|
@ -738,6 +751,19 @@ $parse-mu:abort:
|
|||
cd/syscall 0x80/imm8
|
||||
# never gets here
|
||||
|
||||
$parse-mu:error2:
|
||||
# error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
|
||||
(print-int32-buffered Stderr *ebx)
|
||||
(write-buffered Stderr " vars not reclaimed after fn '")
|
||||
(write-slice-buffered Stderr *eax) # Function-name
|
||||
(write-buffered Stderr "'\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
|
||||
|
||||
# scenarios considered:
|
||||
# ✗ fn foo # no block
|
||||
# ✓ fn foo {
|
||||
|
@ -749,12 +775,13 @@ $parse-mu:abort:
|
|||
# ✓ fn foo x : int {
|
||||
# ✓ fn foo x: int {
|
||||
# ✓ fn foo x: int -> y/eax: int {
|
||||
populate-mu-function-header: # first-line : (address stream byte), out : (handle function)
|
||||
populate-mu-function-header: # first-line : (address stream byte), out : (handle function), vars : (address stack (address var))
|
||||
# pseudocode:
|
||||
# var name : (ref slice)
|
||||
# next-word(first-line, name)
|
||||
# assert(name not in '{' '}' '->')
|
||||
# out->name = slice-to-string(name)
|
||||
# var next-offset : int = 8
|
||||
# ## inouts
|
||||
# while true
|
||||
# ## name
|
||||
|
@ -763,6 +790,10 @@ populate-mu-function-header: # first-line : (address stream byte), out : (handl
|
|||
# if (name == '->') break
|
||||
# assert(name != '}')
|
||||
# var v : (handle var) = parse-var-with-type(name, first-line)
|
||||
# assert(v->register == null)
|
||||
# v->stack-offset = next-offset
|
||||
# next-offset += size-of(var)
|
||||
# push(vars, var)
|
||||
# out->inouts = append(out->inouts, v)
|
||||
# ## outputs
|
||||
# while true
|
||||
|
@ -770,6 +801,7 @@ populate-mu-function-header: # first-line : (address stream byte), out : (handl
|
|||
# name = next-word(first-line)
|
||||
# assert(name not in '{' '}' '->')
|
||||
# var v : (handle var) = parse-var-with-type(name, first-line)
|
||||
# assert(v->register != null)
|
||||
# out->outputs = append(out->outputs, v)
|
||||
# done:
|
||||
#
|
||||
|
@ -779,6 +811,8 @@ populate-mu-function-header: # first-line : (address stream byte), out : (handl
|
|||
# . save registers
|
||||
50/push-eax
|
||||
51/push-ecx
|
||||
52/push-edx
|
||||
53/push-ebx
|
||||
57/push-edi
|
||||
# edi = out
|
||||
8b/-> *(ebp+0xc) 7/r32/edi
|
||||
|
@ -786,26 +820,29 @@ populate-mu-function-header: # first-line : (address stream byte), out : (handl
|
|||
68/push 0/imm32/end
|
||||
68/push 0/imm32/start
|
||||
89/<- %ecx 4/r32/esp
|
||||
# var next-offset/edx = 8
|
||||
ba/copy-to-edx 8/imm32
|
||||
# read function name
|
||||
(next-word *(ebp+8) %ecx)
|
||||
# error checking
|
||||
# if (word-slice == '{') abort
|
||||
(slice-equal? %ecx "{") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error1/disp32
|
||||
# if (word-slice == '->') abort
|
||||
(slice-equal? %ecx "->") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error1/disp32
|
||||
# if (word-slice == '}') abort
|
||||
(slice-equal? %ecx "}") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error1/disp32
|
||||
# save function name
|
||||
(slice-to-string Heap %ecx) # => eax
|
||||
89/<- *edi 0/r32/eax # Function-name
|
||||
# save function inouts
|
||||
{
|
||||
$populate-mu-function-header:check-for-inout:
|
||||
(next-word *(ebp+8) %ecx)
|
||||
# if (word-slice == '{') goto done
|
||||
(slice-equal? %ecx "{") # => eax
|
||||
|
@ -818,31 +855,47 @@ populate-mu-function-header: # first-line : (address stream byte), out : (handl
|
|||
# if (word-slice == '}') abort
|
||||
(slice-equal? %ecx "}") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error1/disp32
|
||||
# var var/ebx : (handle var) = parse-var-with-type(word-slice, first-line)
|
||||
(parse-var-with-type %ecx *(ebp+8)) # => eax
|
||||
89/<- %ebx 0/r32/eax
|
||||
# assert(var->register == null)
|
||||
81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error2/disp32
|
||||
# var->stack-offset = next-offset
|
||||
89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset
|
||||
# next-offset += size-of(var)
|
||||
(size-of %ebx) # => eax
|
||||
01/add %edx 0/r32/eax
|
||||
#
|
||||
(parse-var-with-type %ecx *(ebp+8))
|
||||
(append-list Heap %eax *(edi+8)) # Function-inouts => eax
|
||||
(append-list Heap %ebx *(edi+8)) # Function-inouts => eax
|
||||
89/<- *(edi+8) 0/r32/eax # Function-inouts
|
||||
#
|
||||
e9/jump loop/disp32
|
||||
}
|
||||
# save function outputs
|
||||
{
|
||||
$parse-var-with-type:check-for-out:
|
||||
(next-word *(ebp+8) %ecx)
|
||||
# if (word-slice == '{') break
|
||||
(slice-equal? %ecx "{") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
0f 85/jump-if-not-equal break/disp32
|
||||
# if (word-slice == '->') abort
|
||||
(slice-equal? %ecx "->") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error1/disp32
|
||||
# if (word-slice == '}') abort
|
||||
(slice-equal? %ecx "}") # => eax
|
||||
3d/compare-eax-and 0/imm32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:abort/disp32
|
||||
0f 85/jump-if-not-equal $populate-mu-function-header:error1/disp32
|
||||
#
|
||||
(parse-var-with-type %ecx *(ebp+8))
|
||||
(append-list Heap %eax *(edi+0xc)) # Function-outputs
|
||||
(parse-var-with-type %ecx *(ebp+8)) # => eax
|
||||
89/<- %ebx 0/r32/eax
|
||||
# assert(var->register != null)
|
||||
81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register
|
||||
0f 84/jump-if-equal $populate-mu-function-header:error3/disp32
|
||||
(append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax
|
||||
89/<- *(edi+0xc) 0/r32/eax # Function-outputs
|
||||
e9/jump loop/disp32
|
||||
}
|
||||
|
@ -853,6 +906,8 @@ $populate-mu-function-header:end:
|
|||
81 0/subop/add %esp 8/imm32
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5b/pop-to-ebx
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
58/pop-to-eax
|
||||
# . epilogue
|
||||
|
@ -860,7 +915,7 @@ $populate-mu-function-header:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
$populate-mu-function-header:abort:
|
||||
$populate-mu-function-header:error1:
|
||||
# error("function header not in form 'fn <name> {'")
|
||||
(write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
|
||||
(flush Stderr)
|
||||
|
@ -874,6 +929,34 @@ $populate-mu-function-header:abort:
|
|||
cd/syscall 0x80/imm8
|
||||
# never gets here
|
||||
|
||||
$populate-mu-function-header:error2:
|
||||
# error("function input '" var "' cannot be in a register")
|
||||
(write-buffered Stderr "function input '")
|
||||
(write-buffered Stderr *ebx) # Var-name
|
||||
(write-buffered Stderr "' cannot be in a register")
|
||||
(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
|
||||
|
||||
$populate-mu-function-header:error3:
|
||||
# error("function input '" var "' must be in a register")
|
||||
(write-buffered Stderr "function input '")
|
||||
(write-buffered Stderr *eax) # Var-name
|
||||
(write-buffered Stderr " must be in a register'")
|
||||
(flush Stderr)
|
||||
(rewind-stream *(ebp+8))
|
||||
(write-stream 2 *(ebp+8))
|
||||
(write-buffered Stderr "'\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
|
||||
|
||||
test-function-header-with-arg:
|
||||
# 'foo n : int {'
|
||||
# . prologue
|
||||
|
@ -919,22 +1002,25 @@ test-function-header-with-multiple-args:
|
|||
(check-strings-equal *ecx "foo") # Function-name
|
||||
# edx : (handle list var) = result->inouts
|
||||
8b/-> *(ecx+8) 2/r32/edx # Function-inouts
|
||||
$test-function-header-with-multiple-args:inout0:
|
||||
# ebx : (handle var) = result->inouts->value
|
||||
8b/-> *edx 3/r32/ebx # List-value
|
||||
(check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name
|
||||
(check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:0/type") # Var-type
|
||||
(check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args/inout:0/type") # Var-type
|
||||
# edx = result->inouts->next
|
||||
8b/-> *(edx+4) 2/r32/edx # List-next
|
||||
$test-function-header-with-multiple-args:inout1:
|
||||
# ebx = result->inouts->next->value
|
||||
8b/-> *edx 3/r32/ebx # List-value
|
||||
(check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name
|
||||
(check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:1/type") # Var-type
|
||||
(check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args/inout:1/type") # Var-type
|
||||
# edx = result->inouts->next->next
|
||||
8b/-> *(edx+4) 2/r32/edx # List-next
|
||||
$test-function-header-with-multiple-args:inout2:
|
||||
# ebx = result->inouts->next->next->value
|
||||
8b/-> *edx 3/r32/ebx # List-value
|
||||
(check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name
|
||||
(check-ints-equal *(ebx+4) 1 "F - test-function-header-with-arg/inout:2/type") # Var-type
|
||||
(check-ints-equal *(ebx+4) 1 "F - test-function-header-with-multiple-args/inout:2/type") # Var-type
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -1038,7 +1124,8 @@ parse-var-with-type: # name: (address slice), first-line: (address stream byte)
|
|||
56/push-esi
|
||||
57/push-edi
|
||||
# var result/edi : (handle var) = allocate(Heap, Var-size)
|
||||
(allocate Heap *Var-size)
|
||||
(allocate Heap *Var-size) # => eax
|
||||
(zero-out %eax *Var-size)
|
||||
89/<- %edi 0/r32/eax
|
||||
# esi = name
|
||||
8b/-> *(ebp+8) 6/r32/esi
|
||||
|
@ -1046,6 +1133,7 @@ parse-var-with-type: # name: (address slice), first-line: (address stream byte)
|
|||
68/push 0/imm32/end
|
||||
68/push 0/imm32/start
|
||||
89/<- %ecx 4/r32/esp
|
||||
$parse-var-with-type:save-name:
|
||||
# save v->name
|
||||
(next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/'
|
||||
# . end/edx = s->end
|
||||
|
@ -1070,9 +1158,11 @@ parse-var-with-type: # name: (address slice), first-line: (address stream byte)
|
|||
75/jump-if-not-equal break/disp8
|
||||
89/<- *(ecx+4) 0/r32/eax
|
||||
}
|
||||
$parse-var-with-type:write-name:
|
||||
(slice-to-string Heap %ecx) # => eax
|
||||
89/<- *edi 0/r32/eax # Var-name
|
||||
# save v->register
|
||||
$parse-var-with-type:save-register:
|
||||
(next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/'
|
||||
# . if s ends with ':', decrement s->end
|
||||
{
|
||||
|
@ -1096,9 +1186,12 @@ parse-var-with-type: # name: (address slice), first-line: (address stream byte)
|
|||
}
|
||||
# if (!slice-empty?(s)) v->register = slice-to-string(s)
|
||||
{
|
||||
(slice-empty? %ecx)
|
||||
3d/compare-eax-and 0/imm32
|
||||
75/jump-if-not-equal break/disp8
|
||||
$parse-var-with-type:write-register:
|
||||
# HACK: s->end can be less than s->start with all the decrements above
|
||||
# That's probably a sign we have the wrong algorithm for this function.
|
||||
8b/-> *ecx 0/r32/eax
|
||||
39/compare 0/r32/eax *(ecx+4)
|
||||
76/jump-if-lesser-or-equal break/disp8
|
||||
(slice-to-string Heap %ecx)
|
||||
89/<- *(edi+0x10) 0/r32/eax # Var-register
|
||||
}
|
||||
|
@ -1285,8 +1378,8 @@ test-parse-var-with-trailing-characters:
|
|||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# (eax..ecx) = "x/eax:"
|
||||
b8/copy-to-eax "x/eax:"/imm32
|
||||
# (eax..ecx) = "x:"
|
||||
b8/copy-to-eax "x:"/imm32
|
||||
8b/-> *eax 1/r32/ecx
|
||||
8d/copy-address *(eax+ecx+4) 1/r32/ecx
|
||||
05/add-to-eax 4/imm32
|
||||
|
@ -1302,7 +1395,7 @@ test-parse-var-with-trailing-characters:
|
|||
8b/-> *eax 2/r32/edx # Var-name
|
||||
(check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name")
|
||||
8b/-> *(eax+0x10) 2/r32/edx # Var-register
|
||||
(check-strings-equal %edx "eax" "F - test-var-with-trailing-characters/register")
|
||||
(check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register")
|
||||
8b/-> *(eax+4) 2/r32/edx # Var-type
|
||||
(check-ints-equal %edx 1 "F - test-var-with-trailing-characters/type")
|
||||
# . epilogue
|
||||
|
@ -1310,6 +1403,35 @@ test-parse-var-with-trailing-characters:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
test-parse-var-with-register-and-trailing-characters:
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# (eax..ecx) = "x/eax:"
|
||||
b8/copy-to-eax "x/eax:"/imm32
|
||||
8b/-> *eax 1/r32/ecx
|
||||
8d/copy-address *(eax+ecx+4) 1/r32/ecx
|
||||
05/add-to-eax 4/imm32
|
||||
# var slice/ecx : (ref slice) = {eax, ecx}
|
||||
51/push-ecx
|
||||
50/push-eax
|
||||
89/<- %ecx 4/r32/esp
|
||||
# _test-input-stream contains "int,"
|
||||
(clear-stream _test-input-stream)
|
||||
(write _test-input-stream "int,")
|
||||
#
|
||||
(parse-var-with-type %ecx _test-input-stream)
|
||||
8b/-> *eax 2/r32/edx # Var-name
|
||||
(check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name")
|
||||
8b/-> *(eax+0x10) 2/r32/edx # Var-register
|
||||
(check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register")
|
||||
8b/-> *(eax+4) 2/r32/edx # Var-type
|
||||
(check-ints-equal %edx 1 "F - test-var-with-register-and-trailing-characters/type")
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
# identifier starts with a letter or '$' or '_'
|
||||
# no constraints at the moment on later letters
|
||||
# all we really want to do so far is exclude '{', '}' and '->'
|
||||
|
@ -1675,7 +1797,6 @@ parse-mu-block: # in : (address buffered-file) -> result/eax : (handle block)
|
|||
51/push-ecx
|
||||
52/push-edx
|
||||
53/push-ebx
|
||||
56/push-esi
|
||||
57/push-edi
|
||||
# var line/ecx : (ref stream byte 512)
|
||||
81 5/subop/subtract %esp 0x200/imm32
|
||||
|
@ -1689,6 +1810,7 @@ parse-mu-block: # in : (address buffered-file) -> result/eax : (handle block)
|
|||
89/<- %edx 4/r32/esp
|
||||
# edi = result
|
||||
(allocate Heap *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
89/<- %edi 0/r32/eax
|
||||
{ # line loop
|
||||
$parse-mu-block:line-loop:
|
||||
|
@ -1776,7 +1898,6 @@ $parse-mu-block:end:
|
|||
81 0/subop/add %esp 0x214/imm32
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5e/pop-to-esi
|
||||
5b/pop-to-ebx
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
|
@ -1933,7 +2054,8 @@ parse-mu-stmt: # line : (address stream byte) -> result/eax : (handle stmt)
|
|||
68/push 0/imm32/start
|
||||
89/<- %ecx 4/r32/esp
|
||||
# result/edi : (handle stmt)
|
||||
(allocate Heap *Stmt-size)
|
||||
(allocate Heap *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
89/<- %edi 0/r32/eax
|
||||
# result->tag = 1/stmt
|
||||
c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag
|
||||
|
@ -2081,11 +2203,10 @@ parse-var: # ad: allocation-descriptor, name: (address slice) -> result/eax: (h
|
|||
(slice-to-string Heap %ecx) # => eax
|
||||
89/<- %ecx 0/r32/eax
|
||||
(allocate *(ebp+8) *Var-size) # => eax
|
||||
(zero-out %eax *Var-size)
|
||||
89/<- *eax 1/r32/ecx # Var-name
|
||||
# var->type = int
|
||||
c7 0/subop/copy *(eax+4) 1/imm32/int-type # Var-type
|
||||
# var->stack-offset = 8
|
||||
c7 0/subop/copy *(eax+0xc) 8/imm32 # Var-stack-offset
|
||||
$parse-var:end:
|
||||
# . restore registers
|
||||
59/pop-to-ecx
|
||||
|
@ -2178,6 +2299,7 @@ new-block: # ad: allocation-descriptor, data: (handle list statement) -> result
|
|||
51/push-ecx
|
||||
#
|
||||
(allocate *(ebp+8) *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag
|
||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
89/<- *(eax+4) 1/r32/ecx # Block-statements
|
||||
|
@ -2197,6 +2319,7 @@ new-stmt: # ad: allocation-descriptor, operation: string, inouts: (handle list
|
|||
51/push-ecx
|
||||
#
|
||||
(allocate *(ebp+8) *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
c7 0/subop/copy *eax 1/imm32/tag/regular-stmt # Stmt-tag
|
||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
89/<- *(eax+4) 1/r32/ecx # Stmt1-operation
|
||||
|
@ -2220,6 +2343,7 @@ new-vardef: # ad: allocation-descriptor, name: string, type: int -> result/eax:
|
|||
51/push-ecx
|
||||
#
|
||||
(allocate *(ebp+8) *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag
|
||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
89/<- *(eax+4) 1/r32/ecx # Vardef-name
|
||||
|
@ -2241,6 +2365,7 @@ new-regvardef: # ad: allocation-descriptor, name: string, type: int, register:
|
|||
51/push-ecx
|
||||
#
|
||||
(allocate *(ebp+8) *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
c7 0/subop/copy *eax 3/imm32/tag/var-in-register
|
||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
89/<- *(eax+4) 1/r32/ecx # Regvardef-name
|
||||
|
@ -2264,6 +2389,7 @@ new-named-block: # ad: allocation-descriptor, name: string, data: (handle list
|
|||
51/push-ecx
|
||||
#
|
||||
(allocate *(ebp+8) *Stmt-size) # => eax
|
||||
(zero-out %eax *Stmt-size)
|
||||
c7 0/subop/copy *eax 4/imm32/tag/named-block
|
||||
8b/-> *(ebp+0xc) 1/r32/ecx
|
||||
89/<- *(eax+4) 1/r32/ecx # Named-block-name
|
||||
|
@ -2366,6 +2492,18 @@ $check-mu-types:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
size-of: # n : (address var)
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# hard-coded since we only support 'int' types for now
|
||||
b8/copy-to-eax 4/imm32
|
||||
$size-of:end:
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
#######################################################
|
||||
# Code-generation
|
||||
#######################################################
|
||||
|
@ -2438,11 +2576,12 @@ emit-subx-block: # out : (address buffered-file), block : (handle block)
|
|||
8b/-> *(esi+4) 6/r32/esi # Block-statements
|
||||
#
|
||||
{
|
||||
$emit-subx-block:stmt:
|
||||
$emit-subx-block:check-empty:
|
||||
81 7/subop/compare %esi 0/imm32
|
||||
0f 84/jump-if-equal break/disp32
|
||||
(write-buffered *(ebp+8) "{\n")
|
||||
{
|
||||
$emit-subx-block:stmt:
|
||||
81 7/subop/compare %esi 0/imm32
|
||||
74/jump-if-equal break/disp8
|
||||
(emit-subx-statement *(ebp+8) *esi 0 Primitives 0) # TODO: initialize vars and functions
|
||||
|
|
Loading…
Reference in New Issue
Block a user