diff options
-rwxr-xr-x | apps/mu | bin | 256204 -> 256251 bytes | |||
-rw-r--r-- | apps/mu.subx | 263 |
2 files changed, 115 insertions, 148 deletions
diff --git a/apps/mu b/apps/mu index fa14405a..7ad2a412 100755 --- a/apps/mu +++ b/apps/mu Binary files differdiff --git a/apps/mu.subx b/apps/mu.subx index 61c0c390..85794961 100644 --- a/apps/mu.subx +++ b/apps/mu.subx @@ -355,6 +355,15 @@ Stmt-var-is-deref: # boolean Stmt-var-size: # (addr int) 0x14/imm32 +# A live-var is a var augmented with information needed for tracking live +# variables. +Live-var-value: # (handle var) + 0/imm32 +Live-var-register-spilled: # boolean; only used if value is in a register, and only during code-gen + 8/imm32 +Live-var-size: # (addr int) + 0xc/imm32 + # Types are expressed as trees (s-expressions) of type-ids (ints). # However, there's no need for singletons, so we can assume (int) == int # - if x->right == nil, x is an atom @@ -3593,7 +3602,7 @@ parse-mu: # in: (addr buffered-file) # continue # end of line # else if slice-equal?(word-slice, "fn") # var new-function: (handle function) = allocate(function) - # var vars: (stack (handle var) 256) + # var vars: (stack live-var 256) # populate-mu-function-header(line, new-function, vars) # populate-mu-function-body(in, new-function, vars) # assert(vars->top == 0) @@ -3630,9 +3639,9 @@ parse-mu: # in: (addr buffered-file) 89/<- %edx 4/r32/esp # var curr-function/edi: (addr handle function) bf/copy-to-edi _Program-functions/imm32 - # var vars/ebx: (stack (handle var) 256) - 81 5/subop/subtract %esp 0x800/imm32 - 68/push 0x800/imm32/size + # var vars/ebx: (stack live-var 256) + 81 5/subop/subtract %esp 0xc00/imm32 + 68/push 0xc00/imm32/size 68/push 0/imm32/top 89/<- %ebx 4/r32/esp { @@ -3726,7 +3735,7 @@ $parse-mu:type: } # end line loop $parse-mu:end: # . reclaim locals - 81 0/subop/add %esp 0xa1c/imm32 + 81 0/subop/add %esp 0xe1c/imm32 # . restore registers 5f/pop-to-edi 5e/pop-to-esi @@ -3775,7 +3784,7 @@ $parse-mu:error2: # ✓ fn foo x: int { # ✓ fn foo x: int { # ✓ fn foo x: int -> y/eax: int { -populate-mu-function-header: # first-line: (addr stream byte), out: (addr function), vars: (addr stack (handle var)) +populate-mu-function-header: # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var) # pseudocode: # var name: slice # next-mu-token(first-line, name) @@ -3792,7 +3801,7 @@ populate-mu-function-header: # first-line: (addr stream byte), out: (addr funct # assert(v->register == null) # # v->block-depth is implicitly 0 # out->inouts = append(v, out->inouts) - # push(vars, v) + # push(vars, {v, false}) # ## outputs # while true # ## name @@ -3868,9 +3877,10 @@ $populate-mu-function-header:check-for-inout: # out->inouts = append(v, out->inouts) 8d/copy-address *(edi+8) 0/r32/eax # Function-inouts (append-list Heap *ebx *(ebx+4) *(edi+8) *(edi+0xc) %eax) # Function-inouts, Function-inouts - # push(vars, v) + # push(vars, {v, false}) (push *(ebp+0x10) *ebx) (push *(ebp+0x10) *(ebx+4)) + (push *(ebp+0x10) 0) # false # e9/jump loop/disp32 } @@ -3974,9 +3984,9 @@ test-function-header-with-arg: 2b/subtract *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp (zero-out %ecx *Function-size) - # var vars/ebx: (stack (handle var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + # var vars/ebx: (stack live-var 16) + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ebx 4/r32/esp # convert @@ -4012,9 +4022,9 @@ test-function-header-with-multiple-args: 2b/subtract *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp (zero-out %ecx *Function-size) - # var vars/ebx: (stack (handle var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + # var vars/ebx: (stack live-var 16) + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ebx 4/r32/esp # convert @@ -4083,9 +4093,9 @@ test-function-header-with-multiple-args-and-outputs: 2b/subtract *Function-size 4/r32/esp 89/<- %ecx 4/r32/esp (zero-out %ecx *Function-size) - # var vars/ebx: (stack (handle var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + # var vars/ebx: (stack live-var 16) + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ebx 4/r32/esp # convert @@ -5221,7 +5231,7 @@ test-is-identifier-hyphen: 5d/pop-to-ebp c3/return -populate-mu-function-body: # in: (addr buffered-file), out: (addr function), vars: (addr stack (handle var)) +populate-mu-function-body: # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -5247,7 +5257,7 @@ $populate-mu-function-body:end: c3/return # parses a block, assuming that the leading '{' has already been read by the caller -parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (addr function), out: (addr handle block) +parse-mu-block: # in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle block) # pseudocode: # var line: (stream byte 512) # var word-slice: slice @@ -5255,7 +5265,7 @@ parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn # var out-addr: (addr block) = lookup(*out) # out-addr->tag = 0/block # out-addr->var = some unique name - # push(vars, out-addr->var) + # push(vars, {out-addr->var, false}) # while true # line loop # clear-stream(line) # read-line-buffered(in, line) @@ -5316,6 +5326,7 @@ parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn # push(vars, out-addr->var) (push *(ebp+0xc) *(edi+0xc)) # Block-var (push *(ebp+0xc) *(edi+0x10)) # Block-var + (push *(ebp+0xc) 0) # false { $parse-mu-block:line-loop: # line = read-line-buffered(in) @@ -5433,6 +5444,7 @@ $parse-mu-block:regular-stmt: # pop(vars) (pop *(ebp+0xc)) # => eax (pop *(ebp+0xc)) # => eax + (pop *(ebp+0xc)) # => eax $parse-mu-block:end: # . reclaim locals 81 0/subop/add %esp 0x214/imm32 @@ -5579,11 +5591,11 @@ $check-no-tokens-left:end: 5d/pop-to-ebp c3/return -parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (addr function), out: (addr handle stmt) +parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt) # pseudocode: # var v: (handle var) # new-literal(name, v) - # push(vars, v) + # push(vars, {v, false}) # parse-mu-block(in, vars, fn, out) # pop(vars) # out->tag = block @@ -5605,11 +5617,13 @@ parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (ad # push(vars, v) (push *(ebp+0x10) *ecx) (push *(ebp+0x10) *(ecx+4)) + (push *(ebp+0x10) 0) # false # (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18)) # pop v off vars (pop *(ebp+0x10)) # => eax (pop *(ebp+0x10)) # => eax + (pop *(ebp+0x10)) # => eax # var out-addr/edi: (addr stmt) = lookup(*out) 8b/-> *(ebp+0x18) 7/r32/edi (lookup *edi *(edi+4)) # => eax @@ -5633,7 +5647,7 @@ $parse-mu-named-block:end: 5d/pop-to-ebp c3/return -parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)), out: (addr handle stmt) +parse-mu-var-def: # line: (addr stream byte), vars: (addr stack live-var), out: (addr handle stmt) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -5658,6 +5672,7 @@ parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)), # (push *(ebp+0xc) *edx) (push *(ebp+0xc) *(edx+4)) + (push *(ebp+0xc) 0) # Live-var-register-spilled is unused during parsing # either v has no register and there's no more to this line (lookup *edx *(edx+4)) # => eax 8b/-> *(eax+0x18) 0/r32/eax # Var-register @@ -5721,8 +5736,8 @@ test-parse-mu-var-def: 68/push 0/imm32 89/<- %esi 4/r32/esp # var vars/ecx: (stack (addr var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ecx 4/r32/esp (clear-stack %ecx) @@ -5764,8 +5779,8 @@ test-parse-mu-reg-var-def: 68/push 0/imm32 89/<- %esi 4/r32/esp # var vars/ecx: (stack (addr var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ecx 4/r32/esp (clear-stack %ecx) @@ -5801,7 +5816,7 @@ test-parse-mu-reg-var-def: 5d/pop-to-ebp c3/return -parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (addr function), out: (addr handle stmt) +parse-mu-stmt: # line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt) # pseudocode: # var name: slice # allocate(Heap, Stmt-size, out) @@ -5910,7 +5925,7 @@ $parse-mu-stmt:abort: cd/syscall 0x80/imm8 # never gets here -add-operation-and-inputs-to-stmt: # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack (handle var)) +add-operation-and-inputs-to-stmt: # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var) # pseudocode: # stmt->name = slice-to-string(next-mu-token(line)) # while true @@ -6076,7 +6091,7 @@ $stmt-has-outputs:end: # if 'name' starts with a digit, create a new literal var for it # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)), out: (addr handle var) +lookup-var-or-literal: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -6133,7 +6148,7 @@ $lookup-var-or-literal:abort: # never gets here # return first 'name' from the top (back) of 'vars' and abort if not found -lookup-var: # name: (addr slice), vars: (addr stack (handle var)), out: (addr handle var) +lookup-var: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -6165,15 +6180,15 @@ $lookup-var:abort: # never gets here # return first 'name' from the top (back) of 'vars', and 0/null if not found -lookup-var-helper: # name: (addr slice), vars: (addr stack (handle var)), out: (addr handle var) +lookup-var-helper: # name: (addr slice), vars: (addr stack live-var), out: (addr handle var) # pseudocode: - # var curr: (addr handle var) = &vars->data[vars->top - 8] + # var curr: (addr handle var) = &vars->data[vars->top - 12] # var min = vars->data # while curr >= min # var v: (handle var) = *curr # if v->name == name # return - # curr -= 8 + # curr -= 12 # # . prologue 55/push-ebp @@ -6195,8 +6210,8 @@ lookup-var-helper: # name: (addr slice), vars: (addr stack (handle var)), out: 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 # var min/edx: (addr handle var) = vars->data 8d/copy-address *(esi+8) 2/r32/edx - # var curr/ebx: (addr handle var) = &vars->data[vars->top - 8] - 8d/copy-address *(esi+ebx) 3/r32/ebx # vars + 8 + vars->type - 8 + # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12] + 8d/copy-address *(esi+ebx-4) 3/r32/ebx # vars + 8 + vars->type - 12 { # if (curr < min) return 39/compare %ebx 2/r32/edx @@ -6221,8 +6236,8 @@ lookup-var-helper: # name: (addr slice), vars: (addr stack (handle var)), out: # return eb/jump $lookup-var-helper:end/disp8 } - # curr -= 8 - 81 5/subop/subtract %ebx 8/imm32 + # curr -= 12 + 81 5/subop/subtract %ebx 0xc/imm32 e9/jump loop/disp32 } $lookup-var-helper:end: @@ -6249,7 +6264,7 @@ $lookup-var-helper:error1: # never gets here # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (addr function), out: (addr handle var) +lookup-or-define-var: # name: (addr slice), vars: (addr stack live-var), fn: (addr function), out: (addr handle var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -6339,8 +6354,8 @@ test-parse-mu-stmt: (clear-stream _test-input-stream) (write _test-input-stream "increment n\n") # var vars/ecx: (stack (addr var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ecx 4/r32/esp (clear-stack %ecx) @@ -6358,6 +6373,7 @@ test-parse-mu-stmt: # (push %ecx *edx) (push %ecx *(edx+4)) + (push %ecx 0) # var out/eax: (handle stmt) 68/push 0/imm32 68/push 0/imm32 @@ -6394,8 +6410,8 @@ test-parse-mu-stmt-with-comma: (clear-stream _test-input-stream) (write _test-input-stream "copy-to n, 3\n") # var vars/ecx: (stack (addr var) 16) - 81 5/subop/subtract %esp 0x80/imm32 - 68/push 0x80/imm32/size + 81 5/subop/subtract %esp 0xc0/imm32 + 68/push 0xc0/imm32/size 68/push 0/imm32/top 89/<- %ecx 4/r32/esp (clear-stack %ecx) @@ -6413,6 +6429,7 @@ test-parse-mu-stmt-with-comma: # (push %ecx *edx) (push %ecx *(edx+4)) + (push %ecx 0) # var out/eax: (handle stmt) 68/push 0/imm32 68/push 0/imm32 @@ -8069,8 +8086,8 @@ emit-subx-function: # out: (addr buffered-file), f: (addr function) # ecx = f 8b/-> *(ebp+0xc) 1/r32/ecx # var vars/edx: (stack (addr var) 256) - 81 5/subop/subtract %esp 0x800/imm32 - 68/push 0x800/imm32/size + 81 5/subop/subtract %esp 0xc00/imm32 + 68/push 0xc00/imm32/size 68/push 0/imm32/top 89/<- %edx 4/r32/esp # var name/eax: (addr array byte) = lookup(f->name) @@ -8088,7 +8105,7 @@ emit-subx-function: # out: (addr buffered-file), f: (addr function) # been cleaned up $emit-subx-function:end: # . reclaim locals - 81 0/subop/add %esp 808/imm32 + 81 0/subop/add %esp 0xc08/imm32 # . restore registers 5a/pop-to-edx 59/pop-to-ecx @@ -8153,7 +8170,7 @@ $populate-mu-type-offsets-in-inouts:end: 5d/pop-to-ebp c3/return -emit-subx-stmt-list: # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack (handle var)) +emit-subx-stmt-list: # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack live-var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8309,6 +8326,7 @@ $emit-subx-stmt-list:var-def: (emit-subx-var-def *(ebp+8) %ecx) (push *(ebp+0x10) *(ecx+4)) # Vardef-var (push *(ebp+0x10) *(ecx+8)) # Vardef-var + (push *(ebp+0x10) 0) # Live-var-register-spilled = 0 for vars on the stack # var-seen? = true ba/copy-to-edx 1/imm32/true eb/jump $emit-subx-stmt-list:continue/disp8 @@ -8348,13 +8366,14 @@ $emit-subx-stmt-list:end: 5d/pop-to-ebp c3/return -push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)) +push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack live-var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 51/push-ecx + 52/push-edx # ecx = stmt 8b/-> *(ebp+0xc) 1/r32/ecx # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs) @@ -8376,8 +8395,10 @@ push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg- # ensure that v is in a register 81 7/subop/compare *(ecx+0x18) 0/imm32 # Var-register 0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32 - # if not-yet-spilled-this-block?(reg, vars) emit code to spill reg + # var emit-spill?/edx: boolean = not-yet-spilled-this-block?(reg, vars) (not-yet-spilled-this-block? %ecx *(ebp+0x10)) # => eax + 89/<- %edx 0/r32/eax + # if emit-spill? then emit code to spill reg 3d/compare-eax-and 0/imm32/false 74/jump-if-= $push-output-and-maybe-emit-spill:push/disp8 # TODO: assert(size-of(output) == 4) @@ -8392,11 +8413,13 @@ push-output-and-maybe-emit-spill: # out: (addr buffered-file), stmt: (addr reg- $push-output-and-maybe-emit-spill:push: 8b/-> *(ebp+0xc) 1/r32/ecx (lookup *(ecx+0x14) *(ecx+0x18)) # Regvardef-outputs Regvardef-outputs => eax - # push(vars, sv->value) + # push(vars, {sv->value, emit-spill?}) (push *(ebp+0x10) *eax) # Stmt-var-value (push *(ebp+0x10) *(eax+4)) # Stmt-var-value + (push *(ebp+0x10) %edx) $push-output-and-maybe-emit-spill:end: # . restore registers + 5a/pop-to-edx 59/pop-to-ecx 58/pop-to-eax # . epilogue @@ -8416,7 +8439,7 @@ $push-output-and-maybe-emit-spill:abort: cd/syscall 0x80/imm8 # never gets here -emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) +emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8535,7 +8558,7 @@ Reverse-branch: # (table (handle array byte) (handle array byte)) == code -emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) +emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8549,8 +8572,8 @@ emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stac 8b/-> *(ebp+0xc) 1/r32/ecx # var eax: int = vars->top 8b/-> *ecx 0/r32/eax - # var curr/esi: (addr handle var) = &vars->data[vars->top - 8] - 8d/copy-address *(ecx+eax) 6/r32/esi # vars + 8 + vars->top - 8 + # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] + 8d/copy-address *(ecx+eax-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size # var min/ecx: (addr handle var) = vars->data 8d/copy-address *(ecx+8) 1/r32/ecx # edx = depth @@ -8587,8 +8610,8 @@ $emit-unconditional-jump-to-depth:label-found: (write-buffered *(ebp+8) "/disp32\n") eb/jump $emit-unconditional-jump-to-depth:end/disp8 } - # curr -= 8 - 81 5/subop/subtract %esi 8/imm32 + # curr -= 12 + 81 5/subop/subtract %esi 0xc/imm32 e9/jump loop/disp32 } # TODO: error if no label at 'depth' was found @@ -8606,7 +8629,7 @@ $emit-unconditional-jump-to-depth:end: # emit clean-up code for 'vars' until some block depth # doesn't actually modify 'vars' so we need traverse manually inside the stack -emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int +emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8622,8 +8645,8 @@ emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack ( 8b/-> *(ebp+0xc) 1/r32/ecx # var esi: int = vars->top 8b/-> *ecx 6/r32/esi - # var curr/esi: (addr handle var) = &vars->data[vars->top - 8] - 8d/copy-address *(ecx+esi) 6/r32/esi # vars + 8 + vars->top - 8 + # var curr/esi: (addr handle var) = &vars->data[vars->top - 12] + 8d/copy-address *(ecx+esi-4) 6/r32/esi # vars + 8 + vars->top - 12/Live-var-size # var min/ecx: (addr handle var) = vars->data 81 0/subop/add %ecx 8/imm32 # edx = until-block-depth @@ -8650,9 +8673,9 @@ $emit-cleanup-code-until-depth:loop: 0f 84/jump-if-= break/disp32 { $emit-cleanup-code-until-depth:check-for-previous-spill: - (same-register-spilled-before? %ebx *(ebp+0xc) %esi) # => eax + 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= break/disp32 + 74/jump-if-= break/disp8 $emit-cleanup-code-until-depth:reclaim-var-in-register: (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "8f 0/subop/pop %") @@ -8677,8 +8700,8 @@ $emit-cleanup-code-until-depth:reclaim-var-on-stack: (write-buffered *(ebp+8) "/imm32\n") } $emit-cleanup-code-until-depth:continue: - # curr -= 8 - 81 5/subop/subtract %esi 8/imm32 + # curr -= 12 + 81 5/subop/subtract %esi 0xc/imm32 e9/jump loop/disp32 } $emit-cleanup-code-until-depth:end: @@ -8695,7 +8718,7 @@ $emit-cleanup-code-until-depth:end: # emit clean-up code for 'vars' until a given label is encountered # doesn't actually modify 'vars' so we need traverse manually inside the stack -emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) +emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8708,8 +8731,8 @@ emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack 8b/-> *(ebp+0xc) 1/r32/ecx # var eax: int = vars->top 8b/-> *ecx 0/r32/eax - # var curr/edx: (addr handle var) = &vars->data[vars->top - 8] - 8d/copy-address *(ecx+eax) 2/r32/edx # vars + 8 + vars->top - 8 + # var curr/edx: (addr handle var) = &vars->data[vars->top - 12] + 8d/copy-address *(ecx+eax-4) 2/r32/edx # vars + 8 + vars->top - 12/Live-var-size # var min/ecx: (addr handle var) = vars->data 81 0/subop/add %ecx 8/imm32 { @@ -8731,9 +8754,9 @@ $emit-cleanup-code-until-target:loop: 0f 84/jump-if-= break/disp32 { $emit-cleanup-code-until-target:check-for-previous-spill: - (same-register-spilled-before? %ebx *(ebp+0xc) %edx) # => eax + 8b/-> *(esi+8) 0/r32/eax # Live-var-register-spilled 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= break/disp8 + 74/jump-if-= break/disp8 $emit-cleanup-code-until-target:reclaim-var-in-register: (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "8f 0/subop/pop %") @@ -8758,8 +8781,8 @@ $emit-cleanup-code-until-target:reclaim-var-on-stack: (write-buffered *(ebp+8) "/imm32\n") } $emit-cleanup-code-until-target:continue: - # curr -= 8 - 81 5/subop/subtract %edx 8/imm32 + # curr -= 12 + 81 5/subop/subtract %edx 0xc/imm32 e9/jump loop/disp32 } $emit-cleanup-code-until-target:end: @@ -8776,7 +8799,7 @@ $emit-cleanup-code-until-target:end: # Return true if there isn't a variable in 'vars' with the same block-depth # and register as 'v'. # 'v' is guaranteed not to be within 'vars'. -not-yet-spilled-this-block?: # v: (addr var), vars: (addr stack (handle var)) -> result/eax: boolean +not-yet-spilled-this-block?: # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8790,8 +8813,8 @@ not-yet-spilled-this-block?: # v: (addr var), vars: (addr stack (handle var)) - 8b/-> *(ebp+0xc) 1/r32/ecx # var eax: int = vars->top 8b/-> *ecx 0/r32/eax - # var curr/edx: (addr handle var) = &vars->data[vars->top - 8] - 8d/copy-address *(ecx+eax) 2/r32/edx # vars + 8 + vars->top - 8 + # var curr/edx: (addr handle var) = &vars->data[vars->top - 12] + 8d/copy-address *(ecx+eax-4) 2/r32/edx # vars + 8 + vars->top - 12/Live-var-size # var min/ecx: (addr handle var) = vars->data 8d/copy-address *(ecx+8) 1/r32/ecx # var depth/ebx: int = v->block-depth @@ -8829,8 +8852,8 @@ $not-yet-spilled-this-block?:return-false: eb/jump $not-yet-spilled-this-block?:end/disp8 } $not-yet-spilled-this-block?:continue: - # curr -= 8 - 81 5/subop/subtract %edx 8/imm32 + # curr -= 12 + 81 5/subop/subtract %edx 0xc/imm32 e9/jump loop/disp32 } $not-yet-spilled-this-block?:return-true: @@ -8848,76 +8871,8 @@ $not-yet-spilled-this-block?:end: 5d/pop-to-ebp c3/return -# is there a var before 'v' with the same block-depth and register on the 'vars' stack? -# v is guaranteed to be within vars -# 'start' is provided as an optimization, a pointer within vars -# *start == v -same-register-spilled-before?: # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean - # . prologue - 55/push-ebp - 89/<- %ebp 4/r32/esp - # . save registers - 51/push-ecx - 52/push-edx - 53/push-ebx - 56/push-esi - 57/push-edi - # ecx = v - 8b/-> *(ebp+8) 1/r32/ecx - # var reg/edx: (addr array byte) = lookup(v->register) - (lookup *(ecx+0x18) *(ecx+0x1c)) # Var-register Var-register => eax - 89/<- %edx 0/r32/eax - # var depth/ebx: int = v->block-depth - 8b/-> *(ecx+0x10) 3/r32/ebx # Var-block-depth - # var min/ecx: (addr handle var) = vars->data - 8b/-> *(ebp+0xc) 1/r32/ecx - 8d/copy-address *(ecx+8) 1/r32/ecx - # TODO: check that start >= min and start < &vars->data[top] - # TODO: check that *start == v - # var curr/esi: (addr handle var) = start - 8b/-> *(ebp+0x10) 6/r32/esi - # curr -= 8 - 81 5/subop/subtract %esi 8/imm32 - { -$same-register-spilled-before?:loop: - # if (curr < min) break - 39/compare %esi 1/r32/ecx - 0f 82/jump-if-addr< break/disp32 - # var x/eax: (addr var) = lookup(*curr) - (lookup *esi *(esi+4)) # => eax - # if (x->block-depth < depth) break - 39/compare *(eax+0x10) 3/r32/ebx # Var-block-depth - 0f 8c/jump-if-< break/disp32 - # if (x->register == 0) continue - 81 7/subop/compare *(eax+0x18) 0/imm32 # Var-register - 74/jump-if-= $same-register-spilled-before?:continue/disp8 - # if (x->register == reg) return true - (lookup *(eax+0x18) *(eax+0x1c)) # Var-register Var-register => eax - (string-equal? %eax %edx) # => eax - 3d/compare-eax-and 0/imm32/false - b8/copy-to-eax 1/imm32/true - 75/jump-if-!= $same-register-spilled-before?:end/disp8 -$same-register-spilled-before?:continue: - # curr -= 8 - 81 5/subop/subtract %esi 8/imm32 - e9/jump loop/disp32 - } -$same-register-spilled-before?:false: - b8/copy-to-eax 0/imm32/false -$same-register-spilled-before?: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 - # clean up global state for 'vars' until some block depth -clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int +clean-up-blocks: # vars: (addr stack live-var), until-block-depth: int # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -8934,9 +8889,18 @@ $clean-up-blocks:reclaim-loop: # if (vars->top <= 0) break 8b/-> *esi 0/r32/eax # Stack-top 3d/compare-eax-and 0/imm32 - 7e/jump-if-<= break/disp8 - # var v/eax: (addr var) = lookup(vars[vars->top-8]) - (lookup *(esi+eax) *(esi+eax+4)) # vars + 8 + vars->top - 8 => eax + 0f 8e/jump-if-<= break/disp32 + # var v/eax: (addr var) = lookup(vars[vars->top-12]) +#? (print-int32-buffered Stderr %eax) +#? (write-buffered Stderr ": ") +#? (print-int32-buffered Stderr *(esi+eax-4)) +#? (write-buffered Stderr " ") +#? (print-int32-buffered Stderr *(esi+eax)) +#? (write-buffered Stderr " ") +#? (print-int32-buffered Stderr *(esi+eax+4)) +#? (write-buffered Stderr Newline) +#? (flush Stderr) + (lookup *(esi+eax-4) *(esi+eax)) # vars + 8 + vars->top - 12 => eax # if (v->block-depth < until-block-depth) break 39/compare *(eax+0x10) 1/r32/ecx # Var-block-depth 7c/jump-if-< break/disp8 @@ -8950,6 +8914,7 @@ $clean-up-blocks:reclaim-var-on-stack: } (pop %esi) # => eax (pop %esi) # => eax + (pop %esi) # => eax e9/jump loop/disp32 } $clean-up-blocks:end: @@ -9798,7 +9763,7 @@ $emit-get-offset:end: 5d/pop-to-ebp c3/return -emit-subx-block: # out: (addr buffered-file), block: (addr block), vars: (addr stack (handle var)) +emit-subx-block: # out: (addr buffered-file), block: (addr block), vars: (addr stack live-var) # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp @@ -9831,11 +9796,13 @@ $emit-subx-block:check-empty: ff 0/subop/increment *Curr-block-depth (push *(ebp+0x10) *(esi+0xc)) # Block-var (push *(ebp+0x10) *(esi+0x10)) # Block-var + (push *(ebp+0x10) 0) # false # emit block->statements (lookup *(esi+4) *(esi+8)) # Block-stmts Block-stmts => eax (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) (pop *(ebp+0x10)) # => eax (pop *(ebp+0x10)) # => eax + (pop *(ebp+0x10)) # => eax ff 1/subop/decrement *Curr-block-depth (emit-indent *(ebp+8) *Curr-block-depth) (write-buffered *(ebp+8) "}\n") |